Esempio n. 1
0
/* 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;
}
Esempio n. 2
0
// 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;
}