1 /*
2 	synth.h: generic synth functions
3 
4 	copyright 1995-2008 by the mpg123 project - free software under the terms of the LGPL 2.1
5 	see COPYING and AUTHORS files in distribution or http://mpg123.org
6 	initially written by Michael Hipp, generalized by Thomas Orgis
7 
8 	This header is used multiple times to create different variants of these functions.
9 	See decode.c and friends.
10 	Hint: BLOCK, MONO_NAME, MONO2STEREO_NAME, SYNTH_NAME and SAMPLE_T as well as WRITE_SAMPLE do vary.
11 
12 	Thomas looked closely at the decode_1to1, decode_2to1 and decode_4to1 contents, seeing that they are too similar to be separate files.
13 	This is what resulted...
14 
15 	Basically, you need one set of these functions for each output sample type.
16 	That currently means signed short, 8bit or float/double; though unsigned short may come, too.
17 
18 	Define NO_AUTOINCREMENT i386 code that shall not rely on autoincrement.
19 	Actual benefit of this has to be examined; may apply to specific (old) compilers, only.
20 */
21 
22 
23 /* Main synth function, uses the plain dct64 or dct64_i386. */
SYNTH_NAME(real * bandPtr,int channel,mpg123_handle * fr,int final)24 int SYNTH_NAME(real *bandPtr, int channel, mpg123_handle *fr, int final)
25 {
26 #ifndef NO_AUTOINCREMENT
27 #define BACKPEDAL 0x10 /* We use autoincrement and thus need this re-adjustment for window/b0. */
28 #define MY_DCT64 dct64
29 #else
30 #define BACKPEDAL 0x00 /* i386 code does not need that. */
31 #define MY_DCT64 dct64_i386
32 #endif
33 	static const int step = 2;
34 	SAMPLE_T *samples = (SAMPLE_T *) (fr->buffer.data + fr->buffer.fill);
35 
36 	real *b0, **buf; /* (*buf)[0x110]; */
37 	int clip = 0;
38 	int bo1;
39 #ifndef NO_EQUALIZER
40 	if(fr->have_eq_settings) do_equalizer(bandPtr,channel,fr->equalizer);
41 #endif
42 	if(!channel)
43 	{
44 		fr->bo--;
45 		fr->bo &= 0xf;
46 		buf = fr->real_buffs[0];
47 	}
48 	else
49 	{
50 #ifdef USE_DITHER
51 		/* We always go forward 32 dither points (and back again for the second channel),
52 		   (re)sampling the noise the same way as the original signal. */
53 		fr->ditherindex -= 32;
54 #endif
55 		samples++;
56 		buf = fr->real_buffs[1];
57 	}
58 #ifdef USE_DITHER
59 	/* We check only once for the overflow of dither index here ...
60 	   this wraps differently than the original i586 dither code, in theory (but when DITHERSIZE % BLOCK/2 == 0 it's the same). */
61 	if(DITHERSIZE-fr->ditherindex < 32) fr->ditherindex = 0;
62 	/* And we define a macro for the dither action... */
63 	#define ADD_DITHER(fr,sum) sum+=fr->dithernoise[fr->ditherindex]; fr->ditherindex += 64/BLOCK;
64 #else
65 	#define ADD_DITHER(fr,sum)
66 #endif
67 
68 	if(fr->bo & 0x1)
69 	{
70 		b0 = buf[0];
71 		bo1 = fr->bo;
72 		MY_DCT64(buf[1]+((fr->bo+1)&0xf),buf[0]+fr->bo,bandPtr);
73 	}
74 	else
75 	{
76 		b0 = buf[1];
77 		bo1 = fr->bo+1;
78 		MY_DCT64(buf[0]+fr->bo,buf[1]+fr->bo+1,bandPtr);
79 	}
80 
81 	{
82 		register int j;
83 		real *window = fr->decwin + 16 - bo1;
84 
85 		for(j=(BLOCK/4); j; j--, b0+=0x400/BLOCK-BACKPEDAL, window+=0x800/BLOCK-BACKPEDAL, samples+=step)
86 		{
87 			real sum;
88 #ifndef NO_AUTOINCREMENT
89 			sum  = REAL_MUL_SYNTH(*window++, *b0++);
90 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
91 			sum += REAL_MUL_SYNTH(*window++, *b0++);
92 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
93 			sum += REAL_MUL_SYNTH(*window++, *b0++);
94 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
95 			sum += REAL_MUL_SYNTH(*window++, *b0++);
96 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
97 			sum += REAL_MUL_SYNTH(*window++, *b0++);
98 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
99 			sum += REAL_MUL_SYNTH(*window++, *b0++);
100 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
101 			sum += REAL_MUL_SYNTH(*window++, *b0++);
102 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
103 			sum += REAL_MUL_SYNTH(*window++, *b0++);
104 			sum -= REAL_MUL_SYNTH(*window++, *b0++);
105 #else
106 			sum  = REAL_MUL_SYNTH(window[0x0], b0[0x0]);
107 			sum -= REAL_MUL_SYNTH(window[0x1], b0[0x1]);
108 			sum += REAL_MUL_SYNTH(window[0x2], b0[0x2]);
109 			sum -= REAL_MUL_SYNTH(window[0x3], b0[0x3]);
110 			sum += REAL_MUL_SYNTH(window[0x4], b0[0x4]);
111 			sum -= REAL_MUL_SYNTH(window[0x5], b0[0x5]);
112 			sum += REAL_MUL_SYNTH(window[0x6], b0[0x6]);
113 			sum -= REAL_MUL_SYNTH(window[0x7], b0[0x7]);
114 			sum += REAL_MUL_SYNTH(window[0x8], b0[0x8]);
115 			sum -= REAL_MUL_SYNTH(window[0x9], b0[0x9]);
116 			sum += REAL_MUL_SYNTH(window[0xA], b0[0xA]);
117 			sum -= REAL_MUL_SYNTH(window[0xB], b0[0xB]);
118 			sum += REAL_MUL_SYNTH(window[0xC], b0[0xC]);
119 			sum -= REAL_MUL_SYNTH(window[0xD], b0[0xD]);
120 			sum += REAL_MUL_SYNTH(window[0xE], b0[0xE]);
121 			sum -= REAL_MUL_SYNTH(window[0xF], b0[0xF]);
122 #endif
123 
124 			ADD_DITHER(fr,sum)
125 			WRITE_SAMPLE(samples,sum,clip);
126 		}
127 
128 		{
129 			real sum;
130 			sum  = REAL_MUL_SYNTH(window[0x0], b0[0x0]);
131 			sum += REAL_MUL_SYNTH(window[0x2], b0[0x2]);
132 			sum += REAL_MUL_SYNTH(window[0x4], b0[0x4]);
133 			sum += REAL_MUL_SYNTH(window[0x6], b0[0x6]);
134 			sum += REAL_MUL_SYNTH(window[0x8], b0[0x8]);
135 			sum += REAL_MUL_SYNTH(window[0xA], b0[0xA]);
136 			sum += REAL_MUL_SYNTH(window[0xC], b0[0xC]);
137 			sum += REAL_MUL_SYNTH(window[0xE], b0[0xE]);
138 
139 			ADD_DITHER(fr,sum)
140 			WRITE_SAMPLE(samples,sum,clip);
141 			samples += step;
142 			b0-=0x400/BLOCK;
143 			window-=0x800/BLOCK;
144 		}
145 		window += bo1<<1;
146 
147 		for(j=(BLOCK/4)-1; j; j--, b0-=0x400/BLOCK+BACKPEDAL, window-=0x800/BLOCK-BACKPEDAL, samples+=step)
148 		{
149 			real sum;
150 #ifndef NO_AUTOINCREMENT
151 			sum = -REAL_MUL_SYNTH(*(--window), *b0++);
152 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
153 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
154 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
155 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
156 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
157 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
158 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
159 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
160 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
161 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
162 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
163 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
164 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
165 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
166 			sum -= REAL_MUL_SYNTH(*(--window), *b0++);
167 #else
168 			sum = -REAL_MUL_SYNTH(window[-0x1], b0[0x0]);
169 			sum -= REAL_MUL_SYNTH(window[-0x2], b0[0x1]);
170 			sum -= REAL_MUL_SYNTH(window[-0x3], b0[0x2]);
171 			sum -= REAL_MUL_SYNTH(window[-0x4], b0[0x3]);
172 			sum -= REAL_MUL_SYNTH(window[-0x5], b0[0x4]);
173 			sum -= REAL_MUL_SYNTH(window[-0x6], b0[0x5]);
174 			sum -= REAL_MUL_SYNTH(window[-0x7], b0[0x6]);
175 			sum -= REAL_MUL_SYNTH(window[-0x8], b0[0x7]);
176 			sum -= REAL_MUL_SYNTH(window[-0x9], b0[0x8]);
177 			sum -= REAL_MUL_SYNTH(window[-0xA], b0[0x9]);
178 			sum -= REAL_MUL_SYNTH(window[-0xB], b0[0xA]);
179 			sum -= REAL_MUL_SYNTH(window[-0xC], b0[0xB]);
180 			sum -= REAL_MUL_SYNTH(window[-0xD], b0[0xC]);
181 			sum -= REAL_MUL_SYNTH(window[-0xE], b0[0xD]);
182 			sum -= REAL_MUL_SYNTH(window[-0xF], b0[0xE]);
183 			sum -= REAL_MUL_SYNTH(window[-0x0], b0[0xF]); /* Is that right? 0x0? Just wondering... */
184 #endif
185 			ADD_DITHER(fr,sum)
186 			WRITE_SAMPLE(samples,sum,clip);
187 		}
188 	}
189 
190 	if(final) fr->buffer.fill += BLOCK*sizeof(SAMPLE_T);
191 
192 	return clip;
193 #undef ADD_DITHER
194 #undef BACKPEDAL
195 #undef MY_DCT64
196 }
197