diff options
author | Alex Marsev <alex.marsev@gmail.com> | 2015-08-01 16:04:22 +0300 |
---|---|---|
committer | Alex Marsev <alex.marsev@gmail.com> | 2015-08-02 20:21:32 +0300 |
commit | 9f3776d2506a512ea24774c4e7d3bee273cf90b6 (patch) | |
tree | 0802291a93cea87c004536b8acab42d3efc32510 | |
parent | d9c9e286678a9d17654ffe5ccc29d0547ff82ca1 (diff) |
Fix DspDither
It's used in ->PCM16 downsampling. Error feedback coefficients were
wrong and it was causing audible noise. Also switch to TPDF dither while at it.
-rwxr-xr-x[-rw-r--r--] | src/DspDither.cpp | 23 | ||||
-rwxr-xr-x[-rw-r--r--] | src/DspDither.h | 6 |
2 files changed, 18 insertions, 11 deletions
diff --git a/src/DspDither.cpp b/src/DspDither.cpp index c0c91a5..c8682b0 100644..100755 --- a/src/DspDither.cpp +++ b/src/DspDither.cpp @@ -6,8 +6,13 @@ namespace SaneAudioRenderer void DspDither::Initialize(DspFormat outputFormat)
{
m_active = (outputFormat == DspFormat::Pcm16);
- m_error1 = {};
- m_error2 = {};
+
+ for (size_t i = 0; i < 18; i++)
+ {
+ m_previous[i] = 0.0f;
+ m_generator[i].seed((uint32_t)(GetPerformanceCounter() + i));
+ m_distributor[i] = std::uniform_real_distribution<float>(0, 1.0f);
+ }
}
bool DspDither::Active()
@@ -32,12 +37,14 @@ namespace SaneAudioRenderer {
for (size_t channel = 0; channel < channels; channel++)
{
- // Rectangular dither with simple second-order noise shaping.
- float inputSample = inputData[frame * channels + channel] * (INT16_MAX - 4);
- float noise = (float)m_rand() / m_rand.max() + 0.5f * m_error1[channel] - m_error2[channel];
- float outputSample = round(inputSample + noise);
- m_error2[channel] = m_error1[channel];
- m_error1[channel] = outputSample - inputSample;
+ float inputSample = inputData[frame * channels + channel] * (INT16_MAX - 1);
+
+ // High-pass TPDF, 2 LSB amplitude.
+ float r = m_distributor[channel](m_generator[channel]);
+ float noise = r - m_previous[channel];
+ m_previous[channel] = r;
+
+ float outputSample = std::round(inputSample + noise);
assert(outputSample >= INT16_MIN && outputSample <= INT16_MAX);
outputData[frame * channels + channel] = (int16_t)outputSample;
}
diff --git a/src/DspDither.h b/src/DspDither.h index b41c37e..6fe5422 100644..100755 --- a/src/DspDither.h +++ b/src/DspDither.h @@ -25,8 +25,8 @@ namespace SaneAudioRenderer private:
bool m_active = false;
- std::array<float, 18> m_error1;
- std::array<float, 18> m_error2;
- std::minstd_rand m_rand;
+ std::array<float, 18> m_previous;
+ std::array<std::minstd_rand, 18> m_generator;
+ std::array<std::uniform_real_distribution<float>, 18> m_distributor;
};
}
|