mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
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:
parent
7bb149dcc1
commit
f692d5e459
3 changed files with 62 additions and 51 deletions
|
@ -673,14 +673,18 @@ chain_resample (GstAudioConverter * convert, AudioChain * prev)
|
||||||
GstAudioResamplerFlags flags;
|
GstAudioResamplerFlags flags;
|
||||||
GstAudioFormat format = convert->current_format;
|
GstAudioFormat format = convert->current_format;
|
||||||
gint channels = convert->current_channels;
|
gint channels = convert->current_channels;
|
||||||
|
gboolean variable_rate;
|
||||||
|
|
||||||
if (in->rate != out->rate
|
variable_rate = convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE;
|
||||||
|| convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE) {
|
|
||||||
|
if (in->rate != out->rate || variable_rate) {
|
||||||
method = GET_OPT_RESAMPLER_METHOD (convert);
|
method = GET_OPT_RESAMPLER_METHOD (convert);
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
|
if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
|
||||||
flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED;
|
flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED;
|
||||||
|
if (variable_rate)
|
||||||
|
flags |= GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE;
|
||||||
|
|
||||||
convert->resampler =
|
convert->resampler =
|
||||||
gst_audio_resampler_new (method, flags, format, channels, in->rate,
|
gst_audio_resampler_new (method, flags, format, channels, in->rate,
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct _GstAudioResampler
|
||||||
GstAudioResamplerFlags flags;
|
GstAudioResamplerFlags flags;
|
||||||
GstAudioFormat format;
|
GstAudioFormat format;
|
||||||
GstStructure *options;
|
GstStructure *options;
|
||||||
|
gint format_index;
|
||||||
gint channels;
|
gint channels;
|
||||||
gint in_rate;
|
gint in_rate;
|
||||||
gint out_rate;
|
gint out_rate;
|
||||||
|
@ -354,9 +355,6 @@ make_taps (GstAudioResampler * resampler,
|
||||||
get_kaiser_tap (x + i, resampler->n_taps,
|
get_kaiser_tap (x + i, resampler->n_taps,
|
||||||
resampler->cutoff, resampler->kaiser_beta);
|
resampler->cutoff, resampler->kaiser_beta);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
|
@ -1146,40 +1144,9 @@ alloc_cache_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
|
||||||
static void
|
static void
|
||||||
setup_functions (GstAudioResampler * resampler)
|
setup_functions (GstAudioResampler * resampler)
|
||||||
{
|
{
|
||||||
gboolean non_interleaved;
|
|
||||||
gint index, fidx;
|
gint index, fidx;
|
||||||
|
|
||||||
non_interleaved =
|
index = resampler->format_index;
|
||||||
(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];
|
|
||||||
|
|
||||||
switch (resampler->filter_interpolation) {
|
switch (resampler->filter_interpolation) {
|
||||||
default:
|
default:
|
||||||
|
@ -1266,10 +1233,6 @@ resampler_calculate_taps (GstAudioResampler * resampler)
|
||||||
GET_OPT_FILTER_MODE_THRESHOLD (resampler->options);
|
GET_OPT_FILTER_MODE_THRESHOLD (resampler->options);
|
||||||
filter_interpolation = GET_OPT_FILTER_INTERPOLATION (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 {
|
} else {
|
||||||
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
|
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
|
||||||
filter_interpolation = GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE;
|
filter_interpolation = GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE;
|
||||||
|
@ -1299,7 +1262,6 @@ resampler_calculate_taps (GstAudioResampler * resampler)
|
||||||
oversample = 1;
|
oversample = 1;
|
||||||
}
|
}
|
||||||
resampler->oversample = oversample;
|
resampler->oversample = oversample;
|
||||||
resampler->filter_interpolation = filter_interpolation;
|
|
||||||
|
|
||||||
n_taps = resampler->n_taps;
|
n_taps = resampler->n_taps;
|
||||||
bps = resampler->bps;
|
bps = resampler->bps;
|
||||||
|
@ -1308,7 +1270,8 @@ resampler_calculate_taps (GstAudioResampler * resampler)
|
||||||
oversample);
|
oversample);
|
||||||
|
|
||||||
if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO) {
|
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
|
/* don't interpolate if we need to calculate at least the same amount
|
||||||
* of filter coefficients than the full table case */
|
* of filter coefficients than the full table case */
|
||||||
resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
|
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;
|
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 &&
|
if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
|
||||||
resampler->method != GST_AUDIO_RESAMPLER_METHOD_NEAREST) {
|
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);
|
alloc_cache_mem (resampler, bps, n_taps, out_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_functions (resampler);
|
|
||||||
|
|
||||||
if (resampler->filter_interpolation !=
|
if (resampler->filter_interpolation !=
|
||||||
GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
|
GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
|
||||||
gint i, isize;
|
gint i, isize;
|
||||||
|
@ -1358,6 +1325,7 @@ resampler_calculate_taps (GstAudioResampler * resampler)
|
||||||
resampler->convert_taps (tmp_taps, taps, weight, n_taps);
|
resampler->convert_taps (tmp_taps, taps, weight, n_taps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setup_functions (resampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PRINT_TAPS(type,print) \
|
#define PRINT_TAPS(type,print) \
|
||||||
|
@ -1499,13 +1467,19 @@ gst_audio_resampler_new (GstAudioResamplerMethod method,
|
||||||
GstAudioFormat format, gint channels,
|
GstAudioFormat format, gint channels,
|
||||||
gint in_rate, gint out_rate, GstStructure * options)
|
gint in_rate, gint out_rate, GstStructure * options)
|
||||||
{
|
{
|
||||||
|
gboolean non_interleaved;
|
||||||
GstAudioResampler *resampler;
|
GstAudioResampler *resampler;
|
||||||
const GstAudioFormatInfo *info;
|
const GstAudioFormatInfo *info;
|
||||||
GstStructure *def_options = NULL;
|
GstStructure *def_options = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (channels > 0, FALSE);
|
g_return_val_if_fail (method >= GST_AUDIO_RESAMPLER_METHOD_NEAREST
|
||||||
g_return_val_if_fail (in_rate > 0, FALSE);
|
&& method <= GST_AUDIO_RESAMPLER_METHOD_KAISER, NULL);
|
||||||
g_return_val_if_fail (out_rate > 0, FALSE);
|
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 ();
|
audio_resampler_init ();
|
||||||
|
|
||||||
|
@ -1515,10 +1489,38 @@ gst_audio_resampler_new (GstAudioResamplerMethod method,
|
||||||
resampler->format = format;
|
resampler->format = format;
|
||||||
resampler->channels = channels;
|
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);
|
info = gst_audio_format_get_info (format);
|
||||||
resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
|
resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
|
||||||
resampler->sbuf = g_malloc0 (sizeof (gpointer) * channels);
|
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,
|
GST_DEBUG ("method %d, bps %d, channels %d", method, resampler->bps,
|
||||||
resampler->channels);
|
resampler->channels);
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,8 @@ typedef struct _GstAudioResampler GstAudioResampler;
|
||||||
/**
|
/**
|
||||||
* GstAudioResamplerFilterMode:
|
* GstAudioResamplerFilterMode:
|
||||||
* @GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED: Use interpolated filter tables. This
|
* @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
|
* @GST_AUDIO_RESAMPLER_FILTER_MODE_FULL: Use full filter table. This uses more memory
|
||||||
* but less CPU.
|
* but less CPU.
|
||||||
* @GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO: Automatically choose between interpolated
|
* @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
|
* GST_TYPE_AUDIO_RESAMPLER_INTERPOLATION: how the filter coeficients should be
|
||||||
* interpolated.
|
* 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"
|
#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
|
* G_TYPE_DOUBLE: The maximum allowed phase error when switching sample
|
||||||
* rates.
|
* rates.
|
||||||
* 0.05 is the default.
|
* 0.1 is the default.
|
||||||
*/
|
*/
|
||||||
#define GST_AUDIO_RESAMPLER_OPT_MAX_PHASE_ERROR "GstAudioResampler.max-phase-error"
|
#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
|
* @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
|
* of blocks of samples, one for each channel, should be passed to the resample
|
||||||
* function.
|
* 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.
|
* Different resampler flags.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_AUDIO_RESAMPLER_FLAG_NONE = (0),
|
GST_AUDIO_RESAMPLER_FLAG_NONE = (0),
|
||||||
GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED = (1 << 0),
|
GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED = (1 << 0),
|
||||||
|
GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE = (1 << 1),
|
||||||
} GstAudioResamplerFlags;
|
} GstAudioResamplerFlags;
|
||||||
|
|
||||||
#define GST_AUDIO_RESAMPLER_QUALITY_MIN 0
|
#define GST_AUDIO_RESAMPLER_QUALITY_MIN 0
|
||||||
|
|
Loading…
Reference in a new issue