mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-21 15:56:42 +00:00
audiofxbasefirfilter: Add special processing functions for Mono/Stereo
This provides another 7% speedup for the time domain convolution and 1.5% speedup for the FFT convolution on Mono input. This optimization assumes that the compiler simplifies calculations and conditions on constant numbers and unrolls loops with a constant number of repeats.
This commit is contained in:
parent
a3d7321c50
commit
cd2b1c1b58
1 changed files with 79 additions and 16 deletions
|
@ -100,9 +100,20 @@ static const GstQueryType *gst_audio_fx_base_fir_filter_query_type (GstPad *
|
||||||
static guint \
|
static guint \
|
||||||
process_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, g##ctype * dst, guint input_samples) \
|
process_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, g##ctype * dst, guint input_samples) \
|
||||||
{ \
|
{ \
|
||||||
|
gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels; \
|
||||||
|
TIME_DOMAIN_CONVOLUTION_BODY (channels); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_PROCESS_FUNC_FIXED_CHANNELS(width,channels,ctype) \
|
||||||
|
static guint \
|
||||||
|
process_##channels##_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, g##ctype * dst, guint input_samples) \
|
||||||
|
{ \
|
||||||
|
TIME_DOMAIN_CONVOLUTION_BODY (channels); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TIME_DOMAIN_CONVOLUTION_BODY(channels) G_STMT_START { \
|
||||||
gint kernel_length = self->kernel_length; \
|
gint kernel_length = self->kernel_length; \
|
||||||
gint i, j, k, l; \
|
gint i, j, k, l; \
|
||||||
gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels; \
|
|
||||||
gint res_start; \
|
gint res_start; \
|
||||||
gint from_input; \
|
gint from_input; \
|
||||||
gint off; \
|
gint off; \
|
||||||
|
@ -155,12 +166,20 @@ process_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, g##ctype
|
||||||
self->buffer_fill = kernel_length; \
|
self->buffer_fill = kernel_length; \
|
||||||
\
|
\
|
||||||
return input_samples / channels; \
|
return input_samples / channels; \
|
||||||
}
|
} G_STMT_END
|
||||||
|
|
||||||
DEFINE_PROCESS_FUNC (32, float);
|
DEFINE_PROCESS_FUNC (32, float);
|
||||||
DEFINE_PROCESS_FUNC (64, double);
|
DEFINE_PROCESS_FUNC (64, double);
|
||||||
|
|
||||||
|
DEFINE_PROCESS_FUNC_FIXED_CHANNELS (32, 1, float);
|
||||||
|
DEFINE_PROCESS_FUNC_FIXED_CHANNELS (64, 1, double);
|
||||||
|
|
||||||
|
DEFINE_PROCESS_FUNC_FIXED_CHANNELS (32, 2, float);
|
||||||
|
DEFINE_PROCESS_FUNC_FIXED_CHANNELS (64, 2, double);
|
||||||
|
|
||||||
|
#undef TIME_DOMAIN_CONVOLUTION_BODY
|
||||||
#undef DEFINE_PROCESS_FUNC
|
#undef DEFINE_PROCESS_FUNC
|
||||||
|
#undef DEFINE_PROCESS_FUNC_FIXED_CHANNELS
|
||||||
|
|
||||||
/* This implements FFT convolution and uses the overlap-save algorithm.
|
/* This implements FFT convolution and uses the overlap-save algorithm.
|
||||||
* See http://cnx.org/content/m12022/latest/ or your favorite
|
* See http://cnx.org/content/m12022/latest/ or your favorite
|
||||||
|
@ -221,6 +240,18 @@ process_fft_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, \
|
||||||
g##ctype * dst, guint input_samples) \
|
g##ctype * dst, guint input_samples) \
|
||||||
{ \
|
{ \
|
||||||
gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels; \
|
gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels; \
|
||||||
|
FFT_CONVOLUTION_BODY (channels); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS(width,channels,ctype) \
|
||||||
|
static guint \
|
||||||
|
process_fft_##channels##_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, \
|
||||||
|
g##ctype * dst, guint input_samples) \
|
||||||
|
{ \
|
||||||
|
FFT_CONVOLUTION_BODY (channels); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FFT_CONVOLUTION_BODY(channels) G_STMT_START { \
|
||||||
gint i, j; \
|
gint i, j; \
|
||||||
guint pass; \
|
guint pass; \
|
||||||
guint kernel_length = self->kernel_length; \
|
guint kernel_length = self->kernel_length; \
|
||||||
|
@ -323,12 +354,20 @@ process_fft_##width (GstAudioFXBaseFIRFilter * self, const g##ctype * src, \
|
||||||
self->buffer_fill = buffer_fill; \
|
self->buffer_fill = buffer_fill; \
|
||||||
\
|
\
|
||||||
return generated; \
|
return generated; \
|
||||||
}
|
} G_STMT_END
|
||||||
|
|
||||||
DEFINE_FFT_PROCESS_FUNC (32, float);
|
DEFINE_FFT_PROCESS_FUNC (32, float);
|
||||||
DEFINE_FFT_PROCESS_FUNC (64, double);
|
DEFINE_FFT_PROCESS_FUNC (64, double);
|
||||||
|
|
||||||
|
DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS (32, 1, float);
|
||||||
|
DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS (64, 1, double);
|
||||||
|
|
||||||
|
DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS (32, 2, float);
|
||||||
|
DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS (64, 2, double);
|
||||||
|
|
||||||
|
#undef FFT_CONVOLUTION_BODY
|
||||||
#undef DEFINE_FFT_PROCESS_FUNC
|
#undef DEFINE_FFT_PROCESS_FUNC
|
||||||
|
#undef DEFINE_FFT_PROCESS_FUNC_FIXED_CHANNELS
|
||||||
|
|
||||||
/* Element class */
|
/* Element class */
|
||||||
static void
|
static void
|
||||||
|
@ -376,18 +415,39 @@ static void
|
||||||
/* Must be called with base transform lock! */
|
/* Must be called with base transform lock! */
|
||||||
static void
|
static void
|
||||||
gst_audio_fx_base_fir_filter_select_process_function (GstAudioFXBaseFIRFilter *
|
gst_audio_fx_base_fir_filter_select_process_function (GstAudioFXBaseFIRFilter *
|
||||||
self, gint width)
|
self, gint width, gint channels)
|
||||||
{
|
{
|
||||||
if (width == 32 && self->fft && !self->low_latency)
|
if (width == 32 && self->fft && !self->low_latency) {
|
||||||
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_32;
|
if (channels == 1)
|
||||||
else if (width == 64 && self->fft && !self->low_latency)
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_1_32;
|
||||||
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_64;
|
else if (channels == 2)
|
||||||
else if (width == 32)
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_2_32;
|
||||||
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_32;
|
|
||||||
else if (width == 64)
|
|
||||||
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_64;
|
|
||||||
else
|
else
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_32;
|
||||||
|
} else if (width == 64 && self->fft && !self->low_latency) {
|
||||||
|
if (channels == 1)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_1_64;
|
||||||
|
else if (channels == 2)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_2_64;
|
||||||
|
else
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_fft_64;
|
||||||
|
} else if (width == 32) {
|
||||||
|
if (channels == 1)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_1_32;
|
||||||
|
else if (channels == 2)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_2_32;
|
||||||
|
else
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_32;
|
||||||
|
} else if (width == 64) {
|
||||||
|
if (channels == 1)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_1_64;
|
||||||
|
else if (channels == 2)
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_2_64;
|
||||||
|
else
|
||||||
|
self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_64;
|
||||||
|
} else {
|
||||||
self->process = NULL;
|
self->process = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -439,7 +499,8 @@ gst_audio_fx_base_fir_filter_set_property (GObject * object, guint prop_id,
|
||||||
self->low_latency = low_latency;
|
self->low_latency = low_latency;
|
||||||
gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
|
gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
|
||||||
gst_audio_fx_base_fir_filter_select_process_function (self,
|
gst_audio_fx_base_fir_filter_select_process_function (self,
|
||||||
GST_AUDIO_FILTER_CAST (self)->format.width);
|
GST_AUDIO_FILTER_CAST (self)->format.width,
|
||||||
|
GST_AUDIO_FILTER_CAST (self)->format.channels);
|
||||||
}
|
}
|
||||||
GST_BASE_TRANSFORM_UNLOCK (self);
|
GST_BASE_TRANSFORM_UNLOCK (self);
|
||||||
break;
|
break;
|
||||||
|
@ -677,7 +738,8 @@ gst_audio_fx_base_fir_filter_setup (GstAudioFilter * base,
|
||||||
self->nsamples_in = 0;
|
self->nsamples_in = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_audio_fx_base_fir_filter_select_process_function (self, format->width);
|
gst_audio_fx_base_fir_filter_select_process_function (self, format->width,
|
||||||
|
format->channels);
|
||||||
|
|
||||||
return (self->process != NULL);
|
return (self->process != NULL);
|
||||||
}
|
}
|
||||||
|
@ -973,7 +1035,8 @@ gst_audio_fx_base_fir_filter_set_kernel (GstAudioFXBaseFIRFilter * self,
|
||||||
|
|
||||||
gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
|
gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
|
||||||
gst_audio_fx_base_fir_filter_select_process_function (self,
|
gst_audio_fx_base_fir_filter_select_process_function (self,
|
||||||
GST_AUDIO_FILTER_CAST (self)->format.width);
|
GST_AUDIO_FILTER_CAST (self)->format.width,
|
||||||
|
GST_AUDIO_FILTER_CAST (self)->format.channels);
|
||||||
|
|
||||||
if (latency_changed) {
|
if (latency_changed) {
|
||||||
self->latency = latency;
|
self->latency = latency;
|
||||||
|
|
Loading…
Reference in a new issue