mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-22 02:13:46 +00:00
scaletempo: Add support for F64
This commit is contained in:
parent
cdd7091c1c
commit
1e0b9b9853
2 changed files with 86 additions and 57 deletions
|
@ -94,6 +94,7 @@ enum
|
||||||
#define SUPPORTED_CAPS \
|
#define SUPPORTED_CAPS \
|
||||||
GST_STATIC_CAPS ( \
|
GST_STATIC_CAPS ( \
|
||||||
GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (F32)) "; " \
|
GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (F32)) "; " \
|
||||||
|
GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (F64)) "; " \
|
||||||
GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (S16)) \
|
GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (S16)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -113,40 +114,44 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstScaletempo, gst_scaletempo,
|
G_DEFINE_TYPE_WITH_CODE (GstScaletempo, gst_scaletempo,
|
||||||
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT (0));
|
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT (0));
|
||||||
|
|
||||||
static guint
|
#define CREATE_BEST_OVERLAP_OFFSET_FLOAT_FUNC(type) \
|
||||||
best_overlap_offset_float (GstScaletempo * st)
|
static guint \
|
||||||
{
|
best_overlap_offset_##type (GstScaletempo * st) \
|
||||||
gfloat *pw, *po, *ppc, *search_start;
|
{ \
|
||||||
gfloat best_corr = G_MININT;
|
g##type *pw, *po, *ppc, *search_start; \
|
||||||
guint best_off = 0;
|
g##type best_corr = G_MININT; \
|
||||||
gint i, off;
|
guint best_off = 0; \
|
||||||
|
gint i, off; \
|
||||||
pw = st->table_window;
|
\
|
||||||
po = st->buf_overlap;
|
pw = st->table_window; \
|
||||||
po += st->samples_per_frame;
|
po = st->buf_overlap; \
|
||||||
ppc = st->buf_pre_corr;
|
po += st->samples_per_frame; \
|
||||||
for (i = st->samples_per_frame; i < st->samples_overlap; i++) {
|
ppc = st->buf_pre_corr; \
|
||||||
*ppc++ = *pw++ * *po++;
|
for (i = st->samples_per_frame; i < st->samples_overlap; i++) { \
|
||||||
}
|
*ppc++ = *pw++ * *po++; \
|
||||||
|
} \
|
||||||
search_start = (gfloat *) st->buf_queue + st->samples_per_frame;
|
\
|
||||||
for (off = 0; off < st->frames_search; off++) {
|
search_start = (g##type *) st->buf_queue + st->samples_per_frame; \
|
||||||
gfloat corr = 0;
|
for (off = 0; off < st->frames_search; off++) { \
|
||||||
gfloat *ps = search_start;
|
g##type corr = 0; \
|
||||||
ppc = st->buf_pre_corr;
|
g##type *ps = search_start; \
|
||||||
for (i = st->samples_per_frame; i < st->samples_overlap; i++) {
|
ppc = st->buf_pre_corr; \
|
||||||
corr += *ppc++ * *ps++;
|
for (i = st->samples_per_frame; i < st->samples_overlap; i++) { \
|
||||||
}
|
corr += *ppc++ * *ps++; \
|
||||||
if (corr > best_corr) {
|
} \
|
||||||
best_corr = corr;
|
if (corr > best_corr) { \
|
||||||
best_off = off;
|
best_corr = corr; \
|
||||||
}
|
best_off = off; \
|
||||||
search_start += st->samples_per_frame;
|
} \
|
||||||
}
|
search_start += st->samples_per_frame; \
|
||||||
|
} \
|
||||||
return best_off * st->bytes_per_frame;
|
\
|
||||||
|
return best_off * st->bytes_per_frame; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CREATE_BEST_OVERLAP_OFFSET_FLOAT_FUNC (float);
|
||||||
|
CREATE_BEST_OVERLAP_OFFSET_FLOAT_FUNC (double);
|
||||||
|
|
||||||
/* buffer padding for loop optimization: sizeof(gint32) * (loop_size - 1) */
|
/* buffer padding for loop optimization: sizeof(gint32) * (loop_size - 1) */
|
||||||
#define UNROLL_PADDING (4*3)
|
#define UNROLL_PADDING (4*3)
|
||||||
static guint
|
static guint
|
||||||
|
@ -192,20 +197,24 @@ best_overlap_offset_s16 (GstScaletempo * st)
|
||||||
return best_off * st->bytes_per_frame;
|
return best_off * st->bytes_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#define CREATE_OUTPUT_OVERLAP_FLOAT_FUNC(type) \
|
||||||
output_overlap_float (GstScaletempo * st, gpointer buf_out, guint bytes_off)
|
static void \
|
||||||
{
|
output_overlap_##type (GstScaletempo * st, gpointer buf_out, guint bytes_off) \
|
||||||
gfloat *pout = buf_out;
|
{ \
|
||||||
gfloat *pb = st->table_blend;
|
g##type *pout = buf_out; \
|
||||||
gfloat *po = st->buf_overlap;
|
g##type *pb = st->table_blend; \
|
||||||
gfloat *pin = (gfloat *) (st->buf_queue + bytes_off);
|
g##type *po = st->buf_overlap; \
|
||||||
gint i;
|
g##type *pin = (g##type *) (st->buf_queue + bytes_off); \
|
||||||
for (i = 0; i < st->samples_overlap; i++) {
|
gint i; \
|
||||||
*pout++ = *po - *pb++ * (*po - *pin++);
|
for (i = 0; i < st->samples_overlap; i++) { \
|
||||||
po++;
|
*pout++ = *po - *pb++ * (*po - *pin++); \
|
||||||
}
|
po++; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CREATE_OUTPUT_OVERLAP_FLOAT_FUNC (float);
|
||||||
|
CREATE_OUTPUT_OVERLAP_FLOAT_FUNC (double);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_overlap_s16 (GstScaletempo * st, gpointer buf_out, guint bytes_off)
|
output_overlap_s16 (GstScaletempo * st, gpointer buf_out, guint bytes_off)
|
||||||
{
|
{
|
||||||
|
@ -283,12 +292,13 @@ reinit_buffers (GstScaletempo * st)
|
||||||
st->bytes_standing = st->bytes_stride - st->bytes_overlap;
|
st->bytes_standing = st->bytes_stride - st->bytes_overlap;
|
||||||
st->samples_standing = st->bytes_standing / st->bytes_per_sample;
|
st->samples_standing = st->bytes_standing / st->bytes_per_sample;
|
||||||
st->buf_overlap = g_realloc (st->buf_overlap, st->bytes_overlap);
|
st->buf_overlap = g_realloc (st->buf_overlap, st->bytes_overlap);
|
||||||
st->table_blend = g_realloc (st->table_blend, st->samples_overlap * 4); /* sizeof (gint32|gfloat) */
|
st->table_blend =
|
||||||
|
g_realloc (st->table_blend, st->samples_overlap * st->bytes_per_sample);
|
||||||
if (st->bytes_overlap > prev_overlap) {
|
if (st->bytes_overlap > prev_overlap) {
|
||||||
memset ((guint8 *) st->buf_overlap + prev_overlap, 0,
|
memset ((guint8 *) st->buf_overlap + prev_overlap, 0,
|
||||||
st->bytes_overlap - prev_overlap);
|
st->bytes_overlap - prev_overlap);
|
||||||
}
|
}
|
||||||
if (st->use_int) {
|
if (st->format == GST_AUDIO_FORMAT_S16) {
|
||||||
gint32 *pb = st->table_blend;
|
gint32 *pb = st->table_blend;
|
||||||
gint64 blend = 0;
|
gint64 blend = 0;
|
||||||
for (i = 0; i < frames_overlap; i++) {
|
for (i = 0; i < frames_overlap; i++) {
|
||||||
|
@ -299,7 +309,7 @@ reinit_buffers (GstScaletempo * st)
|
||||||
blend += 65535; /* 2^16 */
|
blend += 65535; /* 2^16 */
|
||||||
}
|
}
|
||||||
st->output_overlap = output_overlap_s16;
|
st->output_overlap = output_overlap_s16;
|
||||||
} else {
|
} else if (st->format == GST_AUDIO_FORMAT_F32) {
|
||||||
gfloat *pb = st->table_blend;
|
gfloat *pb = st->table_blend;
|
||||||
gfloat t = (gfloat) frames_overlap;
|
gfloat t = (gfloat) frames_overlap;
|
||||||
for (i = 0; i < frames_overlap; i++) {
|
for (i = 0; i < frames_overlap; i++) {
|
||||||
|
@ -309,6 +319,16 @@ reinit_buffers (GstScaletempo * st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st->output_overlap = output_overlap_float;
|
st->output_overlap = output_overlap_float;
|
||||||
|
} else {
|
||||||
|
gdouble *pb = st->table_blend;
|
||||||
|
gdouble t = (gdouble) frames_overlap;
|
||||||
|
for (i = 0; i < frames_overlap; i++) {
|
||||||
|
gdouble v = i / t;
|
||||||
|
for (j = 0; j < st->samples_per_frame; j++) {
|
||||||
|
*pb++ = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st->output_overlap = output_overlap_double;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,11 +338,12 @@ reinit_buffers (GstScaletempo * st)
|
||||||
if (st->frames_search < 1) { /* if no search */
|
if (st->frames_search < 1) { /* if no search */
|
||||||
st->best_overlap_offset = NULL;
|
st->best_overlap_offset = NULL;
|
||||||
} else {
|
} else {
|
||||||
guint bytes_pre_corr = (st->samples_overlap - st->samples_per_frame) * 4; /* sizeof (gint32|gfloat) */
|
guint bytes_pre_corr =
|
||||||
|
(st->samples_overlap - st->samples_per_frame) * st->bytes_per_sample;
|
||||||
st->buf_pre_corr =
|
st->buf_pre_corr =
|
||||||
g_realloc (st->buf_pre_corr, bytes_pre_corr + UNROLL_PADDING);
|
g_realloc (st->buf_pre_corr, bytes_pre_corr + UNROLL_PADDING);
|
||||||
st->table_window = g_realloc (st->table_window, bytes_pre_corr);
|
st->table_window = g_realloc (st->table_window, bytes_pre_corr);
|
||||||
if (st->use_int) {
|
if (st->format == GST_AUDIO_FORMAT_S16) {
|
||||||
gint64 t = frames_overlap;
|
gint64 t = frames_overlap;
|
||||||
gint32 n = 8589934588LL / (t * t); /* 4 * (2^31 - 1) / t^2 */
|
gint32 n = 8589934588LL / (t * t); /* 4 * (2^31 - 1) / t^2 */
|
||||||
gint32 *pw;
|
gint32 *pw;
|
||||||
|
@ -336,7 +357,7 @@ reinit_buffers (GstScaletempo * st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st->best_overlap_offset = best_overlap_offset_s16;
|
st->best_overlap_offset = best_overlap_offset_s16;
|
||||||
} else {
|
} else if (st->format == GST_AUDIO_FORMAT_F32) {
|
||||||
gfloat *pw = st->table_window;
|
gfloat *pw = st->table_window;
|
||||||
for (i = 1; i < frames_overlap; i++) {
|
for (i = 1; i < frames_overlap; i++) {
|
||||||
gfloat v = i * (frames_overlap - i);
|
gfloat v = i * (frames_overlap - i);
|
||||||
|
@ -345,6 +366,15 @@ reinit_buffers (GstScaletempo * st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st->best_overlap_offset = best_overlap_offset_float;
|
st->best_overlap_offset = best_overlap_offset_float;
|
||||||
|
} else {
|
||||||
|
gdouble *pw = st->table_window;
|
||||||
|
for (i = 1; i < frames_overlap; i++) {
|
||||||
|
gdouble v = i * (frames_overlap - i);
|
||||||
|
for (j = 0; j < st->samples_per_frame; j++) {
|
||||||
|
*pw++ = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st->best_overlap_offset = best_overlap_offset_double;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +416,7 @@ reinit_buffers (GstScaletempo * st)
|
||||||
(gint) (st->bytes_standing / st->bytes_per_frame),
|
(gint) (st->bytes_standing / st->bytes_per_frame),
|
||||||
(gint) (st->bytes_overlap / st->bytes_per_frame), st->frames_search,
|
(gint) (st->bytes_overlap / st->bytes_per_frame), st->frames_search,
|
||||||
(gint) (st->bytes_queue_max / st->bytes_per_frame),
|
(gint) (st->bytes_queue_max / st->bytes_per_frame),
|
||||||
(st->use_int ? "s16" : "float"));
|
gst_audio_format_to_string (st->format));
|
||||||
|
|
||||||
st->reinit_buffers = FALSE;
|
st->reinit_buffers = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -535,8 +565,8 @@ gst_scaletempo_set_caps (GstBaseTransform * trans,
|
||||||
GstScaletempo *scaletempo = GST_SCALETEMPO (trans);
|
GstScaletempo *scaletempo = GST_SCALETEMPO (trans);
|
||||||
|
|
||||||
gint width, bps, nch, rate;
|
gint width, bps, nch, rate;
|
||||||
gboolean use_int;
|
|
||||||
GstAudioInfo info;
|
GstAudioInfo info;
|
||||||
|
GstAudioFormat format;
|
||||||
|
|
||||||
if (!gst_audio_info_from_caps (&info, incaps))
|
if (!gst_audio_info_from_caps (&info, incaps))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -544,7 +574,7 @@ gst_scaletempo_set_caps (GstBaseTransform * trans,
|
||||||
nch = GST_AUDIO_INFO_CHANNELS (&info);
|
nch = GST_AUDIO_INFO_CHANNELS (&info);
|
||||||
rate = GST_AUDIO_INFO_RATE (&info);
|
rate = GST_AUDIO_INFO_RATE (&info);
|
||||||
width = GST_AUDIO_INFO_WIDTH (&info);
|
width = GST_AUDIO_INFO_WIDTH (&info);
|
||||||
use_int = GST_AUDIO_INFO_IS_INTEGER (&info);
|
format = GST_AUDIO_INFO_FORMAT (&info);
|
||||||
|
|
||||||
bps = width / 8;
|
bps = width / 8;
|
||||||
|
|
||||||
|
@ -552,13 +582,12 @@ gst_scaletempo_set_caps (GstBaseTransform * trans,
|
||||||
|
|
||||||
if (rate != scaletempo->sample_rate
|
if (rate != scaletempo->sample_rate
|
||||||
|| nch != scaletempo->samples_per_frame
|
|| nch != scaletempo->samples_per_frame
|
||||||
|| bps != scaletempo->bytes_per_sample
|
|| bps != scaletempo->bytes_per_sample || format != scaletempo->format) {
|
||||||
|| use_int != scaletempo->use_int) {
|
|
||||||
scaletempo->sample_rate = rate;
|
scaletempo->sample_rate = rate;
|
||||||
scaletempo->samples_per_frame = nch;
|
scaletempo->samples_per_frame = nch;
|
||||||
scaletempo->bytes_per_sample = bps;
|
scaletempo->bytes_per_sample = bps;
|
||||||
scaletempo->bytes_per_frame = nch * bps;
|
scaletempo->bytes_per_frame = nch * bps;
|
||||||
scaletempo->use_int = use_int;
|
scaletempo->format = format;
|
||||||
scaletempo->reinit_buffers = TRUE;
|
scaletempo->reinit_buffers = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct _GstScaletempo
|
||||||
guint ms_search;
|
guint ms_search;
|
||||||
|
|
||||||
/* caps */
|
/* caps */
|
||||||
gboolean use_int;
|
GstAudioFormat format;
|
||||||
guint samples_per_frame; /* AKA number of channels */
|
guint samples_per_frame; /* AKA number of channels */
|
||||||
guint bytes_per_sample;
|
guint bytes_per_sample;
|
||||||
guint bytes_per_frame;
|
guint bytes_per_frame;
|
||||||
|
|
Loading…
Reference in a new issue