add support for synthesis to big-endian in plugins
This commit is contained in:
parent
42acbd0a95
commit
1bf46dc3aa
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user