Audacity 3.2.0
Dither.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Dither.cpp
6
7 Steve Harris
8 Markus Meyer
9
10*******************************************************************//*******************************************************************/
36
37
38#include "Dither.h"
39
40#include "Internat.h"
41#include "Prefs.h"
42
43// Erik de Castro Lopo's header file that
44// makes sure that we have lrint and lrintf
45// (Note: this file should be included first)
46#include "float_cast.h"
47
48#include <stdlib.h>
49#include <math.h>
50#include <string.h>
51//#include <sys/types.h>
52//#include <memory.h>
53//#include <assert.h>
54
55#include <wx/defs.h>
56
58
59// Constants for the noise shaping buffer
60constexpr int BUF_SIZE = 8;
61constexpr int BUF_MASK = 7;
62
63// Lipshitz's minimally audible FIR
64const float SHAPED_BS[] = { 2.033f, -2.165f, 1.959f, -1.590f, 0.6149f };
65
66// Dither state
67struct State {
68 int mPhase;
70 float mBuffer[8 /* = BUF_SIZE */];
72
73using Ditherer = float (*)(State &, float);
74
75// This is supposed to produce white noise and no dc
76static inline float DITHER_NOISE()
77{
78 return rand() / (float)RAND_MAX - 0.5f;
79}
80
81// Defines for sample conversion
82constexpr auto CONVERT_DIV16 = float(1<<15);
83constexpr auto CONVERT_DIV24 = float(1<<23);
84
85// Dereference sample pointer and convert to float sample
86static inline float FROM_INT16(const short *ptr)
87{
88 return *ptr / CONVERT_DIV16;
89}
90
91static inline float FROM_INT24(const int *ptr)
92{
93 return *ptr / CONVERT_DIV24;
94}
95
96// For float, we internally allow values greater than 1.0, which
97// would blow up the dithering to int values. FROM_FLOAT is
98// only used to dither to int, so clip here.
99static inline float FROM_FLOAT(const float *ptr)
100{
101 return *((float*)(ptr)) > 1.0
102 ? 1.0 :
103 *((float*)(ptr)) < -1.0
104 ? -1.0 :
105 *((float*)(ptr));
106}
107
108// Store float sample 'sample' into pointer 'ptr', clip it, if necessary
109template<typename dst_type>
110static inline void IMPLEMENT_STORE(
111 dst_type *ptr, float sample, dst_type min_bound, dst_type max_bound)
112{
113 int x = lrintf(sample);
114 if (x > max_bound)
115 *ptr = max_bound;
116 else if (x<(min_bound))
117 *ptr = min_bound;
118 else
119 *ptr = static_cast<dst_type>(x);
120}
121
122// Dither single float 'sample' and store it in pointer 'dst', using 'dither' as algorithm
123static inline void DITHER_TO_INT16(Ditherer dither, State &state,
124 short *dst, float sample)
125{
126 IMPLEMENT_STORE<short>(dst,
127 dither(state, sample * CONVERT_DIV16),
128 short(-32768), short(32767));
129}
130
131// Dither single float 'sample' and store it in pointer 'dst', using 'dither' as algorithm
132static inline void DITHER_TO_INT24(Ditherer dither, State &state,
133 int *dst, float sample)
134{
135 IMPLEMENT_STORE<int>(dst,
136 dither(state, sample * CONVERT_DIV24), -8388608, 8388607);
137}
138
139// Implement one single dither step
140
141// Implement a dithering loop
142template<typename srcType, typename dstType>
143static inline void DITHER_LOOP( Ditherer dither, State &state,
144 void (*store)(Ditherer, State &, dstType *, float),
145 float (*load)(const srcType *),
146 samplePtr dst, sampleFormat dstFormat, size_t dstStride,
147 constSamplePtr src, sampleFormat srcFormat, size_t srcStride, size_t len)
148{
149 char *d;
150 const char *s;
151 unsigned int ii;
152 for (d = (char*)dst, s = (char*)src, ii = 0;
153 ii < len;
154 ii++, d += SAMPLE_SIZE(dstFormat) * dstStride,
155 s += SAMPLE_SIZE(srcFormat) * srcStride) {
156 store(dither, state, reinterpret_cast<dstType *>(d), load(reinterpret_cast<const srcType *>(s)));
157 }
158}
159
160// Implement a dither. There are only 3 cases where we must dither,
161// in all other cases, no dithering is necessary.
162static inline void DITHER( Ditherer dither, State &state,
163 samplePtr dst, sampleFormat dstFormat, size_t dstStride,
164 constSamplePtr src, sampleFormat srcFormat, size_t srcStride, size_t len)
165{
166 if (srcFormat == int24Sample && dstFormat == int16Sample)
167 DITHER_LOOP<int, short>(dither, state,
169 int16Sample, dstStride, src, int24Sample, srcStride, len);
170 else if (srcFormat == floatSample && dstFormat == int16Sample)
171 DITHER_LOOP<float, short>(dither, state,
173 int16Sample, dstStride, src, floatSample, srcStride, len);
174 else if (srcFormat == floatSample && dstFormat == int24Sample)
175 DITHER_LOOP<float, int>(dither, state,
177 int24Sample, dstStride, src, floatSample, srcStride, len);
178 else { wxASSERT(false); }
179}
180
181
182static inline float NoDither(State &, float sample);
183static inline float RectangleDither(State &, float sample);
184static inline float TriangleDither(State &state, float sample);
185static inline float ShapedDither(State &state, float sample);
186
188{
189 // On startup, initialize dither by resetting values
190 Reset();
191}
192
194{
196 mState.mPhase = 0;
197 memset(mState.mBuffer, 0, sizeof(float) * BUF_SIZE);
198}
199
200// This only decides if we must dither at all, the dithers
201// are all implemented using macros.
202//
203// "source" and "dest" can contain either interleaved or non-interleaved
204// samples. They do not have to be the same...one can be interleaved while
205// the otner non-interleaved.
206//
207// The "len" argument specifies the number of samples to process.
208//
209// If either stride value equals 1 then the corresponding buffer contains
210// non-interleaved samples.
211//
212// If either stride value is greater than 1 then the corresponding buffer
213// contains interleaved samples and they will be processed by skipping every
214// stride number of samples.
215
216void Dither::Apply(enum DitherType ditherType,
217 constSamplePtr source, sampleFormat sourceFormat,
218 samplePtr dest, sampleFormat destFormat,
219 unsigned int len,
220 unsigned int sourceStride /* = 1 */,
221 unsigned int destStride /* = 1 */)
222{
223 unsigned int i;
224
225 // This code is not designed for 16-bit or 64-bit machine
226 wxASSERT(sizeof(int) == 4);
227 wxASSERT(sizeof(short) == 2);
228
229 // Check parameters
230 wxASSERT(source);
231 wxASSERT(dest);
232 wxASSERT(len >= 0);
233 wxASSERT(sourceStride > 0);
234 wxASSERT(destStride > 0);
235
236 if (len == 0)
237 return; // nothing to do
238
239 if (destFormat == sourceFormat)
240 {
241 // No need to dither, because source and destination
242 // format are the same. Just copy samples.
243 if (destStride == 1 && sourceStride == 1)
244 memcpy(dest, source, len * SAMPLE_SIZE(destFormat));
245 else
246 {
247 if (sourceFormat == floatSample)
248 {
249 auto d = (float*)dest;
250 auto s = (const float*)source;
251
252 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
253 *d = *s;
254 } else
255 if (sourceFormat == int24Sample)
256 {
257 auto d = (int*)dest;
258 auto s = (const int*)source;
259
260 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
261 *d = *s;
262 } else
263 if (sourceFormat == int16Sample)
264 {
265 auto d = (short*)dest;
266 auto s = (const short*)source;
267
268 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
269 *d = *s;
270 } else {
271 wxASSERT(false); // source format unknown
272 }
273 }
274 } else
275 if (destFormat == floatSample)
276 {
277 // No need to dither, just convert samples to float.
278 // No clipping should be necessary.
279 auto d = (float*)dest;
280
281 if (sourceFormat == int16Sample)
282 {
283 auto s = (const short*)source;
284 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
285 *d = FROM_INT16(s);
286 } else
287 if (sourceFormat == int24Sample)
288 {
289 auto s = (const int*)source;
290 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
291 *d = FROM_INT24(s);
292 } else {
293 wxASSERT(false); // source format unknown
294 }
295 } else
296 if (destFormat == int24Sample && sourceFormat == int16Sample)
297 {
298 // Special case when promoting 16 bit to 24 bit
299 auto d = (int*)dest;
300 auto s = (const short*)source;
301 for (i = 0; i < len; i++, d += destStride, s += sourceStride)
302 *d = ((int)*s) << 8;
303 } else
304 {
305 // We must do dithering
306 switch (ditherType)
307 {
308 case DitherType::none:
309 DITHER(NoDither, mState, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
310 break;
312 DITHER(RectangleDither, mState, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
313 break;
315 Reset(); // reset dither filter for this NEW conversion
316 DITHER(TriangleDither, mState, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
317 break;
319 Reset(); // reset dither filter for this NEW conversion
320 DITHER(ShapedDither, mState, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
321 break;
322 default:
323 wxASSERT(false); // unknown dither algorithm
324 }
325 }
326}
327
328// Dither implementations
329
330// No dither, just return sample
331inline float NoDither(State &, float sample)
332{
333 return sample;
334}
335
336// Rectangle dithering, apply one-step noise
337inline float RectangleDither(State &, float sample)
338{
339 return sample - DITHER_NOISE();
340}
341
342// Triangle dither - high pass filtered
343inline float TriangleDither(State &state, float sample)
344{
345 float r = DITHER_NOISE();
346 float result = sample + r - state.mTriangleState;
347 state.mTriangleState = r;
348
349 return result;
350}
351
352// Shaped dither
353inline float ShapedDither(State &state, float sample)
354{
355 // Generate triangular dither, +-1 LSB, flat psd
356 float r = DITHER_NOISE() + DITHER_NOISE();
357 if(sample != sample) // test for NaN
358 sample = 0; // and do the best we can with it
359
360 // Run FIR
361 float xe = sample + state.mBuffer[state.mPhase] * SHAPED_BS[0]
362 + state.mBuffer[(state.mPhase - 1) & BUF_MASK] * SHAPED_BS[1]
363 + state.mBuffer[(state.mPhase - 2) & BUF_MASK] * SHAPED_BS[2]
364 + state.mBuffer[(state.mPhase - 3) & BUF_MASK] * SHAPED_BS[3]
365 + state.mBuffer[(state.mPhase - 4) & BUF_MASK] * SHAPED_BS[4];
366
367 // Accumulate FIR and triangular noise
368 float result = xe + r;
369
370 // Roll buffer and store last error
371 state.mPhase = (state.mPhase + 1) & BUF_MASK;
372 state.mBuffer[state.mPhase] = xe - lrintf(result);
373
374 return result;
375}
376
377static const std::initializer_list<EnumValueSymbol> choicesDither{
378 { XO("None") },
379 { XO("Rectangle") },
380 { XC("Triangle", "dither") },
381 { XO("Shaped") },
382};
383static auto intChoicesDither = {
388};
389
391 wxT("Quality/DitherAlgorithmChoice"),
393 0, // none
394
395 // for migrating old preferences:
397 wxT("Quality/DitherAlgorithm")
398};
399
401 wxT("Quality/HQDitherAlgorithmChoice"),
403 3, // shaped
404
405 // for migrating old preferences:
407 wxT("Quality/HQDitherAlgorithm")
408};
409
411{
413}
414
416{
418}
wxT("CloseDown"))
static void DITHER_TO_INT24(Ditherer dither, State &state, int *dst, float sample)
Definition: Dither.cpp:132
float(*)(State &, float) Ditherer
Definition: Dither.cpp:73
static float DITHER_NOISE()
Definition: Dither.cpp:76
static float FROM_INT24(const int *ptr)
Definition: Dither.cpp:91
static void DITHER_TO_INT16(Ditherer dither, State &state, short *dst, float sample)
Definition: Dither.cpp:123
const float SHAPED_BS[]
Definition: Dither.cpp:64
static const std::initializer_list< EnumValueSymbol > choicesDither
Definition: Dither.cpp:377
struct State mState
static void IMPLEMENT_STORE(dst_type *ptr, float sample, dst_type min_bound, dst_type max_bound)
Definition: Dither.cpp:110
static float FROM_INT16(const short *ptr)
Definition: Dither.cpp:86
static auto intChoicesDither
Definition: Dither.cpp:383
static void DITHER(Ditherer dither, State &state, samplePtr dst, sampleFormat dstFormat, size_t dstStride, constSamplePtr src, sampleFormat srcFormat, size_t srcStride, size_t len)
Definition: Dither.cpp:162
static float ShapedDither(State &state, float sample)
Definition: Dither.cpp:353
static void DITHER_LOOP(Ditherer dither, State &state, void(*store)(Ditherer, State &, dstType *, float), float(*load)(const srcType *), samplePtr dst, sampleFormat dstFormat, size_t dstStride, constSamplePtr src, sampleFormat srcFormat, size_t srcStride, size_t len)
Definition: Dither.cpp:143
constexpr int BUF_SIZE
Definition: Dither.cpp:60
constexpr int BUF_MASK
Definition: Dither.cpp:61
static float NoDither(State &, float sample)
Definition: Dither.cpp:331
static float TriangleDither(State &state, float sample)
Definition: Dither.cpp:343
static float FROM_FLOAT(const float *ptr)
Definition: Dither.cpp:99
constexpr auto CONVERT_DIV16
Definition: Dither.cpp:82
constexpr auto CONVERT_DIV24
Definition: Dither.cpp:83
static float RectangleDither(State &, float sample)
Definition: Dither.cpp:337
DitherType
These ditherers are currently available:
Definition: Dither.h:19
@ rectangle
Definition: Dither.h:20
@ shaped
Definition: Dither.h:20
@ triangle
Definition: Dither.h:20
@ none
Definition: Dither.h:20
XO("Cut/Copy/Paste")
#define XC(s, c)
Definition: Internat.h:37
constexpr sampleFormat int16Sample
Definition: SampleFormat.h:43
constexpr sampleFormat floatSample
Definition: SampleFormat.h:45
constexpr sampleFormat int24Sample
Definition: SampleFormat.h:44
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
char * samplePtr
Definition: SampleFormat.h:57
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52
const char * constSamplePtr
Definition: SampleFormat.h:58
static DitherType FastDitherChoice()
Definition: Dither.cpp:410
void Reset()
Reset state of the dither.
Definition: Dither.cpp:193
Dither()
Default constructor.
Definition: Dither.cpp:187
static EnumSetting< DitherType > BestSetting
Definition: Dither.h:29
static DitherType BestDitherChoice()
Definition: Dither.cpp:415
static EnumSetting< DitherType > FastSetting
Definition: Dither.h:28
void Apply(DitherType ditherType, constSamplePtr source, sampleFormat sourceFormat, samplePtr dest, sampleFormat destFormat, unsigned int len, unsigned int sourceStride=1, unsigned int destStride=1)
Definition: Dither.cpp:216
Enum ReadEnum() const
Definition: Prefs.h:534
#define lrintf(flt)
Definition: float_cast.h:170
Definition: Dither.cpp:67
float mTriangleState
Definition: Dither.cpp:69
int mPhase
Definition: Dither.cpp:68
float mBuffer[8]
Definition: Dither.cpp:70