Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
Dither Class Reference

This class implements various functions for dithering and is derived from the dither code in the Ardour project, written by Steve Harris. More...

#include <Dither.h>

Collaboration diagram for Dither:
[legend]

Public Member Functions

 Dither ()
 Default constructor. More...
 
void Reset ()
 Reset state of the dither. More...
 
void Apply (DitherType ditherType, constSamplePtr source, sampleFormat sourceFormat, samplePtr dest, sampleFormat destFormat, unsigned int len, unsigned int sourceStride=1, unsigned int destStride=1)
 

Static Public Member Functions

static DitherType FastDitherChoice ()
 
static DitherType BestDitherChoice ()
 

Static Public Attributes

static EnumSetting< DitherTypeFastSetting
 
static EnumSetting< DitherTypeBestSetting
 

Detailed Description

This class implements various functions for dithering and is derived from the dither code in the Ardour project, written by Steve Harris.

Dithering is only done if it really is necessary. Otherwise (e.g. when the source and destination format of the samples is the same), the samples are only copied or converted. However, copied samples are always checked for out-of-bounds values and possibly clipped accordingly.

These dither algorithms are currently implemented:

Dither class. You must construct an instance because it keeps state. Call Dither::Apply() to apply the dither. You can call Reset() between subsequent dithers to reset the dither state and get deterministic behaviour.

Definition at line 22 of file Dither.h.

Constructor & Destructor Documentation

◆ Dither()

Dither::Dither ( )

Default constructor.

Definition at line 187 of file Dither.cpp.

188{
189 // On startup, initialize dither by resetting values
190 Reset();
191}
void Reset()
Reset state of the dither.
Definition: Dither.cpp:193

References Reset().

Here is the call graph for this function:

Member Function Documentation

◆ Apply()

void Dither::Apply ( DitherType  ditherType,
constSamplePtr  source,
sampleFormat  sourceFormat,
samplePtr  dest,
sampleFormat  destFormat,
unsigned int  len,
unsigned int  sourceStride = 1,
unsigned int  destStride = 1 
)

Apply the actual dithering. Expects the source sample in the 'source' variable, the destination sample in the 'dest' variable, and hints to the formats of the samples. Even if the sample formats are the same, samples are clipped, if necessary.

Definition at line 216 of file Dither.cpp.

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}
static float FROM_INT24(const int *ptr)
Definition: Dither.cpp:91
struct State mState
static float FROM_INT16(const short *ptr)
Definition: Dither.cpp:86
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 float NoDither(State &, float sample)
Definition: Dither.cpp:331
static float TriangleDither(State &state, float sample)
Definition: Dither.cpp:343
static float RectangleDither(State &, float sample)
Definition: Dither.cpp:337
@ rectangle
Definition: Dither.h:20
@ shaped
Definition: Dither.h:20
@ triangle
Definition: Dither.h:20
@ none
Definition: Dither.h:20
@ floatSample
Definition: SampleFormat.h:34
@ int16Sample
Definition: SampleFormat.h:32
@ int24Sample
Definition: SampleFormat.h:33
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44

References DITHER(), floatSample, FROM_INT16(), FROM_INT24(), int16Sample, int24Sample, mState, NoDither(), none, rectangle, RectangleDither(), Reset(), SAMPLE_SIZE, shaped, ShapedDither(), triangle, and TriangleDither().

Referenced by CopySamples().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ BestDitherChoice()

DitherType Dither::BestDitherChoice ( )
static

Definition at line 415 of file Dither.cpp.

416{
418}
DitherType
These ditherers are currently available:
Definition: Dither.h:19
static EnumSetting< DitherType > BestSetting
Definition: Dither.h:29
Enum ReadEnum() const
Definition: Prefs.h:524

References BestSetting, and EnumSetting< Enum >::ReadEnum().

Referenced by InitDitherers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FastDitherChoice()

DitherType Dither::FastDitherChoice ( )
static

Definition at line 410 of file Dither.cpp.

411{
413}
static EnumSetting< DitherType > FastSetting
Definition: Dither.h:28

References FastSetting, and EnumSetting< Enum >::ReadEnum().

Referenced by InitDitherers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Reset()

void Dither::Reset ( )

Reset state of the dither.

Definition at line 193 of file Dither.cpp.

194{
196 mState.mPhase = 0;
197 memset(mState.mBuffer, 0, sizeof(float) * BUF_SIZE);
198}
constexpr int BUF_SIZE
Definition: Dither.cpp:60
float mTriangleState
Definition: Dither.cpp:69
int mPhase
Definition: Dither.cpp:68
float mBuffer[8]
Definition: Dither.cpp:70

References BUF_SIZE, State::mBuffer, State::mPhase, mState, and State::mTriangleState.

Referenced by Apply(), and Dither().

Here is the caller graph for this function:

Member Data Documentation

◆ BestSetting

EnumSetting< DitherType > Dither::BestSetting
static
Initial value:
{
wxT("Quality/HQDitherAlgorithmChoice"),
3,
wxT("Quality/HQDitherAlgorithm")
}
wxT("CloseDown"))
static const std::initializer_list< EnumValueSymbol > choicesDither
Definition: Dither.cpp:377
static auto intChoicesDither
Definition: Dither.cpp:383

Definition at line 29 of file Dither.h.

Referenced by BestDitherChoice(), and QualityPrefs::PopulateOrExchange().

◆ FastSetting

EnumSetting< DitherType > Dither::FastSetting
static
Initial value:
{
wxT("Quality/DitherAlgorithmChoice"),
0,
wxT("Quality/DitherAlgorithm")
}

Definition at line 28 of file Dither.h.

Referenced by FastDitherChoice(), and QualityPrefs::PopulateOrExchange().


The documentation for this class was generated from the following files: