After careful poring over dither.c:pack_pcm_signed_little_endian, I
cannot see how it is (a) useful, or (b) correct. It appears to be an
older version of code found in the flac source distribution as
src/plugin_common/dither.c - which you will see has a different
function signature and a fix to make it copy the right data for
channels >0
As we never call any of the dithering code in that file anyway, it
seems much more straightforward to convert the data inline in
Decoder.xs
--- libaudio-flac-decoder-perl-0.2/Decoder.xs 2008-10-06 12:28:02.000000000 +0100
+++ libaudio-flac-decoder-perl-0.2-dan/Decoder.xs 2008-10-06 12:21:30.000000000 +0100
@@ -470,11 +470,32 @@
const unsigned n = min(datasource->wide_samples_in_reservoir, SAMPLES_PER_WRITE);
const unsigned delta = n * channels;
unsigned i;
-
+ FLAC__byte *out=datasource->sample_buffer;
+ /*
int bytes = (int)pack_pcm_signed_little_endian(
datasource->sample_buffer, datasource->reservoir, n, channels, bps, bps
);
-
+ bps==bps (trivially) so all the fancy dithering stuff
+ that pack_pcm_signed_little_endian might do will
+ never get called. Let's just do it inline
+ */
+ int bytes;
+ for(i=0; i<channels*n; i++) {
+ FLAC__int32 sample=(datasource->reservoir)[i];
+ switch(bps) {
+ case 8:
+ out[0] = sample ^ 0x80;
+ break;
+ case 24:
+ out[2] = (FLAC__byte)(sample >> 16);
+ /* fall through */
+ case 16:
+ out[1] = (FLAC__byte)(sample >> 8);
+ out[0] = (FLAC__byte)sample;
+ }
+ out+=bps/8;
+ }
+ bytes=(out-datasource->sample_buffer);
for (i = delta; i < datasource->wide_samples_in_reservoir * channels; i++) {
datasource->reservoir[i-delta] = datasource->reservoir[i];
}
Note that I have only tested this
- on a little-endian host
- with a 2 channel 16 bit input file
but it does definitely sound a lot better in those circumstances
-dan