Re: [Audacity-devel] [audacity] r12574 committed - ...
A free multi-track audio editor and recorder
Brought to you by:
aosiniao
From: Gale A. <ga...@au...> - 2013-09-20 16:38:06
|
| From Martyn Shaw <mar...@gm...> | Fri, 20 Sep 2013 01:02:34 +0100 | Subject: [Audacity-devel] [audacity] r12574 committed - ... > Hi Leland > > You have been very dedicated here, as have the people testing, and > thanks for that! I wish I was able to do more testing. > > Is the issue on > http://www.diyaudio.com/forums/pc-based/235687-24-bit-input-only-16-bit-audacity.html > linking back to > http://audacity.238276.n2.nabble.com/Problem-recording-gt-16-bits-tt6036293.html > > relevant here? I have not read all. My understanding (gleaned from Leland) is that WDM-KS supports true 24-bit recording, and WASAPI will do so when it is extended beyond loopback recording and loopback problems fixed. If I'm right, that means that the PortAudio implementation of MME or WDS doesn't or cannot support true 24-bit recording. But the great man himself will correct me if needed and comment on dither implications. Gale > On 19/09/2013 08:31, aud...@go... wrote: > > Revision: 12574 > > Author: lllucius > > Date: Thu Sep 19 07:30:58 2013 UTC > > Log: > > Okay, try #3(!) > > > > The problem from the beginning has been that some parts of the code > > expected to > > receive interleaved buffers from Dither and some expected > > non-interleaved buffers. > > I was trying to keep the changes to a minimum, but it just wasn't > > possible. > > > > The result is that Dither can now accept any combination of > > non-interleaved and > > interleaved source and destination buffers. > > > > I still want to review every single usage of Dither (and all of the > > intermediaries) > > because I've seen allowances here and there for the lack of Dither > > returning > > interleaved buffers. Since it can now return interleaved buffers, > > some of that > > extra processing can be removed. > > > > > > http://code.google.com/p/audacity/source/detail?r=12574 > > > > Modified: > > /audacity-src/trunk/src/Dither.cpp > > /audacity-src/trunk/src/Dither.h > > /audacity-src/trunk/src/Mix.cpp > > /audacity-src/trunk/src/SampleFormat.cpp > > /audacity-src/trunk/src/SampleFormat.h > > > > ======================================= > > --- /audacity-src/trunk/src/Dither.cpp Wed Sep 18 13:26:20 2013 UTC > > +++ /audacity-src/trunk/src/Dither.cpp Thu Sep 19 07:30:58 2013 UTC > > @@ -73,68 +73,60 @@ > > // To assist in understanding what the macros are doing, here's an > > example of what > > // the result would be for Shaped dither: > > // > > -// DITHER(ShapedDither, dest, destFormat, source, sourceFormat, len, > > stride); > > +// DITHER(ShapedDither, dest, destFormat, destStride, source, > > sourceFormat, sourceStride, len); > > > > - do { > > - if (sourceFormat == int24Sample && destFormat == int16Sample) > > - do { > > - char *d, *s; > > - unsigned int i; > > - int x; > > - for (d = (char*)dest, s = (char*)source, i = 0; i < len; > > i++, d += (int16Sample >> 16) * stride, s += (int24Sample >> 16) * > > stride) > > - do { > > - x = lrintf((ShapedDither((((*(( int*)(s)) / > > float(1<<23))) * float(1<<15))))); > > - if (x>(32767)) > > - *((short*)((((d)))))=(32767); > > - else if (x<(-32768)) > > - *((short*)((((d)))))=(-32768); > > - else > > - *((short*)((((d)))))=(short)x; > > - } while (0); > > - } while (0); > > - else if (sourceFormat == floatSample && destFormat == int16Sample) > > - do { > > - char *d, *s; > > - unsigned int i; > > - int x; > > - for (d = (char*)dest, s = (char*)source, i = 0; i < len; > > i++, d += (int16Sample >> 16) * stride, s += (floatSample >> 16) * > > stride) > > - do { > > - x = lrintf((ShapedDither((((*((float*)(s)) > 1.0 ? > > 1.0 : > > - *((float*)(s)) < -1.0 ? -1.0 : > > - *((float*)(s)))) * float(1<<15))))); > > - if (x>(32767)) > > - *((short*)((((d)))))=(32767); > > - else if (x<(-32768)) > > - *((short*)((((d)))))=(-32768); > > - else > > - *((short*)((((d)))))=(short)x; > > - } while (0); > > - } while (0); > > - else if (sourceFormat == floatSample && destFormat == int24Sample) > > - do { > > - char *d, *s; > > - unsigned int i; > > - int x; > > - for (d = (char*)dest, s = (char*)source, i = 0; i < len; > > i++, d += (int24Sample >> 16) * stride, s += (floatSample >> 16) * > > stride) > > - do { > > - x = lrintf((ShapedDither((((*((float*)(s)) > 1.0 ? > > 1.0 : > > - *((float*)(s)) < -1.0 ? -1.0 : > > - *((float*)(s)))) * float(1<<23))))); > > - if (x>(8388607)) > > - *((int*)((((d)))))=(8388607); > > - else if (x<(-8388608)) > > - *((int*)((((d)))))=(-8388608); > > - else > > - *((int*)((((d)))))=(int)x; > > - } while (0); > > - } while (0); > > - else { > > - if ( false ) > > - ; > > - else > > - wxOnAssert(L"c:\\audacity\\src\\dither.cpp", 252, > > __FUNCTION__ , L"false", 0); > > - } > > - } while (0); > > + do { > > + if (sourceFormat == int24Sample && destFormat == int16Sample) > > + do { > > + char *d, *s; > > + unsigned int i; > > + int x; > > + for (d = (char*)dest, s = (char*)source, i = 0; i < > > len; i++, d += (int16Sample >> 16) * destStride, s += (int24Sample >> > > 16) * sourceStride) > > + do { > > + x = lrintf((ShapedDither((((*(( int*)(s)) / > > float(1<<23))) * float(1<<15))))); > > + if (x>(32767)) > > + *((short*)((((d)))))=(32767); > > + else if (x<(-32768)) > > + *((short*)((((d)))))=(-32768); > > + else *((short*)((((d)))))=(short)x; > > + } while (0); > > + } while (0); > > + else if (sourceFormat == floatSample && destFormat == > > int16Sample) > > + do { > > + char *d, *s; > > + unsigned int i; > > + int x; > > + for (d = (char*)dest, s = (char*)source, i = 0; i < > > len; i++, d += (int16Sample >> 16) * destStride, s += (floatSample >> > > 16) * sourceStride) > > + do { > > + x = lrintf((ShapedDither((((*((float*)(s)) > > > 1.0 ? 1.0 : *((float*)(s)) < -1.0 ? -1.0 : *((float*)(s)))) * > > float(1<<15))))); > > + if (x>(32767)) > > + *((short*)((((d)))))=(32767); > > + else if (x<(-32768)) > > + *((short*)((((d)))))=(-32768); > > + else *((short*)((((d)))))=(short)x; > > + } while (0); > > + } while (0); > > + else if (sourceFormat == floatSample && destFormat == > > int24Sample) > > + do { > > + char *d, *s; > > + unsigned int i; > > + int x; > > + for (d = (char*)dest, s = (char*)source, i = 0; i < > > len; i++, d += (int24Sample >> 16) * destStride, s += (floatSample >> > > 16) * sourceStride) > > + do { > > + x = lrintf((ShapedDither((((*((float*)(s)) > > > 1.0 ? 1.0 : *((float*)(s)) < -1.0 ? -1.0 : *((float*)(s)))) * > > float(1<<23))))); > > + if (x>(8388607)) > > + *((int*)((((d)))))=(8388607); > > + else if (x<(-8388608)) > > + *((int*)((((d)))))=(-8388608); > > + else *((int*)((((d)))))=(int)x; > > + } while (0); > > + } while (0); > > + else { > > + if ( false ) > > + ; > > + else > > wxOnAssert(L"c:\\users\\yam\\documents\\audacity\\mixer\\n\\audacity\\src\\dither.cpp", > > 348, __FUNCTION__ , L"false", 0); > > + } > > + } while (0); > > #endif > > > > // Defines for sample conversion > > @@ -179,35 +171,35 @@ > > > > // Implement a dithering loop > > // Note: The variable 'x' is needed for the STORE_... macros > > -#define DITHER_LOOP(dither, store, load, dst, dstFormat, src, > > srcFormat, len, stride) \ > > +#define DITHER_LOOP(dither, store, load, dst, dstFormat, dstStride, > > src, srcFormat, srcStride, len) \ > > do { \ > > char *d, *s; \ > > unsigned int i; \ > > int x; \ > > for (d = (char*)dst, s = (char*)src, i = 0; \ > > i < len; \ > > - i++, d += SAMPLE_SIZE(dstFormat), \ > > - s += SAMPLE_SIZE(srcFormat) * stride) \ > > + i++, d += SAMPLE_SIZE(dstFormat) * dstStride, \ > > + s += SAMPLE_SIZE(srcFormat) * srcStride) \ > > DITHER_STEP(dither, store, load, d, s); \ > > } while (0) > > > > // Shortcuts to dithering loops > > -#define DITHER_INT24_TO_INT16(dither, dst, src, len, stride) \ > > - DITHER_LOOP(dither, DITHER_TO_INT16, FROM_INT24, dst, > > int16Sample, src, int24Sample, len, stride) > > -#define DITHER_FLOAT_TO_INT16(dither, dst, src, len, stride) \ > > - DITHER_LOOP(dither, DITHER_TO_INT16, FROM_FLOAT, dst, > > int16Sample, src, floatSample, len, stride) > > -#define DITHER_FLOAT_TO_INT24(dither, dst, src, len, stride) \ > > - DITHER_LOOP(dither, DITHER_TO_INT24, FROM_FLOAT, dst, > > int24Sample, src, floatSample, len, stride) > > +#define DITHER_INT24_TO_INT16(dither, dst, dstStride, src, srcStride, > > len) \ > > + DITHER_LOOP(dither, DITHER_TO_INT16, FROM_INT24, dst, > > int16Sample, dstStride, src, int24Sample, srcStride, len) > > +#define DITHER_FLOAT_TO_INT16(dither, dst, dstStride, src, srcStride, > > len) \ > > + DITHER_LOOP(dither, DITHER_TO_INT16, FROM_FLOAT, dst, > > int16Sample, dstStride, src, floatSample, srcStride, len) > > +#define DITHER_FLOAT_TO_INT24(dither, dst, dstStride, src, srcStride, > > len) \ > > + DITHER_LOOP(dither, DITHER_TO_INT24, FROM_FLOAT, dst, > > int24Sample, dstStride, src, floatSample, srcStride, len) > > > > // Implement a dither. There are only 3 cases where we must dither, > > // in all other cases, no dithering is necessary. > > -#define DITHER(dither, dst, dstFormat, src, srcFormat, len, stride) \ > > +#define DITHER(dither, dst, dstFormat, dstStride, src, srcFormat, > > srcStride, len) \ > > do { if (srcFormat == int24Sample && dstFormat == int16Sample) \ > > - DITHER_INT24_TO_INT16(dither, dst, src, len, stride); \ > > + DITHER_INT24_TO_INT16(dither, dst, dstStride, src, srcStride, > > len); \ > > else if (srcFormat == floatSample && dstFormat == int16Sample) \ > > - DITHER_FLOAT_TO_INT16(dither, dst, src, len, stride); \ > > + DITHER_FLOAT_TO_INT16(dither, dst, dstStride, src, srcStride, > > len); \ > > else if (srcFormat == floatSample && dstFormat == int24Sample) \ > > - DITHER_FLOAT_TO_INT24(dither, dst, src, len, stride); \ > > + DITHER_FLOAT_TO_INT24(dither, dst, dstStride, src, srcStride, > > len); \ > > else { wxASSERT(false); } \ > > } while (0) > > > > @@ -228,31 +220,25 @@ > > // This only decides if we must dither at all, the dithers > > // are all implemented using macros. > > // > > -// "source" can contain interleaved or non-interleaved samples. This is > > -// controlled via the "stride" argument. > > -// > > -// "dest" is always non-interleaved and should be large enough to > > hold "len" > > -// samples in the "destFormat". > > -// > > -// The "len" argument specifies the number of "sourceFormat" samples to > > -// process. > > -// > > -// In the case of a non-interleaved "source", this will usually equal > > the > > -// number of samples in "source". > > +// "source" and "dest" can contain either interleaved or non-interleaved > > +// samples. They do not have to be the same...one can be interleaved > > while > > +// the otner non-interleaved. > > // > > -// With an interleaved "source", "source" should contain "stride" > > times "len" > > -// samples. > > +// The "len" argument specifies the number of samples to process. > > // > > -// If the "stride" value is 1 then "source" contains non-interleaved > > samples. > > +// If either stride value equals 1 then the corresponding buffer > > contains > > +// non-interleaved samples. > > // > > -// If the "stride" value is greater than 1 then "source" contains > > interleaved > > -// samples and they will be processed by skipping every "stride" > > number of > > -// samples. > > +// If either stride value is greater than 1 then the corresponding > > buffer > > +// contains interleaved samples and they will be processed by > > skipping every > > +// stride number of samples. > > > > void Dither::Apply(enum DitherType ditherType, > > const samplePtr source, sampleFormat sourceFormat, > > samplePtr dest, sampleFormat destFormat, > > - unsigned int len, unsigned int stride /* = 1 */) > > + unsigned int len, > > + unsigned int sourceStride /* = 1 */, > > + unsigned int destStride /* = 1 */) > > { > > unsigned int i; > > > > @@ -264,32 +250,47 @@ > > wxASSERT(source); > > wxASSERT(dest); > > wxASSERT(len >= 0); > > - wxASSERT(stride > 0); > > + wxASSERT(sourceStride > 0); > > + wxASSERT(destStride > 0); > > > > if (len == 0) > > return; // nothing to do > > > > - if (sourceFormat == destFormat) > > + if (destFormat == sourceFormat) > > { > > // No need to dither, because source and destination > > // format are the same. Just copy samples. > > - unsigned int srcBytes = SAMPLE_SIZE(destFormat); > > - > > - if (stride == 1) > > - memcpy(dest, source, len * srcBytes); > > + if (destStride == 1 && sourceStride == 1) > > + memcpy(dest, source, len * SAMPLE_SIZE(destFormat)); > > else > > { > > - samplePtr s = source; > > - samplePtr d = dest; > > + if (sourceFormat == floatSample) > > + { > > + float* d = (float*)dest; > > + float* s = (float*)source; > > + > > + for (i = 0; i < len; i++, d += destStride, s += > > sourceStride) > > + *d = *s; > > + } else > > + if (sourceFormat == int24Sample) > > + { > > + int* d = (int*)dest; > > + int* s = (int*)source; > > > > - for (i = 0; i < len; i++) > > + for (i = 0; i < len; i++, d += destStride, s += > > sourceStride) > > + *d = *s; > > + } else > > + if (sourceFormat == int16Sample) > > { > > - memcpy(d, s, srcBytes); > > - s += stride * srcBytes; > > - d += srcBytes; > > + short* d = (short*)dest; > > + short* s = (short*)source; > > + > > + for (i = 0; i < len; i++, d += destStride, s += > > sourceStride) > > + *d = *s; > > + } else { > > + wxASSERT(false); // source format unknown > > } > > } > > - > > } else > > if (destFormat == floatSample) > > { > > @@ -300,47 +301,43 @@ > > if (sourceFormat == int16Sample) > > { > > short* s = (short*)source; > > - for (i = 0; i < len; i++, d++, s+= stride) > > + for (i = 0; i < len; i++, d += destStride, s += > > sourceStride) > > *d = FROM_INT16(s); > > } else > > if (sourceFormat == int24Sample) > > { > > int* s = (int*)source; > > - for (i = 0; i < len; i++, d++, s+= stride) > > + for (i = 0; i < len; i++, d += destStride, s += > > sourceStride) > > *d = FROM_INT24(s); > > } else { > > wxASSERT(false); // source format unknown > > } > > } else > > - if (sourceFormat == int16Sample && destFormat == int24Sample) > > + if (destFormat == int24Sample && sourceFormat == int16Sample) > > { > > // Special case when promoting 16 bit to 24 bit > > + int* d = (int*)dest; > > short* s = (short*)source; > > - int* d = (int*)dest; > > - for (i = 0; i < len; i++) > > - { > > + for (i = 0; i < len; i++, d += destStride, s += sourceStride) > > *d = ((int)*s) << 8; > > - s += stride; > > - d++; > > - } > > } else > > { > > // We must do dithering > > switch (ditherType) > > { > > case none: > > - DITHER(NoDither, dest, destFormat, source, sourceFormat, > > len, stride); > > + DITHER(NoDither, dest, destFormat, destStride, source, > > sourceFormat, sourceStride, len); > > break; > > case rectangle: > > - DITHER(RectangleDither, dest, destFormat, source, > > sourceFormat, len, stride); > > + DITHER(RectangleDither, dest, destFormat, destStride, > > source, sourceFormat, sourceStride, len); > > break; > > case triangle: > > Reset(); // reset dither filter for this new conversion > > - DITHER(TriangleDither, dest, destFormat, source, > > sourceFormat, len, stride); > > + DITHER(TriangleDither, dest, destFormat, destStride, > > source, sourceFormat, sourceStride, len); > > break; > > case shaped: > > Reset(); // reset dither filter for this new conversion > > - DITHER(ShapedDither, dest, destFormat, source, > > sourceFormat, len, stride); > > + DITHER(ShapedDither, dest, destFormat, destStride, > > source, sourceFormat, sourceStride, len); > > break; > > default: > > wxASSERT(false); // unknown dither algorithm > > ======================================= > > --- /audacity-src/trunk/src/Dither.h Sun Jan 24 13:33:28 2010 UTC > > +++ /audacity-src/trunk/src/Dither.h Thu Sep 19 07:30:58 2013 UTC > > @@ -32,7 +32,9 @@ > > void Apply(DitherType ditherType, > > const samplePtr source, sampleFormat sourceFormat, > > samplePtr dest, sampleFormat destFormat, > > - unsigned int len, unsigned int stride = 1); > > + unsigned int len, > > + unsigned int sourceStride = 1, > > + unsigned int destStride = 1); > > > > private: > > // Dither methods > > ======================================= > > --- /audacity-src/trunk/src/Mix.cpp Mon Sep 16 02:32:43 2013 UTC > > +++ /audacity-src/trunk/src/Mix.cpp Thu Sep 19 07:30:58 2013 UTC > > @@ -604,6 +604,7 @@ > > mFormat, > > maxOut, > > mHighQuality, > > + mNumChannels, > > mNumChannels); > > } > > } > > @@ -614,8 +615,7 @@ > > mBuffer[c], > > mFormat, > > maxOut, > > - mHighQuality, > > - 1); > > + mHighQuality); > > } > > } > > // MB: this doesn't take warping into account, replaced with code > > based on mSamplePos > > ======================================= > > --- /audacity-src/trunk/src/SampleFormat.cpp Sun Mar 25 16:19:08 > > 2012 UTC > > +++ /audacity-src/trunk/src/SampleFormat.cpp Thu Sep 19 07:30:58 > > 2013 UTC > > @@ -96,21 +96,23 @@ > > samplePtr dst, sampleFormat dstFormat, > > unsigned int len, > > bool highQuality, /* = true */ > > - unsigned int stride /* = 1 */) > > + unsigned int srcStride /* = 1 */, > > + unsigned int dstStride /* = 1 */) > > { > > gDitherAlgorithm.Apply( > > highQuality ? gHighQualityDither : gLowQualityDither, > > - src, srcFormat, dst, dstFormat, len, stride); > > + src, srcFormat, dst, dstFormat, len, srcStride, dstStride); > > } > > > > void CopySamplesNoDither(samplePtr src, sampleFormat srcFormat, > > samplePtr dst, sampleFormat dstFormat, > > unsigned int len, > > - unsigned int stride /* = 1 */) > > + unsigned int srcStride /* = 1 */, > > + unsigned int dstStride /* = 1 */) > > { > > gDitherAlgorithm.Apply( > > Dither::none, > > - src, srcFormat, dst, dstFormat, len, stride); > > + src, srcFormat, dst, dstFormat, len, srcStride, dstStride); > > } > > > > // Indentation settings for Vim and Emacs and unique identifier for > > Arch, a > > ======================================= > > --- /audacity-src/trunk/src/SampleFormat.h Sun Mar 25 16:19:08 2012 > > UTC > > +++ /audacity-src/trunk/src/SampleFormat.h Thu Sep 19 07:30:58 2013 > > UTC > > @@ -54,12 +54,14 @@ > > void CopySamples(samplePtr src, sampleFormat srcFormat, > > samplePtr dst, sampleFormat dstFormat, > > unsigned int len, bool highQuality=true, > > - unsigned int stride=1); > > + unsigned int srcStride=1, > > + unsigned int dstStride=1); > > > > void CopySamplesNoDither(samplePtr src, sampleFormat srcFormat, > > samplePtr dst, sampleFormat dstFormat, > > unsigned int len, > > - unsigned int stride=1); > > + unsigned int srcStride=1, > > + unsigned int dstStride=1); > > > > void ClearSamples(samplePtr buffer, sampleFormat format, > > int start, int len); |