From 09b30852abea162298b845db94b3900589bc565e Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Wed, 29 Jan 2025 14:49:12 +0100 Subject: [PATCH] nug fixes and small tweaks --- .vscode/.server-controller-port.log | 2 +- lib/constants.h | 6 +-- lib/filters.c | 13 +++--- lib/fm_modulator.c | 1 + lib/hilbert.c | 2 +- lib/oscillator.c | 16 ++++--- lib/oscillator.h | 3 +- src/fm95.c | 65 ++++++++++++++--------------- 8 files changed, 53 insertions(+), 55 deletions(-) diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 3d93d12..cd4b1af 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1737972017853, + "time": 1738158496504, "version": "0.0.3" } \ No newline at end of file diff --git a/lib/constants.h b/lib/constants.h index 5945881..5239276 100644 --- a/lib/constants.h +++ b/lib/constants.h @@ -1,6 +1,6 @@ -#ifndef PI -#define PI 3.14159265358979323846 +#ifndef M_PI +#define M_PI 3.14159265358979323846 #endif #ifndef M_2PI -#define M_2PI (3.14159265358979323846 * 2.0) +#define M_2PI (M_PI * 2.0) #endif \ No newline at end of file diff --git a/lib/filters.c b/lib/filters.c index 0f401fb..fb5a21a 100644 --- a/lib/filters.c +++ b/lib/filters.c @@ -25,11 +25,11 @@ void init_lpf(FrequencyFilter* filter, float cutoffFreq, float sampleRate) { float m = n - (FILTER_TAPS - 1.0f) / 2.0f; // Sinc function - float sinc = (m == 0) ? 1.0f : sinf(PI * m * fc) / (PI * m); + float sinc = (m == 0) ? 1.0f : sinf(M_PI * m * fc) / (M_PI * m); // Blackman window - float window = 0.42f - 0.5f * cosf(2.0f * PI * n / (FILTER_TAPS - 1)) - + 0.08f * cosf(4.0f * PI * n / (FILTER_TAPS - 1)); + float window = 0.42f - 0.5f * cosf(2.0f * M_PI * n / (FILTER_TAPS - 1)) + + 0.08f * cosf(4.0f * M_PI * n / (FILTER_TAPS - 1)); filter->coeffs[n] = sinc * window; } @@ -53,11 +53,11 @@ void init_hpf(FrequencyFilter* filter, float cutoffFreq, float sampleRate) { float m = n - (FILTER_TAPS - 1.0f) / 2.0f; // Sinc function - float sinc = (m == 0) ? -1.0f : sinf(PI * m * fc) / (PI * m); + float sinc = (m == 0) ? 1.0f : -sinf(M_PI * m * fc) / (M_PI * m); // Blackman window - float window = 0.42f - 0.5f * cosf(2.0f * PI * n / (FILTER_TAPS - 1)) - + 0.08f * cosf(4.0f * PI * n / (FILTER_TAPS - 1)); + float window = 0.42f - 0.5f * cosf(2.0f * M_PI * n / (FILTER_TAPS - 1)) + + 0.08f * cosf(4.0f * M_PI * n / (FILTER_TAPS - 1)); filter->coeffs[n] = sinc * window; } @@ -148,4 +148,5 @@ float delay_line(DelayLine *delay_line, float in) { void exit_delay_line(DelayLine *delay_line) { free(delay_line->buffer); + delay_line->buffer = NULL; } \ No newline at end of file diff --git a/lib/fm_modulator.c b/lib/fm_modulator.c index ac6447d..0ed4287 100644 --- a/lib/fm_modulator.c +++ b/lib/fm_modulator.c @@ -8,6 +8,7 @@ void init_fm_modulator(FMModulator *fm, float frequency, float deviation, float float modulate_fm(FMModulator *fm, float sample) { float inst_freq = fm->frequency+(sample*fm->deviation); + if (inst_freq < 0.0f) inst_freq = 0.0f; change_oscillator_frequency(&fm->osc, inst_freq); return get_oscillator_sin_sample(&fm->osc); } \ No newline at end of file diff --git a/lib/hilbert.c b/lib/hilbert.c index cec50fb..8a38ee3 100644 --- a/lib/hilbert.c +++ b/lib/hilbert.c @@ -6,7 +6,7 @@ void compute_hilbert_coeffs(float* coeffs, int taps) { if ((i - mid) % 2 == 0) { coeffs[i] = 0.0f; } else { - coeffs[i] = 2.0f / (PI * (i - mid)); + coeffs[i] = 2.0f / (M_PI * (i - mid)); } } } diff --git a/lib/oscillator.c b/lib/oscillator.c index 47fd3cb..cffc1f5 100644 --- a/lib/oscillator.c +++ b/lib/oscillator.c @@ -12,25 +12,23 @@ void change_oscillator_frequency(Oscillator *osc, float frequency) { 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; - } + advance_oscillator(osc); 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; - } + advance_oscillator(osc); return sample; } -float get_oscillator_sin_multiplier_ni(Oscillator *osc, float multiplier) { +float get_oscillator_sin_multiplier_ni(Oscillator *osc, float multiplier) { // ni = No Increment return sinf(osc->phase*multiplier); } float get_oscillator_cos_multiplier_ni(Oscillator *osc, float multiplier) { return cosf(osc->phase*multiplier); +} + +void advance_oscillator(Oscillator *osc) { + osc->phase = fmodf(osc->phase + osc->phase_increment, M_2PI); } \ No newline at end of file diff --git a/lib/oscillator.h b/lib/oscillator.h index 69b794b..e84f205 100644 --- a/lib/oscillator.h +++ b/lib/oscillator.h @@ -14,4 +14,5 @@ void change_oscillator_frequency(Oscillator *osc, float frequency); float get_oscillator_sin_sample(Oscillator *osc); float get_oscillator_cos_sample(Oscillator *osc); float get_oscillator_sin_multiplier_ni(Oscillator *osc, float multiplier); -float get_oscillator_cos_multiplier_ni(Oscillator *osc, float multiplier); \ No newline at end of file +float get_oscillator_cos_multiplier_ni(Oscillator *osc, float multiplier); +void advance_oscillator(Oscillator *osc); \ No newline at end of file diff --git a/src/fm95.c b/src/fm95.c index be5b1f0..bbcc2d7 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -4,7 +4,7 @@ #define buffer_maxlength 12288 #define buffer_tlength_fragsize 12288 -#define buffer_prebuf 16 +#define buffer_prebuf 32 #define DEFAULT_STEREO 1 #define DEFAULT_STEREO_POLAR 0 @@ -14,8 +14,8 @@ #define DEFAULT_ALSA_OUTPUT 1 #define DEFAULT_SCA_FREQUENCY 67000.0f #define DEFAULT_SCA_DEVIATION 7000.0f -#define DEFAULT_SCA_CLIPPER_THRESHOLD 1.0f // Full deviation -#define DEFAULT_PREEMPHASIS_TAU 50e-6 // Europe +#define DEFAULT_SCA_CLIPPER_THRESHOLD 1.0f // Full deviation, if you set this to 0.5 then you may as well set the deviation to 3.5k +#define DEFAULT_PREEMPHASIS_TAU 50e-6 // Europe, the freedomers use 75µs //#define USB @@ -25,7 +25,7 @@ #include "../lib/hilbert.h" #include "../lib/fm_modulator.h" -#define SAMPLE_RATE 192000 // Don't go lower than 108 KHz, becuase it (53000*2) and (38000+15000) +#define SAMPLE_RATE 192000 #define INPUT_DEVICE "FM_Audio.monitor" #define OUTPUT_DEVICE "plughw:1,0" @@ -46,6 +46,7 @@ #define LPF_CUTOFF 15000 // Should't need to be changed #define HPF_CUTOFF 30 // Unless you wanna have SOME bass then leave this alone +#define CENTER_BASS 50 // Bass upto this will be mono volatile sig_atomic_t to_run = 1; @@ -398,7 +399,7 @@ int main(int argc, char **argv) { // #endregion // #region Setup Filters/Modulaltors/Oscillators Oscillator osc; - if(polar_stereo == 1) { + if(polar_stereo) { init_oscillator(&osc, 31250.0, SAMPLE_RATE); // The stereo carrier itself, the stereo carrier in polar is modulated directly on 31.25 khz with a bit of a carrier } else { init_oscillator(&osc, 19000.0, SAMPLE_RATE); // Pilot, it's there to indicate stereo and as a refrence signal with the stereo carrier @@ -423,6 +424,9 @@ int main(int argc, char **argv) { FrequencyFilter hpf_l, hpf_r; init_hpf(&hpf_l, HPF_CUTOFF, SAMPLE_RATE); init_hpf(&hpf_r, HPF_CUTOFF, SAMPLE_RATE); + + FrequencyFilter bass_hpf; + init_hpf(&bass_hpf, CENTER_BASS, SAMPLE_RATE); // #endregion signal(SIGINT, stop); @@ -477,54 +481,47 @@ int main(int argc, char **argv) { float mono = (ready_l + ready_r) / 2.0f; // Stereo to Mono if(stereo == 1) { float stereo = (ready_l - ready_r) / 2.0f; // Also Stereo to Mono but a bit diffrent - if(polar_stereo == 1) { - if(ssb) { - float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc, 1); // Get stereo carrier via multiplication - float stereo_carrier_cos = get_oscillator_cos_sample(&osc); // Get Carrier Q of I/Q + if(CENTER_BASS != 0) stereo = apply_frequency_filter(&bass_hpf, stereo); - float stereo_i, stereo_q; - stereo += 0.2; - apply_hilbert(&hilbert, stereo, &stereo_i, &stereo_q); // Compute I/Q - output[i] = delay_line(&monoDelay, mono)*MONO_VOLUME + - (stereo_i*stereo_carrier_cos+stereo_q*(stereo_carrier))*STEREO_VOLUME; - if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; - if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; + float stereo_i, stereo_q; + if(ssb) { + // Compute hilbert here + apply_hilbert(&hilbert, stereo, &stereo_i, &stereo_q); + mono = delay_line(&monoDelay, mono); // Delay Mono + } + + if(polar_stereo) { + float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc, 1); + if(ssb) { + float stereo_carrier_cos = get_oscillator_cos_multiplier_ni(&osc, 1); // Get Carrier Q of I/Q + + output[i] = mono*MONO_VOLUME + + ((stereo_i+0.2)*stereo_carrier_cos+(stereo_q+0.2)*stereo_carrier)*STEREO_VOLUME; } else { - float stereo_carrier = get_oscillator_sin_sample(&osc); + float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc, 1); output[i] = mono*MONO_VOLUME + ((stereo+0.2)*stereo_carrier)*STEREO_VOLUME; - if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; - if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; } } else { + float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc, 2); // Get stereo carrier via multiplication + float pilot = get_oscillator_sin_multiplier_ni(&osc, 1); if(ssb) { - float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc, 2); // Get stereo carrier via multiplication float stereo_carrier_cos = get_oscillator_cos_multiplier_ni(&osc, 2); // Get Carrier Q of I/Q - float pilot = get_oscillator_sin_sample(&osc); - - float stereo_i, stereo_q; - apply_hilbert(&hilbert, stereo, &stereo_i, &stereo_q); // Compute I/Q - - output[i] = delay_line(&monoDelay, mono)*MONO_VOLUME + + output[i] = mono*MONO_VOLUME + pilot*PILOT_VOLUME + (stereo_i*stereo_carrier_cos+stereo_q*stereo_carrier)*STEREO_VOLUME; - if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; - if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; } else { - float stereo_carrier = get_oscillator_sin_multiplier_ni(&osc,2); - float pilot = get_oscillator_sin_sample(&osc); output[i] = mono*MONO_VOLUME + pilot*PILOT_VOLUME + (stereo*stereo_carrier)*STEREO_VOLUME; - if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; - if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; } } + advance_oscillator(&osc); } else { output[i] = mono*MONO_VOLUME; // Only Mono - if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; - if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; } + if(strlen(audio_mpx_device) != 0) output[i] += current_mpx_in*MPX_VOLUME; + if(strlen(audio_sca_device) != 0) output[i] += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; } if(alsa_output == 0) {