summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/decode/ad_lavc.c20
-rw-r--r--audio/decode/ad_spdif.c19
-rw-r--r--audio/filter/af_drop.c18
-rw-r--r--audio/filter/af_format.c4
-rw-r--r--audio/filter/af_lavcac3enc.c14
-rw-r--r--audio/filter/af_rubberband.c16
-rw-r--r--audio/filter/af_scaletempo.c254
-rw-r--r--audio/filter/af_scaletempo2.c51
-rw-r--r--audio/filter/af_scaletempo2_internals.c80
-rw-r--r--audio/filter/af_scaletempo2_internals.h1
-rw-r--r--audio/out/ao_alsa.c3
-rw-r--r--audio/out/ao_audiotrack.c4
-rw-r--r--audio/out/ao_avfoundation.m14
-rw-r--r--audio/out/ao_coreaudio.c50
-rw-r--r--audio/out/ao_coreaudio_chmap.c2
-rw-r--r--audio/out/ao_coreaudio_chmap.h7
-rw-r--r--audio/out/ao_coreaudio_properties.h5
-rw-r--r--audio/out/ao_coreaudio_utils.c36
-rw-r--r--audio/out/ao_coreaudio_utils.h9
-rw-r--r--audio/out/ao_jack.c1
-rw-r--r--audio/out/ao_oss.c3
-rw-r--r--audio/out/ao_pipewire.c37
-rw-r--r--audio/out/ao_pulse.c42
-rw-r--r--audio/out/ao_sndio.c2
-rw-r--r--audio/out/ao_wasapi.c101
-rw-r--r--audio/out/ao_wasapi.h7
-rw-r--r--audio/out/ao_wasapi_changenotify.c5
-rw-r--r--audio/out/ao_wasapi_utils.c84
-rw-r--r--audio/out/buffer.c54
-rw-r--r--audio/out/internal.h10
30 files changed, 571 insertions, 382 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 08b789a709..39cd74cd2a 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -17,7 +17,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <stdbool.h>
#include <assert.h>
@@ -44,6 +43,7 @@
#include "options/options.h"
struct priv {
+ struct mp_codec_params *codec;
AVCodecContext *avctx;
AVFrame *avframe;
AVPacket *avpkt;
@@ -156,7 +156,7 @@ static bool init(struct mp_filter *da, struct mp_codec_params *codec,
return true;
}
-static void destroy(struct mp_filter *da)
+static void ad_lavc_destroy(struct mp_filter *da)
{
struct priv *ctx = da->priv;
@@ -165,7 +165,7 @@ static void destroy(struct mp_filter *da)
mp_free_av_packet(&ctx->avpkt);
}
-static void reset(struct mp_filter *da)
+static void ad_lavc_reset(struct mp_filter *da)
{
struct priv *ctx = da->priv;
@@ -219,6 +219,8 @@ static int receive_frame(struct mp_filter *da, struct mp_frame *out)
if (!priv->avframe->buf[0])
return ret;
+ mp_codec_info_from_av(avctx, priv->codec);
+
double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase);
struct mp_aframe *mpframe = mp_aframe_from_avframe(priv->avframe);
@@ -276,7 +278,7 @@ static int receive_frame(struct mp_filter *da, struct mp_frame *out)
return ret;
}
-static void process(struct mp_filter *ad)
+static void ad_lavc_process(struct mp_filter *ad)
{
struct priv *priv = ad->priv;
@@ -286,9 +288,9 @@ static void process(struct mp_filter *ad)
static const struct mp_filter_info ad_lavc_filter = {
.name = "ad_lavc",
.priv_size = sizeof(struct priv),
- .process = process,
- .reset = reset,
- .destroy = destroy,
+ .process = ad_lavc_process,
+ .reset = ad_lavc_reset,
+ .destroy = ad_lavc_destroy,
};
static struct mp_decoder *create(struct mp_filter *parent,
@@ -305,12 +307,16 @@ static struct mp_decoder *create(struct mp_filter *parent,
da->log = mp_log_new(da, parent->log, NULL);
struct priv *priv = da->priv;
+ priv->codec = codec;
priv->public.f = da;
if (!init(da, codec, decoder)) {
talloc_free(da);
return NULL;
}
+
+ codec->codec_desc = priv->avctx->codec_descriptor->long_name;
+
return &priv->public;
}
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index a8e77b4e99..1d9e9711fe 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -79,7 +79,7 @@ static int write_packet(void *p, const uint8_t *buf, int buf_size)
}
// (called on both filter destruction _and_ if lavf fails to init)
-static void destroy(struct mp_filter *da)
+static void ad_spdif_destroy(struct mp_filter *da)
{
struct spdifContext *spdif_ctx = da->priv;
AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx;
@@ -89,7 +89,7 @@ static void destroy(struct mp_filter *da)
av_write_trailer(lavf_ctx);
if (lavf_ctx->pb)
av_freep(&lavf_ctx->pb->buffer);
- av_freep(&lavf_ctx->pb);
+ avio_context_free(&lavf_ctx->pb);
avformat_free_context(lavf_ctx);
spdif_ctx->lavf_ctx = NULL;
}
@@ -181,7 +181,7 @@ static int init_filter(struct mp_filter *da)
goto fail;
void *buffer = av_mallocz(OUTBUF_SIZE);
- MP_HANDLE_OOM(buffer);
+ MP_HANDLE_OOM(buffer);
lavf_ctx->pb = avio_alloc_context(buffer, OUTBUF_SIZE, 1, spdif_ctx, NULL,
write_packet, NULL);
if (!lavf_ctx->pb) {
@@ -196,7 +196,8 @@ static int init_filter(struct mp_filter *da)
if (!stream)
goto fail;
- stream->codecpar->codec_id = spdif_ctx->codec_id;
+ stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+ stream->codecpar->codec_id = spdif_ctx->codec_id;
AVDictionary *format_opts = NULL;
@@ -260,6 +261,8 @@ static int init_filter(struct mp_filter *da)
abort();
}
+ stream->codecpar->sample_rate = samplerate;
+
struct mp_chmap chmap;
mp_chmap_from_channels(&chmap, num_channels);
mp_aframe_set_chmap(spdif_ctx->fmt, &chmap);
@@ -280,12 +283,12 @@ static int init_filter(struct mp_filter *da)
return 0;
fail:
- destroy(da);
+ ad_spdif_destroy(da);
mp_filter_internal_mark_failed(da);
return -1;
}
-static void process(struct mp_filter *da)
+static void ad_spdif_process(struct mp_filter *da)
{
struct spdifContext *spdif_ctx = da->priv;
@@ -410,8 +413,8 @@ struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref)
static const struct mp_filter_info ad_spdif_filter = {
.name = "ad_spdif",
.priv_size = sizeof(struct spdifContext),
- .process = process,
- .destroy = destroy,
+ .process = ad_spdif_process,
+ .destroy = ad_spdif_destroy,
};
static struct mp_decoder *create(struct mp_filter *parent,
diff --git a/audio/filter/af_drop.c b/audio/filter/af_drop.c
index 724c482720..499389dd2b 100644
--- a/audio/filter/af_drop.c
+++ b/audio/filter/af_drop.c
@@ -11,7 +11,7 @@ struct priv {
struct mp_aframe *last; // for repeating
};
-static void process(struct mp_filter *f)
+static void af_drop_process(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -52,7 +52,7 @@ static void process(struct mp_filter *f)
mp_pin_in_write(f->ppins[1], frame);
}
-static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
+static bool af_drop_command(struct mp_filter *f, struct mp_filter_command *cmd)
{
struct priv *p = f->priv;
@@ -65,7 +65,7 @@ static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
return false;
}
-static void reset(struct mp_filter *f)
+static void af_drop_reset(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -73,18 +73,18 @@ static void reset(struct mp_filter *f)
p->diff = 0;
}
-static void destroy(struct mp_filter *f)
+static void af_drop_destroy(struct mp_filter *f)
{
- reset(f);
+ af_drop_reset(f);
}
static const struct mp_filter_info af_drop_filter = {
.name = "drop",
.priv_size = sizeof(struct priv),
- .process = process,
- .command = command,
- .reset = reset,
- .destroy = destroy,
+ .process = af_drop_process,
+ .command = af_drop_command,
+ .reset = af_drop_reset,
+ .destroy = af_drop_destroy,
};
static struct mp_filter *af_drop_create(struct mp_filter *parent, void *options)
diff --git a/audio/filter/af_format.c b/audio/filter/af_format.c
index 2d1c1cc97d..eddce6422f 100644
--- a/audio/filter/af_format.c
+++ b/audio/filter/af_format.c
@@ -38,7 +38,7 @@ struct priv {
struct mp_pin *in_pin;
};
-static void process(struct mp_filter *f)
+static void af_format_process(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -85,7 +85,7 @@ error:
static const struct mp_filter_info af_format_filter = {
.name = "format",
.priv_size = sizeof(struct priv),
- .process = process,
+ .process = af_format_process,
};
static struct mp_filter *af_format_create(struct mp_filter *parent,
diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c
index ec3330f17b..def9700d18 100644
--- a/audio/filter/af_lavcac3enc.c
+++ b/audio/filter/af_lavcac3enc.c
@@ -139,18 +139,18 @@ static bool reinit(struct mp_filter *f)
return true;
}
-static void reset(struct mp_filter *f)
+static void af_lavcac3enc_reset(struct mp_filter *f)
{
struct priv *s = f->priv;
TA_FREEP(&s->in_frame);
}
-static void destroy(struct mp_filter *f)
+static void af_lavcac3enc_destroy(struct mp_filter *f)
{
struct priv *s = f->priv;
- reset(f);
+ af_lavcac3enc_reset(f);
av_packet_free(&s->lavc_pkt);
avcodec_free_context(&s->lavc_actx);
}
@@ -161,7 +161,7 @@ static void swap_16(uint16_t *ptr, size_t size)
ptr[n] = av_bswap16(ptr[n]);
}
-static void process(struct mp_filter *f)
+static void af_lavcac3enc_process(struct mp_filter *f)
{
struct priv *s = f->priv;
@@ -281,9 +281,9 @@ error:
static const struct mp_filter_info af_lavcac3enc_filter = {
.name = "lavcac3enc",
.priv_size = sizeof(struct priv),
- .process = process,
- .reset = reset,
- .destroy = destroy,
+ .process = af_lavcac3enc_process,
+ .reset = af_lavcac3enc_reset,
+ .destroy = af_lavcac3enc_destroy,
};
static void add_chmaps_to_autoconv(struct mp_filter *f,
diff --git a/audio/filter/af_rubberband.c b/audio/filter/af_rubberband.c
index 48e5cc1e86..e71937fcb2 100644
--- a/audio/filter/af_rubberband.c
+++ b/audio/filter/af_rubberband.c
@@ -105,7 +105,7 @@ static bool init_rubberband(struct mp_filter *f)
return true;
}
-static void process(struct mp_filter *f)
+static void af_rubberband_process(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -233,7 +233,7 @@ error:
mp_filter_internal_mark_failed(f);
}
-static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
+static bool af_rubberband_command(struct mp_filter *f, struct mp_filter_command *cmd)
{
struct priv *p = f->priv;
@@ -263,7 +263,7 @@ static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
return false;
}
-static void reset(struct mp_filter *f)
+static void af_rubberband_reset(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -274,7 +274,7 @@ static void reset(struct mp_filter *f)
TA_FREEP(&p->pending);
}
-static void destroy(struct mp_filter *f)
+static void af_rubberband_destroy(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -286,10 +286,10 @@ static void destroy(struct mp_filter *f)
static const struct mp_filter_info af_rubberband_filter = {
.name = "rubberband",
.priv_size = sizeof(struct priv),
- .process = process,
- .command = command,
- .reset = reset,
- .destroy = destroy,
+ .process = af_rubberband_process,
+ .command = af_rubberband_command,
+ .reset = af_rubberband_reset,
+ .destroy = af_rubberband_destroy,
};
static struct mp_filter *af_rubberband_create(struct mp_filter *parent,
diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c
index f06478f750..482b91209e 100644
--- a/audio/filter/af_scaletempo.c
+++ b/audio/filter/af_scaletempo.c
@@ -2,7 +2,7 @@
* scaletempo audio filter
*
* scale tempo while maintaining pitch
- * (WSOLA technique with cross correlation)
+ * (WSOLA technique with taxicab distance)
* inspired by SoundTouch library by Olli Parviainen
*
* basic algorithm
@@ -35,6 +35,7 @@
#include <string.h>
#include <limits.h>
#include <assert.h>
+#include <math.h>
#include "audio/aframe.h"
#include "audio/format.h"
@@ -87,8 +88,6 @@ struct priv {
// best overlap
int frames_search;
int num_channels;
- void *buf_pre_corr;
- void *table_window;
int (*best_overlap_offset)(struct priv *s);
};
@@ -135,72 +134,144 @@ static bool fill_queue(struct priv *s)
return bytes_needed == 0;
}
-#define UNROLL_PADDING (4 * 4)
+// Fit the curve f(x) = a * x^2 + b * x + c such that
+// f(-1) = y[0]
+// f(0) = y[1]
+// f(1) = y[2]
+// and return the extremum position and value
+// assuming y[0] <= y[1] >= y[2] || y[0] >= y[1] <= y[2]
+static void quadratic_interpolation_float(
+ const float* y_values, float* x, float* value)
+{
+ const float b = (y_values[2] - y_values[0]) * 0.5f;
+ const float c = y_values[1];
+ const float a = y_values[0] + b - c;
+
+ if (a == 0.f) {
+ // it's a flat line
+ *x = 0;
+ *value = c;
+ } else {
+ const float pos = -b / (2.f * a);
+ *x = pos;
+ *value = a * pos * pos + b * pos + c;
+ }
+}
+
+static void quadratic_interpolation_s16(
+ const int32_t* y_values, float* x, int32_t* value)
+{
+ const float b = (y_values[2] - y_values[0]) * 0.5f;
+ const float c = y_values[1];
+ const float a = y_values[0] + b - c;
+
+ if (a == 0.f) {
+ // it's a flat line
+ *x = 0;
+ *value = c;
+ } else {
+ const float pos = -b / (2.f * a);
+ *x = pos;
+ *value = a * pos * pos + b * pos + c;
+ }
+}
static int best_overlap_offset_float(struct priv *s)
{
- float best_corr = INT_MIN;
- int best_off = 0;
-
- float *pw = s->table_window;
- float *po = s->buf_overlap;
- po += s->num_channels;
- float *ppc = s->buf_pre_corr;
- for (int i = s->num_channels; i < s->samples_overlap; i++)
- *ppc++ = *pw++ **po++;
-
- float *search_start = (float *)s->buf_queue + s->num_channels;
- for (int off = 0; off < s->frames_search; off++) {
- float corr = 0;
- float *ps = search_start;
- ppc = s->buf_pre_corr;
- for (int i = s->num_channels; i < s->samples_overlap; i++)
- corr += *ppc++ **ps++;
- if (corr > best_corr) {
- best_corr = corr;
- best_off = off;
+ int num_channels = s->num_channels, frames_search = s->frames_search;
+ float *source = (float *)s->buf_queue + num_channels;
+ float *target = (float *)s->buf_overlap + num_channels;
+ int num_samples = s->samples_overlap - num_channels;
+ int step_size = 3;
+ float history[3] = {};
+
+ float best_distance = FLT_MAX;
+ int best_offset_approx = 0;
+ for (int offset = 0; offset < frames_search; offset += step_size) {
+ float distance = 0;
+ for (int i = 0; i < num_samples; i++)
+ distance += fabsf(target[i] - source[offset * num_channels + i]);
+
+ int offset_approx = offset;
+ history[0] = history[1];
+ history[1] = history[2];
+ history[2] = distance;
+ if(offset >= 2 && history[0] >= history[1] && history[1] <= history[2]) {
+ float extremum;
+ quadratic_interpolation_float(history, &extremum, &distance);
+ offset_approx = offset - step_size + (int)(extremum * step_size + 0.5f);
+ }
+
+ if (distance < best_distance) {
+ best_distance = distance;
+ best_offset_approx = offset_approx;
+ }
+ }
+
+ best_distance = FLT_MAX;
+ int best_offset = 0;
+ int min_offset = MPMAX(0, best_offset_approx - step_size + 1);
+ int max_offset = MPMIN(frames_search, best_offset_approx + step_size);
+ for (int offset = min_offset; offset < max_offset; offset++) {
+ float distance = 0;
+ for (int i = 0; i < num_samples; i++)
+ distance += fabsf(target[i] - source[offset * num_channels + i]);
+ if (distance < best_distance) {
+ best_distance = distance;
+ best_offset = offset;
}
- search_start += s->num_channels;
}
- return best_off * 4 * s->num_channels;
+ return best_offset * 4 * num_channels;
}
static int best_overlap_offset_s16(struct priv *s)
{
- int64_t best_corr = INT64_MIN;
- int best_off = 0;
-
- int32_t *pw = s->table_window;
- int16_t *po = s->buf_overlap;
- po += s->num_channels;
- int32_t *ppc = s->buf_pre_corr;
- for (long i = s->num_channels; i < s->samples_overlap; i++)
- *ppc++ = (*pw++ **po++) >> 15;
-
- int16_t *search_start = (int16_t *)s->buf_queue + s->num_channels;
- for (int off = 0; off < s->frames_search; off++) {
- int64_t corr = 0;
- int16_t *ps = search_start;
- ppc = s->buf_pre_corr;
- ppc += s->samples_overlap - s->num_channels;
- ps += s->samples_overlap - s->num_channels;
- long i = -(s->samples_overlap - s->num_channels);
- do {
- corr += ppc[i + 0] * (int64_t)ps[i + 0];
- corr += ppc[i + 1] * (int64_t)ps[i + 1];
- corr += ppc[i + 2] * (int64_t)ps[i + 2];
- corr += ppc[i + 3] * (int64_t)ps[i + 3];
- i += 4;
- } while (i < 0);
- if (corr > best_corr) {
- best_corr = corr;
- best_off = off;
+ int num_channels = s->num_channels, frames_search = s->frames_search;
+ int16_t *source = (int16_t *)s->buf_queue + num_channels;
+ int16_t *target = (int16_t *)s->buf_overlap + num_channels;
+ int num_samples = s->samples_overlap - num_channels;
+ int step_size = 3;
+ int32_t history[3] = {};
+
+ int32_t best_distance = INT32_MAX;
+ int best_offset_approx = 0;
+ for (int offset = 0; offset < frames_search; offset += step_size) {
+ int32_t distance = 0;
+ for (int i = 0; i < num_samples; i++)
+ distance += abs((int32_t)target[i] - source[offset * num_channels + i]);
+
+ int offset_approx = offset;
+ history[0] = history[1];
+ history[1] = history[2];
+ history[2] = distance;
+ if(offset >= 2 && history[0] >= history[1] && history[1] <= history[2]) {
+ float extremum;
+ quadratic_interpolation_s16(history, &extremum, &distance);
+ offset_approx = offset - step_size + (int)(extremum * step_size + 0.5f);
+ }
+
+ if (distance < best_distance) {
+ best_distance = distance;
+ best_offset_approx = offset_approx;
}
- search_start += s->num_channels;
}
- return best_off * 2 * s->num_channels;
+ best_distance = INT32_MAX;
+ int best_offset = 0;
+ int min_offset = MPMAX(0, best_offset_approx - step_size + 1);
+ int max_offset = MPMIN(frames_search, best_offset_approx + step_size);
+ for (int offset = min_offset; offset < max_offset; offset++) {
+ int32_t distance = 0;
+ for (int i = 0; i < num_samples; i++)
+ distance += abs((int32_t)target[i] - source[offset * num_channels + i]);
+ if (distance < best_distance) {
+ best_distance = distance;
+ best_offset = offset;
+ }
+ }
+
+ return best_offset * 2 * s->num_channels;
}
static void output_overlap_float(struct priv *s, void *buf_out,
@@ -211,8 +282,9 @@ static void output_overlap_float(struct priv *s, void *buf_out,
float *po = s->buf_overlap;
float *pin = (float *)(s->buf_queue + bytes_off);
for (int i = 0; i < s->samples_overlap; i++) {
- *pout++ = *po - *pb++ *(*po - *pin++);
- po++;
+ // the math is equal to *po * (1 - *pb) + *pin * *pb
+ float o = *po++;
+ *pout++ = o - *pb++ * (o - *pin++);
}
}
@@ -224,12 +296,13 @@ static void output_overlap_s16(struct priv *s, void *buf_out,
int16_t *po = s->buf_overlap;
int16_t *pin = (int16_t *)(s->buf_queue + bytes_off);
for (int i = 0; i < s->samples_overlap; i++) {
- *pout++ = *po - ((*pb++ *(*po - *pin++)) >> 16);
- po++;
+ // the math is equal to *po * (1 - *pb) + *pin * *pb
+ int32_t o = *po++;
+ *pout++ = o - ((*pb++ *(o - *pin++)) >> 16);
}
}
-static void process(struct mp_filter *f)
+static void af_scaletempo_process(struct mp_filter *f)
{
struct priv *s = f->priv;
@@ -420,18 +493,20 @@ static bool reinit(struct mp_filter *f)
memset(s->buf_overlap, 0, s->bytes_overlap);
if (use_int) {
int32_t *pb = s->table_blend;
- int64_t blend = 0;
+ const float scale = M_PI / frames_overlap;
for (int i = 0; i < frames_overlap; i++) {
- int32_t v = blend / frames_overlap;
+ // Hann function
+ const int32_t v = 0.5f * (1.0f - cosf(i * scale)) * 65536 + 0.5;
for (int j = 0; j < nch; j++)
*pb++ = v;
- blend += 65536; // 2^16
}
s->output_overlap = output_overlap_s16;
} else {
float *pb = s->table_blend;
+ const float scale = M_PI / frames_overlap;
for (int i = 0; i < frames_overlap; i++) {
- float v = i / (float)frames_overlap;
+ // Hann function
+ const float v = 0.5f * (1.0f - cosf(i * scale));
for (int j = 0; j < nch; j++)
*pb++ = v;
}
@@ -444,39 +519,8 @@ static bool reinit(struct mp_filter *f)
s->best_overlap_offset = NULL;
else {
if (use_int) {
- int64_t t = frames_overlap;
- int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2
- s->buf_pre_corr = realloc(s->buf_pre_corr,
- s->bytes_overlap * 2 + UNROLL_PADDING);
- s->table_window = realloc(s->table_window,
- s->bytes_overlap * 2 - nch * bps * 2);
- if (!s->buf_pre_corr || !s->table_window) {
- MP_FATAL(f, "Out of memory\n");
- return false;
- }
- memset((char *)s->buf_pre_corr + s->bytes_overlap * 2, 0,
- UNROLL_PADDING);
- int32_t *pw = s->table_window;
- for (int i = 1; i < frames_overlap; i++) {
- int32_t v = (i * (t - i) * n) >> 15;
- for (int j = 0; j < nch; j++)
- *pw++ = v;
- }
s->best_overlap_offset = best_overlap_offset_s16;
} else {
- s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap);
- s->table_window = realloc(s->table_window,
- s->bytes_overlap - nch * bps);
- if (!s->buf_pre_corr || !s->table_window) {
- MP_FATAL(f, "Out of memory\n");
- return false;
- }
- float *pw = s->table_window;
- for (int i = 1; i < frames_overlap; i++) {
- float v = i * (frames_overlap - i);
- for (int j = 0; j < nch; j++)
- *pw++ = v;
- }
s->best_overlap_offset = best_overlap_offset_float;
}
}
@@ -486,7 +530,7 @@ static bool reinit(struct mp_filter *f)
s->bytes_queue = (s->frames_search + s->frames_stride + frames_overlap)
* bps * nch;
- s->buf_queue = realloc(s->buf_queue, s->bytes_queue + UNROLL_PADDING);
+ s->buf_queue = realloc(s->buf_queue, s->bytes_queue);
if (!s->buf_queue) {
MP_FATAL(f, "Out of memory\n");
return false;
@@ -511,7 +555,7 @@ static bool reinit(struct mp_filter *f)
return true;
}
-static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
+static bool af_scaletempo_command(struct mp_filter *f, struct mp_filter_command *cmd)
{
struct priv *s = f->priv;
@@ -530,7 +574,7 @@ static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
return false;
}
-static void reset(struct mp_filter *f)
+static void af_scaletempo_reset(struct mp_filter *f)
{
struct priv *s = f->priv;
@@ -543,14 +587,12 @@ static void reset(struct mp_filter *f)
TA_FREEP(&s->in);
}
-static void destroy(struct mp_filter *f)
+static void af_scaletempo_destroy(struct mp_filter *f)
{
struct priv *s = f->priv;
free(s->buf_queue);
free(s->buf_overlap);
- free(s->buf_pre_corr);
free(s->table_blend);
- free(s->table_window);
TA_FREEP(&s->in);
mp_filter_free_children(f);
}
@@ -558,10 +600,10 @@ static void destroy(struct mp_filter *f)
static const struct mp_filter_info af_scaletempo_filter = {
.name = "scaletempo",
.priv_size = sizeof(struct priv),
- .process = process,
- .command = command,
- .reset = reset,
- .destroy = destroy,
+ .process = af_scaletempo_process,
+ .command = af_scaletempo_command,
+ .reset = af_scaletempo_reset,
+ .destroy = af_scaletempo_destroy,
};
static struct mp_filter *af_scaletempo_create(struct mp_filter *parent,
diff --git a/audio/filter/af_scaletempo2.c b/audio/filter/af_scaletempo2.c
index 7ad8e3566d..749e219454 100644
--- a/audio/filter/af_scaletempo2.c
+++ b/audio/filter/af_scaletempo2.c
@@ -8,7 +8,7 @@
#include "options/m_option.h"
struct priv {
- struct mp_scaletempo2 data;
+ struct mp_scaletempo2 *data;
struct mp_pin *in_pin;
struct mp_aframe *cur_format;
struct mp_aframe_pool *out_pool;
@@ -19,9 +19,9 @@ struct priv {
};
static bool init_scaletempo2(struct mp_filter *f);
-static void reset(struct mp_filter *f);
+static void af_scaletempo2_reset(struct mp_filter *f);
-static void process(struct mp_filter *f)
+static void af_scaletempo2_process(struct mp_filter *f)
{
struct priv *p = f->priv;
@@ -29,7 +29,7 @@ static void process(struct mp_filter *f)
return;
while (!p->initialized || !p->pending ||
- !mp_scaletempo2_frames_available(&p->data, p->speed))
+ !mp_scaletempo2_frames_available(p->data, p->speed))
{
bool eof = false;
if (!p->pending || !mp_aframe_get_size(p->pending)) {
@@ -64,16 +64,16 @@ static void process(struct mp_filter *f)
if (p->pending && !format_change && !p->sent_final) {
int frame_size = mp_aframe_get_size(p->pending);
uint8_t **planes = mp_aframe_get_data_ro(p->pending);
- int read = mp_scaletempo2_fill_input_buffer(&p->data,
+ int read = mp_scaletempo2_fill_input_buffer(p->data,
planes, frame_size, p->speed);
mp_aframe_skip_samples(p->pending, read);
}
if (final && p->pending && !p->sent_final) {
- mp_scaletempo2_set_final(&p->data);
+ mp_scaletempo2_set_final(p->data);
p->sent_final = true;
}
- if (mp_scaletempo2_frames_available(&p->data, p->speed)) {
+ if (mp_scaletempo2_frames_available(p->data, p->speed)) {
if (eof) {
mp_pin_out_repeat_eof(p->in_pin); // drain more next time
}
@@ -89,9 +89,9 @@ static void process(struct mp_filter *f)
}
assert(p->pending);
- if (mp_scaletempo2_frames_available(&p->data, p->speed)) {
+ if (mp_scaletempo2_frames_available(p->data, p->speed)) {
struct mp_aframe *out = mp_aframe_new_ref(p->cur_format);
- int out_samples = p->data.ola_hop_size;
+ int out_samples = p->data->ola_hop_size;
if (mp_aframe_pool_allocate(p->out_pool, out, out_samples) < 0) {
talloc_free(out);
goto error;
@@ -101,14 +101,14 @@ static void process(struct mp_filter *f)
uint8_t **planes = mp_aframe_get_data_rw(out);
assert(planes);
- assert(mp_aframe_get_planes(out) == p->data.channels);
+ assert(mp_aframe_get_planes(out) == p->data->channels);
- out_samples = mp_scaletempo2_fill_buffer(&p->data,
+ out_samples = mp_scaletempo2_fill_buffer(p->data,
(float**)planes, out_samples, p->speed);
double pts = mp_aframe_get_pts(p->pending);
if (pts != MP_NOPTS_VALUE) {
- double frame_delay = mp_scaletempo2_get_latency(&p->data, p->speed)
+ double frame_delay = mp_scaletempo2_get_latency(p->data, p->speed)
+ out_samples * p->speed;
mp_aframe_set_pts(out, pts - frame_delay / mp_aframe_get_effective_rate(out));
@@ -122,7 +122,7 @@ static void process(struct mp_filter *f)
// reset the filter to ensure it stops generating audio