static void create_filter(struct eq_data *eq, unsigned size_log2, struct eq_gain *gains, unsigned num_gains, double beta) { int i; int half_block_size = eq->block_size >> 1; double window_mod = 1.0 / kaiser_window(0.0, beta); fft_t *fft = fft_new(size_log2); float *time_filter = (float*)calloc(eq->block_size * 2, sizeof(*time_filter)); if (!fft || !time_filter) goto end; // Make sure bands are in correct order. qsort(gains, num_gains, sizeof(*gains), gains_cmp); // Compute desired filter response. generate_response(eq->filter, gains, num_gains, half_block_size); // Get equivalent time-domain filter. fft_process_inverse(fft, time_filter, eq->filter, 1); // ifftshift() to create the correct linear phase filter. // The filter response was designed with zero phase, which won't work unless we compensate // for the repeating property of the FFT here by flipping left and right blocks. for (i = 0; i < half_block_size; i++) { float tmp = time_filter[i + half_block_size]; time_filter[i + half_block_size] = time_filter[i]; time_filter[i] = tmp; } // Apply a window to smooth out the frequency repsonse. for (i = 0; i < (int)eq->block_size; i++) { // Kaiser window. double phase = (double)i / (eq->block_size - 1); phase = 2.0 * (phase - 0.5); time_filter[i] *= window_mod * kaiser_window(phase, beta); } // Debugging. #if 0 FILE *file = fopen("/tmp/test.txt", "w"); if (file) { for (i = 0; i < (int)eq->block_size; i++) fprintf(file, "%.6f\n", time_filter[i]); fclose(file); } #endif // Padded FFT to create our FFT filter. fft_process_forward(eq->fft, eq->filter, time_filter, 1); end: fft_free(fft); free(time_filter); }
static void *eq_init(const struct dspfilter_info *info, const struct dspfilter_config *config, void *userdata) { float *frequencies, *gain; unsigned num_freq, num_gain, i, size; int size_log2; float beta; struct eq_gain *gains = NULL; char *filter_path = NULL; const float default_freq[] = { 0.0f, info->input_rate }; const float default_gain[] = { 0.0f, 0.0f }; struct eq_data *eq = (struct eq_data*)calloc(1, sizeof(*eq)); if (!eq) return NULL; config->get_float(userdata, "window_beta", &beta, 4.0f); config->get_int(userdata, "block_size_log2", &size_log2, 8); size = 1 << size_log2; config->get_float_array(userdata, "frequencies", &frequencies, &num_freq, default_freq, 2); config->get_float_array(userdata, "gains", &gain, &num_gain, default_gain, 2); if (!config->get_string(userdata, "impulse_response_output", &filter_path, "")) { config->free(filter_path); filter_path = NULL; } num_gain = num_freq = MIN(num_gain, num_freq); gains = (struct eq_gain*)calloc(num_gain, sizeof(*gains)); if (!gains) goto error; for (i = 0; i < num_gain; i++) { gains[i].freq = frequencies[i] / (0.5f * info->input_rate); gains[i].gain = pow(10.0, gain[i] / 20.0); } config->free(frequencies); config->free(gain); eq->block_size = size; eq->save = (float*)calloc( size, 2 * sizeof(*eq->save)); eq->block = (float*)calloc(2 * size, 2 * sizeof(*eq->block)); eq->fftblock = (fft_complex_t*)calloc(2 * size, sizeof(*eq->fftblock)); eq->filter = (fft_complex_t*)calloc(2 * size, sizeof(*eq->filter)); /* Use an FFT which is twice the block size with zero-padding * to make circular convolution => proper convolution. */ eq->fft = fft_new(size_log2 + 1); if (!eq->fft || !eq->fftblock || !eq->save || !eq->block || !eq->filter) goto error; create_filter(eq, size_log2, gains, num_gain, beta, filter_path); config->free(filter_path); filter_path = NULL; free(gains); return eq; error: free(gains); eq_free(eq); return NULL; }
static void create_filter(struct eq_data *eq, unsigned size_log2, struct eq_gain *gains, unsigned num_gains, double beta, const char *filter_path) { int i; int half_block_size = eq->block_size >> 1; double window_mod = 1.0 / kaiser_window_function(0.0, beta); fft_t *fft = fft_new(size_log2); float *time_filter = (float*)calloc(eq->block_size * 2 + 1, sizeof(*time_filter)); if (!fft || !time_filter) goto end; /* Make sure bands are in correct order. */ qsort(gains, num_gains, sizeof(*gains), gains_cmp); /* Compute desired filter response. */ generate_response(eq->filter, gains, num_gains, half_block_size); /* Get equivalent time-domain filter. */ fft_process_inverse(fft, time_filter, eq->filter, 1); // ifftshift() to create the correct linear phase filter. // The filter response was designed with zero phase, which won't work unless we compensate // for the repeating property of the FFT here by flipping left and right blocks. for (i = 0; i < half_block_size; i++) { float tmp = time_filter[i + half_block_size]; time_filter[i + half_block_size] = time_filter[i]; time_filter[i] = tmp; } /* Apply a window to smooth out the frequency repsonse. */ for (i = 0; i < (int)eq->block_size; i++) { /* Kaiser window. */ double phase = (double)i / eq->block_size; phase = 2.0 * (phase - 0.5); time_filter[i] *= window_mod * kaiser_window_function(phase, beta); } /* Debugging. */ if (filter_path) { FILE *file = fopen(filter_path, "w"); if (file) { for (i = 0; i < (int)eq->block_size - 1; i++) fprintf(file, "%.8f\n", time_filter[i + 1]); fclose(file); } } /* Padded FFT to create our FFT filter. * Make our even-length filter odd by discarding the first coefficient. * For some interesting reason, this allows us to design an odd-length linear phase filter. */ fft_process_forward(eq->fft, eq->filter, time_filter + 1, 1); end: fft_free(fft); free(time_filter); }
struct FDMDV * CODEC2_WIN32SUPPORT fdmdv_create(void) { struct FDMDV *f; int c, i; float carrier_freq; assert(FDMDV_BITS_PER_FRAME == NC*NB); assert(FDMDV_NOM_SAMPLES_PER_FRAME == M); assert(FDMDV_MAX_SAMPLES_PER_FRAME == (M+M/P)); f = (struct FDMDV*)malloc(sizeof(struct FDMDV)); if (f == NULL) return NULL; f->current_test_bit = 0; for(i=0; i<NTEST_BITS; i++) f->rx_test_bits_mem[i] = 0; f->tx_pilot_bit = 0; for(c=0; c<NC+1; c++) { f->prev_tx_symbols[c].real = 1.0; f->prev_tx_symbols[c].imag = 0.0; f->prev_rx_symbols[c].real = 1.0; f->prev_rx_symbols[c].imag = 0.0; init_comp_array(f->tx_filter_memory[c], NSYM); init_comp_array(f->rx_filter_memory[c], NFILTER); /* Spread initial FDM carrier phase out as far as possible. This helped PAPR for a few dB. We don't need to adjust rx phase as DQPSK takes care of that. */ f->phase_tx[c].real = cosf(2.0*PI*c/(NC+1)); f->phase_tx[c].imag = sinf(2.0*PI*c/(NC+1)); f->phase_rx[c].real = 1.0; f->phase_rx[c].imag = 0.0; init_comp_array(f->rx_filter_mem_timing[c], NT*P); init_comp_array(f->rx_baseband_mem_timing[c], NFILTERTIMING); } /* Set up frequency of each carrier */ for(c=0; c<NC/2; c++) { carrier_freq = (-NC/2 + c)*FSEP + FCENTRE; f->freq[c].real = cosf(2.0*PI*carrier_freq/FS); f->freq[c].imag = sinf(2.0*PI*carrier_freq/FS); } for(c=NC/2; c<NC; c++) { carrier_freq = (-NC/2 + c + 1)*FSEP + FCENTRE; f->freq[c].real = cosf(2.0*PI*carrier_freq/FS); f->freq[c].imag = sinf(2.0*PI*carrier_freq/FS); } f->freq[NC].real = cosf(2.0*PI*FCENTRE/FS); f->freq[NC].imag = sinf(2.0*PI*FCENTRE/FS); /* Generate DBPSK pilot Look Up Table (LUT) */ generate_pilot_lut(f->pilot_lut, &f->freq[NC]); /* freq Offset estimation states */ f->fft_pilot_cfg = fft_new (MPILOTFFT, 0); assert(f->fft_pilot_cfg != NULL); init_comp_array(f->pilot_baseband1, NPILOTBASEBAND); init_comp_array(f->pilot_baseband2, NPILOTBASEBAND); f->pilot_lut_index = 0; f->prev_pilot_lut_index = 3*M; init_comp_array(f->pilot_lpf1, NPILOTLPF); init_comp_array(f->pilot_lpf2, NPILOTLPF); f->foff = 0.0; f->foff_rect.real = 1.0; f->foff_rect.imag = 0.0; f->foff_phase_rect.real = 1.0; f->foff_phase_rect.imag = 0.0; f->fest_state = 0; f->coarse_fine = COARSE; for(c=0; c<NC+1; c++) { f->sig_est[c] = 0.0; f->noise_est[c] = 0.0; } for(i=0; i<2*FDMDV_NSPEC; i++) f->fft_buf[i] = 0.0; f->fft_cfg = fft_new (2*FDMDV_NSPEC, 0); assert(f->fft_cfg != NULL); return f; }
int main(void) { PaStreamParameters inputParameters, outputParameters; PaStream *stream; PaError err; err = Pa_Initialize(); if( err != paNoError ) goto error; inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ if (inputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default input device.\n"); goto error; } inputParameters.channelCount = 2; /* stereo input */ inputParameters.sampleFormat = PA_SAMPLE_TYPE; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = PA_SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; /* Instantiate FFT */ fft_new(&fft, FRAMES_PER_BUFFER); spectrum = malloc(FRAMES_PER_BUFFER * sizeof(double)); /* Instantiate Spectral Features */ spectralFeatures_new(&features, FRAMES_PER_BUFFER); err = Pa_OpenStream( &stream, &inputParameters, &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, 0, /* paClipOff, */ /* we won't output out of range samples so don't bother clipping them */ onsetCallback, NULL ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Hit ENTER to stop program.\n"); getchar(); err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; printf("Finished. gNumNoInputs = %d\n", gNumNoInputs ); Pa_Terminate(); return 0; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return -1; }