Mercurial > audlegacy-plugins
comparison src/flac113/plugin_common/dither.c @ 103:117bc56d906b trunk
[svn] flac -> flac113
| author | nenolod |
|---|---|
| date | Mon, 23 Oct 2006 19:51:39 -0700 |
| parents | src/flac/plugin_common/dither.c@3da1b8942b8b |
| children |
comparison
equal
deleted
inserted
replaced
| 102:aff1cf3e86dd | 103:117bc56d906b |
|---|---|
| 1 /* plugin_common - Routines common to several plugins | |
| 2 * Copyright (C) 2002,2003,2004,2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 21 */ | |
| 22 | |
| 23 #include "dither.h" | |
| 24 #include "FLAC/assert.h" | |
| 25 | |
| 26 #ifdef max | |
| 27 #undef max | |
| 28 #endif | |
| 29 #define max(a,b) ((a)>(b)?(a):(b)) | |
| 30 | |
| 31 | |
| 32 #if defined _MSC_VER | |
| 33 #define FLAC__INLINE __inline | |
| 34 #else | |
| 35 #define FLAC__INLINE | |
| 36 #endif | |
| 37 | |
| 38 /* 32-bit pseudo-random number generator | |
| 39 * | |
| 40 * @@@ According to Miroslav, this one is poor quality, the one from the | |
| 41 * @@@ original replaygain code is much better | |
| 42 */ | |
| 43 static FLAC__INLINE FLAC__uint32 prng(FLAC__uint32 state) | |
| 44 { | |
| 45 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; | |
| 46 } | |
| 47 | |
| 48 /* dither routine derived from MAD winamp plugin */ | |
| 49 | |
| 50 typedef struct { | |
| 51 FLAC__int32 error[3]; | |
| 52 FLAC__int32 random; | |
| 53 } dither_state; | |
| 54 | |
| 55 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) | |
| 56 { | |
| 57 unsigned scalebits; | |
| 58 FLAC__int32 output, mask, random; | |
| 59 | |
| 60 FLAC__ASSERT(source_bps < 32); | |
| 61 FLAC__ASSERT(target_bps <= 24); | |
| 62 FLAC__ASSERT(target_bps <= source_bps); | |
| 63 | |
| 64 /* noise shape */ | |
| 65 sample += dither->error[0] - dither->error[1] + dither->error[2]; | |
| 66 | |
| 67 dither->error[2] = dither->error[1]; | |
| 68 dither->error[1] = dither->error[0] / 2; | |
| 69 | |
| 70 /* bias */ | |
| 71 output = sample + (1L << (source_bps - target_bps - 1)); | |
| 72 | |
| 73 scalebits = source_bps - target_bps; | |
| 74 mask = (1L << scalebits) - 1; | |
| 75 | |
| 76 /* dither */ | |
| 77 random = (FLAC__int32)prng(dither->random); | |
| 78 output += (random & mask) - (dither->random & mask); | |
| 79 | |
| 80 dither->random = random; | |
| 81 | |
| 82 /* clip */ | |
| 83 if(output > MAX) { | |
| 84 output = MAX; | |
| 85 | |
| 86 if(sample > MAX) | |
| 87 sample = MAX; | |
| 88 } | |
| 89 else if(output < MIN) { | |
| 90 output = MIN; | |
| 91 | |
| 92 if(sample < MIN) | |
| 93 sample = MIN; | |
| 94 } | |
| 95 | |
| 96 /* quantize */ | |
| 97 output &= ~mask; | |
| 98 | |
| 99 /* error feedback */ | |
| 100 dither->error[0] = sample - output; | |
| 101 | |
| 102 /* scale */ | |
| 103 return output >> scalebits; | |
| 104 } | |
| 105 | |
| 106 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) | |
| 107 { | |
| 108 static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; | |
| 109 FLAC__byte * const start = data; | |
| 110 FLAC__int32 sample; | |
| 111 const FLAC__int32 *input_; | |
| 112 unsigned samples, channel; | |
| 113 const unsigned bytes_per_sample = target_bps / 8; | |
| 114 const unsigned incr = bytes_per_sample * channels; | |
| 115 | |
| 116 FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS); | |
| 117 FLAC__ASSERT(source_bps < 32); | |
| 118 FLAC__ASSERT(target_bps <= 24); | |
| 119 FLAC__ASSERT(target_bps <= source_bps); | |
| 120 FLAC__ASSERT((source_bps & 7) == 0); | |
| 121 FLAC__ASSERT((target_bps & 7) == 0); | |
| 122 | |
| 123 if(source_bps != target_bps) { | |
| 124 const FLAC__int32 MIN = -(1L << (source_bps - 1)); | |
| 125 const FLAC__int32 MAX = ~MIN; /*(1L << (source_bps-1)) - 1 */ | |
| 126 | |
| 127 for(channel = 0; channel < channels; channel++) { | |
| 128 | |
| 129 samples = wide_samples; | |
| 130 data = start + bytes_per_sample * channel; | |
| 131 input_ = input[channel]; | |
| 132 | |
| 133 while(samples--) { | |
| 134 sample = linear_dither(source_bps, target_bps, *input_++, &dither[channel], MIN, MAX); | |
| 135 | |
| 136 switch(target_bps) { | |
| 137 case 8: | |
| 138 data[0] = sample ^ 0x80; | |
| 139 break; | |
| 140 case 16: | |
| 141 data[0] = (FLAC__byte)(sample >> 8); | |
| 142 data[1] = (FLAC__byte)sample; | |
| 143 break; | |
| 144 case 24: | |
| 145 data[0] = (FLAC__byte)(sample >> 16); | |
| 146 data[1] = (FLAC__byte)(sample >> 8); | |
| 147 data[2] = (FLAC__byte)sample; | |
| 148 break; | |
| 149 } | |
| 150 | |
| 151 data += incr; | |
| 152 } | |
| 153 } | |
| 154 } | |
| 155 else { | |
| 156 for(channel = 0; channel < channels; channel++) { | |
| 157 samples = wide_samples; | |
| 158 data = start + bytes_per_sample * channel; | |
| 159 input_ = input[channel]; | |
| 160 | |
| 161 while(samples--) { | |
| 162 sample = *input_++; | |
| 163 | |
| 164 switch(target_bps) { | |
| 165 case 8: | |
| 166 data[0] = sample ^ 0x80; | |
| 167 break; | |
| 168 case 16: | |
| 169 data[0] = (FLAC__byte)(sample >> 8); | |
| 170 data[1] = (FLAC__byte)sample; | |
| 171 break; | |
| 172 case 24: | |
| 173 data[0] = (FLAC__byte)(sample >> 16); | |
| 174 data[1] = (FLAC__byte)(sample >> 8); | |
| 175 data[2] = (FLAC__byte)sample; | |
| 176 break; | |
| 177 } | |
| 178 | |
| 179 data += incr; | |
| 180 } | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 return wide_samples * channels * (target_bps/8); | |
| 185 } | |
| 186 | |
| 187 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) | |
| 188 { | |
| 189 static dither_state dither[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; | |
| 190 FLAC__byte * const start = data; | |
| 191 FLAC__int32 sample; | |
| 192 const FLAC__int32 *input_; | |
| 193 unsigned samples, channel; | |
| 194 const unsigned bytes_per_sample = target_bps / 8; | |
| 195 const unsigned incr = bytes_per_sample * channels; | |
| 196 | |
| 197 FLAC__ASSERT(channels > 0 && channels <= FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS); | |
| 198 FLAC__ASSERT(source_bps < 32); | |
| 199 FLAC__ASSERT(target_bps <= 24); | |
| 200 FLAC__ASSERT(target_bps <= source_bps); | |
| 201 FLAC__ASSERT((source_bps & 7) == 0); | |
| 202 FLAC__ASSERT((target_bps & 7) == 0); | |
| 203 | |
| 204 if(source_bps != target_bps) { | |
| 205 const FLAC__int32 MIN = -(1L << (source_bps - 1)); | |
| 206 const FLAC__int32 MAX = ~MIN; /*(1L << (source_bps-1)) - 1 */ | |
| 207 | |
| 208 for(channel = 0; channel < channels; channel++) { | |
| 209 | |
| 210 samples = wide_samples; | |
| 211 data = start + bytes_per_sample * channel; | |
| 212 input_ = input[channel]; | |
| 213 | |
| 214 while(samples--) { | |
| 215 sample = linear_dither(source_bps, target_bps, *input_++, &dither[channel], MIN, MAX); | |
| 216 | |
| 217 switch(target_bps) { | |
| 218 case 8: | |
| 219 data[0] = sample ^ 0x80; | |
| 220 break; | |
| 221 case 24: | |
| 222 data[2] = (FLAC__byte)(sample >> 16); | |
| 223 /* fall through */ | |
| 224 case 16: | |
| 225 data[1] = (FLAC__byte)(sample >> 8); | |
| 226 data[0] = (FLAC__byte)sample; | |
| 227 } | |
| 228 | |
| 229 data += incr; | |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 else { | |
| 234 for(channel = 0; channel < channels; channel++) { | |
| 235 samples = wide_samples; | |
| 236 data = start + bytes_per_sample * channel; | |
| 237 input_ = input[channel]; | |
| 238 | |
| 239 while(samples--) { | |
| 240 sample = *input_++; | |
| 241 | |
| 242 switch(target_bps) { | |
| 243 case 8: | |
| 244 data[0] = sample ^ 0x80; | |
| 245 break; | |
| 246 case 24: | |
| 247 data[2] = (FLAC__byte)(sample >> 16); | |
| 248 /* fall through */ | |
| 249 case 16: | |
| 250 data[1] = (FLAC__byte)(sample >> 8); | |
| 251 data[0] = (FLAC__byte)sample; | |
| 252 } | |
| 253 | |
| 254 data += incr; | |
| 255 } | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 return wide_samples * channels * (target_bps/8); | |
| 260 } |
