📄 replaygain_synthesis.c
字号:
* the following is based on parts of wavegain.c
*/
static FLAC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k)
{
union {
double d;
FLAC__int64 i;
} doubletmp;
double Sum2;
FLAC__int64 val;
#define ROUND64(x) ( doubletmp.d = (x) + d->Add + (FLAC__int64)FLAC__I64L(0x001FFFFD80000000), doubletmp.i - (FLAC__int64)FLAC__I64L(0x433FFFFD80000000) )
if(do_dithering) {
if(shapingtype == 0) {
double tmp = random_equi_(d->Dither);
Sum2 = tmp - d->LastRandomNumber [k];
d->LastRandomNumber [k] = (int)tmp;
Sum2 = Sum += Sum2;
val = ROUND64(Sum2) & d->Mask;
}
else {
Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i);
Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2;
Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i);
val = ROUND64(Sum2) & d->Mask;
d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val);
}
return val;
}
else
return ROUND64(Sum);
#undef ROUND64
}
#if 0
float peak = 0.f,
new_peak,
factor_clip
double scale,
dB;
...
peak is in the range -32768.0 .. 32767.0
/* calculate factors for ReplayGain and ClippingPrevention */
*track_gain = GetTitleGain() + settings->man_gain;
scale = (float) pow(10., *track_gain * 0.05);
if(settings->clip_prev) {
factor_clip = (float) (32767./( peak + 1));
if(scale < factor_clip)
factor_clip = 1.f;
else
factor_clip /= scale;
scale *= factor_clip;
}
new_peak = (float) peak * scale;
dB = 20. * log10(scale);
*track_gain = (float) dB;
const double scale = pow(10., (double)gain * 0.05);
#endif
size_t FLAC__replaygain_synthesis__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, FLAC__bool unsigned_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const double 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) */
-1, /* 1 bits-per-sample (not supported) */
-1, /* 2 bits-per-sample (not supported) */
-1, /* 3 bits-per-sample (not supported) */
268435456, /* 4 bits-per-sample */
134217728, /* 5 bits-per-sample */
67108864, /* 6 bits-per-sample */
33554432, /* 7 bits-per-sample */
16777216, /* 8 bits-per-sample */
8388608, /* 9 bits-per-sample */
4194304, /* 10 bits-per-sample */
2097152, /* 11 bits-per-sample */
1048576, /* 12 bits-per-sample */
524288, /* 13 bits-per-sample */
262144, /* 14 bits-per-sample */
131072, /* 15 bits-per-sample */
65536, /* 16 bits-per-sample */
32768, /* 17 bits-per-sample */
16384, /* 18 bits-per-sample */
8192, /* 19 bits-per-sample */
4096, /* 20 bits-per-sample */
2048, /* 21 bits-per-sample */
1024, /* 22 bits-per-sample */
512, /* 23 bits-per-sample */
256, /* 24 bits-per-sample */
128, /* 25 bits-per-sample */
64, /* 26 bits-per-sample */
32, /* 27 bits-per-sample */
16, /* 28 bits-per-sample */
8, /* 29 bits-per-sample */
4, /* 30 bits-per-sample */
2, /* 31 bits-per-sample */
1 /* 32 bits-per-sample */
};
static const FLAC__int64 hard_clip_factors_[33] = {
0, /* 0 bits-per-sample (not supported) */
0, /* 1 bits-per-sample (not supported) */
0, /* 2 bits-per-sample (not supported) */
0, /* 3 bits-per-sample (not supported) */
-8, /* 4 bits-per-sample */
-16, /* 5 bits-per-sample */
-32, /* 6 bits-per-sample */
-64, /* 7 bits-per-sample */
-128, /* 8 bits-per-sample */
-256, /* 9 bits-per-sample */
-512, /* 10 bits-per-sample */
-1024, /* 11 bits-per-sample */
-2048, /* 12 bits-per-sample */
-4096, /* 13 bits-per-sample */
-8192, /* 14 bits-per-sample */
-16384, /* 15 bits-per-sample */
-32768, /* 16 bits-per-sample */
-65536, /* 17 bits-per-sample */
-131072, /* 18 bits-per-sample */
-262144, /* 19 bits-per-sample */
-524288, /* 20 bits-per-sample */
-1048576, /* 21 bits-per-sample */
-2097152, /* 22 bits-per-sample */
-4194304, /* 23 bits-per-sample */
-8388608, /* 24 bits-per-sample */
-16777216, /* 25 bits-per-sample */
-33554432, /* 26 bits-per-sample */
-67108864, /* 27 bits-per-sample */
-134217728, /* 28 bits-per-sample */
-268435456, /* 29 bits-per-sample */
-536870912, /* 30 bits-per-sample */
-1073741824, /* 31 bits-per-sample */
(FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */
};
const FLAC__int32 conv_factor = conv_factors_[target_bps];
const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps];
/*
* The integer input coming in has a varying range based on the
* source_bps. We want to normalize it to [-1.0, 1.0) so instead
* of doing two multiplies on each sample, we just multiple
* 'scale' by 1/(2^(source_bps-1))
*/
const double multi_scale = scale / (double)(1u << (source_bps-1));
FLAC__byte * const start = data_out;
unsigned i, channel;
const FLAC__int32 *input_;
double sample;
const unsigned bytes_per_sample = target_bps / 8;
const unsigned last_history_index = dither_context->LastHistoryIndex;
NoiseShaping noise_shaping = dither_context->ShapingType;
FLAC__int64 val64;
FLAC__int32 val32;
FLAC__int32 uval32;
const FLAC__uint32 twiggle = 1u << (target_bps - 1);
FLAC__ASSERT(channels > 0 && channels <= FLAC_SHARE__MAX_SUPPORTED_CHANNELS);
FLAC__ASSERT(source_bps >= 4);
FLAC__ASSERT(target_bps >= 4);
FLAC__ASSERT(source_bps <= 32);
FLAC__ASSERT(target_bps < 32);
FLAC__ASSERT((target_bps & 7) == 0);
for(channel = 0; channel < channels; channel++) {
const unsigned incr = bytes_per_sample * channels;
data_out = start + bytes_per_sample * channel;
input_ = input[channel];
for(i = 0; i < wide_samples; i++, data_out += incr) {
sample = (double)input_[i] * multi_scale;
if(hard_limit) {
/* hard 6dB limiting */
if(sample < -0.5)
sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
else if(sample > 0.5)
sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
}
sample *= 2147483647.f;
val64 = dither_output_(dither_context, do_dithering, noise_shaping, (i + last_history_index) % 32, sample, channel) / conv_factor;
val32 = (FLAC__int32)val64;
if(val64 >= -hard_clip_factor)
val32 = (FLAC__int32)(-(hard_clip_factor+1));
else if(val64 < hard_clip_factor)
val32 = (FLAC__int32)hard_clip_factor;
uval32 = (FLAC__uint32)val32;
if (unsigned_data_out)
uval32 ^= twiggle;
if (little_endian_data_out) {
switch(target_bps) {
case 24:
data_out[2] = (FLAC__byte)(uval32 >> 16);
/* fall through */
case 16:
data_out[1] = (FLAC__byte)(uval32 >> 8);
/* fall through */
case 8:
data_out[0] = (FLAC__byte)uval32;
break;
}
}
else {
switch(target_bps) {
case 24:
data_out[0] = (FLAC__byte)(uval32 >> 16);
data_out[1] = (FLAC__byte)(uval32 >> 8);
data_out[2] = (FLAC__byte)uval32;
break;
case 16:
data_out[0] = (FLAC__byte)(uval32 >> 8);
data_out[1] = (FLAC__byte)uval32;
break;
case 8:
data_out[0] = (FLAC__byte)uval32;
break;
}
}
}
}
dither_context->LastHistoryIndex = (last_history_index + wide_samples) % 32;
return wide_samples * channels * (target_bps/8);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -