static void eq_deinstantiate(struct dsp_module *module) { struct eq_data *data = (struct eq_data *) module->data; if (data->eq) eq_free(data->eq); free(data); }
/* Generates impulse response */ static void test_ir() { int N = 32768; float *data; struct eq *eq; double NQ = 44100 / 2; /* nyquist frequency */ struct timespec tp1, tp2; int i; FILE *ir; data = calloc(1, sizeof(float) * N); data[0] = 1; eq = eq_new(); eq_append_biquad(eq, BQ_PEAKING, 380/NQ, 3, -10); eq_append_biquad(eq, BQ_PEAKING, 720/NQ, 3, -12); eq_append_biquad(eq, BQ_PEAKING, 1705/NQ, 3, -8); eq_append_biquad(eq, BQ_HIGHPASS, 218/NQ, 0.7, -10.2); eq_append_biquad(eq, BQ_PEAKING, 580/NQ, 6, -8); eq_append_biquad(eq, BQ_HIGHSHELF, 8000/NQ, 3, 2); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp1); eq_process(eq, data, N); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp2); printf("processing takes %g seconds\n", tp_diff(&tp2, &tp1)); eq_free(eq); ir = fopen("ir.dat", "w"); for (i = 0; i < N; i++) fprintf(ir, "%g\n", data[i]); fclose(ir); free(data); }
/* Runs the filters on an input file */ static void test_file(const char *input_filename, const char *output_filename) { size_t frames; int i; double NQ = 44100 / 2; /* nyquist frequency */ struct timespec tp1, tp2; struct eq *eq; float *data = read_raw(input_filename, &frames); /* Set some data to 0 to test for denormals. */ for (i = frames / 10; i < frames; i++) data[i] = 0.0; /* Left eq chain */ eq = eq_new(); eq_append_biquad(eq, BQ_PEAKING, 380/NQ, 3, -10); eq_append_biquad(eq, BQ_PEAKING, 720/NQ, 3, -12); eq_append_biquad(eq, BQ_PEAKING, 1705/NQ, 3, -8); eq_append_biquad(eq, BQ_HIGHPASS, 218/NQ, 0.7, -10.2); eq_append_biquad(eq, BQ_PEAKING, 580/NQ, 6, -8); eq_append_biquad(eq, BQ_HIGHSHELF, 8000/NQ, 3, 2); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp1); process(eq, data, frames); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp2); printf("processing takes %g seconds for %zu samples\n", tp_diff(&tp2, &tp1), frames); eq_free(eq); /* Right eq chain */ eq = eq_new(); eq_append_biquad(eq, BQ_PEAKING, 450/NQ, 3, -12); eq_append_biquad(eq, BQ_PEAKING, 721/NQ, 3, -12); eq_append_biquad(eq, BQ_PEAKING, 1800/NQ, 8, -10.2); eq_append_biquad(eq, BQ_PEAKING, 580/NQ, 6, -8); eq_append_biquad(eq, BQ_HIGHPASS, 250/NQ, 0.6578, 0); eq_append_biquad(eq, BQ_HIGHSHELF, 8000/NQ, 0, 2); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp1); process(eq, data + frames, frames); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp2); printf("processing takes %g seconds for %zu samples\n", tp_diff(&tp2, &tp1), frames); eq_free(eq); write_raw(output_filename, data, frames); free(data); }
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; }