From 135842803156ab3d983babb61d22905a43977be3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 19 Nov 2009 21:00:50 +0100 Subject: [PATCH] pcm_volume: implemented 32 bit support Support 32 bit samples with software mixer. --- NEWS | 1 + src/pcm_utils.h | 14 ++++++++++++++ src/pcm_volume.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/NEWS b/NEWS index 4986ca300..2afda2f99 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,7 @@ ver 0.16 (20??/??/??) * database: eliminated maximum line length * log: redirect stdout/stderr to /dev/null if syslog is used * set the close-on-exec flag on all file descriptors +* pcm_volume: implemented 32 bit support * obey $(sysconfdir) for default mpd.conf location * build with large file support by default * require GLib 2.12 diff --git a/src/pcm_utils.h b/src/pcm_utils.h index 93f414231..8b2259655 100644 --- a/src/pcm_utils.h +++ b/src/pcm_utils.h @@ -38,4 +38,18 @@ pcm_range(int32_t sample, unsigned bits) return sample; } +/** + * Check if the value is within the range of the provided bit size, + * and caps it if necessary. + */ +static inline int64_t +pcm_range_64(int64_t sample, unsigned bits) +{ + if (G_UNLIKELY(sample < ((int64_t)-1 << (bits - 1)))) + return (int64_t)-1 << (bits - 1); + if (G_UNLIKELY(sample >= ((int64_t)1 << (bits - 1)))) + return ((int64_t)1 << (bits - 1)) - 1; + return sample; +} + #endif diff --git a/src/pcm_volume.c b/src/pcm_volume.c index ca720a30e..90ad17d6d 100644 --- a/src/pcm_volume.c +++ b/src/pcm_volume.c @@ -114,6 +114,29 @@ pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume) } } +static void +pcm_volume_change_32(int32_t *buffer, unsigned num_samples, int volume) +{ + while (num_samples > 0) { +#ifdef __i386__ + /* assembly version for i386 */ + int32_t sample = *buffer; + + *buffer++ = pcm_volume_sample_24(sample, volume, 0); +#else + /* portable version */ + int64_t sample = *buffer; + + sample = (sample * volume + pcm_volume_dither() + + PCM_VOLUME_1 / 2) + / PCM_VOLUME_1; + *buffer++ = pcm_range_64(sample, 32); +#endif + + --num_samples; + } +} + bool pcm_volume(void *buffer, int length, const struct audio_format *format, @@ -142,6 +165,11 @@ pcm_volume(void *buffer, int length, volume); return true; + case 32: + pcm_volume_change_32((int32_t*)buffer, length / 4, + volume); + return true; + default: return false; }