From 3cb4116243e54b0452d88c70a7acd4af17cf8d02 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:05:51 +0100 Subject: ao: add ao_play_silence, use for ao_alsa and ao_oss Also add a corresponding function to audio/format.c, which fills an audio block with silence. --- audio/format.c | 6 ++++++ audio/format.h | 5 +++++ audio/out/ao.c | 12 ++++++++++++ audio/out/ao.h | 2 ++ audio/out/ao_alsa.c | 8 ++------ audio/out/ao_oss.c | 11 ++++------- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/audio/format.c b/audio/format.c index b933d07e16..448b670671 100644 --- a/audio/format.c +++ b/audio/format.c @@ -127,3 +127,9 @@ int af_str2fmt_short(bstr str) } return 0; } + +void af_fill_silence(void *dst, size_t bytes, int format) +{ + bool us = (format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_US; + memset(dst, us ? 0x80 : 0, bytes); +} diff --git a/audio/format.h b/audio/format.h index 3a80a601c5..95e792340c 100644 --- a/audio/format.h +++ b/audio/format.h @@ -134,6 +134,9 @@ enum af_format { (AF_FORMAT_IS_AC3(fmt) || \ ((fmt) & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_S_IEC61937) +#define AF_FORMAT_IS_SPECIAL(fmt) \ + ((fmt & AF_FORMAT_SPECIAL_MASK) != 0) + struct af_fmt_entry { const char *name; int format; @@ -152,4 +155,6 @@ int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int sampler bool af_fmt_is_valid(int format); +void af_fill_silence(void *dst, size_t bytes, int format); + #endif /* MPLAYER_AF_FORMAT_H */ diff --git a/audio/out/ao.c b/audio/out/ao.c index 88f0b2223d..55db34becb 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -250,6 +250,18 @@ void ao_resume(struct ao *ao) ao->driver->resume(ao); } +int ao_play_silence(struct ao *ao, int samples) +{ + if (samples <= 0 || AF_FORMAT_IS_SPECIAL(ao->format)) + return 0; + int s = ao->channels.num * (af_fmt2bits(ao->format) / 8); + char *p = talloc_size(NULL, samples * s); + af_fill_silence(p, samples * s, ao->format); + int r = ao_play(ao, p, samples * s, 0); + talloc_free(p); + return r; +} + bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map) { diff --git a/audio/out/ao.h b/audio/out/ao.h index c6ad5455d2..159a6adc0f 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -103,6 +103,8 @@ void ao_reset(struct ao *ao); void ao_pause(struct ao *ao); void ao_resume(struct ao *ao); +int ao_play_silence(struct ao *ao, int samples); + bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map); bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index bdfd8fae76..5816ee5f5f 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -78,7 +78,6 @@ struct priv { } while (0) static float get_delay(struct ao *ao); -static int play(struct ao *ao, void *data, int len, int flags); static void uninit(struct ao *ao, bool immed); static void alsa_error_handler(const char *file, int line, const char *function, @@ -612,11 +611,8 @@ static void audio_resume(struct ao *ao) MP_VERBOSE(ao, "resume not supported by hardware\n"); err = snd_pcm_prepare(p->alsa); CHECK_ALSA_ERROR("pcm prepare error"); - if (p->prepause_frames) { - void *silence = calloc(p->prepause_frames, p->bytes_per_sample); - play(ao, silence, p->prepause_frames * p->bytes_per_sample, 0); - free(silence); - } + if (p->prepause_frames) + ao_play_silence(ao, p->prepause_frames); } alsa_error: ; diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 556f3c25c9..db9847851d 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -508,16 +508,13 @@ static int play(struct ao *ao, void *data, int len, int flags) static void audio_resume(struct ao *ao) { struct priv *p = ao->priv; - int fillcnt; #ifndef SNDCTL_DSP_RESET reset(ao); #endif - fillcnt = get_space(ao) - p->prepause_space; - if (fillcnt > 0 && !(ao->format & AF_FORMAT_SPECIAL_MASK)) { - void *silence = calloc(fillcnt, 1); - play(ao, silence, fillcnt, 0); - free(silence); - } + int fillframes = (get_space(ao) - p->prepause_space) / + (af_fmt2bits(ao->format) / 8 * ao->channels.num); + if (fillframes > 0) + ao_play_silence(ao, fillframes); } // return: delay in seconds between first and last sample in buffer -- cgit v1.2.3