unify inlining method in prep for inline tests
[flac.git] / src / plugin_common / dither.c
1 /* plugin_common - Routines common to several plugins
2  * Copyright (C) 2002,2003,2004,2005,2006,2007  Josh Coalson
3  *
4  * dithering routine derived from (other GPLed source):
5  * mad - MPEG audio decoder
6  * Copyright (C) 2000-2001 Robert Leslie
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #if HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include "dither.h"
28 #include "FLAC/assert.h"
29
30 #ifdef max
31 #undef max
32 #endif
33 #define max(a,b) ((a)>(b)?(a):(b))
34
35 #ifndef FLaC__INLINE
36 #define FLaC__INLINE
37 #endif
38
39
40 /* 32-bit pseudo-random number generator
41  *
42  * @@@ According to Miroslav, this one is poor quality, the one from the
43  * @@@ original replaygain code is much better
44  */
45 static FLaC__INLINE FLAC__uint32 prng(FLAC__uint32 state)
46 {
47         return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
48 }
49
50 /* dither routine derived from MAD winamp plugin */
51
52 typedef struct {
53         FLAC__int32 error[3];
54         FLAC__int32 random;
55 } dither_state;
56
57 static FLaC__INLINE FLAC__int32 linear_dither(unsigned source_bps, unsigned target_bps, FLAC__int32 sample, dither_state *dither, const FLAC__int32 MIN, const FLAC__int32 MAX)
58 {
59         unsigned scalebits;
60         FLAC__int32 output, mask, random;
61
62         FLAC__ASSERT(source_bps < 32);
63         FLAC__ASSERT(target_bps <= 24);
64         FLAC__ASSERT(target_bps <= source_bps);
65
66         /* noise shape */
67         sample += dither->error[0] - dither->error[1] + dither->error[2];
68
69         dither->error[2] = dither->error[1];
70         dither->error[1] = dither->error[0] / 2;
71
72         /* bias */
73         output = sample + (1L << (source_bps - target_bps - 1));
74
75         scalebits = source_bps - target_bps;
76         mask = (1L << scalebits) - 1;
77
78         /* dither */
79         random = (FLAC__int32)prng(dither->random);
80         output += (random & mask) - (dither->random & mask);
81
82         dither->random = random;
83
84         /* clip */
85         if(output > MAX) {
86                 output = MAX;
87
88                 if(sample > MAX)
89                         sample = MAX;
90         }
91         else if(output < MIN) {
92                 output = MIN;
93
94                 if(sample < MIN)
95                         sample = MIN;
96         }
97
98         /* quantize */
99         output &= ~mask;
100
101         /* error feedback */
102         dither->error[0] = sample - output;
103
104         /* scale */
105         return output >> scalebits;
106 }
107
108 size_t FLAC__plugin_common__pack_pcm_signed_big_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps)
109 {
110         static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
111         FLAC__byte * const start = data;
112         FLAC__int32 sample;
113         const FLAC__int32 *input_;
114         unsigned samples, channel;
115         const unsigned bytes_per_sample = target_bps / 8;
116         const unsigned incr = bytes_per_sample * channels;
117
118         FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS);
119         FLAC__ASSERT(source_bps < 32);
120         FLAC__ASSERT(target_bps <= 24);
121         FLAC__ASSERT(target_bps <= source_bps);
122         FLAC__ASSERT((source_bps & 7) == 0);
123         FLAC__ASSERT((target_bps & 7) == 0);
124
125         if(source_bps != target_bps) {
126                 const FLAC__int32 MIN = -(1L << (source_bps - 1));
127                 const FLAC__int32 MAX = ~MIN; /*(1L << (source_bps-1)) - 1 */
128
129                 for(channel = 0; channel < channels; channel++) {
130                         
131                         samples = wide_samples;
132                         data = start + bytes_per_sample * channel;
133                         input_ = input[channel];
134
135                         while(samples--) {
136                                 sample = linear_dither(source_bps, target_bps, *input_++, &dither[channel], MIN, MAX);
137
138                                 switch(target_bps) {
139                                         case 8:
140                                                 data[0] = sample ^ 0x80;
141                                                 break;
142                                         case 16:
143                                                 data[0] = (FLAC__byte)(sample >> 8);
144                                                 data[1] = (FLAC__byte)sample;
145                                                 break;
146                                         case 24:
147                                                 data[0] = (FLAC__byte)(sample >> 16);
148                                                 data[1] = (FLAC__byte)(sample >> 8);
149                                                 data[2] = (FLAC__byte)sample;
150                                                 break;
151                                 }
152
153                                 data += incr;
154                         }
155                 }
156         }
157         else {
158                 for(channel = 0; channel < channels; channel++) {
159                         samples = wide_samples;
160                         data = start + bytes_per_sample * channel;
161                         input_ = input[channel];
162
163                         while(samples--) {
164                                 sample = *input_++;
165
166                                 switch(target_bps) {
167                                         case 8:
168                                                 data[0] = sample ^ 0x80;
169                                                 break;
170                                         case 16:
171                                                 data[0] = (FLAC__byte)(sample >> 8);
172                                                 data[1] = (FLAC__byte)sample;
173                                                 break;
174                                         case 24:
175                                                 data[0] = (FLAC__byte)(sample >> 16);
176                                                 data[1] = (FLAC__byte)(sample >> 8);
177                                                 data[2] = (FLAC__byte)sample;
178                                                 break;
179                                 }
180
181                                 data += incr;
182                         }
183                 }
184         }
185
186         return wide_samples * channels * (target_bps/8);
187 }
188
189 size_t FLAC__plugin_common__pack_pcm_signed_little_endian(FLAC__byte *data, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, unsigned source_bps, unsigned target_bps)
190 {
191         static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
192         FLAC__byte * const start = data;
193         FLAC__int32 sample;
194         const FLAC__int32 *input_;
195         unsigned samples, channel;
196         const unsigned bytes_per_sample = target_bps / 8;
197         const unsigned incr = bytes_per_sample * channels;
198
199         FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS);
200         FLAC__ASSERT(source_bps < 32);
201         FLAC__ASSERT(target_bps <= 24);
202         FLAC__ASSERT(target_bps <= source_bps);
203         FLAC__ASSERT((source_bps & 7) == 0);
204         FLAC__ASSERT((target_bps & 7) == 0);
205
206         if(source_bps != target_bps) {
207                 const FLAC__int32 MIN = -(1L << (source_bps - 1));
208                 const FLAC__int32 MAX = ~MIN; /*(1L << (source_bps-1)) - 1 */
209
210                 for(channel = 0; channel < channels; channel++) {
211                         
212                         samples = wide_samples;
213                         data = start + bytes_per_sample * channel;
214                         input_ = input[channel];
215
216                         while(samples--) {
217                                 sample = linear_dither(source_bps, target_bps, *input_++, &dither[channel], MIN, MAX);
218
219                                 switch(target_bps) {
220                                         case 8:
221                                                 data[0] = sample ^ 0x80;
222                                                 break;
223                                         case 24:
224                                                 data[2] = (FLAC__byte)(sample >> 16);
225                                                 /* fall through */
226                                         case 16:
227                                                 data[1] = (FLAC__byte)(sample >> 8);
228                                                 data[0] = (FLAC__byte)sample;
229                                 }
230
231                                 data += incr;
232                         }
233                 }
234         }
235         else {
236                 for(channel = 0; channel < channels; channel++) {
237                         samples = wide_samples;
238                         data = start + bytes_per_sample * channel;
239                         input_ = input[channel];
240
241                         while(samples--) {
242                                 sample = *input_++;
243
244                                 switch(target_bps) {
245                                         case 8:
246                                                 data[0] = sample ^ 0x80;
247                                                 break;
248                                         case 24:
249                                                 data[2] = (FLAC__byte)(sample >> 16);
250                                                 /* fall through */
251                                         case 16:
252                                                 data[1] = (FLAC__byte)(sample >> 8);
253                                                 data[0] = (FLAC__byte)sample;
254                                 }
255
256                                 data += incr;
257                         }
258                 }
259         }
260
261         return wide_samples * channels * (target_bps/8);
262 }