diff options
Diffstat (limited to 'src/libmpg123/synth.h')
-rw-r--r-- | src/libmpg123/synth.h | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/libmpg123/synth.h b/src/libmpg123/synth.h new file mode 100644 index 0000000..8ea0765 --- /dev/null +++ b/src/libmpg123/synth.h @@ -0,0 +1,196 @@ +/* + synth.h: generic synth functions + + copyright 1995-2008 by the mpg123 project - free software under the terms of the LGPL 2.1 + see COPYING and AUTHORS files in distribution or http://mpg123.org + initially written by Michael Hipp, generalized by Thomas Orgis + + This header is used multiple times to create different variants of these functions. + See decode.c and friends. + Hint: BLOCK, MONO_NAME, MONO2STEREO_NAME, SYNTH_NAME and SAMPLE_T as well as WRITE_SAMPLE do vary. + + Thomas looked closely at the decode_1to1, decode_2to1 and decode_4to1 contents, seeing that they are too similar to be separate files. + This is what resulted... + + Basically, you need one set of these functions for each output sample type. + That currently means signed short, 8bit or float/double; though unsigned short may come, too. + + Define NO_AUTOINCREMENT i386 code that shall not rely on autoincrement. + Actual benefit of this has to be examined; may apply to specific (old) compilers, only. +*/ + + +/* Main synth function, uses the plain dct64 or dct64_i386. */ +int SYNTH_NAME(real *bandPtr, int channel, mpg123_handle *fr, int final) +{ +#ifndef NO_AUTOINCREMENT +#define BACKPEDAL 0x10 /* We use autoincrement and thus need this re-adjustment for window/b0. */ +#define MY_DCT64 dct64 +#else +#define BACKPEDAL 0x00 /* i386 code does not need that. */ +#define MY_DCT64 dct64_i386 +#endif + static const int step = 2; + SAMPLE_T *samples = (SAMPLE_T *) (fr->buffer.data + fr->buffer.fill); + + real *b0, **buf; /* (*buf)[0x110]; */ + int clip = 0; + int bo1; + + if(fr->have_eq_settings) do_equalizer(bandPtr,channel,fr->equalizer); + + if(!channel) + { + fr->bo--; + fr->bo &= 0xf; + buf = fr->real_buffs[0]; + } + else + { +#ifdef USE_DITHER + /* We always go forward 32 dither points (and back again for the second channel), + (re)sampling the noise the same way as the original signal. */ + fr->ditherindex -= 32; +#endif + samples++; + buf = fr->real_buffs[1]; + } +#ifdef USE_DITHER + /* We check only once for the overflow of dither index here ... + this wraps differently than the original i586 dither code, in theory (but when DITHERSIZE % BLOCK/2 == 0 it's the same). */ + if(DITHERSIZE-fr->ditherindex < 32) fr->ditherindex = 0; + /* And we define a macro for the dither action... */ + #define ADD_DITHER(fr,sum) sum+=fr->dithernoise[fr->ditherindex]; fr->ditherindex += 64/BLOCK; +#else + #define ADD_DITHER(fr,sum) +#endif + + if(fr->bo & 0x1) + { + b0 = buf[0]; + bo1 = fr->bo; + MY_DCT64(buf[1]+((fr->bo+1)&0xf),buf[0]+fr->bo,bandPtr); + } + else + { + b0 = buf[1]; + bo1 = fr->bo+1; + MY_DCT64(buf[0]+fr->bo,buf[1]+fr->bo+1,bandPtr); + } + + { + register int j; + real *window = fr->decwin + 16 - bo1; + + for(j=(BLOCK/4); j; j--, b0+=0x400/BLOCK-BACKPEDAL, window+=0x800/BLOCK-BACKPEDAL, samples+=step) + { + real sum; +#ifndef NO_AUTOINCREMENT + sum = REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); + sum += REAL_MUL(*window++, *b0++); + sum -= REAL_MUL(*window++, *b0++); +#else + sum = REAL_MUL(window[0x0], b0[0x0]); + sum -= REAL_MUL(window[0x1], b0[0x1]); + sum += REAL_MUL(window[0x2], b0[0x2]); + sum -= REAL_MUL(window[0x3], b0[0x3]); + sum += REAL_MUL(window[0x4], b0[0x4]); + sum -= REAL_MUL(window[0x5], b0[0x5]); + sum += REAL_MUL(window[0x6], b0[0x6]); + sum -= REAL_MUL(window[0x7], b0[0x7]); + sum += REAL_MUL(window[0x8], b0[0x8]); + sum -= REAL_MUL(window[0x9], b0[0x9]); + sum += REAL_MUL(window[0xA], b0[0xA]); + sum -= REAL_MUL(window[0xB], b0[0xB]); + sum += REAL_MUL(window[0xC], b0[0xC]); + sum -= REAL_MUL(window[0xD], b0[0xD]); + sum += REAL_MUL(window[0xE], b0[0xE]); + sum -= REAL_MUL(window[0xF], b0[0xF]); +#endif + + ADD_DITHER(fr,sum) + WRITE_SAMPLE(samples,sum,clip); + } + + { + real sum; + sum = REAL_MUL(window[0x0], b0[0x0]); + sum += REAL_MUL(window[0x2], b0[0x2]); + sum += REAL_MUL(window[0x4], b0[0x4]); + sum += REAL_MUL(window[0x6], b0[0x6]); + sum += REAL_MUL(window[0x8], b0[0x8]); + sum += REAL_MUL(window[0xA], b0[0xA]); + sum += REAL_MUL(window[0xC], b0[0xC]); + sum += REAL_MUL(window[0xE], b0[0xE]); + + ADD_DITHER(fr,sum) + WRITE_SAMPLE(samples,sum,clip); + samples += step; + b0-=0x400/BLOCK; + window-=0x800/BLOCK; + } + window += bo1<<1; + + for(j=(BLOCK/4)-1; j; j--, b0-=0x400/BLOCK+BACKPEDAL, window-=0x800/BLOCK-BACKPEDAL, samples+=step) + { + real sum; +#ifndef NO_AUTOINCREMENT + sum = -REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); + sum -= REAL_MUL(*(--window), *b0++); +#else + sum = -REAL_MUL(window[-0x1], b0[0x0]); + sum -= REAL_MUL(window[-0x2], b0[0x1]); + sum -= REAL_MUL(window[-0x3], b0[0x2]); + sum -= REAL_MUL(window[-0x4], b0[0x3]); + sum -= REAL_MUL(window[-0x5], b0[0x4]); + sum -= REAL_MUL(window[-0x6], b0[0x5]); + sum -= REAL_MUL(window[-0x7], b0[0x6]); + sum -= REAL_MUL(window[-0x8], b0[0x7]); + sum -= REAL_MUL(window[-0x9], b0[0x8]); + sum -= REAL_MUL(window[-0xA], b0[0x9]); + sum -= REAL_MUL(window[-0xB], b0[0xA]); + sum -= REAL_MUL(window[-0xC], b0[0xB]); + sum -= REAL_MUL(window[-0xD], b0[0xC]); + sum -= REAL_MUL(window[-0xE], b0[0xD]); + sum -= REAL_MUL(window[-0xF], b0[0xE]); + sum -= REAL_MUL(window[-0x0], b0[0xF]); /* Is that right? 0x0? Just wondering... */ +#endif + ADD_DITHER(fr,sum) + WRITE_SAMPLE(samples,sum,clip); + } + } + + if(final) fr->buffer.fill += BLOCK*sizeof(SAMPLE_T); + + return clip; +#undef ADD_DITHER +#undef BACKPEDAL +#undef MY_DCT64 +} |