diff options
author | Max Kellermann <max@duempel.org> | 2013-12-22 17:39:26 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-12-28 18:30:24 +0100 |
commit | afcf0795c44260f54e74ec854297de439e7562c3 (patch) | |
tree | f4ec95c5d889d81ec840f83f105a03625f663cb6 /src/pcm/Volume.cxx | |
parent | 394e2815dbaf0edb8d0f34b6ceab96b58f071ea8 (diff) | |
download | mpd-afcf0795c44260f54e74ec854297de439e7562c3.tar.gz mpd-afcf0795c44260f54e74ec854297de439e7562c3.tar.xz mpd-afcf0795c44260f54e74ec854297de439e7562c3.zip |
pcm/Volume: improved dithering
Instead of just adding a rectangular random value before shifting back
to the normal scale, use the existing PcmDither library.
Diffstat (limited to 'src/pcm/Volume.cxx')
-rw-r--r-- | src/pcm/Volume.cxx | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/src/pcm/Volume.cxx b/src/pcm/Volume.cxx index 0ccfe03b5..6347657c6 100644 --- a/src/pcm/Volume.cxx +++ b/src/pcm/Volume.cxx @@ -25,62 +25,69 @@ #include "util/ConstBuffer.hxx" #include "util/Error.hxx" +#include "PcmDither.cxx" // including the .cxx file to get inlined templates + #include <stdint.h> #include <string.h> template<SampleFormat F, class Traits=SampleTraits<F>> static inline typename Traits::value_type -pcm_volume_sample(typename Traits::value_type _sample, +pcm_volume_sample(PcmDither &dither, + typename Traits::value_type _sample, int volume) { typename Traits::long_type sample(_sample); - sample = (sample * volume + pcm_volume_dither() + - PCM_VOLUME_1S / 2) - >> PCM_VOLUME_BITS; - - return PcmClamp<F, Traits>(sample); + return dither.DitherShift<typename Traits::long_type, + Traits::BITS + PCM_VOLUME_BITS, + Traits::BITS>(sample * volume); } template<SampleFormat F, class Traits=SampleTraits<F>> static void -pcm_volume_change(typename Traits::pointer_type dest, +pcm_volume_change(PcmDither &dither, + typename Traits::pointer_type dest, typename Traits::const_pointer_type src, typename Traits::const_pointer_type end, int volume) { while (src < end) { const auto sample = *src++; - *dest++ = pcm_volume_sample<F, Traits>(sample, volume); + *dest++ = pcm_volume_sample<F, Traits>(dither, sample, volume); } } static void -pcm_volume_change_8(int8_t *dest, const int8_t *src, const int8_t *end, +pcm_volume_change_8(PcmDither &dither, + int8_t *dest, const int8_t *src, const int8_t *end, int volume) { - pcm_volume_change<SampleFormat::S8>(dest, src, end, volume); + pcm_volume_change<SampleFormat::S8>(dither, dest, src, end, volume); } static void -pcm_volume_change_16(int16_t *dest, const int16_t *src, const int16_t *end, +pcm_volume_change_16(PcmDither &dither, + int16_t *dest, const int16_t *src, const int16_t *end, int volume) { - pcm_volume_change<SampleFormat::S16>(dest, src, end, volume); + pcm_volume_change<SampleFormat::S16>(dither, dest, src, end, volume); } static void -pcm_volume_change_24(int32_t *dest, const int32_t *src, const int32_t *end, +pcm_volume_change_24(PcmDither &dither, + int32_t *dest, const int32_t *src, const int32_t *end, int volume) { - pcm_volume_change<SampleFormat::S24_P32>(dest, src, end, volume); + pcm_volume_change<SampleFormat::S24_P32>(dither, dest, src, end, + volume); } static void -pcm_volume_change_32(int32_t *dest, const int32_t *src, const int32_t *end, +pcm_volume_change_32(PcmDither &dither, + int32_t *dest, const int32_t *src, const int32_t *end, int volume) { - pcm_volume_change<SampleFormat::S32>(dest, src, end, volume); + pcm_volume_change<SampleFormat::S32>(dither, dest, src, end, volume); } static void @@ -143,28 +150,28 @@ PcmVolume::Apply(ConstBuffer<void> src) gcc_unreachable(); case SampleFormat::S8: - pcm_volume_change_8((int8_t *)data, + pcm_volume_change_8(dither, (int8_t *)data, (const int8_t *)src.data, (const int8_t *)end, volume); break; case SampleFormat::S16: - pcm_volume_change_16((int16_t *)data, + pcm_volume_change_16(dither, (int16_t *)data, (const int16_t *)src.data, (const int16_t *)end, volume); break; case SampleFormat::S24_P32: - pcm_volume_change_24((int32_t *)data, + pcm_volume_change_24(dither, (int32_t *)data, (const int32_t *)src.data, (const int32_t *)end, volume); break; case SampleFormat::S32: - pcm_volume_change_32((int32_t *)data, + pcm_volume_change_32(dither, (int32_t *)data, (const int32_t *)src.data, (const int32_t *)end, volume); |