1 /*
2  * Copyright (c) 2009, The MilkyTracker Team.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  * - Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * - Neither the name of the <ORGANIZATION> nor the names of its contributors
14  *   may be used to endorse or promote products derived from this software
15  *   without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  *  ResamplerMacros.h
32  *  MilkyPlay mixer macros & "templates"
33  *
34  *
35  *  "- Be prepared! Are you sure you want to know? :-)"
36  *
37  */
38 #ifndef __RESAMPLERMACROS_H__
39 #define __RESAMPLERMACROS_H__
40 
41 #define VALIDATE \
42 	/*ASSERT((void*)(sample+(posfixed>>16)) >= (void*)chn->sample);*/
43 
44 #define PROCESS_BLOCK(MIXER) \
45 	mp_sint32 blockCount = count>>3; \
46 	mp_sint32 remainCount = count & 7; \
47 	while (blockCount) \
48 	{ \
49 		VALIDATE \
50 		MIXER \
51 		posfixed+=smpadd; \
52 		VALIDATE \
53 		MIXER \
54 		posfixed+=smpadd; \
55 		VALIDATE \
56 		MIXER \
57 		posfixed+=smpadd; \
58 		VALIDATE \
59 		MIXER \
60 		posfixed+=smpadd; \
61 		VALIDATE \
62 		MIXER \
63 		posfixed+=smpadd; \
64 		VALIDATE \
65 		MIXER \
66 		posfixed+=smpadd; \
67 		VALIDATE \
68 		MIXER \
69 		posfixed+=smpadd; \
70 		VALIDATE \
71 		MIXER \
72 		posfixed+=smpadd; \
73 		blockCount--; \
74 	} \
75 	while (remainCount) \
76 	{ \
77 		VALIDATE \
78 		MIXER \
79 		posfixed+=smpadd; \
80 		remainCount--; \
81 	}
82 
83 #define NOCHECKMIXER_TEMPLATE(MIXER_8BIT,MIXER_16BIT) \
84 	if (!(chn->flags&4)) \
85 	{ \
86 		const mp_sbyte* sample = chn->sample + basepos; \
87 		PROCESS_BLOCK(MIXER_8BIT) \
88 	} \
89 	else \
90 	{ \
91 		const mp_sword* sample = (const mp_sword*)chn->sample + basepos; \
92 		PROCESS_BLOCK(MIXER_16BIT) \
93 	}
94 
95 /////////////////////////////////////////////////////////
96 //		NO INTERPOLATION AND NO VOLUME RAMPING		   //
97 /////////////////////////////////////////////////////////
98 #define NOCHECKMIXER_8BIT_NORMAL \
99 	sd1 = sample[posfixed>>16]<<8; \
100 	\
101 	/* adjust volume for left channel & mix */ \
102 	(*buffer++)+=((sd1*(voll>>15))>>15); \
103 	/* adjust volume for right channel & mix */ \
104 	(*buffer++)+=((sd1*(volr>>15))>>15);
105 
106 #define NOCHECKMIXER_16BIT_NORMAL \
107 	sd1 = sample[posfixed>>16]; \
108 	\
109 	/* adjust volume for left channel & mix */ \
110 	(*buffer++)+=((sd1*(voll>>15))>>15); \
111 	/* adjust volume for right channel & mix */ \
112 	(*buffer++)+=((sd1*(volr>>15))>>15);
113 
114 /////////////////////////////////////////////////////////
115 //			NO INTERPOLATION BUT VOLUME RAMPING		   //
116 /////////////////////////////////////////////////////////
117 #define NOCHECKMIXER_8BIT_NORMAL_RAMP(_RAMP_) \
118 	sd1 = sample[posfixed>>16]<<8; \
119 	/* adjust volume for left channel & mix */ \
120 	(*buffer++)+=((sd1*(voll>>15))>>15); \
121 	/* adjust volume for right channel & mix */ \
122 	(*buffer++)+=((sd1*(volr>>15))>>15); \
123 	if ((_RAMP_)) \
124 	{ \
125 		voll+=rampFromVolStepL; \
126 		volr+=rampFromVolStepR; \
127 	}
128 
129 #define NOCHECKMIXER_16BIT_NORMAL_RAMP(_RAMP_) \
130 	sd1 = sample[posfixed>>16]; \
131 	/* adjust volume for left channel & mix */ \
132 	(*buffer++)+=((sd1*(voll>>15))>>15); \
133 	/* adjust volume for right channel & mix */ \
134 	(*buffer++)+=((sd1*(volr>>15))>>15); \
135 	if ((_RAMP_)) \
136 	{ \
137 		voll+=rampFromVolStepL; \
138 		volr+=rampFromVolStepR; \
139 	}
140 
141 /////////////////////////////////////////////////////////
142 //			INTERPOLATION AND NO VOLUME RAMPING		   //
143 /////////////////////////////////////////////////////////
144 #define NOCHECKMIXER_8BIT_LERP \
145 	sd1 = sample[posfixed>>16]<<8; \
146 	sd2 = sample[(posfixed>>16)+1]<<8; \
147 	\
148 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
149 	\
150 	/* adjust volume for left channel & mix */ \
151 	(*buffer++)+=((sd1*(voll>>15))>>15); \
152 	/* adjust volume for right channel & mix */ \
153 	(*buffer++)+=((sd1*(volr>>15))>>15);
154 
155 #define NOCHECKMIXER_16BIT_LERP \
156 	sd1 = sample[posfixed>>16]; \
157 	sd2 = sample[(posfixed>>16)+1]; \
158 	\
159 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
160 	\
161 	/* adjust volume for left channel & mix */ \
162 	(*buffer++)+=((sd1*(voll>>15))>>15); \
163 	/* adjust volume for right channel & mix */ \
164 	(*buffer++)+=((sd1*(volr>>15))>>15);
165 
166 /////////////////////////////////////////////////////////
167 //			INTERPOLATION AND VOLUME RAMPING		   //
168 /////////////////////////////////////////////////////////
169 #define NOCHECKMIXER_8BIT_LERP_RAMP(_RAMP_) \
170 	sd1 = sample[posfixed>>16]<<8; \
171 	sd2 = sample[(posfixed>>16)+1]<<8; \
172 	\
173 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
174 	\
175 	/* adjust volume for left channel & mix */ \
176 	(*buffer++)+=((sd1*(voll>>15))>>15); \
177 	/* adjust volume for right channel & mix */ \
178 	(*buffer++)+=((sd1*(volr>>15))>>15); \
179 	\
180 	if ((_RAMP_)) \
181 	{ \
182 		voll+=rampFromVolStepL; \
183 		volr+=rampFromVolStepR; \
184 	}
185 
186 #define NOCHECKMIXER_16BIT_LERP_RAMP(_RAMP_) \
187 	sd1 = sample[posfixed>>16]; \
188 	sd2 = sample[(posfixed>>16)+1]; \
189 	\
190 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
191 	\
192 	/* adjust volume for left channel & mix */ \
193 	(*buffer++)+=((sd1*(voll>>15))>>15); \
194 	/* adjust volume for right channel & mix */ \
195 	(*buffer++)+=((sd1*(volr>>15))>>15); \
196 	\
197 	if ((_RAMP_)) \
198 	{ \
199 		voll+=rampFromVolStepL; \
200 		volr+=rampFromVolStepR; \
201 	}
202 
203 /////////////////////////////////////////////////////////
204 //	    INTERPOLATION/VOLUME RAMPING and FILTERING     //
205 /////////////////////////////////////////////////////////
206 #define NOCHECKMIXER_8BIT_LERP_RAMP_FILTER(_RAMP_) \
207 	sd1 = sample[posfixed>>16]<<8; \
208 	sd2 = sample[(posfixed>>16)+1]<<8; \
209 	\
210 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
211 	\
212 	sd1 = (MP_FP_MUL(sd1, a) + MP_FP_MUL(currsample, b) + MP_FP_MUL(prevsample, c)) >> ChannelMixer::MP_FILTERPRECISION; \
213 	prevsample = currsample; \
214 	currsample = sd1; \
215 	\
216 	/* adjust volume for left/right channels & mix */ \
217 	(*buffer++)+=MP_FP_MUL(sd1, voll>>14); \
218 	(*buffer++)+=MP_FP_MUL(sd1, volr>>14); \
219 	\
220 	if ((_RAMP_)) \
221 	{ \
222 		voll+=rampFromVolStepL; \
223 		volr+=rampFromVolStepR; \
224 	}
225 
226 #define NOCHECKMIXER_16BIT_LERP_RAMP_FILTER(_RAMP_) \
227 	sd1 = sample[posfixed>>16]; \
228 	sd2 = sample[(posfixed>>16)+1]; \
229 	\
230 	sd1 =((sd1<<12)+((posfixed>>4)&0xfff)*(sd2-sd1))>>12; \
231 	\
232 	sd1 = (MP_FP_MUL(sd1, a) + MP_FP_MUL(currsample, b) + MP_FP_MUL(prevsample, c)) >> ChannelMixer::MP_FILTERPRECISION; \
233 	prevsample = currsample; \
234 	currsample = sd1; \
235 	\
236 	/* adjust volume for left/right channels & mix */ \
237 	(*buffer++)+=MP_FP_MUL(sd1, voll>>14); \
238 	(*buffer++)+=MP_FP_MUL(sd1, volr>>14); \
239 	\
240 	if ((_RAMP_)) \
241 	{ \
242 		voll+=rampFromVolStepL; \
243 		volr+=rampFromVolStepR; \
244 	}
245 
246 #define BIDIR_REPOSITION(FRACBITS, SMPPOS, SMPPOSFRAC, LOOPSTART, LOOPEND) \
247 	if (!((SMPPOS == LOOPEND) && (SMPPOSFRAC == 0) ||\
248 		(SMPPOS == LOOPSTART) && (SMPPOSFRAC == 0))) \
249 	{ \
250 		do \
251 		{ \
252 			if (SMPPOS >= LOOPEND) \
253 				SMPPOS = LOOPEND-(SMPPOS-LOOPEND+1); \
254 			else if (SMPPOS < LOOPSTART) \
255 				SMPPOS = LOOPSTART + (LOOPSTART-SMPPOS - 1); \
256 			SMPPOSFRAC = ((1<<FRACBITS)-SMPPOSFRAC) & ((1<<FRACBITS)-1); \
257 		} while (!(SMPPOS >= LOOPSTART && SMPPOS <= LOOPEND)); \
258 	}
259 
260 
261 #define FULLMIXER_TEMPLATE(MIXER_8BIT, MIXER_16BIT, FRACBITS, LABELNO) \
262 	mp_sint32 smppos = chn->smppos; \
263 	mp_sint32 smpposfrac = chn->smpposfrac; \
264 	mp_sint32 smpadd = chn->smpadd; \
265 	mp_sint32 loopstart = chn->loopstart; \
266 	mp_sint32 loopend = chn->loopend; \
267 	mp_sint32 flags = chn->flags; \
268 	const mp_sbyte* sample = chn->sample; \
269 	mp_sint32 sd1,sd2; \
270 	\
271 	/* 8 bit version */ \
272 	if (!(flags&4)) \
273 	{ \
274 		\
275 		if (((((flags&3) == 0 || (flags&3) == 1)) && !(flags&ChannelMixer::MP_SAMPLE_BACKWARD)) || \
276 			((flags&3) == 2 && (flags&ChannelMixer::MP_SAMPLE_BACKWARD) == 0)) \
277 		{ \
278 			\
279 			while (count) \
280 			{ \
281 				MIXER_8BIT \
282 				MP_INCREASESMPPOS(smppos,smpposfrac,smpadd,FRACBITS); \
283 				/* stop playing if necessary */ \
284 				if (smppos>=loopend) \
285 				{ \
286 					if ((flags & 3) == 0) \
287 					{ \
288 						if (flags & ChannelMixer::MP_SAMPLE_ONESHOT) \
289 						{ \
290 							flags &= ~ChannelMixer::MP_SAMPLE_ONESHOT; \
291 							flags |= 1; \
292 							chn->loopend = chn->loopendcopy; \
293 							loopend = chn->loopend; \
294 							/*ASSERT(loopend-loopstart > 0);*/ \
295 							smppos = ((smppos - loopstart)%(loopend-loopstart))+loopstart; \
296 						} \
297 						else \
298 						{ \
299 							flags&=~ChannelMixer::MP_SAMPLE_PLAY; \
300 							break; \
301 						} \
302 					} \
303 					else if ((flags & 3) == 1) \
304 					{ \
305 						/*if (smppos>=((loopend<<1)-loopstart))*/ \
306 						/*	smppos=loopstart;*/ \
307 						/*else */\
308 						/*	smppos=loopstart+(smppos-loopend); */\
309 						/*ASSERT(loopend-loopstart > 0);*/ \
310 						smppos = ((smppos - loopstart)%(loopend-loopstart))+loopstart; \
311 					} \
312 					else \
313 					{ \
314 						flags|=ChannelMixer::MP_SAMPLE_BACKWARD; \
315 						BIDIR_REPOSITION(FRACBITS, smppos, smpposfrac, loopstart, loopend) \
316 						/*ASSERT(smppos >= loopstart && smppos <= loopend);*/ \
317 						goto continueWithBiDir8_## LABELNO; \
318 					} \
319 				} \
320 				\
321 continueWithNormalDir8_## LABELNO: \
322 					\
323 				count--; \
324 				\
325 			}	\
326 			\
327 		} \
328 		/* bi-dir loop */ \
329 		else \
330 		{ \
331 			while (count) \
332 			{ \
333 				MIXER_8BIT \
334 				MP_INCREASESMPPOS(smppos,smpposfrac,-smpadd,FRACBITS); \
335 				\
336 				if (loopstart>smppos) \
337 				{ \
338 					if ((flags & 3) == 0) \
339 					{ \
340 						flags&=~ChannelMixer::MP_SAMPLE_PLAY; \
341 						break; \
342 					} \
343 					else if ((flags & 3) == 1) \
344 					{ \
345 						smppos = loopend-((loopstart-smppos)%(loopend-loopstart)); \
346 					} \
347 					else \
348 					{ \
349 						flags&=~ChannelMixer::MP_SAMPLE_BACKWARD; \
350 						BIDIR_REPOSITION(FRACBITS, smppos, smpposfrac, loopstart, loopend) \
351 						/*ASSERT(smppos >= loopstart && smppos <= loopend);*/ \
352 						goto continueWithNormalDir8_## LABELNO; \
353 					} \
354 				} \
355 				\
356 continueWithBiDir8_## LABELNO: \
357 					\
358 				count--; \
359 				\
360 			} \
361 			\
362 		} \
363 		\
364 	} \
365 	else \
366 	{ \
367 		\
368 		if (((((flags&3) == 0 || (flags&3) == 1)) && !(flags&ChannelMixer::MP_SAMPLE_BACKWARD)) || \
369 			((flags&3) == 2 && (flags&ChannelMixer::MP_SAMPLE_BACKWARD) == 0)) \
370 		{ \
371 		\
372 			while (count) \
373 			{ \
374 				MIXER_16BIT \
375 				MP_INCREASESMPPOS(smppos,smpposfrac,smpadd,FRACBITS); \
376 				/* stop playing if necessary */ \
377 				if (smppos>=loopend) \
378 				{ \
379 					if ((flags & 3) == 0) \
380 					{ \
381 						if (flags & ChannelMixer::MP_SAMPLE_ONESHOT) \
382 						{ \
383 							flags &= ~ChannelMixer::MP_SAMPLE_ONESHOT; \
384 							flags |= 1; \
385 							chn->loopend = chn->loopendcopy; \
386 							loopend = chn->loopend; \
387 							smppos = ((smppos - loopstart)%(loopend-loopstart))+loopstart; \
388 						} \
389 						else \
390 						{ \
391 							flags&=~ChannelMixer::MP_SAMPLE_PLAY; \
392 							break; \
393 						} \
394 					} \
395 					else if ((flags & 3) == 1) \
396 					{ \
397 						/*if (smppos>=((loopend<<1)-loopstart))*/ \
398 						/*	smppos=loopstart;*/ \
399 						/*else */\
400 						/*	smppos=loopstart+(smppos-loopend); */\
401 						smppos = ((smppos - loopstart)%(loopend-loopstart))+loopstart; \
402 					} \
403 					else \
404 					{ \
405 						flags|=ChannelMixer::MP_SAMPLE_BACKWARD; \
406 						BIDIR_REPOSITION(FRACBITS, smppos, smpposfrac, loopstart, loopend) \
407 						/*ASSERT(smppos >= loopstart && smppos <= loopend);*/ \
408 						goto continueWithBiDir16_## LABELNO; \
409 					} \
410 				} \
411 				\
412 continueWithNormalDir16_## LABELNO: \
413 					\
414 				count--; \
415 				\
416 			}	\
417 			\
418 		} \
419 		/* bi-dir loop */ \
420 		else \
421 		{ \
422 			while (count) \
423 			{ \
424 				MIXER_16BIT \
425 				MP_INCREASESMPPOS(smppos,smpposfrac,-smpadd,FRACBITS); \
426 				\
427 				if (loopstart>smppos) \
428 				{ \
429 					if ((flags & 3) == 0) \
430 					{ \
431 						flags&=~ChannelMixer::MP_SAMPLE_PLAY; \
432 						break; \
433 					} \
434 					else if ((flags & 3) == 1) \
435 					{ \
436 						smppos = loopend-((loopstart-smppos)%(loopend-loopstart)); \
437 					} \
438 					else \
439 					{ \
440 						flags&=~ChannelMixer::MP_SAMPLE_BACKWARD; \
441 						BIDIR_REPOSITION(FRACBITS, smppos, smpposfrac, loopstart, loopend) \
442 						/*ASSERT(smppos >= loopstart && smppos <= loopend);*/ \
443 						goto continueWithNormalDir16_## LABELNO; \
444 					} \
445 				} \
446 				\
447 continueWithBiDir16_## LABELNO: \
448 					\
449 				count--; \
450 				\
451 			} \
452 			\
453 		} \
454 		\
455 	} \
456 	chn->smppos = smppos; \
457 	chn->smpposfrac = smpposfrac; \
458 	/*chn->smpadd = smpadd;*/ \
459 	chn->flags = flags;
460 
461 /////////////////////////////////////////////////////////
462 //		NO INTERPOLATION AND NO VOLUME RAMPING		   //
463 /////////////////////////////////////////////////////////
464 #define FULLMIXER_8BIT_NORMAL \
465 	/* 8 bit sample */ \
466 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
467 	/* adjust volume for left channel & mix */ \
468 	(*buffer++)+=((sd1*(voll>>15))>>15); \
469 	/* adjust volume for right channel & mix */ \
470 	(*buffer++)+=((sd1*(volr>>15))>>15);
471 
472 #define FULLMIXER_16BIT_NORMAL \
473 	/* 16 bit sample */ \
474 	sd1 = ((mp_sword*)(sample))[smppos]; \
475 	/* adjust volume for left channel & mix */ \
476 	(*buffer++)+=((sd1*(voll>>15))>>15); \
477 	/* adjust volume for right channel & mix */ \
478 	(*buffer++)+=((sd1*(volr>>15))>>15);
479 
480 /////////////////////////////////////////////////////////
481 //			NO INTERPOLATION BUT VOLUME RAMPING		   //
482 /////////////////////////////////////////////////////////
483 #define FULLMIXER_8BIT_NORMAL_RAMP(_RAMP_) \
484 	/* 8 bit sample */ \
485 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
486 	/* adjust volume for left channel & mix */ \
487 	(*buffer++)+=((sd1*(voll>>15))>>15); \
488 	/* adjust volume for right channel & mix */ \
489 	(*buffer++)+=((sd1*(volr>>15))>>15); \
490 	if ((_RAMP_)) \
491 	{ \
492 		voll+=rampFromVolStepL; \
493 		volr+=rampFromVolStepR; \
494 	}
495 
496 #define FULLMIXER_16BIT_NORMAL_RAMP(_RAMP_) \
497 	/* 16 bit sample */ \
498 	sd1 = ((mp_sword*)(sample))[smppos]; \
499 	/* adjust volume for left channel & mix */ \
500 	(*buffer++)+=((sd1*(voll>>15))>>15); \
501 	/* adjust volume for right channel & mix */ \
502 	(*buffer++)+=((sd1*(volr>>15))>>15); \
503 	if ((_RAMP_)) \
504 	{ \
505 		voll+=rampFromVolStepL; \
506 		volr+=rampFromVolStepR; \
507 	}
508 
509 /////////////////////////////////////////////////////////
510 //			INTERPOLATION AND NO VOLUME RAMPING		   //
511 /////////////////////////////////////////////////////////
512 #define FULLMIXER_8BIT_LERP \
513 	/* 8 bit sample */ \
514 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
515 	sd2 = ((mp_sbyte)sample[smppos+1])<<8; \
516 	\
517 	sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
518 	\
519 	/* adjust volume for left channel & mix */ \
520 	(*buffer++)+=((sd1*(voll>>15))>>15); \
521 	/* adjust volume for right channel & mix */ \
522 	(*buffer++)+=((sd1*(volr>>15))>>15);
523 
524 #define FULLMIXER_16BIT_LERP \
525 	/* 16 bit sample */ \
526 	sd1 = ((mp_sword*)(sample))[smppos]; \
527 	sd2 = ((mp_sword*)(sample))[smppos+1]; \
528 	\
529 	sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
530 	\
531 	/* adjust volume for left channel & mix */ \
532 	(*buffer++)+=((sd1*(voll>>15))>>15); \
533 	/* adjust volume for right channel & mix */ \
534 	(*buffer++)+=((sd1*(volr>>15))>>15);
535 
536 /////////////////////////////////////////////////////////
537 //			INTERPOLATION AND VOLUME RAMPING		   //
538 /////////////////////////////////////////////////////////
539 #define FULLMIXER_8BIT_LERP_RAMP(_RAMP_) \
540 	/* 8 bit sample */ \
541 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
542 	sd2 = ((mp_sbyte)sample[smppos+1])<<8; \
543 	\
544 	sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
545 	\
546 	/* adjust volume for left channel & mix */ \
547 	(*buffer++)+=((sd1*(voll>>15))>>15); \
548 	/* adjust volume for right channel & mix */ \
549 	(*buffer++)+=((sd1*(volr>>15))>>15); \
550 	\
551 	if ((_RAMP_)) \
552 	{ \
553 		voll+=rampFromVolStepL; \
554 		volr+=rampFromVolStepR; \
555 	}
556 
557 #define FULLMIXER_16BIT_LERP_RAMP(_RAMP_) \
558 	/* 16 bit sample */ \
559 	sd1 = ((mp_sword*)(sample))[smppos]; \
560 	sd2 = ((mp_sword*)(sample))[smppos+1]; \
561 	\
562 	sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
563 	\
564 	/* adjust volume for left channel & mix */ \
565 	(*buffer++)+=((sd1*(voll>>15))>>15); \
566 	/* adjust volume for right channel & mix */ \
567 	(*buffer++)+=((sd1*(volr>>15))>>15); \
568 	\
569 	if ((_RAMP_)) \
570 	{ \
571 		voll+=rampFromVolStepL; \
572 		volr+=rampFromVolStepR; \
573 	}
574 
575 /////////////////////////////////////////////////////////
576 //	    INTERPOLATION/VOLUME RAMPING and FILTERING     //
577 /////////////////////////////////////////////////////////
578 #define FULLMIXER_8BIT_LERP_RAMP_FILTER(_RAMP_) \
579 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
580 	sd2 = ((mp_sbyte)sample[smppos+1])<<8; \
581 	\
582 	sd1 =((sd1<<12)+((smpposfrac>>4)&0xfff)*(sd2-sd1))>>12; \
583 	\
584 	sd1 = (MP_FP_MUL(sd1, a) + MP_FP_MUL(currsample, b) + MP_FP_MUL(prevsample, c)) >> ChannelMixer::MP_FILTERPRECISION; \
585 	prevsample = currsample; \
586 	currsample = sd1; \
587 	\
588 	/* adjust volume for left/right channels & mix */ \
589 	(*buffer++)+=MP_FP_MUL(sd1, voll>>14); \
590 	(*buffer++)+=MP_FP_MUL(sd1, volr>>14); \
591 	\
592 	if ((_RAMP_)) \
593 	{ \
594 		voll+=rampFromVolStepL; \
595 		volr+=rampFromVolStepR; \
596 	}
597 
598 #define FULLMIXER_16BIT_LERP_RAMP_FILTER(_RAMP_) \
599 	sd1 = ((mp_sword*)(sample))[smppos]; \
600 	sd2 = ((mp_sword*)(sample))[smppos+1]; \
601 	\
602 	sd1 =((sd1<<12)+((smpposfrac>>4)&0xfff)*(sd2-sd1))>>12; \
603 	\
604 	sd1 = (MP_FP_MUL(sd1, a) + MP_FP_MUL(currsample, b) + MP_FP_MUL(prevsample, c)) >> ChannelMixer::MP_FILTERPRECISION; \
605 	prevsample = currsample; \
606 	currsample = sd1; \
607 	\
608 	/* adjust volume for left/right channels & mix */ \
609 	(*buffer++)+=MP_FP_MUL(sd1, voll>>14); \
610 	(*buffer++)+=MP_FP_MUL(sd1, volr>>14); \
611 	\
612 	if ((_RAMP_)) \
613 	{ \
614 		voll+=rampFromVolStepL; \
615 		volr+=rampFromVolStepR; \
616 	}
617 
618 
619 /////////////////////////////////////////////////////////
620 //		 INTERPOLATION AND VOLUME RAMPING HIRES		   //
621 /////////////////////////////////////////////////////////
622 #define FULLMIXER_8BIT_LERP_RAMP_HIRES(_RAMP_) \
623 	/* 8 bit sample */ \
624 	sd1 = ((mp_sbyte)sample[smppos])<<8; \
625 	sd2 = ((mp_sbyte)sample[smppos+1])<<8; \
626 	\
627 	sd1 =((sd1<<12)+(smpposfrac>>(4+12))*(sd2-sd1))>>12; \
628 	\
629 	/* adjust volume for left channel & mix */ \
630 	(*buffer++)+=((sd1*(voll>>15))>>15); \
631 	/* adjust volume for right channel & mix */ \
632 	(*buffer++)+=((sd1*(volr>>15))>>15); \
633 	\
634 	if ((_RAMP_)) \
635 	{ \
636 		voll+=rampFromVolStepL; \
637 		volr+=rampFromVolStepR; \
638 	}
639 
640 #define FULLMIXER_16BIT_LERP_RAMP_HIRES(_RAMP_) \
641 	/* 16 bit sample */ \
642 	sd1 = ((mp_sword*)(sample))[smppos]; \
643 	sd2 = ((mp_sword*)(sample))[smppos+1]; \
644 	\
645 	sd1 =((sd1<<12)+(smpposfrac>>(4+12))*(sd2-sd1))>>12; \
646 	\
647 	/* adjust volume for left channel & mix */ \
648 	(*buffer++)+=((sd1*(voll>>15))>>15); \
649 	/* adjust volume for right channel & mix */ \
650 	(*buffer++)+=((sd1*(volr>>15))>>15); \
651 	\
652 	if ((_RAMP_)) \
653 	{ \
654 		voll+=rampFromVolStepL; \
655 		volr+=rampFromVolStepR; \
656 	}
657 
658 
659 #endif
660