Blame src/share/replaygain_synthesis/replaygain_synthesis.c

Packit Service 065837
/* replaygain_synthesis - Routines for applying ReplayGain to a signal
Packit Service 065837
 * Copyright (C) 2002-2009  Josh Coalson
Packit Service 065837
 * Copyright (C) 2011-2016  Xiph.Org Foundation
Packit Service 065837
 *
Packit Service 065837
 * This library is free software; you can redistribute it and/or
Packit Service 065837
 * modify it under the terms of the GNU Lesser General Public
Packit Service 065837
 * License as published by the Free Software Foundation; either
Packit Service 065837
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 065837
 *
Packit Service 065837
 * This library is distributed in the hope that it will be useful,
Packit Service 065837
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 065837
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 065837
 * Lesser General Public License for more details.
Packit Service 065837
 *
Packit Service 065837
 * You should have received a copy of the GNU Lesser General Public
Packit Service 065837
 * License along with this library; if not, write to the Free Software
Packit Service 065837
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service 065837
 */
Packit Service 065837
/*
Packit Service 065837
 * This is an aggregation of pieces of code from John Edwards' WaveGain
Packit Service 065837
 * program.  Mostly cosmetic changes were made; otherwise, the dithering
Packit Service 065837
 * code is almost untouched and the gain processing was converted from
Packit Service 065837
 * processing a whole file to processing chunks of samples.
Packit Service 065837
 *
Packit Service 065837
 * The original copyright notices for WaveGain's dither.c and wavegain.c
Packit Service 065837
 * appear below:
Packit Service 065837
 */
Packit Service 065837
/*
Packit Service 065837
 * (c) 2002 John Edwards
Packit Service 065837
 * mostly lifted from work by Frank Klemm
Packit Service 065837
 * random functions for dithering.
Packit Service 065837
 */
Packit Service 065837
/*
Packit Service 065837
 * Copyright (C) 2002 John Edwards
Packit Service 065837
 * Additional code by Magnus Holmgren and Gian-Carlo Pascutto
Packit Service 065837
 */
Packit Service 065837
Packit Service 065837
#ifdef HAVE_CONFIG_H
Packit Service 065837
#  include <config.h>
Packit Service 065837
#endif
Packit Service 065837
Packit Service 065837
#include <string.h> /* for memset() */
Packit Service 065837
#include <math.h>
Packit Service 065837
#include "share/replaygain_synthesis.h"
Packit Service 065837
#include "FLAC/assert.h"
Packit Service 065837
Packit Service 065837
#define FLAC__I64L(x) x##LL
Packit Service 065837
Packit Service 065837
Packit Service 065837
/*
Packit Service 065837
 * the following is based on parts of dither.c
Packit Service 065837
 */
Packit Service 065837
Packit Service 065837
Packit Service 065837
/*
Packit Service 065837
 *  This is a simple random number generator with good quality for audio purposes.
Packit Service 065837
 *  It consists of two polycounters with opposite rotation direction and different
Packit Service 065837
 *  periods. The periods are coprime, so the total period is the product of both.
Packit Service 065837
 *
Packit Service 065837
 *     -------------------------------------------------------------------------------------------------
Packit Service 065837
 * +-> |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0|
Packit Service 065837
 * |   -------------------------------------------------------------------------------------------------
Packit Service 065837
 * |                                                                          |  |  |  |     |        |
Packit Service 065837
 * |                                                                          +--+--+--+-XOR-+--------+
Packit Service 065837
 * |                                                                                      |
Packit Service 065837
 * +--------------------------------------------------------------------------------------+
Packit Service 065837
 *
Packit Service 065837
 *     -------------------------------------------------------------------------------------------------
Packit Service 065837
 *     |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| <-+
Packit Service 065837
 *     -------------------------------------------------------------------------------------------------   |
Packit Service 065837
 *       |  |           |  |                                                                               |
Packit Service 065837
 *       +--+----XOR----+--+                                                                               |
Packit Service 065837
 *                |                                                                                        |
Packit Service 065837
 *                +----------------------------------------------------------------------------------------+
Packit Service 065837
 *
Packit Service 065837
 *
Packit Service 065837
 *  The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481,
Packit Service 065837
 *  which gives a period of 18.410.713.077.675.721.215. The result is the
Packit Service 065837
 *  XORed values of both generators.
Packit Service 065837
 */
