add support for synthesis to big-endian in plugins
authorJosh Coalson <jcoalson@users.sourceforce.net>
Mon, 15 Sep 2003 20:28:08 +0000 (20:28 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Mon, 15 Sep 2003 20:28:08 +0000 (20:28 +0000)
src/plugin_common/dither.c
src/plugin_common/dither.h
src/plugin_common/replaygain_synthesis.c
src/plugin_common/replaygain_synthesis.h
src/plugin_winamp2/in_flac.c
src/plugin_xmms/plugin.c

index 27e555b..eb379be 100644 (file)
@@ -103,6 +103,87 @@ static FLAC__INLINE FLAC__int32 linear_dither(unsigned source_bps, unsigned targ
        return output >> scalebits;
 }
 
+unsigned FLAC__plugin_common__pack_pcm_signed_big_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps)
+{
+       static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
+       FLAC__byte * const start = data;
+       FLAC__int32 sample;
+       const FLAC__int32 *input_;
+       unsigned samples, channel;
+       const unsigned bytes_per_sample = target_bps / 8;
+       unsigned inc = bytes_per_sample * channels;
+
+       FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS);
+       FLAC__ASSERT(source_bps < 32);
+       FLAC__ASSERT(target_bps <= 24);
+       FLAC__ASSERT(target_bps <= source_bps);
+       FLAC__ASSERT((source_bps & 7) == 0);
+       FLAC__ASSERT((target_bps & 7) == 0);
+
+       if(source_bps != target_bps) {
+               const FLAC__int32 MIN = -(1L << (source_bps - 1));
+               const FLAC__int32 MAX = ~MIN; /*(1L << (source_bps-1)) - 1 */
+
+               for(channel = 0; channel < channels; channel++) {
+                       
+                       samples = wide_samples;
+                       data = start + bytes_per_sample * channel;
+                       input_ = input[channel];
+
+                       while(samples--) {
+                               sample = linear_dither(source_bps, target_bps, *input_++, &dither[channel], MIN, MAX);
+
+                               switch(target_bps) {
+                                       case 8:
+                                               data[0] = sample ^ 0x80;
+                                               break;
+                                       case 16:
+                                               data[0] = (FLAC__byte)(sample >> 8);
+                                               data[1] = (FLAC__byte)sample;
+                                               break;
+                                       case 24:
+                                               data[0] = (FLAC__byte)(sample >> 16);
+                                               data[1] = (FLAC__byte)(sample >> 8);
+                                               data[2] = (FLAC__byte)sample;
+                                               break;
+                               }
+
+                               data += inc;
+                       }
+               }
+       }
+       else {
+               for(channel = 0; channel < channels; channel++) {
+                       samples = wide_samples;
+                       data = start + bytes_per_sample * channel;
+                       input_ = input[channel];
+
+                       while(samples--) {
+                               sample = *input_++;
+
+                               switch(target_bps) {
+                                       case 8:
+                                               data[0] = sample ^ 0x80;
+                                               break;
+                                       case 16:
+                                               data[0] = (FLAC__byte)(sample >> 8);
+                                               data[1] = (FLAC__byte)sample;
+                                               break;
+                                       case 24:
+                                               data[0] = (FLAC__byte)(sample >> 16);
+                                               data[1] = (FLAC__byte)(sample >> 8);
+                                               data[2] = (FLAC__byte)sample;
+                                               break;
+                               }
+
+                               data += inc;
+                       }
+               }
+       }
+
+       return data - start;
+}
+
 unsigned FLAC__plugin_common__pack_pcm_signed_little_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps)
 {
        static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
index 85fa78a..1a85c25 100644 (file)
@@ -22,6 +22,7 @@
 #include "defs.h" /* buy FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS for the caller */
 #include "FLAC/ordinals.h"
 
+unsigned FLAC__plugin_common__pack_pcm_signed_big_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps);
 unsigned FLAC__plugin_common__pack_pcm_signed_little_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps);
 
 #endif
index a7e0d1e..eabcc2b 100644 (file)
@@ -288,7 +288,7 @@ static FLAC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_d
 #endif
 
 
