From 1868cd98caba48464bcb44209b2aa95c4d49a3ff Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Tue, 31 Dec 2024 16:10:21 +0100 Subject: [PATCH] FMTools --- .gitignore | 3 +- .vscode/.server-controller-port.log | 2 +- .vscode/settings.json | 8 ++ CMakeLists.txt | 33 +++++++ README.md | 8 +- compile_sca | 1 - compile_stereo | 1 - lib/constants.h | 6 ++ lib/filters.c | 41 +++++++++ lib/filters.h | 23 +++++ lib/oscillator.c | 29 ++++++ lib/oscillator.h | 13 +++ src/features.h | 2 + quadro_encoder.c => src/quadro_encoder.c | 109 ++++------------------- sca_mod.c => src/sca_mod.c | 99 ++------------------ stereo_coder.c => src/stereo_coder.c | 100 +++------------------ 16 files changed, 199 insertions(+), 279 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt delete mode 100755 compile_sca delete mode 100755 compile_stereo create mode 100644 lib/constants.h create mode 100644 lib/filters.c create mode 100644 lib/filters.h create mode 100644 lib/oscillator.c create mode 100644 lib/oscillator.h create mode 100644 src/features.h rename quadro_encoder.c => src/quadro_encoder.c (75%) rename sca_mod.c => src/sca_mod.c (61%) rename stereo_coder.c => src/stereo_coder.c (70%) diff --git a/.gitignore b/.gitignore index 2d02d50..745df5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ -stereo_coder -sca_mod +build/ # Prerequisites *.d diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 410e56b..4842a2a 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1735641535890, + "time": 1735655261170, "version": "0.0.3" } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..151ce0f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "filters.h": "c", + "features.h": "c", + "constants.h": "c", + "oscillator.h": "c" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b60ee49 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +# Set the minimum required CMake version +cmake_minimum_required(VERSION 3.10) + +# Define the project name and language +project(FMTools LANGUAGES C) + +# Set the C standard (you can adjust this based on your project needs) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED YES) + +# Find all C source files in the src/ directory +file(GLOB SRC_FILES "src/*.c") + +# Find all C source files in the lib/ directory +file(GLOB LIB_FILES "lib/*.c") + +# Create a library to hold all object files from lib/ +add_library(libfm OBJECT ${LIB_FILES}) + +# Linker flags for libraries +set(LINK_LIBS "-lpulse -lpulse-simple -lm") + +# Loop through each file in src and create an executable +foreach(SRC_FILE ${SRC_FILES}) + # Get the filename without the directory and extension + get_filename_component(EXEC_NAME ${SRC_FILE} NAME_WE) + + # Create the executable from each source file + add_executable(${EXEC_NAME} ${SRC_FILE}) + + # Link the necessary libraries and object files from lib/ + target_link_libraries(${EXEC_NAME} PRIVATE libfm ${LINK_LIBS}) +endforeach() diff --git a/README.md b/README.md index feafdb1..fde7de0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# FMTools +FMTools is a repository of apps you can use to make your FM broadcast better, pirate or not this will help you if you don't have something, maybe you want a better stereo encoder? SCA? or even went crazy and decided to do quadrophonic? We have what you need, for RDS just use MiniRDS + # STCode STCode is a simple stereo encoder for FM, it uses pasimple and math to: - Calculate mono signal ((L+R)/2) @@ -9,4 +12,7 @@ All that in about 3.5% cpu usage on a RPI-5 (lpf makes it 10, but stereo tool ha Also nearly no latency, not like Stereo Tool (or mpxgen which doesn't even work) # SCAMod -SCAMod is a simple FM modulator which can be used to modulate a secondary audio stream, has similiar cpu usage and latency as STCode \ No newline at end of file +SCAMod is a simple FM modulator which can be used to modulate a secondary audio stream, has similiar cpu usage and latency as STCode + +# QDCode +QD code is a FM quadrophonic encoder, following the Dorren standard \ No newline at end of file diff --git a/compile_sca b/compile_sca deleted file mode 100755 index 51f2bcc..0000000 --- a/compile_sca +++ /dev/null @@ -1 +0,0 @@ -gcc sca_mod.c -lpulse -lpulse-simple -lm -o sca_mod diff --git a/compile_stereo b/compile_stereo deleted file mode 100755 index 4dc9703..0000000 --- a/compile_stereo +++ /dev/null @@ -1 +0,0 @@ -gcc stereo_coder.c -lpulse -lpulse-simple -lm -o stereo_coder diff --git a/lib/constants.h b/lib/constants.h new file mode 100644 index 0000000..5945881 --- /dev/null +++ b/lib/constants.h @@ -0,0 +1,6 @@ +#ifndef PI +#define PI 3.14159265358979323846 +#endif +#ifndef M_2PI +#define M_2PI (3.14159265358979323846 * 2.0) +#endif \ No newline at end of file diff --git a/lib/filters.c b/lib/filters.c new file mode 100644 index 0000000..b5d0670 --- /dev/null +++ b/lib/filters.c @@ -0,0 +1,41 @@ +#include "filters.h" + +void init_emphasis(Emphasis *pe, float tau, float sample_rate) { + pe->prev_sample = 0.0f; + pe->alpha = exp(-1 / (tau * sample_rate)); +} + +float apply_pre_emphasis(Emphasis *pe, float sample) { + float audio = sample-pe->alpha*pe->prev_sample; + pe->prev_sample = audio; + return audio*2; +} + +void init_low_pass_filter(LowPassFilter *lp, float cutoff_frequency, float sample_rate) { + for (int i = 0; i < FIR_TAPS; i++) { + for (int j = 0; j < FIR_PHASES; j++) { + int mi = i * FIR_PHASES + j + 1; + float sincpos = mi - (((FIR_TAPS * FIR_PHASES) + 1.0f) / 2.0f); + float firlowpass = (sincpos == 0.0f) ? 1.0f : sinf(M_2PI * cutoff_frequency * sincpos / sample_rate) / (PI * sincpos); + float window = 0.54f - 0.46f * cosf(M_2PI * mi / (FIR_TAPS * FIR_PHASES)); // Hamming window + lp->low_pass_fir[j][i] = firlowpass * window; + } + } + memset(lp->sample_buffer, 0, sizeof(lp->sample_buffer)); + lp->buffer_index = 0; +} + +float apply_low_pass_filter(LowPassFilter *lp, float sample) { + // Update the sample buffer + lp->sample_buffer[lp->buffer_index] = sample; + lp->buffer_index = (lp->buffer_index + 1) % FIR_TAPS; + + // Apply the filter + float result = 0.0f; + int index = lp->buffer_index; + for (int i = 0; i < FIR_TAPS; i++) { + result += lp->low_pass_fir[0][i] * lp->sample_buffer[index]; + index = (index + 1) % FIR_TAPS; + } + return result*6; +} \ No newline at end of file diff --git a/lib/filters.h b/lib/filters.h new file mode 100644 index 0000000..853cb96 --- /dev/null +++ b/lib/filters.h @@ -0,0 +1,23 @@ +#include "math.h" +#include +#include "constants.h" + +#define FIR_PHASES 32 +#define FIR_TAPS 32 + +typedef struct { + float alpha; + float prev_sample; +} Emphasis; + +void init_emphasis(Emphasis *pe, float tau, float sample_rate); +float apply_pre_emphasis(Emphasis *pe, float sample); + +typedef struct { + float low_pass_fir[FIR_PHASES][FIR_TAPS]; + float sample_buffer[FIR_TAPS]; + int buffer_index; +} LowPassFilter; + +void init_low_pass_filter(LowPassFilter *lp, float cutoff_frequency, float sample_rate); +float apply_low_pass_filter(LowPassFilter *lp, float sample); \ No newline at end of file diff --git a/lib/oscillator.c b/lib/oscillator.c new file mode 100644 index 0000000..86e5e1e --- /dev/null +++ b/lib/oscillator.c @@ -0,0 +1,29 @@ +#include "oscillator.h" + +void init_oscillator(Oscillator *osc, float frequency, float sample_rate) { + osc->phase = 0.0f; + osc->phase_increment = (M_2PI * frequency) / sample_rate; + osc->sample_rate = sample_rate; +} + +void change_oscillator_frequency(Oscillator *osc, float frequency) { + osc->phase_increment = (M_2PI * frequency) / osc->sample_rate; +} + +float get_oscillator_sin_sample(Oscillator *osc) { + float sample = sinf(osc->phase); + osc->phase += osc->phase_increment; + if (osc->phase >= M_2PI) { + osc->phase -= M_2PI; + } + return sample; +} + +float get_oscillator_cos_sample(Oscillator *osc) { + float sample = cosf(osc->phase); + osc->phase += osc->phase_increment; + if (osc->phase >= M_2PI) { + osc->phase -= M_2PI; + } + return sample; +} \ No newline at end of file diff --git a/lib/oscillator.h b/lib/oscillator.h new file mode 100644 index 0000000..0c7f727 --- /dev/null +++ b/lib/oscillator.h @@ -0,0 +1,13 @@ +#include "constants.h" +#include "math.h" + +typedef struct { + float phase; + float phase_increment; + float sample_rate; +} Oscillator; + +void init_oscillator(Oscillator *osc, float frequency, float sample_rate); +void change_oscillator_frequency(Oscillator *osc, float frequency); +float get_oscillator_sin_sample(Oscillator *osc); +float get_oscillator_cos_sample(Oscillator *osc); diff --git a/src/features.h b/src/features.h new file mode 100644 index 0000000..6d0867f --- /dev/null +++ b/src/features.h @@ -0,0 +1,2 @@ +// #define PREEMPHASIS +#define LPF \ No newline at end of file diff --git a/quadro_encoder.c b/src/quadro_encoder.c similarity index 75% rename from quadro_encoder.c rename to src/quadro_encoder.c index 625187f..811e96f 100644 --- a/quadro_encoder.c +++ b/src/quadro_encoder.c @@ -8,9 +8,12 @@ #include #include +#include "../lib/constants.h" +#include "../lib/oscillator.h" +#include "../lib/filters.h" + // Features -#define PREEMPHASIS -#define LPF +#include "features.h" #define SAMPLE_RATE 192000 // Don't go lower than 182 KHz (91*2) @@ -20,7 +23,7 @@ #define CLIPPER_THRESHOLD 0.425 // Adjust this as needed #define MONO_VOLUME 0.45f // L+R Signal -#define PILOT_VOLUME 0.0225f // 19 KHz Pilot +#define PILOT_VOLUME 0.0175f // 19 KHz Pilot #define SIN38_VOLUME 0.35f #define COS38_VOLUME 0.35f #define SIN76_VOLUME 0.35f @@ -54,88 +57,6 @@ void uninterleave(const float *input, float *front_left, float *front_right, flo } } - -#define FIR_PHASES 32 -#define FIR_TAPS 32 - -#define PI 3.14159265358979323846 -#define M_2PI (3.14159265358979323846 * 2.0) - -// Track phase continuously to maintain frequency accuracy -typedef struct { - float phase; - float phase_increment; -} Oscillator; - -void init_oscillator(Oscillator *osc, float frequency, float sample_rate) { - osc->phase = 0.0f; - osc->phase_increment = (M_2PI * frequency) / sample_rate; -} - -float get_next_sample(Oscillator *osc) { - float sample = sinf(osc->phase); - osc->phase += osc->phase_increment; - if (osc->phase >= M_2PI) { - osc->phase -= M_2PI; - } - return sample; -} - -#ifdef PREEMPHASIS -typedef struct { - float alpha; - float prev_sample; -} Emphasis; - -void init_emphasis(Emphasis *pe, float sample_rate) { - pe->prev_sample = 0.0f; - pe->alpha = exp(-1 / (PREEMPHASIS_TAU * sample_rate)); -} - -float apply_pre_emphasis(Emphasis *pe, float sample) { - float audio = sample-pe->alpha*pe->prev_sample; - pe->prev_sample = audio; - return audio*2; -} -#endif - -#ifdef LPF -typedef struct { - float low_pass_fir[FIR_PHASES][FIR_TAPS]; - float sample_buffer[FIR_TAPS]; - int buffer_index; -} LowPassFilter; - -void init_low_pass_filter(LowPassFilter *lp, float sample_rate) { - for (int i = 0; i < FIR_TAPS; i++) { - for (int j = 0; j < FIR_PHASES; j++) { - int mi = i * FIR_PHASES + j + 1; - float sincpos = mi - (((FIR_TAPS * FIR_PHASES) + 1.0f) / 2.0f); - float firlowpass = (sincpos == 0.0f) ? 1.0f : sinf(M_2PI * LPF_CUTOFF * sincpos / sample_rate) / (PI * sincpos); - float window = 0.54f - 0.46f * cosf(M_2PI * mi / (FIR_TAPS * FIR_PHASES)); // Hamming window - lp->low_pass_fir[j][i] = firlowpass * window; - } - } - memset(lp->sample_buffer, 0, sizeof(lp->sample_buffer)); - lp->buffer_index = 0; -} - -float apply_low_pass_filter(LowPassFilter *lp, float sample) { - // Update the sample buffer - lp->sample_buffer[lp->buffer_index] = sample; - lp->buffer_index = (lp->buffer_index + 1) % FIR_TAPS; - - // Apply the filter - float result = 0.0f; - int index = lp->buffer_index; - for (int i = 0; i < FIR_TAPS; i++) { - result += lp->low_pass_fir[0][i] * lp->sample_buffer[index]; - index = (index + 1) % FIR_TAPS; - } - return result*6; -} -#endif - static void stop(int signum) { (void)signum; printf("\nReceived stop signal. Cleaning up...\n"); @@ -207,17 +128,17 @@ int main() { init_oscillator(&pilot_osc, 19000.0, SAMPLE_RATE); // Pilot, it's there to indicate stereo and as a refrence signal with the stereo carrier #ifdef PREEMPHASIS Emphasis preemp_lf, preemp_lr, preemp_rf, preemp_rr; - init_emphasis(&preemp_lf, SAMPLE_RATE); - init_emphasis(&preemp_lr, SAMPLE_RATE); - init_emphasis(&preemp_rf, SAMPLE_RATE); - init_emphasis(&preemp_rr, SAMPLE_RATE); + init_emphasis(&preemp_lf, PREEMPHASIS_TAU, SAMPLE_RATE); + init_emphasis(&preemp_lr, PREEMPHASIS_TAU, SAMPLE_RATE); + init_emphasis(&preemp_rf, PREEMPHASIS_TAU, SAMPLE_RATE); + init_emphasis(&preemp_rr, PREEMPHASIS_TAU, SAMPLE_RATE); #endif #ifdef LPF LowPassFilter lpf_lf, lpf_lr, lpf_rf, lpf_rr; - init_low_pass_filter(&lpf_lf, SAMPLE_RATE); - init_low_pass_filter(&lpf_lr, SAMPLE_RATE); - init_low_pass_filter(&lpf_rf, SAMPLE_RATE); - init_low_pass_filter(&lpf_rr, SAMPLE_RATE); + init_low_pass_filter(&lpf_lf, LPF_CUTOFF, SAMPLE_RATE); + init_low_pass_filter(&lpf_lr, LPF_CUTOFF, SAMPLE_RATE); + init_low_pass_filter(&lpf_rf, LPF_CUTOFF, SAMPLE_RATE); + init_low_pass_filter(&lpf_rr, LPF_CUTOFF, SAMPLE_RATE); #endif signal(SIGINT, stop); @@ -238,7 +159,7 @@ int main() { float sin38 = sinf((pilot_osc.phase+(0.5*PI))*2); float cos38 = cosf((pilot_osc.phase+(0.5*PI))*2); float sin76 = sinf((pilot_osc.phase+(0.5*PI))*4); - float pilot = get_next_sample(&pilot_osc); + float pilot = get_oscillator_sin_sample(&pilot_osc); float lf_in = left_front[i]; float lr_in = left_rear[i]; float rf_in = right_front[i]; diff --git a/sca_mod.c b/src/sca_mod.c similarity index 61% rename from sca_mod.c rename to src/sca_mod.c index 162d35a..2ed5c46 100644 --- a/sca_mod.c +++ b/src/sca_mod.c @@ -6,9 +6,12 @@ #include #include +#include "../lib/constants.h" +#include "../lib/oscillator.h" +#include "../lib/filters.h" + // Features -// #define PREEMPHASIS -#define LPF +#include "features.h" #define SAMPLE_RATE 192000 @@ -41,90 +44,6 @@ float clip(float sample) { } } -#define FIR_PHASES 32 -#define FIR_TAPS 32 - -#define PI 3.14159265358979323846 -#define M_2PI (3.14159265358979323846 * 2.0) - -// Track phase continuously to maintain frequency accuracy -typedef struct { - float phase; - float frequency; - float sample_rate; -} Oscillator; - -void init_oscillator(Oscillator *osc, float frequency, float sample_rate) { - osc->phase = 0.0f; - osc->frequency = frequency; - osc->sample_rate = sample_rate; -} - -float get_next_sample(Oscillator *osc) { - float phase_increment = (M_2PI * osc->frequency) / osc->sample_rate; // If you want to have dynamic frequency changing you have to compute this every sample - float sample = sinf(osc->phase); - osc->phase += phase_increment; - if (osc->phase >= M_2PI) { - osc->phase -= M_2PI; - } - return sample; -} - -#ifdef PREEMPHASIS -typedef struct { - float alpha; - float prev_sample; -} Emphasis; - -void init_emphasis(Emphasis *pe, float sample_rate) { - pe->prev_sample = 0.0f; - pe->alpha = exp(-1 / (PREEMPHASIS_TAU * sample_rate)); -} - -float apply_pre_emphasis(Emphasis *pe, float sample) { - float audio = sample-pe->alpha*pe->prev_sample; - pe->prev_sample = audio; - return audio*2; -} -#endif - -#ifdef LPF -typedef struct { - float low_pass_fir[FIR_PHASES][FIR_TAPS]; - float sample_buffer[FIR_TAPS]; - int buffer_index; -} LowPassFilter; - -void init_low_pass_filter(LowPassFilter *lp, float sample_rate) { - for (int i = 0; i < FIR_TAPS; i++) { - for (int j = 0; j < FIR_PHASES; j++) { - int mi = i * FIR_PHASES + j + 1; - float sincpos = mi - (((FIR_TAPS * FIR_PHASES) + 1.0f) / 2.0f); - float firlowpass = (sincpos == 0.0f) ? 1.0f : sinf(M_2PI * LPF_CUTOFF * sincpos / sample_rate) / (PI * sincpos); - float window = 0.54f - 0.46f * cosf(M_2PI * mi / (FIR_TAPS * FIR_PHASES)); // Hamming window - lp->low_pass_fir[j][i] = firlowpass * window; - } - } - memset(lp->sample_buffer, 0, sizeof(lp->sample_buffer)); - lp->buffer_index = 0; -} - -float apply_low_pass_filter(LowPassFilter *lp, float sample) { - // Update the sample buffer - lp->sample_buffer[lp->buffer_index] = sample; - lp->buffer_index = (lp->buffer_index + 1) % FIR_TAPS; - - // Apply the filter - float result = 0.0f; - int index = lp->buffer_index; - for (int i = 0; i < FIR_TAPS; i++) { - result += lp->low_pass_fir[0][i] * lp->sample_buffer[index]; - index = (index + 1) % FIR_TAPS; - } - return result*6; -} -#endif - static void stop(int signum) { (void)signum; printf("\nReceived stop signal. Cleaning up...\n"); @@ -192,11 +111,11 @@ int main() { init_oscillator(&osc, FREQUENCY, SAMPLE_RATE); #ifdef PREEMPHASIS Emphasis preemp; - init_emphasis(&preemp, SAMPLE_RATE); + init_emphasis(&preemp, PREEMPHASIS_TAU, SAMPLE_RATE); #endif #ifdef LPF LowPassFilter lpf; - init_low_pass_filter(&lpf, SAMPLE_RATE); + init_low_pass_filter(&lpf, LPF_CUTOFF, SAMPLE_RATE); #endif signal(SIGINT, stop); @@ -231,8 +150,8 @@ int main() { #endif #endif - osc.frequency = (FREQUENCY+(current_input*DEVIATION)); - signal[i] = get_next_sample(&osc)*VOLUME; + change_oscillator_frequency(&osc, (FREQUENCY+(current_input*DEVIATION))); + signal[i] = get_oscillator_sin_sample(&osc)*VOLUME; } if (pa_simple_write(output_device, signal, sizeof(signal), NULL) < 0) { diff --git a/stereo_coder.c b/src/stereo_coder.c similarity index 70% rename from stereo_coder.c rename to src/stereo_coder.c index 6781864..4f1519c 100644 --- a/stereo_coder.c +++ b/src/stereo_coder.c @@ -6,9 +6,12 @@ #include #include +#include "../lib/constants.h" +#include "../lib/oscillator.h" +#include "../lib/filters.h" + // Features -// #define PREEMPHASIS -#define LPF +#include "features.h" #define SAMPLE_RATE 192000 // Don't go lower than 108 KHz, becuase it (53000*2) and (38000+15000) @@ -18,7 +21,7 @@ #define CLIPPER_THRESHOLD 0.425 // Adjust this as needed #define MONO_VOLUME 0.45f // L+R Signal -#define PILOT_VOLUME 0.0225f // 19 KHz Pilot +#define PILOT_VOLUME 0.0175f // 19 KHz Pilot #define STEREO_VOLUME 0.35f // L-R signal #ifdef PREEMPHASIS @@ -49,87 +52,6 @@ void uninterleave(const float *input, float *left, float *right, size_t num_samp } } -#define FIR_PHASES 32 -#define FIR_TAPS 32 - -#define PI 3.14159265358979323846 -#define M_2PI (3.14159265358979323846 * 2.0) - -// Track phase continuously to maintain frequency accuracy -typedef struct { - float phase; - float phase_increment; -} Oscillator; - -void init_oscillator(Oscillator *osc, float frequency, float sample_rate) { - osc->phase = 0.0f; - osc->phase_increment = (M_2PI * frequency) / sample_rate; -} - -float get_next_sample(Oscillator *osc) { - float sample = sinf(osc->phase); - osc->phase += osc->phase_increment; - if (osc->phase >= M_2PI) { - osc->phase -= M_2PI; - } - return sample; -} - -#ifdef PREEMPHASIS -typedef struct { - float alpha; - float prev_sample; -} Emphasis; - -void init_emphasis(Emphasis *pe, float sample_rate) { - pe->prev_sample = 0.0f; - pe->alpha = exp(-1 / (PREEMPHASIS_TAU * sample_rate)); -} - -float apply_pre_emphasis(Emphasis *pe, float sample) { - float audio = sample-pe->alpha*pe->prev_sample; - pe->prev_sample = audio; - return audio*2; -} -#endif - -#ifdef LPF -typedef struct { - float low_pass_fir[FIR_PHASES][FIR_TAPS]; - float sample_buffer[FIR_TAPS]; - int buffer_index; -} LowPassFilter; - -void init_low_pass_filter(LowPassFilter *lp, float sample_rate) { - for (int i = 0; i < FIR_TAPS; i++) { - for (int j = 0; j < FIR_PHASES; j++) { - int mi = i * FIR_PHASES + j + 1; - float sincpos = mi - (((FIR_TAPS * FIR_PHASES) + 1.0f) / 2.0f); - float firlowpass = (sincpos == 0.0f) ? 1.0f : sinf(M_2PI * LPF_CUTOFF * sincpos / sample_rate) / (PI * sincpos); - float window = 0.54f - 0.46f * cosf(M_2PI * mi / (FIR_TAPS * FIR_PHASES)); // Hamming window - lp->low_pass_fir[j][i] = firlowpass * window; - } - } - memset(lp->sample_buffer, 0, sizeof(lp->sample_buffer)); - lp->buffer_index = 0; -} - -float apply_low_pass_filter(LowPassFilter *lp, float sample) { - // Update the sample buffer - lp->sample_buffer[lp->buffer_index] = sample; - lp->buffer_index = (lp->buffer_index + 1) % FIR_TAPS; - - // Apply the filter - float result = 0.0f; - int index = lp->buffer_index; - for (int i = 0; i < FIR_TAPS; i++) { - result += lp->low_pass_fir[0][i] * lp->sample_buffer[index]; - index = (index + 1) % FIR_TAPS; - } - return result*6; -} -#endif - static void stop(int signum) { (void)signum; printf("\nReceived stop signal. Cleaning up...\n"); @@ -201,13 +123,13 @@ int main() { init_oscillator(&pilot_osc, 19000.0, SAMPLE_RATE); // Pilot, it's there to indicate stereo and as a refrence signal with the stereo carrier #ifdef PREEMPHASIS Emphasis preemp_l, preemp_r; - init_emphasis(&preemp_l, SAMPLE_RATE); - init_emphasis(&preemp_r, SAMPLE_RATE); + init_emphasis(&preemp_l, PREEMPHASIS_TAU, SAMPLE_RATE); + init_emphasis(&preemp_r, PREEMPHASIS_TAU, SAMPLE_RATE); #endif #ifdef LPF LowPassFilter lpf_l, lpf_r; - init_low_pass_filter(&lpf_l, SAMPLE_RATE); - init_low_pass_filter(&lpf_r, SAMPLE_RATE); + init_low_pass_filter(&lpf_l, LPF_CUTOFF, SAMPLE_RATE); + init_low_pass_filter(&lpf_r, LPF_CUTOFF, SAMPLE_RATE); #endif signal(SIGINT, stop); @@ -225,7 +147,7 @@ int main() { for (int i = 0; i < BUFFER_SIZE; i++) { float stereo_carrier = sinf(pilot_osc.phase*2); // Stereo carrier should be a harmonic of the pilot which is in phase, best way to generate the harmonic is to multiply the pilot's phase by two, so it is mathematically impossible for them to not be in phase - float pilot = get_next_sample(&pilot_osc); // This is after because if it was before then the stereo would be out of phase by one increment, so [GET STEREO] ([GET PILOT] [INCREMENT PHASE]) + float pilot = get_oscillator_sin_sample(&pilot_osc); // This is after because if it was before then the stereo would be out of phase by one increment, so [GET STEREO] ([GET PILOT] [INCREMENT PHASE]) float l_in = left[i]; float r_in = right[i];