mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
module-equalizer-sink: fixed a bug w/ new zero-latency input scheme (that was an interesting/cool bug!)
This commit is contained in:
parent
735c8ab6fb
commit
2f6fd32cc5
1 changed files with 27 additions and 23 deletions
|
|
@ -104,8 +104,6 @@ struct userdata {
|
||||||
size_t overlap_size;//window_size-R
|
size_t overlap_size;//window_size-R
|
||||||
size_t samples_gathered;
|
size_t samples_gathered;
|
||||||
//message
|
//message
|
||||||
float X;
|
|
||||||
float *H;//frequency response filter (magnitude based)
|
|
||||||
float *W;//windowing function (time domain)
|
float *W;//windowing function (time domain)
|
||||||
float *work_buffer, **input, **overlap_accum;
|
float *work_buffer, **input, **overlap_accum;
|
||||||
fftwf_complex *output_window;
|
fftwf_complex *output_window;
|
||||||
|
|
@ -113,7 +111,7 @@ struct userdata {
|
||||||
//size_t samplings;
|
//size_t samplings;
|
||||||
|
|
||||||
float Xs[2];
|
float Xs[2];
|
||||||
float *Hs[2];//thread updatable copies
|
float *Hs[2];//thread updatable copies of the freq response filters (magintude based)
|
||||||
pa_aupdate *a_H;
|
pa_aupdate *a_H;
|
||||||
pa_memchunk conv_buffer;
|
pa_memchunk conv_buffer;
|
||||||
pa_memblockq *input_q;
|
pa_memblockq *input_q;
|
||||||
|
|
@ -284,7 +282,8 @@ static void dsp_logic(
|
||||||
float * restrict src,/*input data w/ overlap at start,
|
float * restrict src,/*input data w/ overlap at start,
|
||||||
*automatically cycled in routine
|
*automatically cycled in routine
|
||||||
*/
|
*/
|
||||||
float * restrict overlap,//The size of the overlap
|
float * restrict overlap,
|
||||||
|
const float X,//multipliar
|
||||||
const float * restrict H,//The freq. magnitude scalers filter
|
const float * restrict H,//The freq. magnitude scalers filter
|
||||||
const float * restrict W,//The windowing function
|
const float * restrict W,//The windowing function
|
||||||
fftwf_complex * restrict output_window,//The transformed window'd src
|
fftwf_complex * restrict output_window,//The transformed window'd src
|
||||||
|
|
@ -294,15 +293,15 @@ static void dsp_logic(
|
||||||
memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
|
memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
|
||||||
//window the data
|
//window the data
|
||||||
for(size_t j = 0; j < u->window_size; ++j){
|
for(size_t j = 0; j < u->window_size; ++j){
|
||||||
dst[j] = u->X * W[j] * src[j];
|
dst[j] = X * W[j] * src[j];
|
||||||
}
|
}
|
||||||
//Processing is done here!
|
//Processing is done here!
|
||||||
//do fft
|
//do fft
|
||||||
fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
|
fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
|
||||||
//perform filtering
|
//perform filtering
|
||||||
for(size_t j = 0; j < FILTER_SIZE; ++j){
|
for(size_t j = 0; j < FILTER_SIZE; ++j){
|
||||||
u->output_window[j][0] *= u->H[j];
|
u->output_window[j][0] *= H[j];
|
||||||
u->output_window[j][1] *= u->H[j];
|
u->output_window[j][1] *= H[j];
|
||||||
}
|
}
|
||||||
//inverse fft
|
//inverse fft
|
||||||
fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
|
fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
|
||||||
|
|
@ -326,7 +325,7 @@ static void dsp_logic(
|
||||||
|
|
||||||
//preseve the needed input for the next window's overlap
|
//preseve the needed input for the next window's overlap
|
||||||
memmove(src, src + u->R,
|
memmove(src, src + u->R,
|
||||||
((u->overlap_size + u->samples_gathered) - u->R)*sizeof(float)
|
u->overlap_size * sizeof(float)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,11 +346,12 @@ typedef union float_vector {
|
||||||
// *automatically cycled in routine
|
// *automatically cycled in routine
|
||||||
// */
|
// */
|
||||||
// float * restrict overlap,//The size of the overlap
|
// float * restrict overlap,//The size of the overlap
|
||||||
|
// const float X,//multipliar
|
||||||
// const float * restrict H,//The freq. magnitude scalers filter
|
// const float * restrict H,//The freq. magnitude scalers filter
|
||||||
// const float * restrict W,//The windowing function
|
// const float * restrict W,//The windowing function
|
||||||
// fftwf_complex * restrict output_window,//The transformed window'd src
|
// fftwf_complex * restrict output_window,//The transformed window'd src
|
||||||
// struct userdata *u){//Collection of constants
|
// struct userdata *u){//Collection of constants
|
||||||
//float_vector_t x = {u->X, u->X, u->X, u->X};
|
//float_vector_t x = {X, X, X, X};
|
||||||
// const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
|
// const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
|
||||||
// const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
|
// const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
|
||||||
// //const size_t R = PA_ROUND_UP(u->R, v_size);
|
// //const size_t R = PA_ROUND_UP(u->R, v_size);
|
||||||
|
|
@ -431,24 +431,32 @@ typedef union float_vector {
|
||||||
//
|
//
|
||||||
// //preseve the needed input for the next window's overlap
|
// //preseve the needed input for the next window's overlap
|
||||||
// memmove(src, src + u->R,
|
// memmove(src, src + u->R,
|
||||||
// ((u->overlap_size+u->samples_gathered)+-u->R)*sizeof(float)
|
// u->overlap_size * sizeof(float)
|
||||||
// );
|
// );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
static void process_samples(struct userdata *u, pa_memchunk *tchunk){
|
static void process_samples(struct userdata *u, pa_memchunk *tchunk){
|
||||||
size_t fs=pa_frame_size(&(u->sink->sample_spec));
|
size_t fs=pa_frame_size(&(u->sink->sample_spec));
|
||||||
float *dst;
|
float *dst;
|
||||||
|
unsigned a_i;
|
||||||
|
float *H, X;
|
||||||
pa_assert(u->samples_gathered >= u->R);
|
pa_assert(u->samples_gathered >= u->R);
|
||||||
tchunk->index = 0;
|
tchunk->index = 0;
|
||||||
tchunk->length = u->R * fs;
|
tchunk->length = u->R * fs;
|
||||||
tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length);
|
tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length);
|
||||||
dst = ((float*)pa_memblock_acquire(tchunk->memblock));
|
dst = ((float*)pa_memblock_acquire(tchunk->memblock));
|
||||||
|
/* set the H filter */
|
||||||
|
a_i = pa_aupdate_read_begin(u->a_H);
|
||||||
|
X = u->Xs[a_i];
|
||||||
|
H = u->Hs[a_i];
|
||||||
|
|
||||||
for(size_t c=0;c < u->channels; c++) {
|
for(size_t c=0;c < u->channels; c++) {
|
||||||
dsp_logic(
|
dsp_logic(
|
||||||
u->work_buffer,
|
u->work_buffer,
|
||||||
u->input[c],
|
u->input[c],
|
||||||
u->overlap_accum[c],
|
u->overlap_accum[c],
|
||||||
u->H,
|
X,
|
||||||
|
H,
|
||||||
u->W,
|
u->W,
|
||||||
u->output_window,
|
u->output_window,
|
||||||
u
|
u
|
||||||
|
|
@ -465,6 +473,8 @@ static void process_samples(struct userdata *u, pa_memchunk *tchunk){
|
||||||
}
|
}
|
||||||
pa_memblock_release(tchunk->memblock);
|
pa_memblock_release(tchunk->memblock);
|
||||||
u->samples_gathered -= u->R;
|
u->samples_gathered -= u->R;
|
||||||
|
|
||||||
|
pa_aupdate_read_end(u->a_H);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_buffer(struct userdata *u, pa_memchunk *in){
|
static void initialize_buffer(struct userdata *u, pa_memchunk *in){
|
||||||
|
|
@ -492,7 +502,7 @@ static void input_buffer(struct userdata *u, pa_memchunk *in){
|
||||||
pa_assert_se(
|
pa_assert_se(
|
||||||
u->input[c]+u->samples_gathered+samples <= u->input[c]+u->window_size
|
u->input[c]+u->samples_gathered+samples <= u->input[c]+u->window_size
|
||||||
);
|
);
|
||||||
pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c]+u->overlap_size+u->samples_gathered, sizeof(float), src + c, fs, samples);
|
pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c]+u->samples_gathered, sizeof(float), src + c, fs, samples);
|
||||||
}
|
}
|
||||||
u->samples_gathered += samples;
|
u->samples_gathered += samples;
|
||||||
pa_memblock_release(in->memblock);
|
pa_memblock_release(in->memblock);
|
||||||
|
|
@ -503,7 +513,6 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
|
||||||
struct userdata *u;
|
struct userdata *u;
|
||||||
size_t fs;
|
size_t fs;
|
||||||
struct timeval start, end;
|
struct timeval start, end;
|
||||||
unsigned a_i;
|
|
||||||
pa_memchunk tchunk;
|
pa_memchunk tchunk;
|
||||||
pa_sink_input_assert_ref(i);
|
pa_sink_input_assert_ref(i);
|
||||||
pa_assert_se(u = i->userdata);
|
pa_assert_se(u = i->userdata);
|
||||||
|
|
@ -554,15 +563,11 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
|
||||||
pa_assert(u->fft_size >= u->window_size);
|
pa_assert(u->fft_size >= u->window_size);
|
||||||
pa_assert(u->R < u->window_size);
|
pa_assert(u->R < u->window_size);
|
||||||
/* set the H filter */
|
/* set the H filter */
|
||||||
a_i = pa_aupdate_read_begin(u->a_H);
|
|
||||||
u->X = u->Xs[a_i];
|
|
||||||
u->H = u->Hs[a_i];
|
|
||||||
pa_rtclock_get(&start);
|
pa_rtclock_get(&start);
|
||||||
/* process a block */
|
/* process a block */
|
||||||
process_samples(u, chunk);
|
process_samples(u, chunk);
|
||||||
pa_rtclock_get(&end);
|
pa_rtclock_get(&end);
|
||||||
pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
|
pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
|
||||||
pa_aupdate_read_end(u->a_H);
|
|
||||||
|
|
||||||
pa_assert(chunk->memblock);
|
pa_assert(chunk->memblock);
|
||||||
//pa_log_debug("gave %ld", chunk->length/fs);
|
//pa_log_debug("gave %ld", chunk->length/fs);
|
||||||
|
|
@ -1162,7 +1167,6 @@ enum equalizer_handler_index {
|
||||||
EQUALIZER_HANDLER_FILTERSAMPLERATE,
|
EQUALIZER_HANDLER_FILTERSAMPLERATE,
|
||||||
EQUALIZER_HANDLER_N_COEFS,
|
EQUALIZER_HANDLER_N_COEFS,
|
||||||
EQUALIZER_HANDLER_FILTER,
|
EQUALIZER_HANDLER_FILTER,
|
||||||
EQUALIZER_HANDLER_PREAMP,
|
|
||||||
EQUALIZER_HANDLER_MAX
|
EQUALIZER_HANDLER_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue