/* Simple test program */ int main(int argc, char **argv) { if(argc < 3) { fprintf(stderr, "Error: missing argument.\n"); fprintf(stderr, "Syntax: rds_wav <out.wav> <text>\n"); return EXIT_FAILURE; } set_rds_pi(0x1234); set_rds_ps(argv[2]); set_rds_rt(argv[2]); float buffer[LENGTH]; // Set the format of the output file SNDFILE *outf; SF_INFO sfinfo; sfinfo.frames = LENGTH; sfinfo.samplerate = 228000; sfinfo.channels = 1; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; sfinfo.sections = 1; sfinfo.seekable = 0; // Open the output file if (! (outf = sf_open(argv[1], SFM_WRITE, &sfinfo))) { fprintf(stderr, "Error: could not open output file %s.\n", argv[1]) ; return EXIT_FAILURE; } for(int j=0; j<40; j++) { get_rds_samples(buffer, LENGTH); if(sf_write_float(outf, buffer, LENGTH) != LENGTH) { fprintf(stderr, "Error: writing to file %s.\n", argv[1]); return EXIT_FAILURE; } } if(sf_close(outf) ) { fprintf(stderr, "Error: closing file %s.\n", argv[1]); } return EXIT_SUCCESS; }
// samples provided by this function are in 0..10: they need to be divided by // 10 after. int fm_mpx_get_samples(float *mpx_buffer, struct rds_content_struct* rds_params, struct rds_signal_info* rds_signal, struct fm_mpx_struct * fm_mpx_status) { get_rds_samples(mpx_buffer, fm_mpx_status->length, rds_params, rds_signal); if(fm_mpx_status->inf == NULL) return 0; // if there is no audio, stop here int i; for(i=0; i<fm_mpx_status->length; i++) { if(fm_mpx_status->audio_pos >= fm_mpx_status->downsample_factor) { fm_mpx_status->audio_pos -= fm_mpx_status->downsample_factor; if(fm_mpx_status->audio_len == 0) { int j; for(j=0; j<2; j++) { // one retry fm_mpx_status->audio_len = sf_read_float(fm_mpx_status->inf, fm_mpx_status->audio_buffer, fm_mpx_status->length); if (fm_mpx_status->audio_len < 0) { fprintf(stderr, "Error reading audio\n"); return -1; } if(fm_mpx_status->audio_len == 0) { if( sf_seek(fm_mpx_status->inf, 0, SEEK_SET) < 0 ) { fprintf(stderr, "Could not rewind in audio file, terminating\n"); return -1; } } else { break; } } fm_mpx_status->audio_index = 0; } else { fm_mpx_status->audio_index += fm_mpx_status->channels; fm_mpx_status->audio_len -= fm_mpx_status->channels; } } // First store the current sample(s) into the FIR filter's ring buffer if(fm_mpx_status->channels == 0) { fm_mpx_status->fir_buffer_mono[fm_mpx_status->fir_index] = fm_mpx_status->audio_buffer[fm_mpx_status->audio_index]; } else { // In stereo operation, generate sum and difference signals fm_mpx_status->fir_buffer_mono[fm_mpx_status->fir_index] = fm_mpx_status->audio_buffer[fm_mpx_status->audio_index] + fm_mpx_status->audio_buffer[fm_mpx_status->audio_index + 1]; fm_mpx_status->fir_buffer_stereo[fm_mpx_status->fir_index] = fm_mpx_status->audio_buffer[fm_mpx_status->audio_index] - fm_mpx_status->audio_buffer[fm_mpx_status->audio_index + 1]; } fm_mpx_status->fir_index++; if(fm_mpx_status->fir_index >= FIR_SIZE) fm_mpx_status->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 = fm_mpx_status->fir_index; // ifbi = increasing FIR Buffer Index int dfbi = fm_mpx_status->fir_index; // dfbi = decreasing FIR Buffer Index int fi; for(fi=0; fi<FIR_HALF_SIZE; fi++) { // fi = Filter Index dfbi--; if(dfbi < 0) dfbi = FIR_SIZE-1; out_mono += fm_mpx_status->low_pass_fir[fi] * (fm_mpx_status->fir_buffer_mono[ifbi] + fm_mpx_status->fir_buffer_mono[dfbi]); if(fm_mpx_status->channels > 1) { out_stereo += fm_mpx_status->low_pass_fir[fi] * (fm_mpx_status->fir_buffer_stereo[ifbi] + fm_mpx_status->fir_buffer_stereo[dfbi]); } ifbi++; if(ifbi >= FIR_SIZE) ifbi = 0; } // End of FIR filter mpx_buffer[i] = mpx_buffer[i] + // RDS data samples are currently in mpx_buffer 4.05*out_mono; // Unmodulated monophonic (or stereo-sum) signal // XXX: YLB Added the stereo pilot tone to all signals mono or stereo. mpx_buffer[i] += .9*carrier_19[fm_mpx_status->phase_19]; // Stereo pilot tone fm_mpx_status->phase_19++; if(fm_mpx_status->phase_19 >= 12) fm_mpx_status->phase_19 = 0; if(fm_mpx_status->channels>1) { mpx_buffer[i] += 4.05 * carrier_38[fm_mpx_status->phase_38] * out_stereo; // Stereo difference signal fm_mpx_status->phase_38++; if(fm_mpx_status->phase_38 >= 6) fm_mpx_status->phase_38 = 0; } fm_mpx_status->audio_pos++; } return 0; }