diff --git a/src/fm_mpx.c b/src/fm_mpx.c index 3d60121..b1e560e 100644 --- a/src/fm_mpx.c +++ b/src/fm_mpx.c @@ -35,14 +35,14 @@ #define PI 3.141592654 -#define FIR_HALF_SIZE 30 -#define FIR_SIZE (2*FIR_HALF_SIZE-1) - +#define FIR_PHASES (32) +#define FIR_SIZE (1024) // MUST be a power of 2 for the circular buffer +#define FIR_TAPS (FIR_SIZE/FIR_PHASES) size_t length; // coefficients of the low-pass FIR filter -float low_pass_fir[FIR_HALF_SIZE]; +float low_pass_fir[FIR_SIZE]; float carrier_38[] = {0.0, 0.8660254037844386, 0.8660254037844388, 1.2246467991473532e-16, -0.8660254037844384, -0.8660254037844386}; @@ -61,8 +61,8 @@ int audio_index = 0; int audio_len = 0; float audio_pos; -float fir_buffer_mono[FIR_SIZE] = {0}; -float fir_buffer_stereo[FIR_SIZE] = {0}; +float fir_buffer_left[FIR_SIZE] = {0}; +float fir_buffer_right[FIR_SIZE] = {0}; int fir_index = 0; int channels; @@ -116,32 +116,55 @@ int fm_mpx_open(char *filename, size_t len) { printf("1 channel, monophonic operation.\n"); } - - // Create the low-pass FIR filter - float cutoff_freq = 15000 * .8; + // Choose a cutoff frequency for the low-pass FIR filter + float cutoff_freq = 15000; if(in_samplerate/2 < cutoff_freq) cutoff_freq = in_samplerate/2 * .8; - - - - low_pass_fir[FIR_HALF_SIZE-1] = 2 * cutoff_freq / 228000 /2; - // Here we divide this coefficient by two because it will be counted twice - // when applying the filter + - // Only store half of the filter since it is symmetric - for(int i=1; i= FIR_SIZE) fir_index = 0; - - // Now apply the FIR low-pass filter - - /* As the FIR filter is symmetric, we do not multiply all - the coefficients independently, but two-by-two, thus reducing - the total number of multiplications by a factor of two - */ - float out_mono = 0; - float out_stereo = 0; - int ifbi = fir_index; // ifbi = increasing FIR Buffer Index - int dfbi = fir_index; // dfbi = decreasing FIR Buffer Index - for(int fi=0; fi 1) { - out_stereo += - low_pass_fir[fi] * - (fir_buffer_stereo[ifbi] + fir_buffer_stereo[dfbi]); - } - ifbi++; - if(ifbi >= FIR_SIZE) ifbi = 0; - } - // End of FIR filter - + fir_index++; // fir_index will point to newest valid data soon + if(fir_index >= FIR_SIZE) fir_index = 0; + // Store the current sample(s) into the FIR filter's ring buffer + fir_buffer_left[fir_index] = audio_buffer[audio_index]; + if(channels > 1) { + fir_buffer_right[fir_index] = audio_buffer[audio_index+1]; + } + } // if need new sample - mpx_buffer[i] = - mpx_buffer[i] + // RDS data samples are currently in mpx_buffer - 4.05*out_mono; // Unmodulated monophonic (or stereo-sum) signal - - if(channels>1) { - mpx_buffer[i] += - 4.05 * carrier_38[phase_38] * out_stereo + // Stereo difference signal + // Polyphase FIR filter + float out_left = 0; + float out_right = 0; + // Calculate which FIR phase to use + //int iphase = FIR_PHASES-1 - ((int) (audio_pos/downsample_factor*FIR_PHASES) ); + int iphase = ((int) (audio_pos*FIR_PHASES/downsample_factor) );// I think this is correct + //int iphase=FIR_PHASES-1; // test override + //printf("%d %d \n",fir_index,iphase); // diagnostics + // Sanity checks + if ( iphase < 0 ) {iphase=0; printf("low\n"); } + if ( iphase >= FIR_PHASES ) {iphase=FIR_PHASES-2; printf("high\n"); } + int fir_start = (fir_index - FIR_TAPS); + if( fir_start < 0 ) fir_start+=FIR_SIZE; + if( channels > 1 ) + { + for(int fi=0; fi 1 ) { + mpx_buffer[i] += 4.05*(out_left+out_right) + // Stereo sum signal + 4.05 * carrier_38[phase_38] * (out_left-out_right) + // Stereo difference signal .9*carrier_19[phase_19]; // Stereo pilot tone phase_19++; @@ -246,6 +262,12 @@ int fm_mpx_get_samples(float *mpx_buffer) { if(phase_19 >= 12) phase_19 = 0; if(phase_38 >= 6) phase_38 = 0; } + else + { + mpx_buffer[i] = + mpx_buffer[i] + // RDS data samples are currently in mpx_buffer + 9.0*out_left; // Unmodulated monophonic signal + } audio_pos++;