~ubuntu-branches/ubuntu/feisty/flac/feisty

« back to all changes in this revision

Viewing changes to src/plugin_common/replaygain_synthesis.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-04-16 15:14:31 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040416151431-eyloggqxpwbwpogz
Tags: 1.1.0-11
Ensure that libFLAC is linked with -lm on all architectures, and
regardless of whether nasm is present

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* plugin_common - Routines common to several plugins
 
2
 * Copyright (C) 2002,2003  Josh Coalson
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program 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
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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
#include <string.h> /* for memset() */
 
38
#include <math.h>
 
39
#include "private/fast_float_math_hack.h"
 
40
#include "replaygain_synthesis.h"
 
41
#include "FLAC/assert.h"
 
42
 
 
43
#if defined _MSC_VER
 
44
#define FLAC__INLINE __inline
 
45
#else
 
46
#define FLAC__INLINE
 
47
#endif
 
48
 
 
49
 
 
50
/*
 
51
 * the following is based on parts of dither.c
 
52
 */
 
53
 
 
54
 
 
55
/*
 
56
 *  This is a simple random number generator with good quality for audio purposes.
 
57
 *  It consists of two polycounters with opposite rotation direction and different
 
58
 *  periods. The periods are coprime, so the total period is the product of both.
 
59
 *
 
60
 *     -------------------------------------------------------------------------------------------------
 
61
 * +-> |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|
 
62
 * |   -------------------------------------------------------------------------------------------------
 
63
 * |                                                                          |  |  |  |     |        |
 
64
 * |                                                                          +--+--+--+-XOR-+--------+
 
65
 * |                                                                                      |
 
66
 * +--------------------------------------------------------------------------------------+
 
67
 *
 
68
 *     -------------------------------------------------------------------------------------------------
 
69
 *     |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| <-+
 
70
 *     -------------------------------------------------------------------------------------------------   |
 
71
 *       |  |           |  |                                                                               |
 
72
 *       +--+----XOR----+--+                                                                               |
 
73
 *                |                                                                                        |
 
74
 *                +----------------------------------------------------------------------------------------+
 
75
 *
 
76
 *
 
77
 *  The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481,
 
78
 *  which gives a period of 18.410.713.077.675.721.215. The result is the
 
79
 *  XORed values of both generators.
 
80
 */
 
81
 
 
82
static unsigned int random_int_()
 
83
{
 
84
        static const unsigned char parity_[256] = {
 
85
                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,
 
86
                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,
 
87
                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,
 
88
                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,
 
89
                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,
 
90
                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,
 
91
                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,
 
92
                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
 
93
        };
 
94
        static unsigned int r1_ = 1;
 
95
        static unsigned int r2_ = 1;
 
96
 
 
97
        unsigned int t1, t2, t3, t4;
 
98
 
 
99
        /* Parity calculation is done via table lookup, this is also available
 
100
         * on CPUs without parity, can be implemented in C and avoid unpredictable
 
101
         * jumps and slow rotate through the carry flag operations.
 
102
         */
 
103
        t3   = t1 = r1_;    t4   = t2 = r2_;
 
104
        t1  &= 0xF5;        t2 >>= 25;
 
105
        t1   = parity_[t1]; t2  &= 0x63;
 
106
        t1 <<= 31;          t2   = parity_[t2];
 
107
 
 
108
        return (r1_ = (t3 >> 1) | t1 ) ^ (r2_ = (t4 + t4) | t2 );
 
109
}
 
110
 
 
111
/* gives a equal distributed random number */
 
112
/* between -2^31*mult and +2^31*mult */
 
113
static double random_equi_(double mult)
 
114
{
 
115
        return mult * (int) random_int_();
 
116
}
 
117
 
 
118
/* gives a triangular distributed random number */
 
119
/* between -2^32*mult and +2^32*mult */
 
120
static double random_triangular_(double mult)
 
121
{
 
122
        return mult * ( (double) (int) random_int_() + (double) (int) random_int_() );
 
123
}
 