-int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const float scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context)
+int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const float scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context)
 {
        static const FLAC__int32 conv_factors_[33] = {
                -1, /* 0 bits-per-sample (not supported) */
@@ -410,16 +410,35 @@ int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, const FLAC__int32 * co
                        else if(val64 < hard_clip_factor)
                                val32 = (FLAC__int32)hard_clip_factor;
 
-                       switch(target_bps) {
-                               case 8:
-                                       data_out[0] = val32 ^ 0x80;
-                                       break;
-                               case 24:
-                                       data_out[2] = (FLAC__byte)(val32 >> 16);
-                                       /* fall through */
-                               case 16:
-                                       data_out[1] = (FLAC__byte)(val32 >> 8);
-                                       data_out[0] = (FLAC__byte)val32;
+                       if (little_endian_data_out) {
+                               switch(target_bps) {
+                                       case 8:
+                                               data_out[0] = val32 ^ 0x80;
+                                               break;
+                                       case 24:
+                                               data_out[2] = (FLAC__byte)(val32 >> 16);
+                                               /* fall through */
+                                       case 16:
+                                               data_out[1] = (FLAC__byte)(val32 >> 8);
+                                               data_out[0] = (FLAC__byte)val32;
+                                               break;
+                               }
+                       }
+                       else {
+                               switch(target_bps) {
+                                       case 8:
+                                               data_out[0] = val32 ^ 0x80;
+                                               break;
+                                       case 16:
+                                               data_out[0] = (FLAC__byte)(val32 >> 8);
+                                               data_out[1] = (FLAC__byte)val32;
+                                               break;
+                                       case 24:
+                                               data_out[0] = (FLAC__byte)(val32 >> 16);
+                                               data_out[1] = (FLAC__byte)(val32 >> 8);
+                                               data_out[2] = (FLAC__byte)val32;
+                                               break;
+                               }
                        }
                }
        }
index bf59345..6a21bb1 100644 (file)
@@ -44,6 +44,6 @@ typedef struct {
 void FLAC__plugin_common__init_dither_context(DitherContext *dither, int bits, int shapingtype);
 
 /* scale = (float) pow(10., (double)replaygain * 0.05); */
-int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const float scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context);
+int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const float scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context);
 
 #endif
index 8a7fe88..c7dccb6 100644 (file)
@@ -356,6 +356,7 @@ static DWORD WINAPI DecodeThread(void *unused)
                                if(cfg.replaygain.enable && file_info_.has_replaygain) {
                                        bytes = (int)FLAC__plugin_common__apply_gain(
                                                sample_buffer_,
+                                               true, /* little_endian_data_out */
                                                reservoir_,
                                                n,
                                                channels,
index f696ee0..0fb5b01 100644 (file)
@@ -123,6 +123,7 @@ static FLAC__FileDecoder *decoder_ = 0;
 static file_info_struct file_info_;
 static pthread_t decode_thread_;
 static FLAC__bool audio_error_ = false;
+static FLAC__bool is_big_endian_host_;
 
 #define BITRATE_HIST_SEGMENT_MSEC 500
 /* 500ms * 50 = 25s should be enough */
@@ -139,6 +140,9 @@ InputPlugin *get_iplugin_info()
 void FLAC_XMMS__init()
 {
        ConfigFile *cfg;
+       FLAC__uint32 test = 1;
+       is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
 
        flac_cfg.title.tag_override = FALSE;
        g_free(flac_cfg.title.tag_format);
@@ -225,7 +229,7 @@ void FLAC_XMMS__play_file(char *filename)
                        file_info_.sample_format_bytes_per_sample = 1;
                }
                else if(flac_cfg.output.resolution.replaygain.bps_out == 16) {
-                       file_info_.sample_format = FMT_S16_LE;
+                       file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
                        file_info_.sample_format_bytes_per_sample = 2;
                }
                else {
@@ -241,7 +245,7 @@ void FLAC_XMMS__play_file(char *filename)
                        file_info_.sample_format_bytes_per_sample = 1;
                }
                else if(file_info_.bits_per_sample == 16 || (file_info_.bits_per_sample == 24 && flac_cfg.output.resolution.normal.dither_24_to_16)) {
-                       file_info_.sample_format = FMT_S16_LE;
+                       file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
                        file_info_.sample_format_bytes_per_sample = 2;
                }
                else {
@@ -500,6 +504,7 @@ FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder,
        if(file_info_.has_replaygain && flac_cfg.output.replaygain.enable) {
                FLAC__plugin_common__apply_gain(
                                sample_buffer_start,
+                               !is_big_endian_host_,
                                buffer,
                                wide_samples,
                                channels,
@@ -511,6 +516,16 @@ FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder,
                                &file_info_.dither_context
                );
        }
+       else if(is_big_endian_host_) {
+               FLAC__plugin_common__pack_pcm_signed_big_endian(
+                       sample_buffer_start,
+                       buffer,
+                       wide_samples,
+                       channels,
+                       bits_per_sample,
+                       file_info->sample_format_bytes_per_sample * 8
+               );
+       }
        else {
                FLAC__plugin_common__pack_pcm_signed_little_endian(
                        sample_buffer_start,