Mercurial > audlegacy
comparison Plugins/Input/mpg123/psycho.c @ 1090:09eb2c83097a trunk
[svn] Psychoaccoustics support (to disable, temporarily add -UPSYCHO to your CFLAGS.):
This commit brings psychoaccoustics support (as used in mp3surround decoders) to libmpgdec.
For example, we can now almost fully compensate for lack of bandwidth in ISO compliant MP3 encodings.
In addition, further inaccuracies with pitch and the lack of reverb feeling that some MP3s have are
detected and automatically compensated for.
author | nenolod |
---|---|
date | Sat, 20 May 2006 20:36:10 -0700 |
parents | |
children | 5b6fcb22f3c4 |
comparison
equal
deleted
inserted
replaced
1089:e75c7856fbea | 1090:09eb2c83097a |
---|---|
1 /* libmpgdec: An advanced MPEG layer 1/2/3 decoder. | |
2 * psycho.c: Psychoaccoustic modeling. | |
3 * | |
4 * Copyright (C) 2005-2006 William Pitcock <nenolod@nenolod.net> | |
5 * Portions copyright (C) 2001 Rafal Bosak <gyver@fanthom.irc.pl> | |
6 * Portions copyright (C) 1999 Michael Hipp | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (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 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 #include <math.h> | |
26 | |
27 #include "common.h" | |
28 | |
29 int bext_level; | |
30 int echo_level; | |
31 int stereo_level; | |
32 int filter_level; | |
33 int feedback_level; | |
34 int harmonics_level; | |
35 int bext_sfactor; | |
36 int echo_sfactor; | |
37 int stereo_sfactor; | |
38 int feedback_sfactor; | |
39 int harmonics_sfactor; | |
40 int enable_plugin = 1; | |
41 int lsine[65536]; | |
42 int rsine[65536]; | |
43 | |
44 /* | |
45 * Initialize and configure the psychoaccoustics engine. | |
46 */ | |
47 void psycho_init(void) | |
48 { | |
49 int i, x; | |
50 double lsum; | |
51 double rsum; | |
52 | |
53 bext_level = 28; | |
54 echo_level = echo_sfactor = 11; | |
55 stereo_level = stereo_sfactor = 11; | |
56 filter_level = 3; | |
57 feedback_level = 30; | |
58 harmonics_level = harmonics_sfactor = 43; | |
59 | |
60 bext_sfactor = (float)(((float)16384 * 10) / (float)(bext_level + 1)) + (float)(102 - bext_level) * 128; | |
61 feedback_sfactor = (feedback_level * 3) / 2; | |
62 | |
63 #define COND 0 | |
64 /* calculate sinetables */ | |
65 for (i = 0; i < 32768; ++i) | |
66 { | |
67 lsum = rsum = 0; | |
68 if (COND || i < 32768 )lsum+= ((cos((double)i * 3.141592535 / 32768/2 )) + 0) / 2; | |
69 if (COND || i < 16384 )rsum-= ((cos((double)i * 3.141592535 / 16384/2 )) + 0) / 4; | |
70 rsum = lsum; | |
71 | |
72 if (COND || i < 8192 ) lsum += ((cos((double)i * 3.141592535 / 8192/2 )) + 0) / 8; | |
73 if (COND || i < 5641 ) rsum += ((cos((double)i * 3.141592535 / 5641.333333/2)) + 0) / 8; | |
74 | |
75 lsine[32768 + i] = (double)(lsum - 0.5) * 32768 * 1.45; | |
76 lsine[32768 - i] = lsine[32768 + i]; | |
77 rsine[32768 + i] = (double)(rsum - 0.5) * 32768 * 1.45; | |
78 rsine[32768 - i] = rsine[32768 + i]; | |
79 | |
80 x = i; | |
81 } | |
82 } | |
83 | |
84 /* | |
85 * This routine computes a reverb for the track. | |
86 */ | |
87 | |
88 #define DELAY2 21000 | |
89 #define DELAY1 35000 | |
90 #define DELAY3 14000 | |
91 #define DELAY4 5 | |
92 | |
93 #define BUF_SIZE DELAY1+DELAY2+DELAY3+DELAY4 | |
94 | |
95 void echo3d(gint16 *data, int datasize) | |
96 { | |
97 int x; | |
98 int left, right, dif, left0, right0, left1, right1, left2, right2, left3, right3, left4, right4, leftc, rightc, lsf, rsf; | |
99 static int left0p = 0, right0p = 0; | |
100 static int rangeErrorsUp = 0; | |
101 static int rangeErrorsDown = 0; | |
102 gint16 *dataptr; | |
103 static int l0, l1, l2, r0, r1, r2, ls, rs, ls1, rs1; | |
104 static int ll0, ll1, ll2, rr0, rr1, rr2; | |
105 static int lharmb = 0, rharmb = 0, lhfb = 0, rhfb = 0; | |
106 int lharm0, rharm0; | |
107 static gint16 buf[BUF_SIZE]; | |
108 static int bufPos = BUF_SIZE - 1; | |
109 static int bufPos1 = 1 + BUF_SIZE - DELAY1; | |
110 static int bufPos2 = 1 + BUF_SIZE - DELAY1 - DELAY2; | |
111 static int bufPos3 = 1 + BUF_SIZE - DELAY1 - DELAY2 - DELAY3; | |
112 static int bufPos4 = 1 + BUF_SIZE - DELAY1 - DELAY2 - DELAY3 - DELAY4; | |
113 dataptr = data; | |
114 | |
115 for (x = 0; x < datasize; x += 4) { | |
116 | |
117 // ************ load sample ********** | |
118 left0 = dataptr[0]; | |
119 right0 = dataptr[1]; | |
120 | |
121 // ************ slightly expand stereo for direct input ********** | |
122 ll0=left0;rr0=right0; | |
123 dif = (ll0+ll1+ll2 - rr0-rr1-rr2) * stereo_sfactor / 256; | |
124 left0 += dif; | |
125 right0 -= dif; | |
126 ll2= ll1; ll1= ll0; | |
127 rr2= rr1; rr1= rr0; | |
128 | |
129 // ************ echo from buffer - first echo ********** | |
130 // ************ ********** | |
131 left1 = buf[bufPos1++]; | |
132 if (bufPos1 == BUF_SIZE) | |
133 bufPos1 = 0; | |
134 right1 = buf[bufPos1++]; | |
135 if (bufPos1 == BUF_SIZE) | |
136 bufPos1 = 0; | |
137 | |
138 // ************ highly expand stereo for first echo ********** | |
139 dif = (left1 - right1); | |
140 left1 = left1 + dif; | |
141 right1 = right1 - dif; | |
142 | |
143 // ************ second echo ********** | |
144 left2 = buf[bufPos2++]; | |
145 if (bufPos2 == BUF_SIZE) | |
146 bufPos2 = 0; | |
147 right2 = buf[bufPos2++]; | |
148 if (bufPos2 == BUF_SIZE) | |
149 bufPos2 = 0; | |
150 | |
151 // ************ expand stereo for second echo ********** | |
152 dif = (left2 - right2); | |
153 left2 = left2 - dif; | |
154 right2 = right2 - dif; | |
155 | |
156 // ************ third echo ********** | |
157 left3 = buf[bufPos3++]; | |
158 if (bufPos3 == BUF_SIZE) | |
159 bufPos3 = 0; | |
160 right3 = buf[bufPos3++]; | |
161 if (bufPos3 == BUF_SIZE) | |
162 bufPos3 = 0; | |
163 | |
164 // ************ fourth echo ********** | |
165 left4 = buf[bufPos4++]; | |
166 if (bufPos4 == BUF_SIZE) | |
167 bufPos4 = 0; | |
168 right4 = buf[bufPos4++]; | |
169 if (bufPos4 == BUF_SIZE) | |
170 bufPos4 = 0; | |
171 | |
172 left3 = (left4+left3) / 2; | |
173 right3 = (right4+right3) / 2; | |
174 | |
175 // ************ expand stereo for second echo ********** | |
176 dif = (left4 - right4); | |
177 left3 = left3 - dif; | |
178 right3 = right3 - dif; | |
179 | |
180 // ************ a weighted sum taken from reverb buffer ********** | |
181 leftc = left1 / 9 + right2 /8 + left3 / 8; | |
182 rightc = right1 / 11 + left2 / 9 + right3 / 10; | |
183 | |
184 left = left0p + leftc * echo_sfactor / 16; | |
185 right = right0p + rightc * echo_sfactor / 16; | |
186 | |
187 l0 = leftc + left0 / 2; | |
188 r0 = rightc + right0 / 2; | |
189 | |
190 ls = l0 + l1 + l2; // do not reverb high frequencies (filter) | |
191 rs = r0 + r1 + r2; // | |
192 | |
193 buf[bufPos++] = ls * feedback_sfactor / 256; | |
194 if (bufPos == BUF_SIZE) | |
195 bufPos = 0; | |
196 buf[bufPos++] = rs * feedback_sfactor / 256; | |
197 if (bufPos == BUF_SIZE) | |
198 bufPos = 0; | |
199 | |
200 // ************ add some extra even harmonics ********** | |
201 // ************ or rather specific nonlinearity | |
202 | |
203 lhfb = lhfb + (ls * 32768 - lhfb) / 32; | |
204 rhfb = rhfb + (rs * 32768 - rhfb) / 32; | |
205 | |
206 lsf = ls - lhfb / 32768; | |
207 rsf = rs - rhfb / 32768; | |
208 | |
209 lharm0 = 0 | |
210 + ((lsf + 10000) * ((((lsine[((lsf/4) + 32768 + 65536) % 65536] * harmonics_sfactor)) / 64))) / 32768 | |
211 - ((lsine[((lsf/4) + 32768 +65536) % 65536]) * harmonics_sfactor) / 128 | |
212 ; | |
213 | |
214 rharm0 = | |
215 + ((rsf + 10000) * ((((lsine[((rsf/4) + 32768 + 65536) % 65536] * harmonics_sfactor)) / 64))) / 32768 | |
216 - ((rsine[((rsf/4) + 32768 +65536) % 65536]) * harmonics_sfactor) / 128 | |
217 ; | |
218 | |
219 lharmb = lharmb + (lharm0 * 32768 - lharmb) / 16384; | |
220 rharmb = rharmb + (rharm0 * 32768 - rharmb) / 16384; | |
221 | |
222 // ************ for convolution filters ********** | |
223 l2= l1; r2= r1; | |
224 l1 = l0; r1 = r0; | |
225 ls1 = ls; rs1 = rs; | |
226 | |
227 left = 0 + lharm0 - lharmb / 32768 + left; | |
228 right = 0 + rharm0 - rharmb / 32768 + right; | |
229 | |
230 left0p = left0; | |
231 right0p = right0; | |
232 | |
233 | |
234 // ************ limiter ********** | |
235 if (left < -32768) { | |
236 left = -32768; // limit | |
237 rangeErrorsDown++; | |
238 } | |
239 else if (left > 32767) { | |
240 left = 32767; | |
241 rangeErrorsUp++; | |
242 } | |
243 if (right < -32768) { | |
244 right = -32768; | |
245 rangeErrorsDown++; | |
246 } | |
247 else if (right > 32767) { | |
248 right = 32767; | |
249 rangeErrorsUp++; | |
250 } | |
251 // ************ store sample ********** | |
252 dataptr[0] = left; | |
253 dataptr[1] = right; | |
254 dataptr += 2; | |
255 | |
256 } | |
257 } | |
258 | |
259 /* | |
260 * simple pith shifter, plays short fragments at 1.5 speed | |
261 */ | |
262 void pitchShifter(const int lin, const int rin, int *lout, int *rout) | |
263 { | |
264 #define SH_BUF_SIZE 100 * 3 | |
265 static gint16 shBuf[SH_BUF_SIZE]; | |
266 static int shBufPos = SH_BUF_SIZE - 6; | |
267 static int shBufPos1 = SH_BUF_SIZE - 6; | |
268 static int cond; | |
269 | |
270 shBuf[shBufPos++] = lin; | |
271 shBuf[shBufPos++] = rin; | |
272 | |
273 if (shBufPos == SH_BUF_SIZE) shBufPos = 0; | |
274 | |
275 switch (cond){ | |
276 case 1: | |
277 *lout = (shBuf[shBufPos1 + 0] * 2 + shBuf[shBufPos1 + 2])/4; | |
278 *rout = (shBuf[shBufPos1 + 1] * 2 + shBuf[shBufPos1 + 3])/4; | |
279 break; | |
280 case 0: | |
281 *lout = (shBuf[shBufPos1 + 4] * 2 + shBuf[shBufPos1 + 2])/4; | |
282 *rout = (shBuf[shBufPos1 + 5] * 2 + shBuf[shBufPos1 + 3])/4; | |
283 cond = 2; | |
284 shBufPos1 += 6; | |
285 if (shBufPos1 == SH_BUF_SIZE) { | |
286 shBufPos1 = 0; | |
287 } | |
288 break; | |
289 } | |
290 cond--; | |
291 } | |
292 | |
293 | |
294 struct Interpolation{ | |
295 int acount; // counter | |
296 int lval, rval; // value | |
297 int sal, sar; // sum | |
298 int al, ar; | |
299 int a1l, a1r; | |
300 }; | |
301 | |
302 /* | |
303 * interpolation routine for ampliude and "energy" | |
304 */ | |
305 static inline void interpolate(struct Interpolation *s, int l, int r) | |
306 { | |
307 #define AMPL_COUNT 64 | |
308 int a0l, a0r, dal = 0, dar = 0; | |
309 | |
310 if (l < 0) l = -l; | |
311 if (r < 0) r = -r; | |
312 | |
313 s->lval += l / 8; | |
314 s->rval += r / 8; | |
315 | |
316 s->lval = (s->lval * 120) / 128; | |
317 s->rval = (s->rval * 120) / 128; | |
318 | |
319 s->sal += s->lval; | |
320 s->sar += s->rval; | |
321 | |
322 s->acount++; | |
323 if (s->acount == AMPL_COUNT){ | |
324 s->acount = 0; | |
325 a0l = s->a1l; | |
326 a0r = s->a1r; | |
327 s->a1l = s->sal / AMPL_COUNT; | |
328 s->a1r = s->sar / AMPL_COUNT; | |
329 s->sal = 0; | |
330 s->sar = 0; | |
331 dal = s->a1l - a0l; | |
332 dar = s->a1r - a0r; | |
333 s->al = a0l * AMPL_COUNT; | |
334 s->ar = a0r * AMPL_COUNT; | |
335 } | |
336 | |
337 s->al += dal; | |
338 s->ar += dar; | |
339 } | |
340 | |
341 /* | |
342 * calculate scalefactor for mixer | |
343 */ | |
344 inline int calc_scalefactor(int a, int e) | |
345 { | |
346 int x; | |
347 | |
348 if (a > 8192) a = 8192; | |
349 else if (a < 0) a = 0; | |
350 | |
351 if (e > 8192) e = 8192; | |
352 else if (e < 0) e = 0; | |
353 | |
354 x = ((e+500) * 4096 )/ (a + 300) + e; | |
355 | |
356 if (x > 16384) x = 16384; | |
357 else if (x < 0) x = 0; | |
358 return x; | |
359 } | |
360 | |
361 static struct Interpolation bandext_energy; | |
362 static struct Interpolation bandext_amplitude; | |
363 | |
364 /* | |
365 * exact bandwidth extender ("exciter") routine | |
366 */ | |
367 static void bandext(gint16 *data, const int datasize) | |
368 { | |
369 | |
370 int x; | |
371 static int saw; // test stuff | |
372 int left, right; | |
373 gint16 *dataptr = data; | |
374 static int lprev0, rprev0, lprev1, rprev1, lprev2, rprev2; | |
375 int left0, right0, left1, right1, left2, right2, left3, right3; | |
376 static int lamplUp, lamplDown; | |
377 static int ramplUp, ramplDown; | |
378 int lampl, rampl; | |
379 int tmp; | |
380 | |
381 for (x = 0; x < datasize; x += 4) { | |
382 | |
383 // ************ load sample ********** | |
384 left0 = dataptr[0]; | |
385 right0 = dataptr[1]; | |
386 | |
387 // ************ highpass filter part 1 ********** | |
388 left1 = (left0 - lprev0) * 56880 / 65536; | |
389 right1 = (right0 - rprev0) * 56880 / 65536; | |
390 | |
391 left2 = (left1 - lprev1) * 56880 / 65536; | |
392 right2 = (right1 - rprev1) * 56880 / 65536; | |
393 | |
394 left3 = (left2 - lprev2) * 56880 / 65536; | |
395 right3 = (right2 - rprev2) * 56880 / 65536; | |
396 | |
397 switch (filter_level){ | |
398 case 1: | |
399 pitchShifter(left1, right1, &left, &right); | |
400 break; | |
401 case 2: | |
402 pitchShifter(left2, right2, &left, &right); | |
403 break; | |
404 case 3: | |
405 pitchShifter(left3, right3, &left, &right); | |
406 break; | |
407 } | |
408 | |
409 // ************ amplitude detector ************ | |
410 tmp = left1 + lprev1; | |
411 if (tmp * 16 > lamplUp ) lamplUp += (tmp - lamplUp ); | |
412 else if (tmp * 16 < lamplDown) lamplDown += (tmp - lamplDown); | |
413 lamplUp = (lamplUp * 1000) /1024; | |
414 lamplDown = (lamplDown * 1000) /1024; | |
415 lampl = lamplUp - lamplDown; | |
416 | |
417 tmp = right1 + rprev1; | |
418 if (tmp * 16 > ramplUp ) ramplUp += (tmp - ramplUp ); | |
419 else if (tmp * 16 < ramplDown) ramplDown += (tmp - ramplDown); | |
420 ramplUp = (ramplUp * 1000) /1024; | |
421 ramplDown = (ramplDown * 1000) /1024; | |
422 rampl = ramplUp - ramplDown; | |
423 | |
424 interpolate(&bandext_amplitude, lampl, rampl); | |
425 | |
426 // ************ "sound energy" detector (approx. spectrum complexity) *********** | |
427 interpolate(&bandext_energy, left0 - lprev0, right0 - rprev0); | |
428 | |
429 // ************ mixer *********** | |
430 left = left0 + left * calc_scalefactor(bandext_amplitude.lval, bandext_energy.lval) / bext_sfactor; | |
431 right = right0 + right * calc_scalefactor(bandext_amplitude.rval, bandext_energy.rval) / bext_sfactor; //16384 | |
432 | |
433 saw = (saw + 2048) & 0x7fff; | |
434 | |
435 lprev0 = left0; | |
436 rprev0 = right0; | |
437 lprev1 = left1; | |
438 rprev1 = right1; | |
439 lprev2 = left2; | |
440 rprev2 = right2; | |
441 | |
442 if (left < -32768) left = -32768; | |
443 else if (left > 32767) left = 32767; | |
444 if (right < -32768) right = -32768; | |
445 else if (right > 32767) right = 32767; | |
446 | |
447 dataptr[0] = left; | |
448 dataptr[1] = right; | |
449 dataptr += 2; | |
450 } | |
451 } | |
452 | |
453 int psycho_process(void *data, int length, int nch) | |
454 { | |
455 if (nch != 2) | |
456 return length; /* XXX: we cant process mono yet */ | |
457 | |
458 echo3d((gint16 *)data, length); | |
459 bandext((gint16 *)data, length); | |
460 return length; | |
461 } | |
462 |