124
 
 
125
 
 
126
static const float  F44_0 [16 + 32] = {
 
127
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
 
128
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
 
129
 
 
130
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
 
131
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
 
132
 
 
133
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
 
134
        (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0
 
135
};
 
136
 
 
137
 
 
138
static const float  F44_1 [16 + 32] = {  /* SNR(w) = 4.843163 dB, SNR = -3.192134 dB */
 
139
        (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
 
140
        (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
 
141
        (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
 
142
        (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
 
143
 
 
144
        (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
 
145
        (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
 
146
        (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
 
147
        (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
 
148
 
 
149
        (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
 
150
        (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
 
151
        (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
 
152
        (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
 
153
};
 
154
 
 
155
 
 
156
static const float  F44_2 [16 + 32] = {  /* SNR(w) = 10.060213 dB, SNR = -12.766730 dB */
 
157
        (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
 
158
        (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
 
159
        (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
 
160
        (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
 
161
 
 
162
        (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
 
163
        (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
 
164
        (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
 
165
        (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
 
166
 
 
167
        (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
 
168
        (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
 
169
        (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
 
170
        (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
 
171
};
 
172
 
 
173
 
 
174
static const float  F44_3 [16 + 32] = {  /* SNR(w) = 15.382598 dB, SNR = -29.402334 dB */
 
175
        (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
 
176
        (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
 
177
        (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
 
178
        (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
 
179
 
 
180
        (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
 
181
        (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
 
182
        (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
 
183
        (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
 
184
 
 
185
        (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
 
186
        (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
 
187
        (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
 
188
        (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099
 
189
};
 
190
 
 
191
 
 
192
static double scalar16_(const float* x, const float* y)
 
193
{
 
194
        return
 
195
                x[ 0]*y[ 0] + x[ 1]*y[ 1] + x[ 2]*y[ 2] + x[ 3]*y[ 3] +
 
196
                x[ 4]*y[ 4] + x[ 5]*y[ 5] + x[ 6]*y[ 6] + x[ 7]*y[ 7] +
 
197
                x[ 8]*y[ 8] + x[ 9]*y[ 9] + x[10]*y[10] + x[11]*y[11] +
 
198
                x[12]*y[12] + x[13]*y[13] + x[14]*y[14] + x[15]*y[15];
 
199
}
 
200
 
 
201
 
 
202
void FLAC__plugin_common__init_dither_context(DitherContext *d, int bits, int shapingtype)
 
203
{
 
204
        static unsigned char default_dither [] = { 92, 92, 88, 84, 81, 78, 74, 67,  0,  0 };
 
205
        static const float*               F [] = { F44_0, F44_1, F44_2, F44_3 };
 
206
 
 
207
        int index;
 
208
 
 
209
        if (shapingtype < 0) shapingtype = 0;
 
210
        if (shapingtype > 3) shapingtype = 3;
 
211
        index = bits - 11 - shapingtype;
 
212
        if (index < 0) index = 0;
 
213
        if (index > 9) index = 9;
 
214
 
 
215
        memset ( d->ErrorHistory , 0, sizeof (d->ErrorHistory ) );
 
216
        memset ( d->DitherHistory, 0, sizeof (d->DitherHistory) );
 
217
 
 
218
        d->FilterCoeff = F [shapingtype];
 
219
        d->Mask   = ((FLAC__uint64)-1) << (32 - bits);
 
220
        d->Add    = 0.5     * ((1L << (32 - bits)) - 1);
 
221
        d->Dither = 0.01f*default_dither[index] / (((FLAC__int64)1) << bits);
 
222
}
 
223
 
 
224
/*
 
225
 * the following is based on parts of wavegain.c
 
226
 */
 
227
 
 
228
static FLAC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k)
 
229
{
 
230
        double doubletmp, Sum2;
 
231
        FLAC__int64 val;
 
232
 
 
233
#define ROUND64(x)   ( doubletmp = (x) + d->Add + (FLAC__int64)0x001FFFFD80000000L, *(FLAC__int64*)(&doubletmp) - (FLAC__int64)0x433FFFFD80000000L )
 
234
 
 
235
        if(do_dithering) {
 
236
                if(shapingtype == 0) {
 
237
                        double  tmp = random_equi_(d->Dither);
 
238
                        Sum2 = tmp - d->LastRandomNumber [k];
 
239
                        d->LastRandomNumber [k] = (int)tmp;
 
240
                        Sum2 = Sum += Sum2;
 
241
                        val = ROUND64(Sum2) & d->Mask;
 
242
                }
 
243
                else {
 
244
                        Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i);
 
245
                        Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2;
 
246
                        Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i);
 
247
                        val = ROUND64(Sum2) & d->Mask;
 
248
                        d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val);
 
249
                }
 
250
                return val;
 
251
        }
 
252
        else
 
253
                return ROUND64(Sum);
 
254
 
 
255
#undef ROUND64
 
256
}
 
257
 
 
258
#if 0
 
259
        float        peak = 0.f,
 
260
                     new_peak,
 
261
                     factor_clip
 
262
        double       scale,
 
263
                     dB;
 
264
 
 
265
        ...
 
266
 
 
267
        peak is in the range -32768.0 .. 32767.0
 
268
 
 
269
        /* calculate factors for ReplayGain and ClippingPrevention */
 
270
        *track_gain = GetTitleGain() + settings->man_gain;
 
271
        scale = (float) pow(10., *track_gain * 0.05);
 
272
        if(settings->clip_prev) {
 
273
                factor_clip  = (float) (32767./( peak + 1));
 
274
                if(scale < factor_clip)
 
275
                        factor_clip = 1.f;
 
276
                else
 
277
                        factor_clip /= scale;
 
278
                scale *= factor_clip;
 
279
        }
 
280
        new_peak = (float) peak * scale;
 
281
 
 
282
        dB = 20. * log10(scale);
 
283
        *track_gain = (float) dB;
 
284
 
 
285
        const double scale = (float) pow(10., (double)gain * 0.05); /*@@@@ why downcast pow() output to float? */
 
286
#endif
 
287
 
 
288
 
 
289
int FLAC__plugin_common__apply_gain(FLAC__byte *data_out, FLAC__int32 *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, NoiseShaping noise_shaping, DitherContext *dither_context)
 
290
{
 
291
        static const FLAC__int32 conv_factors_[33] = {
 
292
                -1, /* 0 bits-per-sample (not supported) */
 
293
                -1, /* 1 bits-per-sample (not supported) */
 
294
                -1, /* 2 bits-per-sample (not supported) */
 
295
                -1, /* 3 bits-per-sample (not supported) */
 
296
                268435456, /* 4 bits-per-sample */
 
297
                134217728, /* 5 bits-per-sample */
 
298
                67108864, /* 6 bits-per-sample */
 
299
                33554432, /* 7 bits-per-sample */
 
300
                16777216, /* 8 bits-per-sample */
 
301
                8388608, /* 9 bits-per-sample */
 
302
                4194304, /* 10 bits-per-sample */
 
303
                2097152, /* 11 bits-per-sample */
 
304
                1048576, /* 12 bits-per-sample */
 
305
                524288, /* 13 bits-per-sample */
 
306
                262144, /* 14 bits-per-sample */
 
307
                131072, /* 15 bits-per-sample */
 
308
                65536, /* 16 bits-per-sample */
 
309
                32768, /* 17 bits-per-sample */
 
310
                16384, /* 18 bits-per-sample */
 
311
                8192, /* 19 bits-per-sample */
 
312
                4096, /* 20 bits-per-sample */
 
313
                2048, /* 21 bits-per-sample */
 
314
                1024, /* 22 bits-per-sample */
 
315
                512, /* 23 bits-per-sample */
 
316
                256, /* 24 bits-per-sample */
 
317
                128, /* 25 bits-per-sample */
 
318
                64, /* 26 bits-per-sample */
 
319
                32, /* 27 bits-per-sample */
 
320
                16, /* 28 bits-per-sample */
 
321
                8, /* 29 bits-per-sample */
 
322
                4, /* 30 bits-per-sample */
 
323
                2, /* 31 bits-per-sample */
 
324
                1 /* 32 bits-per-sample */
 
325
        };
 
326
        static const FLAC__int64 hard_clip_factors_[33] = {
 
327
                0, /* 0 bits-per-sample (not supported) */
 
328
                0, /* 1 bits-per-sample (not supported) */
 
329
                0, /* 2 bits-per-sample (not supported) */
 
330
                0, /* 3 bits-per-sample (not supported) */
 
331
                -8, /* 4 bits-per-sample */
 
332
                -16, /* 5 bits-per-sample */
 
333
                -32, /* 6 bits-per-sample */
 
334
                -64, /* 7 bits-per-sample */
 
335
                -128, /* 8 bits-per-sample */
 
336
                -256, /* 9 bits-per-sample */
 
337
                -512, /* 10 bits-per-sample */
 
338
                -1024, /* 11 bits-per-sample */
 
339
                -2048, /* 12 bits-per-sample */
 
340
                -4096, /* 13 bits-per-sample */
 
341
                -8192, /* 14 bits-per-sample */
 
342
                -16384, /* 15 bits-per-sample */
 
343
                -32768, /* 16 bits-per-sample */
 
344
                -65536, /* 17 bits-per-sample */
 
345
                -131072, /* 18 bits-per-sample */
 
346
                -262144, /* 19 bits-per-sample */
 
347
                -524288, /* 20 bits-per-sample */
 
348
                -1048576, /* 21 bits-per-sample */
 
349
                -2097152, /* 22 bits-per-sample */
 
350
                -4194304, /* 23 bits-per-sample */
 
351
                -8388608, /* 24 bits-per-sample */
 
352
                -16777216, /* 25 bits-per-sample */
 
353
                -33554432, /* 26 bits-per-sample */
 
354
                -67108864, /* 27 bits-per-sample */
 
355
                -134217728, /* 28 bits-per-sample */
 
356
                -268435456, /* 29 bits-per-sample */
 
357
                -536870912, /* 30 bits-per-sample */
 
358
                -1073741824, /* 31 bits-per-sample */
 
359
                (FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */
 
360
        };
 
361
        const FLAC__int32 conv_factor = conv_factors_[target_bps];
 
362
        const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps];
 
363
        /*
 
364
         * The integer input coming in has a varying range based on the
 
365
         * source_bps.  We want to normalize it to [-1.0, 1.0) so instead
 
366
         * of doing two multiplies on each sample, we just multiple
 
367
         * 'scale' by 1/(2^(source_bps-1))
 
368
         */
 
369
        const double multi_scale = scale / (double)(1u << (source_bps-1));
 
370
 
 
371
        FLAC__byte * const start = data_out;
 
372
        const unsigned samples = wide_samples * channels;
 
373
#ifdef FLAC__PLUGIN_COMMON__DONT_UNROLL
 
374
        const unsigned dither_twiggle = channels - 1;
 
375
        unsigned dither_source = 0;
 
376
#endif
 
377
        unsigned i;
 
378
        int coeff;
 
379
        double sample;
 
380
 
 
381
        FLAC__ASSERT(FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS == 2);
 
382
        FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS);
 
383
        FLAC__ASSERT(source_bps >= 4);
 
384
        FLAC__ASSERT(target_bps >= 4);
 
385
        FLAC__ASSERT(source_bps <= 32);
 
386
        FLAC__ASSERT(target_bps < 32);
 
387
        FLAC__ASSERT((target_bps & 7) == 0);
 
388
 
 
389
#ifdef FLAC__PLUGIN_COMMON__DONT_UNROLL
 
390
        /*
 
391
         * This flavor handles 1 or 2 channels with the same code
 
392
         */
 
393
        coeff = 0;
 
394
        for(i = 0; i < samples; i++, coeff++) {
 
395
                sample = (double)input[i] * multi_scale;
 
396
 
 
397
                if(hard_limit) {
 
398
                        /* hard 6dB limiting */
 
399
                        if(sample < -0.5)
 
400
                                sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
 
401
                        else if(sample > 0.5)
 
402
                                sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
 
403
                }
 
404
                sample *= 2147483647.f;
 
405
 
 
406
                {
 
407
                        FLAC__int64 val64;
 
408
                        FLAC__int32 val32;
 
409
 
 
410
                        if(coeff >= (32<<dither_twiggle))
 
411
                                coeff = 0;
 
412
 
 
413
                        /* 'coeff>>dither_twiggle' is the same as 'coeff/channels' */
 
414
                        val64 = dither_output_(dither_context, do_dithering, noise_shaping, coeff>>dither_twiggle, sample, dither_source) / conv_factor;
 
415
 
 
416
                        dither_source ^= dither_twiggle;
 
417
 
 
418
                        val32 = (FLAC__int32)val64;
 
419
                        if(val64 >= -hard_clip_factor)
 
420
                                val32 = (FLAC__int32)(-(hard_clip_factor+1));
 
421
                        else if(val64 < hard_clip_factor)
 
422
                                val32 = (FLAC__int32)hard_clip_factor;
 
423
 
 
424
                        switch(target_bps) {
 
425
                                case 8:
 
426
                                        data_out[0] = val32 ^ 0x80;
 
427
                                        break;
 
428
                                case 24:
 
429
                                        data_out[2] = (FLAC__byte)(val32 >> 16);
 
430
                                        /* fall through */
 
431
                                case 16:
 
432
                                        data_out[1] = (FLAC__byte)(val32 >> 8);
 
433
                                        data_out[0] = (FLAC__byte)val32;
 
434
                        }
 
435
                }
 
436
 
 
437
                data_out += target_bps/8;
 
438
        }
 
439
#else
 
440
        /*
 
441
         * This flavor has optimized versions for 1 or 2 channels
 
442
         */
 
443
        if(channels == 2) {
 
444
                FLAC__int64 val64;
 
445
                FLAC__int32 val32;
 
446
 
 
447
                coeff = 0;
 
448
                for(i = 0; i < samples; ) {
 
449
                        sample = (double)input[i] * multi_scale;
 
450
 
 
451
                        if(hard_limit) {
 
452
                                /* hard 6dB limiting */
 
453
                                if(sample < -0.5)
 
454
                                        sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
 
455
                                else if(sample > 0.5)
 
456
                                        sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
 
457
                        }
 
458
                        sample *= 2147483647.f;
 
459
 
 
460
                        val64 = dither_output_(dither_context, do_dithering, noise_shaping, coeff, sample, 0) / conv_factor;
 
461
 
 
462
                        val32 = (FLAC__int32)val64;
 
463
                        if(val64 >= -hard_clip_factor)
 
464
                                val32 = (FLAC__int32)(-(hard_clip_factor+1));
 
465
                        else if(val64 < hard_clip_factor)
 
466
                                val32 = (FLAC__int32)hard_clip_factor;
 
467
 
 
468
                        switch(target_bps) {
 
469
                                case 8:
 
470
                                        data_out[0] = val32 ^ 0x80;
 
471
                                        break;
 
472
                                case 24:
 
473
                                        data_out[2] = (FLAC__byte)(val32 >> 16);
 
474
                                        /* fall through */
 
475
                                case 16:
 
476
                                        data_out[1] = (FLAC__byte)(val32 >> 8);
 
477
                                        data_out[0] = (FLAC__byte)val32;
 
478
                        }
 
479
 
 
480
                        data_out += target_bps/8;
 
481
 
 
482
                        i++;
 
483
 
 
484
                        sample = (double)input[i] * multi_scale;
 
485
 
 
486
                        if(hard_limit) {
 
487
                                /* hard 6dB limiting */
 
488
                                if(sample < -0.5)
 
489
                                        sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
 
490
                                else if(sample > 0.5)
 
491
                                        sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
 
492
                        }
 
493
                        sample *= 2147483647.f;
 
494
 
 
495
                        val64 = dither_output_(dither_context, do_dithering, noise_shaping, coeff, sample, 1) / conv_factor;
 
496
 
 
497
                        val32 = (FLAC__int32)val64;
 
498
                        if(val64 >= -hard_clip_factor)
 
499
                                val32 = (FLAC__int32)(-(hard_clip_factor+1));
 
500
                        else if(val64 < hard_clip_factor)
 
501
                                val32 = (FLAC__int32)hard_clip_factor;
 
502
 
 
503
                        switch(target_bps) {
 
504
                                case 8:
 
505
                                        data_out[0] = val32 ^ 0x80;
 
506
                                        break;
 
507
                                case 24:
 
508
                                        data_out[2] = (FLAC__byte)(val32 >> 16);
 
509
                                        /* fall through */
 
510
                                case 16:
 
511
                                        data_out[1] = (FLAC__byte)(val32 >> 8);
 
512
                                        data_out[0] = (FLAC__byte)val32;
 
513
                        }
 
514
 
 
515
                        data_out += target_bps/8;
 
516
 
 
517
                        i++;
 
518
                        coeff++;
 
519
                        if(coeff >= 32)
 
520
                                coeff = 0;
 
521
                }
 
522
        }
 
523
        else {
 
524
                FLAC__int64 val64;
 
525
                FLAC__int32 val32;
 
526
 
 
527
                coeff = 0;
 
528
                for(i = 0; i < samples; i++, coeff++) {
 
529
                        if(coeff >= 32)
 
530
                                coeff = 0;
 
531
 
 
532
                        sample = (double)input[i] * multi_scale;
 
533
 
 
534
                        if(hard_limit) {
 
535
                                /* hard 6dB limiting */
 
536
                                if(sample < -0.5)
 
537
                                        sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
 
538
                                else if(sample > 0.5)
 
539
                                        sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
 
540
                        }
 
541
                        sample *= 2147483647.f;
 
542
 
 
543
                        val64 = dither_output_(dither_context, do_dithering, noise_shaping, coeff, sample, 0) / conv_factor;
 
544
 
 
545
                        val32 = (FLAC__int32)val64;
 
546
                        if(val64 >= -hard_clip_factor)
 
547
                                val32 = (FLAC__int32)(-(hard_clip_factor+1));
 
548
                        else if(val64 < hard_clip_factor)
 
549
                                val32 = (FLAC__int32)hard_clip_factor;
 
550
 
 
551
                        switch(target_bps) {
 
552
                                case 8:
 
553
                                        data_out[0] = val32 ^ 0x80;
 
554
                                        break;
 
555
                                case 24:
 
556
                                        data_out[2] = (FLAC__byte)(val32 >> 16);
 
557
                                        /* fall through */
 
558
                                case 16:
 
559
                                        data_out[1] = (FLAC__byte)(val32 >> 8);
 
560
                                        data_out[0] = (FLAC__byte)val32;
 
561
                        }
 
562
 
 
563
                        data_out += target_bps/8;
 
564
                }
 
565
        }
 
566
#endif
 
567
 
 
568
        return data_out - start;
 
569
}