Commit 1bf46dc3 authored by Josh Coalson's avatar Josh Coalson
Browse files

add support for synthesis to big-endian in plugins

parent 42acbd0a
......@@ -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,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment