summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/aframe.c2
-rw-r--r--audio/decode/ad_lavc.c1
-rw-r--r--audio/decode/ad_spdif.c25
-rw-r--r--audio/filter/af_scaletempo.c238
-rw-r--r--audio/out/ao.c2
-rw-r--r--audio/out/ao_audiotrack.c2
-rw-r--r--audio/out/ao_audiounit.m2
-rw-r--r--audio/out/ao_avfoundation.m11
-rw-r--r--audio/out/ao_coreaudio.c4
-rw-r--r--audio/out/ao_coreaudio_exclusive.c2
-rw-r--r--audio/out/ao_coreaudio_utils.c28
-rw-r--r--audio/out/ao_jack.c3
-rw-r--r--audio/out/ao_opensles.c2
-rw-r--r--audio/out/ao_oss.c3
-rw-r--r--audio/out/ao_pcm.c4
-rw-r--r--audio/out/ao_pipewire.c4
-rw-r--r--audio/out/ao_pulse.c38
-rw-r--r--audio/out/ao_sdl.c2
-rw-r--r--audio/out/ao_wasapi_changenotify.c5
-rw-r--r--audio/out/ao_wasapi_utils.c44
-rw-r--r--audio/out/buffer.c57
-rw-r--r--audio/out/internal.h8
22 files changed, 300 insertions, 187 deletions
diff --git a/audio/aframe.c b/audio/aframe.c
index cb6ea17be3..03e8ab8ae8 100644
--- a/audio/aframe.c
+++ b/audio/aframe.c
@@ -600,7 +600,7 @@ bool mp_aframe_set_silence(struct mp_aframe *f, int offset, int samples)
bool mp_aframe_reverse(struct mp_aframe *f)
{
int format = mp_aframe_get_format(f);
- size_t bps = af_fmt_to_bytes(format);
+ int bps = af_fmt_to_bytes(format);
if (!af_fmt_is_pcm(format) || bps > 16)
return false;
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 9b5f1fb467..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>
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index 98a53f3ca0..3f83ab240e 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -45,6 +45,7 @@
struct spdifContext {
struct mp_log *log;
+ struct mp_codec_params *codec;
enum AVCodecID codec_id;
AVFormatContext *lavf_ctx;
AVPacket *avpkt;
@@ -117,15 +118,17 @@ static void determine_codec_params(struct mp_filter *da, AVPacket *pkt,
uint8_t *d = NULL;
int s = 0;
- av_parser_parse2(parser, ctx, &d, &s, pkt->data, pkt->size, 0, 0, 0);
- *out_profile = profile = ctx->profile;
- *out_rate = ctx->sample_rate;
+ if (av_parser_parse2(parser, ctx, &d, &s, pkt->data, pkt->size, 0, 0, 0) > 0) {
+ *out_profile = profile = ctx->profile;
+ *out_rate = ctx->sample_rate;
+ spdif_ctx->codec->codec_profile = avcodec_profile_name(spdif_ctx->codec_id, profile);
+ }
avcodec_free_context(&ctx);
av_parser_close(parser);
}
- if (profile != AV_PROFILE_UNKNOWN || spdif_ctx->codec_id != AV_CODEC_ID_DTS)
+ if (profile != AV_PROFILE_UNKNOWN || spdif_ctx->codec_id == AV_CODEC_ID_AC3)
return;
const AVCodec *codec = avcodec_find_decoder(spdif_ctx->codec_id);
@@ -151,6 +154,13 @@ static void determine_codec_params(struct mp_filter *da, AVPacket *pkt,
*out_profile = profile = ctx->profile;
*out_rate = ctx->sample_rate;
+ struct mp_codec_params *c = spdif_ctx->codec;
+ c->codec_profile = av_get_profile_name(ctx->codec, ctx->profile);
+ if (!c->codec_profile)
+ c->codec_profile = avcodec_profile_name(ctx->codec_id, ctx->profile);
+ c->codec = ctx->codec_descriptor->name;
+ c->codec_desc = ctx->codec_descriptor->long_name;
+
done:
av_frame_free(&frame);
avcodec_free_context(&ctx);
@@ -181,7 +191,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) {
@@ -432,6 +442,7 @@ static struct mp_decoder *create(struct mp_filter *parent,
struct spdifContext *spdif_ctx = da->priv;
spdif_ctx->log = da->log;
+ spdif_ctx->codec = codec;
spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx);
spdif_ctx->public.f = da;
@@ -446,6 +457,10 @@ static struct mp_decoder *create(struct mp_filter *parent,
return NULL;
}
+ const AVCodecDescriptor *desc = avcodec_descriptor_get(spdif_ctx->codec_id);
+ if (desc)
+ codec->codec_desc = desc->long_name;
+
return &spdif_ctx->public;
}
diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c
index e7b101b260..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,8 +296,9 @@ 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);
}
}
@@ -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;
@@ -548,9 +592,7 @@ 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);
}
diff --git a/audio/out/ao.c b/audio/out/ao.c
index 75fcbac6fa..ee20b736a3 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -241,7 +241,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
} else {
ao->sstride *= ao->channels.num;
}
- ao->bps = ao->samplerate * ao->sstride;
+ ao->bps = (int64_t)ao->samplerate * ao->sstride;
if (ao->device_buffer <= 0 && ao->driver->write) {
MP_ERR(ao, "Device buffer size not set.\n");
diff --git a/audio/out/ao_audiotrack.c b/audio/out/ao_audiotrack.c
index db1da9c407..940bffbec9 100644
--- a/audio/out/ao_audiotrack.c
+++ b/audio/out/ao_audiotrack.c
@@ -564,7 +564,7 @@ static MP_THREAD_VOID ao_thread(void *arg)
int64_t ts = mp_time_ns();
ts += MP_TIME_S_TO_NS(read_samples / (double)(ao->samplerate));
ts += MP_TIME_S_TO_NS(AudioTrack_getLatency(ao));
- int samples = ao_read_data_nonblocking(ao, &p->chunk, read_samples, ts);
+ int samples = ao_read_data(ao, &p->chunk, read_samples, ts, NULL, false, false);
int ret = AudioTrack_write(ao, samples * ao->sstride);
if (ret >= 0) {
p->written_frames += ret / ao->sstride;
diff --git a/audio/out/ao_audiounit.m b/audio/out/ao_audiounit.m
index 85b1226dc9..d35912ceb8 100644
--- a/audio/out/ao_audiounit.m
+++ b/audio/out/ao_audiounit.m
@@ -97,7 +97,7 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
int64_t end = mp_time_ns();
end += MP_TIME_S_TO_NS(p->device_latency);
end += ca_get_latency(ts) + ca_frames_to_ns(ao, frames);
- ao_read_data(ao, planes, frames, end);
+ ao_read_data(ao, planes, frames, end, NULL, true, true);
return noErr;
}
diff --git a/audio/out/ao_avfoundation.m b/audio/out/ao_avfoundation.m
index 7654916519..2e7d194b25 100644
--- a/audio/out/ao_avfoundation.m
+++ b/audio/out/ao_avfoundation.m
@@ -76,11 +76,14 @@ static void feed(struct ao *ao)
int64_t cur_time_mp = mp_time_ns();
int64_t end_time_av = MPMAX(p->end_time_av, cur_time_av);
int64_t time_delta = CMTimeGetNanoseconds(CMTimeMake(request_sample_count, samplerate));
- int real_sample_count = ao_read_data_nonblocking(ao, data, request_sample_count, end_time_av - cur_time_av + cur_time_mp + time_delta);
+ bool eof;
+ int real_sample_count = ao_read_data(ao, data, request_sample_count, end_time_av - cur_time_av + cur_time_mp + time_delta, &eof, false, true);
+ if (eof) {
+ [p->renderer stopRequestingMediaData];
+ ao_stop_streaming(ao);
+ }
if (real_sample_count == 0) {
- // avoid spinning by blocking the thread
- mp_sleep_ns(10000000);
- goto finish;
+ return;
}
if ((err = CMBlockBufferCreateWithMemoryBlock(
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 4abfac38ee..1b0f99a9d1 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -16,6 +16,7 @@
*/
#include <CoreAudio/HostTime.h>
+#include <libavutil/mathematics.h>
#include "ao.h"
#include "internal.h"
@@ -90,7 +91,7 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
int64_t end = mp_time_ns();
end += p->hw_latency_ns + ca_get_latency(ts) + ca_frames_to_ns(ao, frames);
// don't use the returned sample count since CoreAudio always expects full frames
- ao_read_data(ao, planes, frames, end);
+ ao_read_data(ao, planes, frames, end, NULL, true, true);
return noErr;
}
@@ -178,6 +179,7 @@ static int init(struct ao *ao)
goto coreaudio_error;
reinit_latency(ao);
+ ao->device_buffer = av_rescale(p->hw_latency_ns, ao->samplerate, 1000000000) * 2;
p->queue = dispatch_queue_create("io.mpv.coreaudio_stop_during_idle",
DISPATCH_QUEUE_SERIAL);
diff --git a/audio/out/ao_coreaudio_exclusive.c b/audio/out/ao_coreaudio_exclusive.c
index 5e0ec3b19f..dbe7b94ed7 100644
--- a/audio/out/ao_coreaudio_exclusive.c
+++ b/audio/out/ao_coreaudio_exclusive.c
@@ -181,7 +181,7 @@ static OSStatus render_cb_compressed(
end += p->hw_latency_ns + ca_get_latency(ts)
+ ca_frames_to_ns(ao, pseudo_frames);
- ao_read_data(ao, &buf.mData, pseudo_frames, end);
+ ao_read_data(ao, &buf.mData, pseudo_frames, end, NULL, true, true);
if (p->spdif_hack)
bad_hack_mygodwhy(buf.mData, pseudo_frames * ao->channels.num);
diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c
index 44604e6df2..78cdcad393 100644
--- a/audio/out/ao_coreaudio_utils.c
+++ b/audio/out/ao_coreaudio_utils.c
@@ -236,20 +236,20 @@ void ca_print_asbd(struct ao *ao, const char *description,
int mpfmt = ca_asbd_to_mp_format(asbd);
MP_VERBOSE(ao,
- "%s %7.1fHz %" PRIu32 "bit %s "
- "[%" PRIu32 "][%" PRIu32 "bpp][%" PRIu32 "fbp]"
- "[%" PRIu32 "bpf][%" PRIu32 "ch] "
- "%s %s %s%s%s%s (%s)\n",
- description, asbd->mSampleRate, asbd->mBitsPerChannel, format,
- asbd->mFormatFlags, asbd->mBytesPerPacket, asbd->mFramesPerPacket,
- asbd->mBytesPerFrame, asbd->mChannelsPerFrame,
- (flags & kAudioFormatFlagIsFloat) ? "float" : "int",
- (flags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE",
- (flags & kAudioFormatFlagIsSignedInteger) ? "S" : "U",
- (flags & kAudioFormatFlagIsPacked) ? " packed" : "",
- (flags & kAudioFormatFlagIsAlignedHigh) ? " aligned" : "",
- (flags & kAudioFormatFlagIsNonInterleaved) ? " P" : "",
- mpfmt ? af_fmt_to_str(mpfmt) : "-");
+ "%s %7.1fHz %" PRIu32 "bit %s "
+ "[%" PRIu32 "][%" PRIu32 "bpp][%" PRIu32 "fbp]"
+ "[%" PRIu32 "bpf][%" PRIu32 "ch] "
+ "%s %s %s%s%s%s (%s)\n",
+ description, asbd->mSampleRate, asbd->mBitsPerChannel, format,
+ asbd->mFormatFlags, asbd->mBytesPerPacket, asbd->mFramesPerPacket,
+ asbd->mBytesPerFrame, asbd->mChannelsPerFrame,
+ (flags & kAudioFormatFlagIsFloat) ? "float" : "int",
+ (flags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE",
+ (flags & kAudioFormatFlagIsSignedInteger) ? "S" : "U",
+ (flags & kAudioFormatFlagIsPacked) ? " packed" : "",
+ (flags & kAudioFormatFlagIsAlignedHigh) ? " aligned" : "",
+ (flags & kAudioFormatFlagIsNonInterleaved) ? " P" : "",
+ mpfmt ? af_fmt_to_str(mpfmt) : "-");
}
// Return whether new is an improvement over old. Assume a higher value means
diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c
index 412e91d626..bd1a19e67a 100644
--- a/audio/out/ao_jack.c
+++ b/audio/out/ao_jack.c
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "config.h"
#include "common/msg.h"
@@ -125,7 +124,7 @@ static int process(jack_nframes_t nframes, void *arg)
int64_t end_time = mp_time_ns();
end_time += MP_TIME_S_TO_NS((jack_latency + nframes) / (double)ao->samplerate);
- ao_read_data(ao, buffers, nframes, end_time);
+ ao_read_data(ao, buffers, nframes, end_time, NULL, true, true);
return 0;
}
diff --git a/audio/out/ao_opensles.c b/audio/out/ao_opensles.c
index ddcff1904a..6d4b6a78db 100644
--- a/audio/out/ao_opensles.c
+++ b/audio/out/ao_opensles.c
@@ -81,7 +81,7 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
delay = p->frames_per_enqueue / (double)ao->samplerate;
delay += p->audio_latency;
ao_read_data(ao, &p->buf, p->frames_per_enqueue,
- mp_time_ns() + MP_TIME_S_TO_NS(delay));
+ mp_time_ns() + MP_TIME_S_TO_NS(delay), NULL, true, true);
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->bytes_per_enqueue);
if (res != SL_RESULT_SUCCESS)
diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c
index afe5839dd5..31e4700b40 100644
--- a/audio/out/ao_oss.c
+++ b/audio/out/ao_oss.c
@@ -25,7 +25,6 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
-#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
@@ -328,7 +327,7 @@ static bool audio_write(struct ao *ao, void **data, int samples)
while ((rc = write(p->dsp_fd, data[0], size)) == -1) {
if (errno == EINTR)
- continue;
+ continue;
MP_WARN(ao, "audio_write: write() fail, err = %i: %s.\n",
errno, mp_strerror(errno));
return false;
diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c
index 4097aa3bd6..71650c39e3 100644
--- a/audio/out/ao_pcm.c
+++ b/audio/out/ao_pcm.c
@@ -86,7 +86,7 @@ static void write_wave_header(struct ao *ao, FILE *fp, uint64_t data_length)
fput16le(WAV_ID_FORMAT_EXTENSIBLE, fp);
fput16le(ao->channels.num, fp);
fput32le(ao->samplerate, fp);
- fput32le(ao->bps, fp);
+ fput32le(MPCLAMP(ao->bps, 0, UINT32_MAX), fp);
fput16le(ao->channels.num * (bits / 8), fp);
fput16le(bits, fp);
@@ -145,7 +145,7 @@ static int init(struct ao *ao)
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
return -1;
- ao->bps = ao->channels.num * ao->samplerate * af_fmt_to_bytes(ao->format);
+ ao->bps = ao->channels.num * (int64_t)ao->samplerate * af_fmt_to_bytes(ao->format);
MP_INFO(ao, "File: %s (%s)\nPCM: Samplerate: %d Hz Channels: %d Format: %s\n",
outputfilename,
diff --git a/audio/out/ao_pipewire.c b/audio/out/ao_pipewire.c
index 94d393a26d..a04ae9d3d0 100644
--- a/audio/out/ao_pipewire.c
+++ b/audio/out/ao_pipewire.c
@@ -38,7 +38,7 @@
#if !PW_CHECK_VERSION(0, 3, 50)
static inline int pw_stream_get_time_n(struct pw_stream *stream, struct pw_time *time, size_t size) {
- return pw_stream_get_time(stream, time);
+ return pw_stream_get_time(stream, time);
}
#endif
@@ -206,7 +206,7 @@ static void on_process(void *userdata)
#endif
end_time -= pw_stream_get_nsec(p->stream) - time.now;
- int samples = ao_read_data_nonblocking(ao, data, nframes, end_time);
+ int samples = ao_read_data(ao, data, nframes, end_time, NULL, false, false);
b->size = samples;
for (int i = 0; i < buf->n_datas; i++) {
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index 5c86855d71..95a7fb0ea8 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -209,25 +209,25 @@ static pa_encoding_t map_digital_format(int format)
}
static const int speaker_map[][2] = {
- {PA_CHANNEL_POSITION_FRONT_LEFT, MP_SPEAKER_ID_FL},
- {PA_CHANNEL_POSITION_FRONT_RIGHT, MP_SPEAKER_ID_FR},
- {PA_CHANNEL_POSITION_FRONT_CENTER, MP_SPEAKER_ID_FC},
- {PA_CHANNEL_POSITION_REAR_CENTER, MP_SPEAKER_ID_BC},
- {PA_CHANNEL_POSITION_REAR_LEFT, MP_SPEAKER_ID_BL},
- {PA_CHANNEL_POSITION_REAR_RIGHT, MP_SPEAKER_ID_BR},
- {PA_CHANNEL_POSITION_LFE, MP_SPEAKER_ID_LFE},
- {PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, MP_SPEAKER_ID_FLC},
- {PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, MP_SPEAKER_ID_FRC},
- {PA_CHANNEL_POSITION_SIDE_LEFT, MP_SPEAKER_ID_SL},
- {PA_CHANNEL_POSITION_SIDE_RIGHT, MP_SPEAKER_ID_SR},
- {PA_CHANNEL_POSITION_TOP_CENTER, MP_SPEAKER_ID_TC},
- {PA_CHANNEL_POSITION_TOP_FRONT_LEFT, MP_SPEAKER_ID_TFL},
- {PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, MP_SPEAKER_ID_TFR},
- {PA_CHANNEL_POSITION_TOP_FRONT_CENTER, MP_SPEAKER_ID_TFC},
- {PA_CHANNEL_POSITION_TOP_REAR_LEFT, MP_SPEAKER_ID_TBL},
- {PA_CHANNEL_POSITION_TOP_REAR_RIGHT, MP_SPEAKER_ID_TBR},
- {PA_CHANNEL_POSITION_TOP_REAR_CENTER, MP_SPEAKER_ID_TBC},
- {PA_CHANNEL_POSITION_INVALID, -1}
+ {PA_CHANNEL_POSITION_FRONT_LEFT, MP_SPEAKER_ID_FL},
+ {PA_CHANNEL_POSITION_FRONT_RIGHT, MP_SPEAKER_ID_FR},
+ {PA_CHANNEL_POSITION_FRONT_CENTER, MP_SPEAKER_ID_FC},
+ {PA_CHANNEL_POSITION_REAR_CENTER, MP_SPEAKER_ID_BC},
+ {PA_CHANNEL_POSITION_REAR_LEFT, MP_SPEAKER_ID_BL},
+ {PA_CHANNEL_POSITION_REAR_RIGHT, MP_SPEAKER_ID_BR},
+ {PA_CHANNEL_POSITION_LFE, MP_SPEAKER_ID_LFE},
+ {PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, MP_SPEAKER_ID_FLC},
+ {PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, MP_SPEAKER_ID_FRC},
+ {PA_CHANNEL_POSITION_SIDE_LEFT, MP_SPEAKER_ID_SL},
+ {PA_CHANNEL_POSITION_SIDE_RIGHT, MP_SPEAKER_ID_SR},
+ {PA_CHANNEL_POSITION_TOP_CENTER, MP_SPEAKER_ID_TC},
+ {PA_CHANNEL_POSITION_TOP_FRONT_LEFT, MP_SPEAKER_ID_TFL},
+ {PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, MP_SPEAKER_ID_TFR},
+ {PA_CHANNEL_POSITION_TOP_FRONT_CENTER, MP_SPEAKER_ID_TFC},
+ {PA_CHANNEL_POSITION_TOP_REAR_LEFT, MP_SPEAKER_ID_TBL},
+ {PA_CHANNEL_POSITION_TOP_REAR_RIGHT, MP_SPEAKER_ID_TBR},
+ {PA_CHANNEL_POSITION_TOP_REAR_CENTER, MP_SPEAKER_ID_TBC},
+ {PA_CHANNEL_POSITION_INVALID, -1}
};
static bool chmap_pa_from_mp(pa_channel_map *dst, struct mp_chmap *src)
diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c
index 5a6a58b124..5fa8ebbd56 100644
--- a/audio/out/ao_sdl.c
+++ b/audio/out/ao_sdl.c
@@ -61,7 +61,7 @@ static void audio_callback(void *userdata, Uint8 *stream, int len)
// fixed latency.
double delay = 2 * len / (double)ao->bps;
- ao_read_data(ao, data, len / ao->sstride, mp_time_ns() + MP_TIME_S_TO_NS(delay));
+ ao_read_data(ao, data, len / ao->sstride, mp_time_ns() + MP_TIME_S_TO_NS(delay), NULL, true, true);
}
static void uninit(struct ao *ao)
diff --git a/audio/out/ao_wasapi_changenotify.c b/audio/out/ao_wasapi_changenotify.c
index f0e1895305..7f1c16794f 100644
--- a/audio/out/ao_wasapi_changenotify.c
+++ b/audio/out/ao_wasapi_changenotify.c
@@ -155,6 +155,11 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDefaultDeviceChanged(
return S_OK;
}
+// IsEqualIID in Windows SDK passes GUID as REFGUID (reference) in C++, but in
+// C is has to get pointers...
+#undef IsEqualPropertyKey
+#define IsEqualPropertyKey(a, b) (((a).pid == (b).pid) && IsEqualIID(&(a).fmtid, &(b).fmtid))
+
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnPropertyValueChanged(
IMMNotificationClient *This,
LPCWSTR pwstrDeviceId,
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index 2614872b91..7d4c536e78 100644
--- a/