Packit Service 065837
Packit Service 065837
static unsigned int random_int_(void)
Packit Service 065837
{
Packit Service 065837
	static const unsigned char parity_[256] = {
Packit Service 065837
		0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
Packit Service 065837
		1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
Packit Service 065837
		1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
Packit Service 065837
		0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
Packit Service 065837
		1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
Packit Service 065837
		0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
Packit Service 065837
		0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
Packit Service 065837
		1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
Packit Service 065837
	};
Packit Service 065837
	static unsigned int r1_ = 1;
Packit Service 065837
	static unsigned int r2_ = 1;
Packit Service 065837
Packit Service 065837
	unsigned int t1, t2, t3, t4;
Packit Service 065837
Packit Service 065837
	/* Parity calculation is done via table lookup, this is also available
Packit Service 065837
	 * on CPUs without parity, can be implemented in C and avoid unpredictable
Packit Service 065837
	 * jumps and slow rotate through the carry flag operations.
Packit Service 065837
	 */
Packit Service 065837
	t3   = t1 = r1_;    t4   = t2 = r2_;
Packit Service 065837
	t1  &= 0xF5;        t2 >>= 25;
Packit Service 065837
	t1   = parity_[t1]; t2  &= 0x63;
Packit Service 065837
	t1 <<= 31;          t2   = parity_[t2];
Packit Service 065837
Packit Service 065837
	return (r1_ = (t3 >> 1) | t1 ) ^ (r2_ = (t4 + t4) | t2 );
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
/* gives a equal distributed random number */
Packit Service 065837
/* between -2^31*mult and +2^31*mult */
Packit Service 065837
static double random_equi_(double mult)
Packit Service 065837
{
Packit Service 065837
	return mult * (int) random_int_();
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
/* gives a triangular distributed random number */
Packit Service 065837
/* between -2^32*mult and +2^32*mult */
Packit Service 065837
static double random_triangular_(double mult)
Packit Service 065837
{
Packit Service 065837
	return mult * ( (double) (int) random_int_() + (double) (int) random_int_() );
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
Packit Service 065837
static const float  F44_0 [16 + 32] = {
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
Packit Service 065837
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
Packit Service 065837
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
Packit Service 065837
	(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0
Packit Service 065837
};
Packit Service 065837
Packit Service 065837
Packit Service 065837
static const float  F44_1 [16 + 32] = {  /* SNR(w) = 4.843163 dB, SNR = -3.192134 dB */
Packit Service 065837
	(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
Packit Service 065837
	(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
Packit Service 065837
	(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
Packit Service 065837
	(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
Packit Service 065837
Packit Service 065837
	(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
Packit Service 065837
	(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
Packit Service 065837
	(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
Packit Service 065837
	(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
Packit Service 065837
Packit Service 065837
	(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
Packit Service 065837
	(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
Packit Service 065837
	(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
Packit Service 065837
	(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
Packit Service 065837
};
Packit Service 065837
Packit Service 065837
Packit Service 065837
static const float  F44_2 [16 + 32] = {  /* SNR(w) = 10.060213 dB, SNR = -12.766730 dB */
Packit Service 065837
	(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
Packit Service 065837
	(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
Packit Service 065837
	(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
Packit Service 065837
	(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
Packit Service 065837
Packit Service 065837
	(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
Packit Service 065837
	(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
Packit Service 065837
	(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
Packit Service 065837
	(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
Packit Service 065837
Packit Service 065837
	(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
Packit Service 065837
	(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
Packit Service 065837
	(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
Packit Service 065837
	(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
Packit Service 065837
};
Packit Service 065837
Packit Service 065837
Packit Service 065837
static const float  F44_3 [16 + 32] = {  /* SNR(w) = 15.382598 dB, SNR = -29.402334 dB */
Packit Service 065837
	(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
Packit Service 065837
	(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
Packit Service 065837
	(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
Packit Service 065837
	(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
Packit Service 065837
Packit Service 065837
	(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
Packit Service 065837
	(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
Packit Service 065837
	(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
Packit Service 065837
	(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
Packit Service 065837
Packit Service 065837
	(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
Packit Service 065837
	(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
Packit Service 065837
	(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
Packit Service 065837
	(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099
Packit Service 065837
};
Packit Service 065837
Packit Service 065837
Packit Service 065837
static double scalar16_(const float* x, const float* y)
Packit Service 065837
{
Packit Service 065837
	return
Packit Service 065837
		x[ 0]*y[ 0] + x[ 1]*y[ 1] + x[ 2]*y[ 2] + x[ 3]*y[ 3] +
Packit Service 065837
		x[ 4]*y[ 4] + x[ 5]*y[ 5] + x[ 6]*y[ 6] + x[ 7]*y[ 7] +
Packit Service 065837
		x[ 8]*y[ 8] + x[ 9]*y[ 9] + x[10]*y[10] + x[11]*y[11] +
Packit Service 065837
		x[12]*y[12] + x[13]*y[13] + x[14]*y[14] + x[15]*y[15];
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
Packit Service 065837
void FLAC__replaygain_synthesis__init_dither_context(DitherContext *d, int bits, int shapingtype)
Packit Service 065837
{
Packit Service 065837
	static unsigned char default_dither [] = { 92, 92, 88, 84, 81, 78, 74, 67,  0,  0 };
Packit Service 065837
	static const float*               F [] = { F44_0, F44_1, F44_2, F44_3 };
Packit Service 065837
Packit Service 065837
	int indx;
Packit Service 065837
Packit Service 065837
	if (shapingtype < 0) shapingtype = 0;
Packit Service 065837
	if (shapingtype > 3) shapingtype = 3;
Packit Service 065837
	d->ShapingType = (NoiseShaping)shapingtype;
Packit Service 065837
	indx = bits - 11 - shapingtype;
Packit Service 065837
	if (indx < 0) indx = 0;
Packit Service 065837
	if (indx > 9) indx = 9;
Packit Service 065837
Packit Service 065837
	memset ( d->ErrorHistory , 0, sizeof (d->ErrorHistory ) );
Packit Service 065837
	memset ( d->DitherHistory, 0, sizeof (d->DitherHistory) );
Packit Service 065837
Packit Service 065837
	d->FilterCoeff = F [shapingtype];
Packit Service 065837
	d->Mask   = ((FLAC__uint64)-1) << (32 - bits);
Packit Service 065837
	d->Add    = 0.5     * ((1L << (32 - bits)) - 1);
Packit Service 065837
	d->Dither = 0.01f*default_dither[indx] / (((FLAC__int64)1) << bits);
Packit Service 065837
	d->LastHistoryIndex = 0;
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
/*
Packit Service 065837
 * the following is based on parts of wavegain.c
Packit Service 065837
 */
Packit Service 065837
Packit Service 065837
static FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k)
Packit Service 065837
{
Packit Service 065837
	union {
Packit Service 065837
		double d;
Packit Service 065837
		FLAC__int64 i;
Packit Service 065837
	} doubletmp;
Packit Service 065837
	double Sum2;
Packit Service 065837
	FLAC__int64 val;
Packit Service 065837
Packit Service 065837
#define ROUND64(x)   ( doubletmp.d = (x) + d->Add + (FLAC__int64)FLAC__I64L(0x001FFFFD80000000), doubletmp.i - (FLAC__int64)FLAC__I64L(0x433FFFFD80000000) )
Packit Service 065837
Packit Service 065837
	if(do_dithering) {
Packit Service 065837
		if(shapingtype == 0) {
Packit Service 065837
			double  tmp = random_equi_(d->Dither);
Packit Service 065837
			Sum2 = tmp - d->LastRandomNumber [k];
Packit Service 065837
			d->LastRandomNumber [k] = (int)tmp;
Packit Service 065837
			Sum2 = Sum += Sum2;
Packit Service 065837
			val = ROUND64(Sum2) & d->Mask;
Packit Service 065837
		}
Packit Service 065837
		else {
Packit Service 065837
			Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i);
Packit Service 065837
			Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2;
Packit Service 065837
			Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i);
Packit Service 065837
			val = ROUND64(Sum2) & d->Mask;
Packit Service 065837
			d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val);
Packit Service 065837
		}
Packit Service 065837
		return val;
Packit Service 065837
	}
Packit Service 065837
	else
Packit Service 065837
		return ROUND64(Sum);
Packit Service 065837
Packit Service 065837
#undef ROUND64
Packit Service 065837
}
Packit Service 065837
Packit Service 065837
#if 0
Packit Service 065837
	float        peak = 0.f,
Packit Service 065837
	             new_peak,
Packit Service 065837
	             factor_clip
Packit Service 065837
	double       scale,
Packit Service 065837
	             dB;
Packit Service 065837
Packit Service 065837
	...
Packit Service 065837
Packit Service 065837
	peak is in the range -32768.0 .. 32767.0
Packit Service 065837
Packit Service 065837
	/* calculate factors for ReplayGain and ClippingPrevention */
Packit Service 065837
	*track_gain = GetTitleGain() + settings->man_gain;
Packit Service 065837
	scale = (float) pow(10., *track_gain * 0.05);
Packit Service 065837
	if(settings->clip_prev) {
Packit Service 065837
		factor_clip  = (float) (32767./( peak + 1));
Packit Service 065837
		if(scale < factor_clip)
Packit Service 065837
			factor_clip = 1.f;
Packit Service 065837
		else
Packit Service 065837
			factor_clip /= scale;
Packit Service 065837
		scale *= factor_clip;
Packit Service 065837
	}
Packit Service 065837
	new_peak = (float) peak * scale;
Packit Service 065837
Packit Service 065837
	dB = 20. * log10(scale);
Packit Service 065837
	*track_gain = (float) dB;
Packit Service 065837
Packit Service 065837
 	const double scale = pow(10., (double)gain * 0.05);
Packit Service 065837
#endif
Packit Service 065837
Packit Service 065837
Packit Service 065837
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)
Packit Service 065837
{
Packit Service 065837
	static const FLAC__int64 hard_clip_factors_[33] = {
Packit Service 065837
		0, /* 0 bits-per-sample (not supported) */
Packit Service 065837
		0, /* 1 bits-per-sample (not supported) */
Packit Service 065837
		0, /* 2 bits-per-sample (not supported) */
Packit Service 065837
		0, /* 3 bits-per-sample (not supported) */
Packit Service 065837
		-8, /* 4 bits-per-sample */
Packit Service 065837
		-16, /* 5 bits-per-sample */
Packit Service 065837
		-32, /* 6 bits-per-sample */
Packit Service 065837
		-64, /* 7 bits-per-sample */
Packit Service 065837
		-128, /* 8 bits-per-sample */
Packit Service 065837
		-256, /* 9 bits-per-sample */
Packit Service 065837
		-512, /* 10 bits-per-sample */
Packit Service 065837
		-1024, /* 11 bits-per-sample */
Packit Service 065837
		-2048, /* 12 bits-per-sample */
Packit Service 065837
		-4096, /* 13 bits-per-sample */
Packit Service 065837
		-8192, /* 14 bits-per-sample */
Packit Service 065837
		-16384, /* 15 bits-per-sample */
Packit Service 065837
		-32768, /* 16 bits-per-sample */
Packit Service 065837
		-65536, /* 17 bits-per-sample */
Packit Service 065837
		-131072, /* 18 bits-per-sample */
Packit Service 065837
		-262144, /* 19 bits-per-sample */
Packit Service 065837
		-524288, /* 20 bits-per-sample */
Packit Service 065837
		-1048576, /* 21 bits-per-sample */
Packit Service 065837
		-2097152, /* 22 bits-per-sample */
Packit Service 065837
		-4194304, /* 23 bits-per-sample */
Packit Service 065837
		-8388608, /* 24 bits-per-sample */
Packit Service 065837
		-16777216, /* 25 bits-per-sample */
Packit Service 065837
		-33554432, /* 26 bits-per-sample */
Packit Service 065837
		-67108864, /* 27 bits-per-sample */
Packit Service 065837
		-134217728, /* 28 bits-per-sample */
Packit Service 065837
		-268435456, /* 29 bits-per-sample */
Packit Service 065837
		-536870912, /* 30 bits-per-sample */
Packit Service 065837
		-1073741824, /* 31 bits-per-sample */
Packit Service 065837
		(FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */
Packit Service 065837
	};
Packit Service 065837
	const FLAC__int32 conv_shift = 32 - target_bps;
Packit Service 065837
	const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps];
Packit Service 065837
	/*
Packit Service 065837
	 * The integer input coming in has a varying range based on the
Packit Service 065837
	 * source_bps.  We want to normalize it to [-1.0, 1.0) so instead
Packit Service 065837
	 * of doing two multiplies on each sample, we just multiple
Packit Service 065837
	 * 'scale' by 1/(2^(source_bps-1))
Packit Service 065837
	 */
Packit Service 065837
	const double multi_scale = scale / (double)(1u << (source_bps-1));
Packit Service 065837
Packit Service 065837
	FLAC__byte * const start = data_out;
Packit Service 065837
	unsigned i, channel;
Packit Service 065837
	const FLAC__int32 *input_;
Packit Service 065837
	double sample;
Packit Service 065837
	const unsigned bytes_per_sample = target_bps / 8;
Packit Service 065837
	const unsigned last_history_index = dither_context->LastHistoryIndex;
Packit Service 065837
	NoiseShaping noise_shaping = dither_context->ShapingType;
Packit Service 065837
	FLAC__int64 val64;
Packit Service 065837
	FLAC__int32 val32;
Packit Service 065837
	FLAC__int32 uval32;
Packit Service 065837
	const FLAC__uint32 twiggle = 1u << (target_bps - 1);
Packit Service 065837
Packit Service 065837
	FLAC__ASSERT(channels > 0 && channels <= FLAC_SHARE__MAX_SUPPORTED_CHANNELS);
Packit Service 065837
	FLAC__ASSERT(source_bps >= 4);
Packit Service 065837
	FLAC__ASSERT(target_bps >= 4);
Packit Service 065837
	FLAC__ASSERT(source_bps <= 32);
Packit Service 065837
	FLAC__ASSERT(target_bps < 32);
Packit Service 065837
	FLAC__ASSERT((target_bps & 7) == 0);
Packit Service 065837
Packit Service 065837
	for(channel = 0; channel < channels; channel++) {
Packit Service 065837
		const unsigned incr = bytes_per_sample * channels;
Packit Service 065837
		data_out = start + bytes_per_sample * channel;
Packit Service 065837
		input_ = input[channel];
Packit Service 065837
		for(i = 0; i < wide_samples; i++, data_out += incr) {
Packit Service 065837
			sample = (double)input_[i] * multi_scale;
Packit Service 065837
Packit Service 065837
			if(hard_limit) {
Packit Service 065837
				/* hard 6dB limiting */
Packit Service 065837
				if(sample < -0.5)
Packit Service 065837
					sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
Packit Service 065837
				else if(sample > 0.5)
Packit Service 065837
					sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
Packit Service 065837
			}
Packit Service 065837
			sample *= 2147483647.;
Packit Service 065837
Packit Service 065837
			val64 = dither_output_(dither_context, do_dithering, noise_shaping, (i + last_history_index) % 32, sample, channel) >> conv_shift;
Packit Service 065837
Packit Service 065837
			val32 = (FLAC__int32)val64;
Packit Service 065837
			if(val64 >= -hard_clip_factor)
Packit Service 065837
				val32 = (FLAC__int32)(-(hard_clip_factor+1));
Packit Service 065837
			else if(val64 < hard_clip_factor)
Packit Service 065837
				val32 = (FLAC__int32)hard_clip_factor;
Packit Service 065837
Packit Service 065837
			uval32 = (FLAC__uint32)val32;
Packit Service 065837
			if (unsigned_data_out)
Packit Service 065837
				uval32 ^= twiggle;
Packit Service 065837
Packit Service 065837
			if (little_endian_data_out) {
Packit Service 065837
				switch(target_bps) {
Packit Service 065837
					case 24:
Packit Service 065837
						data_out[2] = (FLAC__byte)(uval32 >> 16);
Packit Service 065837
						/* fall through */
Packit Service 065837
					case 16:
Packit Service 065837
						data_out[1] = (FLAC__byte)(uval32 >> 8);
Packit Service 065837
						/* fall through */
Packit Service 065837
					case 8:
Packit Service 065837
						data_out[0] = (FLAC__byte)uval32;
Packit Service 065837
						break;
Packit Service 065837
				}
Packit Service 065837
			}
Packit Service 065837
			else {
Packit Service 065837
				switch(target_bps) {
Packit Service 065837
					case 24:
Packit Service 065837
						data_out[0] = (FLAC__byte)(uval32 >> 16);
Packit Service 065837
						data_out[1] = (FLAC__byte)(uval32 >> 8);
Packit Service 065837
						data_out[2] = (FLAC__byte)uval32;
Packit Service 065837
						break;
Packit Service 065837
					case 16:
Packit Service 065837
						data_out[0] = (FLAC__byte)(uval32 >> 8);
Packit Service 065837
						data_out[1] = (FLAC__byte)uval32;
Packit Service 065837
						break;
Packit Service 065837
					case 8:
Packit Service 065837
						data_out[0] = (FLAC__byte)uval32;
Packit Service 065837
						break;
Packit Service 065837
				}
Packit Service 065837
			}
Packit Service 065837
		}
Packit Service 065837
	}
Packit Service 065837
	dither_context->LastHistoryIndex = (last_history_index + wide_samples) % 32;
Packit Service 065837
Packit Service 065837
	return wide_samples * channels * (target_bps/8);
Packit Service 065837
}