Audacity  3.0.3
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 }

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;
318  case DitherType::shaped:
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 }

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 {
417  return (DitherType) BestSetting.ReadEnum();
418 }

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 {
412  return (DitherType) FastSetting.ReadEnum();
413 }

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 }

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")
}

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:
Dither::BestSetting
static EnumSetting< DitherType > BestSetting
Definition: Dither.h:29
DITHER
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
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
int24Sample
@ int24Sample
Definition: SampleFormat.h:33
shaped
@ shaped
Definition: Dither.h:20
TriangleDither
static float TriangleDither(State &state, float sample)
Definition: Dither.cpp:343
FROM_INT16
static float FROM_INT16(const short *ptr)
Definition: Dither.cpp:86
BUF_SIZE
constexpr int BUF_SIZE
Definition: Dither.cpp:60
State::mBuffer
float mBuffer[8]
Definition: Dither.cpp:70
floatSample
@ floatSample
Definition: SampleFormat.h:34
intChoicesDither
static auto intChoicesDither
Definition: Dither.cpp:383
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
ShapedDither
static float ShapedDither(State &state, float sample)
Definition: Dither.cpp:353
none
@ none
Definition: Dither.h:20
NoDither
static float NoDither(State &, float sample)
Definition: Dither.cpp:331
rectangle
@ rectangle
Definition: Dither.h:20
State::mTriangleState
float mTriangleState
Definition: Dither.cpp:69
choicesDither
static const std::initializer_list< EnumValueSymbol > choicesDither
Definition: Dither.cpp:377
RectangleDither
static float RectangleDither(State &, float sample)
Definition: Dither.cpp:337
DitherType
DitherType
These ditherers are currently available:
Definition: Dither.h:19
EnumSetting::ReadEnum
Enum ReadEnum() const
Definition: Prefs.h:373
Dither::Reset
void Reset()
Reset state of the dither.
Definition: Dither.cpp:193
State::mPhase
int mPhase
Definition: Dither.cpp:68
Dither::FastSetting
static EnumSetting< DitherType > FastSetting
Definition: Dither.h:28
triangle
@ triangle
Definition: Dither.h:20
FROM_INT24
static float FROM_INT24(const int *ptr)
Definition: Dither.cpp:91
mState
struct State mState