1 //
2 // /home/ms/source/sidplay/libsidplay/emu/RCS/mixing.cpp,v
3 //
4 
5 #include "mytypes.h"
6 #include "opstruct.h"
7 #include "samples.h"
8 
9 
10 extern sidOperator optr1, optr2, optr3;          // -> 6581_.cpp
11 extern uword voice4_gainLeft, voice4_gainRight;
12 
13 
14 static const int maxLogicalVoices = 4;
15 
16 static const int mix8monoMiddleIndex = 256*maxLogicalVoices/2;
17 static ubyte mix8mono[256*maxLogicalVoices];
18 
19 static const int mix8stereoMiddleIndex = 256*(maxLogicalVoices/2)/2;
20 static ubyte mix8stereo[256*(maxLogicalVoices/2)];
21 
22 static const int mix16monoMiddleIndex = 256*maxLogicalVoices/2;
23 static uword mix16mono[256*maxLogicalVoices];
24 
25 static const int mix16stereoMiddleIndex = 256*(maxLogicalVoices/2)/2;
26 static uword mix16stereo[256*(maxLogicalVoices/2)];
27 
28 sbyte *signedPanMix8 = 0;
29 sword *signedPanMix16 = 0;
30 
31 static ubyte zero8bit;   // ``zero''-sample
32 static uword zero16bit;  // either signed or unsigned
33 udword splitBufferLen;
34 
35 void* fill8bitMono( void* buffer, udword numberOfSamples );
36 void* fill8bitMonoControl( void* buffer, udword numberOfSamples );
37 void* fill8bitStereo( void* buffer, udword numberOfSamples );
38 void* fill8bitStereoControl( void* buffer, udword numberOfSamples );
39 void* fill8bitStereoSurround( void* buffer, udword numberOfSamples );
40 void* fill8bitSplit( void* buffer, udword numberOfSamples );
41 void* fill16bitMono( void* buffer, udword numberOfSamples );
42 void* fill16bitMonoControl( void* buffer, udword numberOfSamples );
43 void* fill16bitStereo( void* buffer, udword numberOfSamples );
44 void* fill16bitStereoControl( void* buffer, udword numberOfSamples );
45 void* fill16bitStereoSurround( void* buffer, udword numberOfSamples );
46 void* fill16bitSplit( void* buffer, udword numberOfSamples );
47 
48 
MixerInit(bool threeVoiceAmplify,ubyte zero8,uword zero16)49 void MixerInit(bool threeVoiceAmplify, ubyte zero8, uword zero16)
50 {
51 	zero8bit = zero8;
52 	zero16bit = zero16;
53 
54 	long si;
55 	uword ui;
56 
57 	long ampDiv = maxLogicalVoices;
58 	if (threeVoiceAmplify)
59 	{
60 		ampDiv = (maxLogicalVoices-1);
61 	}
62 
63 	// Mixing formulas are optimized by sample input value.
64 
65 	si = (-128*maxLogicalVoices);
66 	for (ui = 0; ui < sizeof(mix8mono); ui++ )
67 	{
68 		mix8mono[ui] = (ubyte)(si/ampDiv) + zero8bit;
69 		si++;
70 	}
71 
72 	si = (-128*maxLogicalVoices);  // optimized by (/2 *2);
73 	for (ui = 0; ui < sizeof(mix8stereo); ui++ )
74 	{
75 		mix8stereo[ui] = (ubyte)(si/ampDiv) + zero8bit;
76 		si+=2;
77 	}
78 
79 	si = (-128*maxLogicalVoices) * 256;
80 	for (ui = 0; ui < sizeof(mix16mono)/sizeof(uword); ui++ )
81 	{
82 		mix16mono[ui] = (uword)(si/ampDiv) + zero16bit;
83 		si+=256;
84 	}
85 
86 	si = (-128*maxLogicalVoices) * 256;  // optimized by (/2 * 512)
87 	for (ui = 0; ui < sizeof(mix16stereo)/sizeof(uword); ui++ )
88 	{
89 		mix16stereo[ui] = (uword)(si/ampDiv) + zero16bit;
90 		si+=512;
91 	}
92 }
93 
94 
syncEm()95 inline void syncEm()
96 {
97 	extern sbyte waveCalcNormal(sidOperator* pVoice);
98 	extern sbyte waveCalcRangeCheck(sidOperator* pVoice);
99 	optr1.cycleLenCount--;
100 	optr2.cycleLenCount--;
101 	optr3.cycleLenCount--;
102 	bool sync1 = (optr1.modulator->cycleLenCount <= 0);
103 	bool sync2 = (optr2.modulator->cycleLenCount <= 0);
104 	bool sync3 = (optr3.modulator->cycleLenCount <= 0);
105 	if (optr1.sync && sync1)
106 	{
107 		optr1.cycleLenCount = 0;
108 		optr1.outProc = &waveCalcNormal;
109 #if defined(DIRECT_FIXPOINT)
110 		optr1.waveStep.l = 0;
111 #else
112 		optr1.waveStep = (optr1.waveStepPnt = 0);
113 #endif
114 	}
115 	if (optr2.sync && sync2)
116 	{
117 		optr2.cycleLenCount = 0;
118 		optr2.outProc = &waveCalcNormal;
119 #if defined(DIRECT_FIXPOINT)
120 		optr2.waveStep.l = 0;
121 #else
122 		optr2.waveStep = (optr2.waveStepPnt = 0);
123 #endif
124 	}
125 	if (optr3.sync && sync3)
126 	{
127 		optr3.cycleLenCount = 0;
128 		optr3.outProc = &waveCalcNormal;
129 #if defined(DIRECT_FIXPOINT)
130 		optr3.waveStep.l = 0;
131 #else
132 		optr3.waveStep = (optr3.waveStepPnt = 0);
133 #endif
134 	}
135 }
136 
137 
138 //
139 // -------------------------------------------------------------------- 8-bit
140 //
141 
fill8bitMono(void * buffer,udword numberOfSamples)142 void* fill8bitMono( void* buffer, udword numberOfSamples )
143 {
144 	ubyte* buffer8bit = (ubyte*)buffer;
145 	for ( ; numberOfSamples > 0; numberOfSamples-- )
146 	{
147 	    *buffer8bit++ = mix8mono[(unsigned)(mix8monoMiddleIndex
148 											+(*optr1.outProc)(&optr1)
149 											+(*optr2.outProc)(&optr2)
150 											+(*optr3.outProc)(&optr3)
151 											+(*sampleEmuRout)())];
152 		syncEm();
153 	}
154 	return buffer8bit;
155 }
156 
fill8bitMonoControl(void * buffer,udword numberOfSamples)157 void* fill8bitMonoControl( void* buffer, udword numberOfSamples )
158 {
159 	ubyte* buffer8bit = (ubyte*)buffer;
160 	for ( ; numberOfSamples > 0; numberOfSamples-- )
161 	{
162 		*buffer8bit++ = zero8bit
163 			+signedPanMix8[optr1.gainLeft+(*optr1.outProc)(&optr1)]
164 			+signedPanMix8[optr2.gainLeft+(*optr2.outProc)(&optr2)]
165 			+signedPanMix8[optr3.gainLeft+(*optr3.outProc)(&optr3)]
166 			+signedPanMix8[voice4_gainLeft+(*sampleEmuRout)()];
167 		syncEm();
168 	}
169 	return buffer8bit;
170 }
171 
fill8bitStereo(void * buffer,udword numberOfSamples)172 void* fill8bitStereo( void* buffer, udword numberOfSamples )
173 {
174 	ubyte* buffer8bit = (ubyte*)buffer;
175   	for ( ; numberOfSamples > 0; numberOfSamples-- )
176 	{
177 		// left
178 	    *buffer8bit++ = mix8stereo[(unsigned)(mix8stereoMiddleIndex
179 											 +(*optr1.outProc)(&optr1)
180 											 +(*optr3.outProc)(&optr3))];
181 		// right
182 	    *buffer8bit++ = mix8stereo[(unsigned)(mix8stereoMiddleIndex
183 											 +(*optr2.outProc)(&optr2)
184 											 +(*sampleEmuRout)())];
185 		syncEm();
186 	}
187 	return buffer8bit;
188 }
189 
fill8bitStereoControl(void * buffer,udword numberOfSamples)190 void* fill8bitStereoControl( void* buffer, udword numberOfSamples )
191 {
192 	ubyte* buffer8bit = (ubyte*)buffer;
193 	sbyte voice1data, voice2data, voice3data, voice4data;
194 	for ( ; numberOfSamples > 0; numberOfSamples-- )
195 	{
196 		voice1data = (*optr1.outProc)(&optr1);
197 		voice2data = (*optr2.outProc)(&optr2);
198 		voice3data = (*optr3.outProc)(&optr3);
199 		voice4data = (*sampleEmuRout)();
200 		// left
201 		*buffer8bit++ = zero8bit
202 			+signedPanMix8[optr1.gainLeft+voice1data]
203 		    +signedPanMix8[optr2.gainLeft+voice2data]
204 			+signedPanMix8[optr3.gainLeft+voice3data]
205 			+signedPanMix8[voice4_gainLeft+voice4data];
206 		// right
207 		*buffer8bit++ = zero8bit
208 			+signedPanMix8[optr1.gainRight+voice1data]
209 			+signedPanMix8[optr2.gainRight+voice2data]
210 			+signedPanMix8[optr3.gainRight+voice3data]
211 			+signedPanMix8[voice4_gainRight+voice4data];
212 		syncEm();
213 	}
214 	return buffer8bit;
215 }
216 
fill8bitStereoSurround(void * buffer,udword numberOfSamples)217 void* fill8bitStereoSurround( void* buffer, udword numberOfSamples )
218 {
219 	ubyte* buffer8bit = (ubyte*)buffer;
220 	sbyte voice1data, voice2data, voice3data, voice4data;
221 	for ( ; numberOfSamples > 0; numberOfSamples-- )
222 	{
223 		voice1data = (*optr1.outProc)(&optr1);
224 		voice2data = (*optr2.outProc)(&optr2);
225 		voice3data = (*optr3.outProc)(&optr3);
226 		voice4data = (*sampleEmuRout)();
227 		// left
228 		*buffer8bit++ = zero8bit
229 			+signedPanMix8[optr1.gainLeft+voice1data]
230 		    +signedPanMix8[optr2.gainLeft+voice2data]
231 			+signedPanMix8[optr3.gainLeft+voice3data]
232 			+signedPanMix8[voice4_gainLeft+voice4data];
233 		// right
234 		*buffer8bit++ = zero8bit
235 			-signedPanMix8[optr1.gainRight+voice1data]
236 			-signedPanMix8[optr2.gainRight+voice2data]
237 			-signedPanMix8[optr3.gainRight+voice3data]
238 			-signedPanMix8[voice4_gainRight+voice4data];
239 		syncEm();
240 	}
241 	return buffer8bit;
242 }
243 
fill8bitSplit(void * buffer,udword numberOfSamples)244 void* fill8bitSplit( void* buffer, udword numberOfSamples )
245 {
246 	ubyte* v1buffer8bit = (ubyte*)buffer;
247 	ubyte* v2buffer8bit = v1buffer8bit + splitBufferLen;
248 	ubyte* v3buffer8bit = v2buffer8bit + splitBufferLen;
249 	ubyte* v4buffer8bit = v3buffer8bit + splitBufferLen;
250 	for ( ; numberOfSamples > 0; numberOfSamples-- )
251 	{
252 		*v1buffer8bit++ = zero8bit+(*optr1.outProc)(&optr1);
253 		*v2buffer8bit++ = zero8bit+(*optr2.outProc)(&optr2);
254 		*v3buffer8bit++ = zero8bit+(*optr3.outProc)(&optr3);
255 		*v4buffer8bit++ = zero8bit+(*sampleEmuRout)();
256 		syncEm();
257 	}
258 	return v1buffer8bit;
259 }
260 
261 //
262 // ------------------------------------------------------------------- 16-bit
263 //
264 
fill16bitMono(void * buffer,udword numberOfSamples)265 void* fill16bitMono( void* buffer, udword numberOfSamples )
266 {
267 	sword* buffer16bit = (sword*)buffer;
268 	for ( ; numberOfSamples > 0; numberOfSamples-- )
269 	{
270 	    *buffer16bit++ = mix16mono[(unsigned)(mix16monoMiddleIndex
271 											 +(*optr1.outProc)(&optr1)
272 											 +(*optr2.outProc)(&optr2)
273 											 +(*optr3.outProc)(&optr3)
274 											 +(*sampleEmuRout)())];
275 		syncEm();
276 	}
277 	return buffer16bit;
278 }
279 
fill16bitMonoControl(void * buffer,udword numberOfSamples)280 void* fill16bitMonoControl( void* buffer, udword numberOfSamples )
281 {
282 	sword* buffer16bit = (sword*)buffer;
283 	for ( ; numberOfSamples > 0; numberOfSamples-- )
284 	{
285 		*buffer16bit++ = zero16bit
286 			+signedPanMix16[optr1.gainLeft+(*optr1.outProc)(&optr1)]
287 			+signedPanMix16[optr2.gainLeft+(*optr2.outProc)(&optr2)]
288 			+signedPanMix16[optr3.gainLeft+(*optr3.outProc)(&optr3)]
289 			+signedPanMix16[voice4_gainLeft+(*sampleEmuRout)()];
290 		syncEm();
291 	}
292 	return buffer16bit;
293 }
294 
fill16bitStereo(void * buffer,udword numberOfSamples)295 void* fill16bitStereo( void* buffer, udword numberOfSamples )
296 {
297 	sword* buffer16bit = (sword*)buffer;
298 	for ( ; numberOfSamples > 0; numberOfSamples-- )
299 	{
300 		// left
301 	    *buffer16bit++ = mix16stereo[(unsigned)(mix16stereoMiddleIndex
302 											 +(*optr1.outProc)(&optr1)
303 											 +(*optr3.outProc)(&optr3))];
304 		// right
305 	    *buffer16bit++ = mix16stereo[(unsigned)(mix16stereoMiddleIndex
306 											 +(*optr2.outProc)(&optr2)
307 											 +(*sampleEmuRout)())];
308 		syncEm();
309 	}
310 	return buffer16bit;
311 }
312 
fill16bitStereoControl(void * buffer,udword numberOfSamples)313 void* fill16bitStereoControl( void* buffer, udword numberOfSamples )
314 {
315 	sword* buffer16bit = (sword*)buffer;
316 	sbyte voice1data, voice2data, voice3data, voice4data;
317 	for ( ; numberOfSamples > 0; numberOfSamples-- )
318 	{
319 		voice1data = (*optr1.outProc)(&optr1);
320 		voice2data = (*optr2.outProc)(&optr2);
321 		voice3data = (*optr3.outProc)(&optr3);
322 		voice4data = (*sampleEmuRout)();
323 		// left
324 		*buffer16bit++ = zero16bit
325 			+signedPanMix16[optr1.gainLeft+voice1data]
326 		    +signedPanMix16[optr2.gainLeft+voice2data]
327 			+signedPanMix16[optr3.gainLeft+voice3data]
328 			+signedPanMix16[voice4_gainLeft+voice4data];
329 		// right
330 		*buffer16bit++ = zero16bit
331 			+signedPanMix16[optr1.gainRight+voice1data]
332 			+signedPanMix16[optr2.gainRight+voice2data]
333 			+signedPanMix16[optr3.gainRight+voice3data]
334 			+signedPanMix16[voice4_gainRight+voice4data];
335 		syncEm();
336 	}
337 	return buffer16bit;
338 }
339 
fill16bitStereoSurround(void * buffer,udword numberOfSamples)340 void* fill16bitStereoSurround( void* buffer, udword numberOfSamples )
341 {
342 	sword* buffer16bit = (sword*)buffer;
343 	sbyte voice1data, voice2data, voice3data, voice4data;
344 	for ( ; numberOfSamples > 0; numberOfSamples-- )
345 	{
346 		voice1data = (*optr1.outProc)(&optr1);
347 		voice2data = (*optr2.outProc)(&optr2);
348 		voice3data = (*optr3.outProc)(&optr3);
349 		voice4data = (*sampleEmuRout)();
350 		// left
351 		*buffer16bit++ = zero16bit
352 			+signedPanMix16[optr1.gainLeft+voice1data]
353 		    +signedPanMix16[optr2.gainLeft+voice2data]
354 			+signedPanMix16[optr3.gainLeft+voice3data]
355 			+signedPanMix16[voice4_gainLeft+voice4data];
356 		// right
357 		*buffer16bit++ = zero16bit
358 			-signedPanMix16[optr1.gainRight+voice1data]
359 			-signedPanMix16[optr2.gainRight+voice2data]
360 			-signedPanMix16[optr3.gainRight+voice3data]
361 			-signedPanMix16[voice4_gainRight+voice4data];
362 		syncEm();
363 	}
364 	return buffer16bit;
365 }
366 
fill16bitSplit(void * buffer,udword numberOfSamples)367 void* fill16bitSplit( void* buffer, udword numberOfSamples )
368 {
369 	sword* v1buffer16bit = (sword*)buffer;
370 	sword* v2buffer16bit = v1buffer16bit + splitBufferLen;
371 	sword* v3buffer16bit = v2buffer16bit + splitBufferLen;
372 	sword* v4buffer16bit = v3buffer16bit + splitBufferLen;
373 	for ( ; numberOfSamples > 0; numberOfSamples-- )
374 	{
375 		*v1buffer16bit++ = zero16bit+((*optr1.outProc)(&optr1)<<8);
376 		*v2buffer16bit++ = zero16bit+((*optr2.outProc)(&optr2)<<8);
377 		*v3buffer16bit++ = zero16bit+((*optr3.outProc)(&optr3)<<8);
378 		*v4buffer16bit++ = zero16bit+((*sampleEmuRout)()<<8);
379 		syncEm();
380 	}
381 	return v1buffer16bit;
382 }
383