audio-resampler: add VARIABLE_RATE flag

Add a VARIABLE rate flag that selects an interpolating filter.
Move some function setup code in the _new function.
This commit is contained in:
Wim Taymans 2016-02-25 14:09:44 +01:00
parent 7bb149dcc1
commit f692d5e459
3 changed files with 62 additions and 51 deletions

View file

@ -673,14 +673,18 @@ chain_resample (GstAudioConverter * convert, AudioChain * prev)
GstAudioResamplerFlags flags;
GstAudioFormat format = convert->current_format;
gint channels = convert->current_channels;
gboolean variable_rate;
if (in->rate != out->rate
|| convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE) {
variable_rate = convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE;
if (in->rate != out->rate || variable_rate) {
method = GET_OPT_RESAMPLER_METHOD (convert);
flags = 0;
if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED;
if (variable_rate)
flags |= GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE;
convert->resampler =
gst_audio_resampler_new (method, flags, format, channels, in->rate,

View file

@ -69,6 +69,7 @@ struct _GstAudioResampler
GstAudioResamplerFlags flags;
GstAudioFormat format;
GstStructure *options;
gint format_index;
gint channels;
gint in_rate;
gint out_rate;
@ -354,9 +355,6 @@ make_taps (GstAudioResampler * resampler,
get_kaiser_tap (x + i, resampler->n_taps,
resampler->cutoff, resampler->kaiser_beta);
break;
default:
break;
}
return weight;
}
@ -1146,40 +1144,9 @@ alloc_cache_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
static void
setup_functions (GstAudioResampler * resampler)
{
gboolean non_interleaved;
gint index, fidx;
non_interleaved =
(resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED);
/* we resample each channel separately */
resampler->blocks = resampler->channels;
resampler->inc = 1;
resampler->ostride = non_interleaved ? 1 : resampler->channels;
switch (resampler->format) {
case GST_AUDIO_FORMAT_S16:
GST_DEBUG ("using S16 functions");
index = 0;
break;
case GST_AUDIO_FORMAT_S32:
GST_DEBUG ("using S32 functions");
index = 1;
break;
case GST_AUDIO_FORMAT_F32:
GST_DEBUG ("using F32 functions");
index = 2;
break;
case GST_AUDIO_FORMAT_F64:
GST_DEBUG ("using F64 functions");
index = 3;
break;
default:
g_assert_not_reached ();
break;
}
resampler->deinterleave = deinterleave_funcs[index];
resampler->convert_taps = convert_taps_funcs[index];
index = resampler->format_index;
switch (resampler->filter_interpolation) {
default:
@ -1266,10 +1233,6 @@ resampler_calculate_taps (GstAudioResampler * resampler)
GET_OPT_FILTER_MODE_THRESHOLD (resampler->options);
filter_interpolation = GET_OPT_FILTER_INTERPOLATION (resampler->options);
/* interpolated table but no interpolation given, assume default */
if (resampler->filter_mode != GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
filter_interpolation == GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE)
filter_interpolation = DEFAULT_OPT_FILTER_INTERPOLATION;
} else {
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
filter_interpolation = GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE;
@ -1299,7 +1262,6 @@ resampler_calculate_taps (GstAudioResampler * resampler)
oversample = 1;
}
resampler->oversample = oversample;
resampler->filter_interpolation = filter_interpolation;
n_taps = resampler->n_taps;
bps = resampler->bps;
@ -1308,7 +1270,8 @@ resampler_calculate_taps (GstAudioResampler * resampler)
oversample);
if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO) {
if (out_rate <= oversample) {
if (out_rate <= oversample
&& !(resampler->flags & GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE)) {
/* don't interpolate if we need to calculate at least the same amount
* of filter coefficients than the full table case */
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
@ -1319,6 +1282,12 @@ resampler_calculate_taps (GstAudioResampler * resampler)
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED;
}
}
/* interpolated table but no interpolation given, assume default */
if (resampler->filter_mode != GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
filter_interpolation == GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE)
filter_interpolation = DEFAULT_OPT_FILTER_INTERPOLATION;
resampler->filter_interpolation = filter_interpolation;
if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
resampler->method != GST_AUDIO_RESAMPLER_METHOD_NEAREST) {
@ -1327,8 +1296,6 @@ resampler_calculate_taps (GstAudioResampler * resampler)
alloc_cache_mem (resampler, bps, n_taps, out_rate);
}
setup_functions (resampler);
if (resampler->filter_interpolation !=
GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
gint i, isize;
@ -1358,6 +1325,7 @@ resampler_calculate_taps (GstAudioResampler * resampler)
resampler->convert_taps (tmp_taps, taps, weight, n_taps);
}
}
setup_functions (resampler);
}
#define PRINT_TAPS(type,print) \
@ -1499,13 +1467,19 @@ gst_audio_resampler_new (GstAudioResamplerMethod method,
GstAudioFormat format, gint channels,
gint in_rate, gint out_rate, GstStructure * options)
{
gboolean non_interleaved;
GstAudioResampler *resampler;
const GstAudioFormatInfo *info;
GstStructure *def_options = NULL;
g_return_val_if_fail (channels > 0, FALSE);
g_return_val_if_fail (in_rate > 0, FALSE);
g_return_val_if_fail (out_rate > 0, FALSE);
g_return_val_if_fail (method >= GST_AUDIO_RESAMPLER_METHOD_NEAREST
&& method <= GST_AUDIO_RESAMPLER_METHOD_KAISER, NULL);
g_return_val_if_fail (format == GST_AUDIO_FORMAT_S16 ||
format == GST_AUDIO_FORMAT_S32 || format == GST_AUDIO_FORMAT_F32 ||
format == GST_AUDIO_FORMAT_F64, NULL);
g_return_val_if_fail (channels > 0, NULL);
g_return_val_if_fail (in_rate > 0, NULL);
g_return_val_if_fail (out_rate > 0, NULL);
audio_resampler_init ();
@ -1515,10 +1489,38 @@ gst_audio_resampler_new (GstAudioResamplerMethod method,
resampler->format = format;
resampler->channels = channels;
switch (format) {
case GST_AUDIO_FORMAT_S16:
resampler->format_index = 0;
break;
case GST_AUDIO_FORMAT_S32:
resampler->format_index = 1;
break;
case GST_AUDIO_FORMAT_F32:
resampler->format_index = 2;
break;
case GST_AUDIO_FORMAT_F64:
resampler->format_index = 3;
break;
default:
g_assert_not_reached ();
break;
}
info = gst_audio_format_get_info (format);
resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
resampler->sbuf = g_malloc0 (sizeof (gpointer) * channels);
non_interleaved =
(resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED);
/* we resample each channel separately */
resampler->blocks = resampler->channels;
resampler->inc = 1;
resampler->ostride = non_interleaved ? 1 : resampler->channels;
resampler->deinterleave = deinterleave_funcs[resampler->format_index];
resampler->convert_taps = convert_taps_funcs[resampler->format_index];
GST_DEBUG ("method %d, bps %d, channels %d", method, resampler->bps,
resampler->channels);

View file

@ -82,7 +82,8 @@ typedef struct _GstAudioResampler GstAudioResampler;
/**
* GstAudioResamplerFilterMode:
* @GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED: Use interpolated filter tables. This
* uses less memory but more CPU and is slightly less accurate.
* uses less memory but more CPU and is slightly less accurate but it allows for more
* efficient variable rate resampling with gst_audio_resampler_update().
* @GST_AUDIO_RESAMPLER_FILTER_MODE_FULL: Use full filter table. This uses more memory
* but less CPU.
* @GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO: Automatically choose between interpolated
@ -132,7 +133,7 @@ typedef enum {
*
* GST_TYPE_AUDIO_RESAMPLER_INTERPOLATION: how the filter coeficients should be
* interpolated.
* GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR is default.
* GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC is default.
*/
#define GST_AUDIO_RESAMPLER_OPT_FILTER_INTERPOLATION "GstAudioResampler.filter-interpolation"
/**
@ -148,7 +149,7 @@ typedef enum {
*
* G_TYPE_DOUBLE: The maximum allowed phase error when switching sample
* rates.
* 0.05 is the default.
* 0.1 is the default.
*/
#define GST_AUDIO_RESAMPLER_OPT_MAX_PHASE_ERROR "GstAudioResampler.max-phase-error"
@ -180,12 +181,16 @@ typedef enum {
* @GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED: samples are non-interleaved. an array
* of blocks of samples, one for each channel, should be passed to the resample
* function.
* @GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE: optimize for dynamic updates of the sample
* rates with gst_audio_resampler_update(). This will select an interpolating filter
* when #GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO is configured.
*
* Different resampler flags.
*/
typedef enum {
GST_AUDIO_RESAMPLER_FLAG_NONE = (0),
GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED = (1 << 0),
GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE = (1 << 1),
} GstAudioResamplerFlags;
#define GST_AUDIO_RESAMPLER_QUALITY_MIN 0