diff options
author | Max Kellermann <max@duempel.org> | 2009-11-19 21:00:50 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-11-19 21:00:50 +0100 |
commit | 135842803156ab3d983babb61d22905a43977be3 (patch) | |
tree | 4087984407caa2361118950238fa8672dce94aa1 /src | |
parent | 5a480137d2c724c8a3359c66a9120e310ea19cd1 (diff) | |
download | mpd-135842803156ab3d983babb61d22905a43977be3.tar.gz mpd-135842803156ab3d983babb61d22905a43977be3.tar.xz mpd-135842803156ab3d983babb61d22905a43977be3.zip |
pcm_volume: implemented 32 bit support
Support 32 bit samples with software mixer.
Diffstat (limited to 'src')
-rw-r--r-- | src/pcm_utils.h | 14 | ||||
-rw-r--r-- | src/pcm_volume.c | 28 |
2 files changed, 42 insertions, 0 deletions
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; } |