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

Reply via email to