final merge down from 1.1.2 maintenance branch (cvs up -j FLAC_RELEASE_1_1_2_MAINTENA...
[flac.git] / src / share / replaygain_synthesis / replaygain_synthesis.c
1 /* replaygain_synthesis - Routines for applying ReplayGain to a signal
2  * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 /*
19  * This is an aggregation of pieces of code from John Edwards' WaveGain
20  * program.  Mostly cosmetic changes were made; otherwise, the dithering
21  * code is almost untouched and the gain processing was converted from
22  * processing a whole file to processing chunks of samples.
23  *
24  * The original copyright notices for WaveGain's dither.c and wavegain.c
25  * appear below:
26  */
27 /*
28  * (c) 2002 John Edwards
29  * mostly lifted from work by Frank Klemm
30  * random functions for dithering.
31  */
32 /*
33  * Copyright (C) 2002 John Edwards
34  * Additional code by Magnus Holmgren and Gian-Carlo Pascutto
35  */
36
37 #if HAVE_CONFIG_H
38 #  include <config.h>
39 #endif
40
41 #include <string.h> /* for memset() */
42 #include <math.h>
43 #include "private/fast_float_math_hack.h"
44 #include "replaygain_synthesis.h"
45 #include "FLAC/assert.h"
46
47 #if defined _MSC_VER
48 #define FLAC__INLINE __inline
49 #else
50 #define FLAC__INLINE
51 #endif
52
53 /* adjust for compilers that can't understand using LL suffix for int64_t literals */
54 #ifdef _MSC_VER
55 #define FLAC__I64L(x) x
56 #else
57 #define FLAC__I64L(x) x##LL
58 #endif
59
60
61 /*
62  * the following is based on parts of dither.c
63  */
64
65
66 /*
67  *  This is a simple random number generator with good quality for audio purposes.
68  *  It consists of two polycounters with opposite rotation direction and different
69  *  periods. The periods are coprime, so the total period is the product of both.
70  *
71  *     -------------------------------------------------------------------------------------------------
72  * +-> |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|
73  * |   -------------------------------------------------------------------------------------------------
74  * |                                                                          |  |  |  |     |        |
75  * |                                                                          +--+--+--+-XOR-+--------+
76  * |                                                                                      |
77  * +--------------------------------------------------------------------------------------+
78  *
79  *     -------------------------------------------------------------------------------------------------
80  *     |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| <-+
81  *     -------------------------------------------------------------------------------------------------   |
82  *       |  |           |  |                                                                               |
83  *       +--+----XOR----+--+                                                                               |
84  *                |                                                                                        |
85  *                +----------------------------------------------------------------------------------------+
86  *
87  *
88  *  The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481,
89  *  which gives a period of 18.410.713.077.675.721.215. The result is the
90  *  XORed values of both generators.
91  */
92
93 static unsigned int random_int_()
94 {
95         static const unsigned char parity_[256] = {
96                 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,
97                 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,
98                 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,
99                 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,
100                 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,
101                 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,
102                 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,
103                 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
104         };
105         static unsigned int r1_ = 1;
106         static unsigned int r2_ = 1;
107
108         unsigned int t1, t2, t3, t4;
109
110         /* Parity calculation is done via table lookup, this is also available
111          * on CPUs without parity, can be implemented in C and avoid unpredictable
112          * jumps and slow rotate through the carry flag operations.
113          */
114         t3   = t1 = r1_;    t4   = t2 = r2_;
115         t1  &= 0xF5;        t2 >>= 25;
116         t1   = parity_[t1]; t2  &= 0x63;
117         t1 <<= 31;          t2   = parity_[t2];
118
119         return (r1_ = (t3 >> 1) | t1 ) ^ (r2_ = (t4 + t4) | t2 );
120 }
121
122 /* gives a equal distributed random number */
123 /* between -2^31*mult and +2^31*mult */
124 static double random_equi_(double mult)
125 {
126         return mult * (int) random_int_();
127 }
128
129 /* gives a triangular distributed random number */
130 /* between -2^32*mult and +2^32*mult */
131 static double random_triangular_(double mult)
132 {
133         return mult * ( (double) (int) random_int_() + (double) (int) random_int_() );
134 }
135
136
137 static const float  F44_0 [16 + 32] = {
138         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
139         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
140
141         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
142         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
143
144         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
145         (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0
146 };
147
148
149 static const float  F44_1 [16 + 32] = {  /* SNR(w) = 4.843163 dB, SNR = -3.192134 dB */
150         (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
151         (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
152         (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
153         (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
154
155         (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
156         (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
157         (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
158         (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
159
160         (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
161         (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
162         (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
163         (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
164 };
165
166
167 static const float  F44_2 [16 + 32] = {  /* SNR(w) = 10.060213 dB, SNR = -12.766730 dB */
168         (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
169         (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
170         (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
171         (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
172
173         (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
174         (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
175         (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
176         (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
177
178         (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
179         (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
180         (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
181         (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
182 };
183
184
185 static const float  F44_3 [16 + 32] = {  /* SNR(w) = 15.382598 dB, SNR = -29.402334 dB */
186         (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
187         (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
188         (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
189         (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
190
191         (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
192         (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
193         (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
194         (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
195
196         (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
197         (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
198         (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
199         (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099
200 };
201
202
203 static double scalar16_(const float* x, const float* y)
204 {
205         return
206                 x[ 0]*y[ 0] + x[ 1]*y[ 1] + x[ 2]*y[ 2] + x[ 3]*y[ 3] +
207                 x[ 4]*y[ 4] + x[ 5]*y[ 5] + x[ 6]*y[ 6] + x[ 7]*y[ 7] +
208                 x[ 8]*y[ 8] + x[ 9]*y[ 9] + x[10]*y[10] + x[11]*y[11] +
209                 x[12]*y[12] + x[13]*y[13] + x[14]*y[14] + x[15]*y[15];
210 }
211
212
213 void FLAC__replaygain_synthesis__init_dither_context(DitherContext *d, int bits, int shapingtype)
214 {
215         static unsigned char default_dither [] = { 92, 92, 88, 84, 81, 78, 74, 67,  0,  0 };
216         static const float*               F [] = { F44_0, F44_1, F44_2, F44_3 };
217
218         int index;
219
220         if (shapingtype < 0) shapingtype = 0;
221         if (shapingtype > 3) shapingtype = 3;
222         d->ShapingType = (NoiseShaping)shapingtype;
223         index = bits - 11 - shapingtype;
224         if (index < 0) index = 0;
225         if (index > 9) index = 9;
226
227         memset ( d->ErrorHistory , 0, sizeof (d->ErrorHistory ) );
228         memset ( d->DitherHistory, 0, sizeof (d->DitherHistory) );
229
230         d->FilterCoeff = F [shapingtype];
231         d->Mask   = ((FLAC__uint64)-1) << (32 - bits);
232         d->Add    = 0.5     * ((1L << (32 - bits)) - 1);
233         d->Dither = 0.01f*default_dither[index] / (((FLAC__int64)1) << bits);
234         d->LastHistoryIndex = 0;
235 }
236
237 /*
238  * the following is based on parts of wavegain.c
239  */
240
241 static FLAC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k)
242 {
243         union {
244                 double d;
245                 FLAC__int64 i;
246         } doubletmp;
247         double Sum2;
248         FLAC__int64 val;
249
250 #define ROUND64(x)   ( doubletmp.d = (x) + d->Add + (FLAC__int64)FLAC__I64L(0x001FFFFD80000000), doubletmp.i - (FLAC__int64)FLAC__I64L(0x433FFFFD80000000) )
251
252         if(do_dithering) {
253                 if(shapingtype == 0) {
254                         double  tmp = random_equi_(d->Dither);
255                         Sum2 = tmp - d->LastRandomNumber [k];
256                         d->LastRandomNumber [k] = (int)tmp;
257                         Sum2 = Sum += Sum2;
258                         val = ROUND64(Sum2) & d->Mask;
259                 }
260                 else {
261                         Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i);
262                         Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2;
263                         Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i);
264                         val = ROUND64(Sum2) & d->Mask;
265                         d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val);
266                 }
267                 return val;
268         }
269         else
270                 return ROUND64(Sum);
271
272 #undef ROUND64
273 }
274
275 #if 0
276         float        peak = 0.f,
277                      new_peak,
278                      factor_clip
279         double       scale,
280                      dB;
281
282         ...
283
284         peak is in the range -32768.0 .. 32767.0
285
286         /* calculate factors for ReplayGain and ClippingPrevention */
287         *track_gain = GetTitleGain() + settings->man_gain;
288         scale = (float) pow(10., *track_gain * 0.05);
289         if(settings->clip_prev) {
290                 factor_clip  = (float) (32767./( peak + 1));
291                 if(scale < factor_clip)
292                         factor_clip = 1.f;
293                 else
294                         factor_clip /= scale;
295                 scale *= factor_clip;
296         }
297         new_peak = (float) peak * scale;
298
299         dB = 20. * log10(scale);
300         *track_gain = (float) dB;
301
302         const double scale = pow(10., (double)gain * 0.05);
303 #endif
304
305
306 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)
307 {
308         static const FLAC__int32 conv_factors_[33] = {
309                 -1, /* 0 bits-per-sample (not supported) */
310                 -1, /* 1 bits-per-sample (not supported) */
311                 -1, /* 2 bits-per-sample (not supported) */
312                 -1, /* 3 bits-per-sample (not supported) */
313                 268435456, /* 4 bits-per-sample */
314                 134217728, /* 5 bits-per-sample */
315                 67108864, /* 6 bits-per-sample */
316                 33554432, /* 7 bits-per-sample */
317                 16777216, /* 8 bits-per-sample */
318                 8388608, /* 9 bits-per-sample */
319                 4194304, /* 10 bits-per-sample */
320                 2097152, /* 11 bits-per-sample */
321                 1048576, /* 12 bits-per-sample */
322                 524288, /* 13 bits-per-sample */
323                 262144, /* 14 bits-per-sample */
324                 131072, /* 15 bits-per-sample */
325                 65536, /* 16 bits-per-sample */
326                 32768, /* 17 bits-per-sample */
327                 16384, /* 18 bits-per-sample */
328                 8192, /* 19 bits-per-sample */
329                 4096, /* 20 bits-per-sample */
330                 2048, /* 21 bits-per-sample */
331                 1024, /* 22 bits-per-sample */
332                 512, /* 23 bits-per-sample */
333                 256, /* 24 bits-per-sample */
334                 128, /* 25 bits-per-sample */
335                 64, /* 26 bits-per-sample */
336                 32, /* 27 bits-per-sample */
337                 16, /* 28 bits-per-sample */
338                 8, /* 29 bits-per-sample */
339                 4, /* 30 bits-per-sample */
340                 2, /* 31 bits-per-sample */
341                 1 /* 32 bits-per-sample */
342         };
343         static const FLAC__int64 hard_clip_factors_[33] = {
344                 0, /* 0 bits-per-sample (not supported) */
345                 0, /* 1 bits-per-sample (not supported) */
346                 0, /* 2 bits-per-sample (not supported) */
347                 0, /* 3 bits-per-sample (not supported) */
348                 -8, /* 4 bits-per-sample */
349                 -16, /* 5 bits-per-sample */
350                 -32, /* 6 bits-per-sample */
351                 -64, /* 7 bits-per-sample */
352                 -128, /* 8 bits-per-sample */
353                 -256, /* 9 bits-per-sample */
354                 -512, /* 10 bits-per-sample */
355                 -1024, /* 11 bits-per-sample */
356                 -2048, /* 12 bits-per-sample */
357                 -4096, /* 13 bits-per-sample */
358                 -8192, /* 14 bits-per-sample */
359                 -16384, /* 15 bits-per-sample */
360                 -32768, /* 16 bits-per-sample */
361                 -65536, /* 17 bits-per-sample */
362                 -131072, /* 18 bits-per-sample */
363                 -262144, /* 19 bits-per-sample */
364                 -524288, /* 20 bits-per-sample */
365                 -1048576, /* 21 bits-per-sample */
366                 -2097152, /* 22 bits-per-sample */
367                 -4194304, /* 23 bits-per-sample */
368                 -8388608, /* 24 bits-per-sample */
369                 -16777216, /* 25 bits-per-sample */
370                 -33554432, /* 26 bits-per-sample */
371                 -67108864, /* 27 bits-per-sample */
372                 -134217728, /* 28 bits-per-sample */
373                 -268435456, /* 29 bits-per-sample */
374                 -536870912, /* 30 bits-per-sample */
375                 -1073741824, /* 31 bits-per-sample */
376                 (FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */
377         };
378         const FLAC__int32 conv_factor = conv_factors_[target_bps];
379         const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps];
380         /*
381          * The integer input coming in has a varying range based on the
382          * source_bps.  We want to normalize it to [-1.0, 1.0) so instead
383          * of doing two multiplies on each sample, we just multiple
384          * 'scale' by 1/(2^(source_bps-1))
385          */
386         const double multi_scale = scale / (double)(1u << (source_bps-1));
387
388         FLAC__byte * const start = data_out;
389         unsigned i, channel;
390         const FLAC__int32 *input_;
391         double sample;
392         const unsigned bytes_per_sample = target_bps / 8;
393         const unsigned last_history_index = dither_context->LastHistoryIndex;
394         NoiseShaping noise_shaping = dither_context->ShapingType;
395         FLAC__int64 val64;
396         FLAC__int32 val32;
397         FLAC__int32 uval32;
398         const FLAC__uint32 twiggle = 1u << (target_bps - 1);
399
400         FLAC__ASSERT(channels > 0 && channels <= FLAC_SHARE__MAX_SUPPORTED_CHANNELS);
401         FLAC__ASSERT(source_bps >= 4);
402         FLAC__ASSERT(target_bps >= 4);
403         FLAC__ASSERT(source_bps <= 32);
404         FLAC__ASSERT(target_bps < 32);
405         FLAC__ASSERT((target_bps & 7) == 0);
406
407         for(channel = 0; channel < channels; channel++) {
408                 const unsigned incr = bytes_per_sample * channels;
409                 data_out = start + bytes_per_sample * channel;
410                 input_ = input[channel];
411                 for(i = 0; i < wide_samples; i++, data_out += incr) {
412                         sample = (double)input_[i] * multi_scale;
413
414                         if(hard_limit) {
415                                 /* hard 6dB limiting */
416                                 if(sample < -0.5)
417                                         sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
418                                 else if(sample > 0.5)
419                                         sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
420                         }
421                         sample *= 2147483647.f;
422
423                         val64 = dither_output_(dither_context, do_dithering, noise_shaping, (i + last_history_index) % 32, sample, channel) / conv_factor;
424
425                         val32 = (FLAC__int32)val64;
426                         if(val64 >= -hard_clip_factor)
427                                 val32 = (FLAC__int32)(-(hard_clip_factor+1));
428                         else if(val64 < hard_clip_factor)
429                                 val32 = (FLAC__int32)hard_clip_factor;
430
431                         uval32 = (FLAC__uint32)val32;
432                         if (unsigned_data_out)
433                                 uval32 ^= twiggle;
434
435                         if (little_endian_data_out) {
436                                 switch(target_bps) {
437                                         case 24:
438                                                 data_out[2] = (FLAC__byte)(uval32 >> 16);
439                                                 /* fall through */
440                                         case 16:
441                                                 data_out[1] = (FLAC__byte)(uval32 >> 8);
442                                                 /* fall through */
443                                         case 8:
444                                                 data_out[0] = (FLAC__byte)uval32;
445                                                 break;
446                                 }
447                         }
448                         else {
449                                 switch(target_bps) {
450                                         case 24:
451                                                 data_out[0] = (FLAC__byte)(uval32 >> 16);
452                                                 data_out[1] = (FLAC__byte)(uval32 >> 8);
453                                                 data_out[2] = (FLAC__byte)uval32;
454                                                 break;
455                                         case 16:
456                                                 data_out[0] = (FLAC__byte)(uval32 >> 8);
457                                                 data_out[1] = (FLAC__byte)uval32;
458                                                 break;
459                                         case 8:
460                                                 data_out[0] = (FLAC__byte)uval32;
461                                                 break;
462                                 }
463                         }
464                 }
465         }
466         dither_context->LastHistoryIndex = (last_history_index + wide_samples) % 32;
467
468         return wide_samples * channels * (target_bps/8);
469 }