📄 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);#endifsize_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 + -