From 1bf46dc3aa95646c6ca304377bb3cecad852b56a Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Mon, 15 Sep 2003 20:28:08 +0000 Subject: [PATCH] add support for synthesis to big-endian in plugins --- src/plugin_common/dither.c | 81 ++++++++++++++++++++++++ src/plugin_common/dither.h | 1 + src/plugin_common/replaygain_synthesis.c | 41 ++++++++---- src/plugin_common/replaygain_synthesis.h | 2 +- src/plugin_winamp2/in_flac.c | 1 + src/plugin_xmms/plugin.c | 19 +++++- 6 files changed, 131 insertions(+), 14 deletions(-) diff --git a/src/plugin_common/dither.c b/src/plugin_common/dither.c index 27e555ba..eb379bed 100644 --- a/src/plugin_common/dither.c +++ b/src/plugin_common/dither.c @@ -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]; diff --git a/src/plugin_common/dither.h b/src/plugin_common/dither.h index 85fa78ac..1a85c25c 100644 --- a/src/plugin_common/dither.h +++ b/src/plugin_common/dither.h @@ -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 diff --git a/src/plugin_common/replaygain_synthesis.c b/src/plugin_common/replaygain_synthesis.c index a7e0d1e7..eabcc2b0 100644 --- a/src/plugin_common/replaygain_synthesis.c +++ b/src/plugin_common/replaygain_synthesis.c @@ -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; + } } } } diff --git a/src/plugin_common/replaygain_synthesis.h b/src/plugin_common/replaygain_synthesis.h index bf593455..6a21bb17 100644 --- a/src/plugin_common/replaygain_synthesis.h +++ b/src/plugin_common/replaygain_synthesis.h @@ -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 diff --git a/src/plugin_winamp2/in_flac.c b/src/plugin_winamp2/in_flac.c index 8a7fe886..c7dccb60 100644 --- a/src/plugin_winamp2/in_flac.c +++ b/src/plugin_winamp2/in_flac.c @@ -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, diff --git a/src/plugin_xmms/plugin.c b/src/plugin_xmms/plugin.c index f696ee03..0fb5b014 100644 --- a/src/plugin_xmms/plugin.c +++ b/src/plugin_xmms/plugin.c @@ -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,