aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-11-22 22:50:29 +0100
committerMax Kellermann <max@duempel.org>2013-11-22 23:27:56 +0100
commitfc7d5b055d98306af0c882282902a23e963f026d (patch)
treebe38c99eef3be2c4acfcbba4077842b7c17b738d
parent87c8953e8ed660b59ea2452b4d3a431785c47495 (diff)
downloadmpd-fc7d5b055d98306af0c882282902a23e963f026d.tar.gz
mpd-fc7d5b055d98306af0c882282902a23e963f026d.tar.xz
mpd-fc7d5b055d98306af0c882282902a23e963f026d.zip
PcmResampleLibsamplerate: clip 24 bit data
Using pcm_resample_lsr_32() for 24 bit samples works, but may cause 24 bit overflows. This commit makes 24 bit a special case with explicit clipping.
-rw-r--r--NEWS1
-rw-r--r--src/pcm/PcmResample.cxx15
-rw-r--r--src/pcm/PcmResampleInternal.hxx9
-rw-r--r--src/pcm/PcmResampleLibsamplerate.cxx25
4 files changed, 48 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 45b0ef242..51a0437ed 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ ver 0.18.5 (20??/??/??)
- proxy: provide "db_update" in "stats" response
* decoder
- fluidsynth: auto-detect by default
+* clip 24 bit data from libsamplerate
* fix ia64, mipsel and other little-endian architectures
* fix build failures due to missing includes
* fix build failure with static libmpdclient
diff --git a/src/pcm/PcmResample.cxx b/src/pcm/PcmResample.cxx
index df37826ba..01f269ea9 100644
--- a/src/pcm/PcmResample.cxx
+++ b/src/pcm/PcmResample.cxx
@@ -155,8 +155,19 @@ PcmResampler::Resample24(unsigned channels, unsigned src_rate,
unsigned dest_rate, size_t *dest_size_r,
Error &error_r)
{
+#ifdef HAVE_LIBSAMPLERATE
+ if (pcm_resample_lsr_enabled())
+ return pcm_resample_lsr_24(this, channels,
+ src_rate, src_buffer, src_size,
+ dest_rate, dest_size_r,
+ error_r);
+#else
+ (void)error_r;
+#endif
+
/* reuse the 32 bit code - the resampler code doesn't care if
the upper 8 bits are actually used */
- return Resample32(channels, src_rate, src_buffer, src_size,
- dest_rate, dest_size_r, error_r);
+ return pcm_resample_fallback_32(this, channels,
+ src_rate, src_buffer, src_size,
+ dest_rate, dest_size_r);
}
diff --git a/src/pcm/PcmResampleInternal.hxx b/src/pcm/PcmResampleInternal.hxx
index 59bb2f5df..5090c13d1 100644
--- a/src/pcm/PcmResampleInternal.hxx
+++ b/src/pcm/PcmResampleInternal.hxx
@@ -69,6 +69,15 @@ pcm_resample_lsr_32(PcmResampler *state,
unsigned dest_rate, size_t *dest_size_r,
Error &error);
+const int32_t *
+pcm_resample_lsr_24(PcmResampler *state,
+ unsigned channels,
+ unsigned src_rate,
+ const int32_t *src_buffer,
+ size_t src_size,
+ unsigned dest_rate, size_t *dest_size_r,
+ Error &error);
+
#endif
const int16_t *
diff --git a/src/pcm/PcmResampleLibsamplerate.cxx b/src/pcm/PcmResampleLibsamplerate.cxx
index 1986e8821..9eac2d545 100644
--- a/src/pcm/PcmResampleLibsamplerate.cxx
+++ b/src/pcm/PcmResampleLibsamplerate.cxx
@@ -19,6 +19,7 @@
#include "config.h"
#include "PcmResampleInternal.hxx"
+#include "PcmUtils.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -283,3 +284,27 @@ pcm_resample_lsr_32(PcmResampler *state,
return dest_buffer;
}
+
+const int32_t *
+pcm_resample_lsr_24(PcmResampler *state,
+ unsigned channels,
+ unsigned src_rate,
+ const int32_t *src_buffer, size_t src_size,
+ unsigned dest_rate, size_t *dest_size_r,
+ Error &error)
+{
+ const auto result = pcm_resample_lsr_32(state, channels,
+ src_rate, src_buffer, src_size,
+ dest_rate, dest_size_r,
+ error);
+ if (result != nullptr)
+ /* src_float_to_int_array() clamps for 32 bit
+ integers; now make sure everything's fine for 24
+ bit */
+ /* TODO: eliminate the 32 bit clamp to reduce overhead */
+ PcmClampN<int32_t, int32_t, 24>(const_cast<int32_t *>(result),
+ result,
+ *dest_size_r / sizeof(*result));
+
+ return result;
+}