Blame src/libmpg123/synth.h

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