summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/virtch2.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/virtch2.c')
-rw-r--r--apps/plugins/mikmod/virtch2.c1370
1 files changed, 1370 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/virtch2.c b/apps/plugins/mikmod/virtch2.c
new file mode 100644
index 0000000000..d512833bbe
--- /dev/null
+++ b/apps/plugins/mikmod/virtch2.c
@@ -0,0 +1,1370 @@
1/* MikMod sound library
2 (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
3 complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id$
24
25 High-quality sample mixing routines, using a 32 bits mixing buffer,
26 interpolation, and sample smoothing to improve sound quality and remove
27 clicks.
28
29==============================================================================*/
30
31/*
32
33 Future Additions:
34 Low-Pass filter to remove annoying staticy buzz.
35
36*/
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include "mikmod.h"
43
44#ifndef NO_HQMIXER
45
46#ifdef HAVE_MEMORY_H
47#include <memory.h>
48#endif
49#include <string.h>
50
51#include "mikmod_internals.h"
52
53/*
54 Constant Definitions
55 ====================
56
57 MAXVOL_FACTOR (was BITSHIFT in virtch.c)
58 Controls the maximum volume of the output data. All mixed data is
59 divided by this number after mixing, so larger numbers result in
60 quieter mixing. Smaller numbers will increase the likeliness of
61 distortion on loud modules.
62
63 REVERBERATION
64 Larger numbers result in shorter reverb duration. Longer reverb
65 durations can cause unwanted static and make the reverb sound more
66 like a crappy echo.
67
68 SAMPLING_SHIFT
69 Specified the shift multiplier which controls by how much the mixing
70 rate is multiplied while mixing. Higher values can improve quality by
71 smoothing the sound and reducing pops and clicks. Note, this is a shift
72 value, so a value of 2 becomes a mixing-rate multiplier of 4, and a
73 value of 3 = 8, etc.
74
75 FRACBITS
76 The number of bits per integer devoted to the fractional part of the
77 number. Generally, this number should not be changed for any reason.
78
79 !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0
80
81*/
82
83#define BITSHIFT 9
84#define MAXVOL_FACTOR (1<<BITSHIFT)
85#define REVERBERATION 11000L
86
87#define SAMPLING_SHIFT 2
88#define SAMPLING_FACTOR (1UL<<SAMPLING_SHIFT)
89
90#define FRACBITS 28
91#define FRACMASK ((1UL<<FRACBITS)-1UL)
92
93#define TICKLSIZE 8192
94#define TICKWSIZE (TICKLSIZE * 2)
95#define TICKBSIZE (TICKWSIZE * 2)
96
97#define CLICK_SHIFT_BASE 6
98#define CLICK_SHIFT (CLICK_SHIFT_BASE + SAMPLING_SHIFT)
99#define CLICK_BUFFER (1L << CLICK_SHIFT)
100
101#ifndef MIN
102#define MIN(a,b) (((a)<(b)) ? (a) : (b))
103#endif
104
105typedef struct VINFO {
106 UBYTE kick; /* =1 -> sample has to be restarted */
107 UBYTE active; /* =1 -> sample is playing */
108 UWORD flags; /* 16/8 bits looping/one-shot */
109 SWORD handle; /* identifies the sample */
110 ULONG start; /* start index */
111 ULONG size; /* samplesize */
112 ULONG reppos; /* loop start */
113 ULONG repend; /* loop end */
114 ULONG frq; /* current frequency */
115 int vol; /* current volume */
116 int pan; /* current panning position */
117
118 int click;
119 int rampvol;
120 SLONG lastvalL,lastvalR;
121 int lvolsel,rvolsel; /* Volume factor in range 0-255 */
122 int oldlvol,oldrvol;
123
124 SLONGLONG current; /* current index in the sample */
125 SLONGLONG increment; /* increment value */
126} VINFO;
127
128static SWORD **Samples;
129static VINFO *vinf=NULL,*vnf;
130static long tickleft,samplesthatfit,vc_memory=0;
131static int vc_softchn;
132static SLONGLONG idxsize,idxlpos,idxlend;
133static SLONG *vc_tickbuf=NULL;
134static UWORD vc_mode;
135
136#ifdef _MSC_VER
137/* Weird bug in compiler */ /* FIXME is this still needed? */
138typedef void (*MikMod_callback_t)(unsigned char *data, size_t len);
139#endif
140
141/* Reverb control variables */
142
143static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8;
144static ULONG RVRindex;
145
146/* For Mono or Left Channel */
147static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL,
148 *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL;
149
150/* For Stereo only (Right Channel) */
151static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL,
152 *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL;
153
154#ifdef NATIVE_64BIT_INT
155#define NATIVE SLONGLONG
156#else
157#define NATIVE SLONG
158#endif
159
160/*========== 32 bit sample mixers - only for 32 bit platforms */
161#ifndef NATIVE_64BIT_INT
162
163static SLONG Mix32MonoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
164{
165 SWORD sample=0;
166 SLONG i,f;
167
168 while(todo--) {
169 i=idx>>FRACBITS,f=idx&FRACMASK;
170 sample=(SWORD)( (((SLONG)(srce[i]*(FRACMASK+1L-f)) +
171 ((SLONG)srce[i+1]*f)) >> FRACBITS));
172 idx+=increment;
173
174 if(vnf->rampvol) {
175 *dest++ += (long)(
176 ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) +
177 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
178 (SLONG)sample ) >> CLICK_SHIFT );
179 vnf->rampvol--;
180 } else
181 if(vnf->click) {
182 *dest++ += (long)(
183 ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
184 (SLONG)sample ) +
185 (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT );
186 vnf->click--;
187 } else
188 *dest++ +=vnf->lvolsel*sample;
189 }
190 vnf->lastvalL=vnf->lvolsel * sample;
191
192 return idx;
193}
194
195static SLONG Mix32StereoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo)
196{
197 SWORD sample=0;
198 SLONG i,f;
199
200 while(todo--) {
201 i=idx>>FRACBITS,f=idx&FRACMASK;
202 sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) +
203 ((SLONG)srce[i+1] * f)) >> FRACBITS));
204 idx += increment;
205
206 if(vnf->rampvol) {
207 *dest++ += (long)(
208 ( ( ((SLONG)vnf->oldlvol*vnf->rampvol) +
209 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
210 ) * (SLONG)sample ) >> CLICK_SHIFT );
211 *dest++ += (long)(
212 ( ( ((SLONG)vnf->oldrvol*vnf->rampvol) +
213 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
214 ) * (SLONG)sample ) >> CLICK_SHIFT );
215 vnf->rampvol--;
216 } else
217 if(vnf->click) {
218 *dest++ += (long)(
219 ( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
220 (SLONG)sample ) + (vnf->lastvalL * vnf->click) )
221 >> CLICK_SHIFT );
222 *dest++ += (long)(
223 ( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
224 (SLONG)sample ) + (vnf->lastvalR * vnf->click) )
225 >> CLICK_SHIFT );
226 vnf->click--;
227 } else {
228 *dest++ +=vnf->lvolsel*sample;
229 *dest++ +=vnf->rvolsel*sample;
230 }
231 }
232 vnf->lastvalL=vnf->lvolsel*sample;
233 vnf->lastvalR=vnf->rvolsel*sample;
234
235 return idx;
236}
237
238static SLONG Mix32StereoSurround(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo)
239{
240 SWORD sample=0;
241 long whoop;
242 SLONG i, f;
243
244 while(todo--) {
245 i=idx>>FRACBITS,f=idx&FRACMASK;
246 sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) +
247 ((SLONG)srce[i+1]*f)) >> FRACBITS));
248 idx+=increment;
249
250 if(vnf->rampvol) {
251 whoop=(long)(
252 ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) +
253 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
254 (SLONG)sample) >> CLICK_SHIFT );
255 *dest++ +=whoop;
256 *dest++ -=whoop;
257 vnf->rampvol--;
258 } else
259 if(vnf->click) {
260 whoop = (long)(
261 ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
262 (SLONG)sample) +
263 (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT );
264 *dest++ +=whoop;
265 *dest++ -=whoop;
266 vnf->click--;
267 } else {
268 *dest++ +=vnf->lvolsel*sample;
269 *dest++ -=vnf->lvolsel*sample;
270 }
271 }
272 vnf->lastvalL=vnf->lvolsel*sample;
273 vnf->lastvalR=vnf->lvolsel*sample;
274
275 return idx;
276}
277#endif
278
279/*========== 64 bit mixers */
280
281static SLONGLONG MixMonoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
282{
283 SWORD sample=0;
284 SLONGLONG i,f;
285
286 while(todo--) {
287 i=idx>>FRACBITS,f=idx&FRACMASK;
288 sample=(SWORD)((((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) +
289 ((SLONGLONG)srce[i+1]*f)) >> FRACBITS));
290 idx+=increment;
291
292 if(vnf->rampvol) {
293 *dest++ += (long)(
294 ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) +
295 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
296 (SLONGLONG)sample ) >> CLICK_SHIFT );
297 vnf->rampvol--;
298 } else
299 if(vnf->click) {
300 *dest++ += (long)(
301 ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
302 (SLONGLONG)sample ) +
303 (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT );
304 vnf->click--;
305 } else
306 *dest++ +=vnf->lvolsel*sample;
307 }
308 vnf->lastvalL=vnf->lvolsel * sample;
309
310 return idx;
311}
312
313/* Slowest part... */
314
315#if defined HAVE_SSE2 || defined HAVE_ALTIVEC
316
317static __inline SWORD GetSample(const SWORD* const srce, SLONGLONG idx)
318{
319 SLONGLONG i=idx>>FRACBITS;
320 SLONGLONG f=idx&FRACMASK;
321 return (SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
322 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS));
323}
324
325static SLONGLONG MixSIMDStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo)
326{
327 SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel};
328 SWORD sample=0;
329 SLONG remain = todo;
330
331 /* Dest can be misaligned */
332 while(!IS_ALIGNED_16(dest)) {
333 sample=srce[idx >> FRACBITS];
334 idx += increment;
335 *dest++ += vol[0] * sample;
336 *dest++ += vol[1] * sample;
337 todo--;
338 if(!todo) goto end;
339 }
340
341 /* Srce is always aligned */
342
343#if defined HAVE_SSE2
344 remain = todo&3;
345 {
346 __m128i v0 = _mm_set_epi16(0, vol[1],
347 0, vol[0],
348 0, vol[1],
349 0, vol[0]);
350 for(todo>>=2;todo; todo--)
351 {
352 SWORD s0 = GetSample(srce, idx);
353 SWORD s1 = GetSample(srce, idx += increment);
354 SWORD s2 = GetSample(srce, idx += increment);
355 SWORD s3 = GetSample(srce, idx += increment);
356 __m128i v1 = _mm_set_epi16(0, s1, 0, s1, 0, s0, 0, s0);
357 __m128i v2 = _mm_set_epi16(0, s3, 0, s3, 0, s2, 0, s2);
358 __m128i v3 = _mm_load_si128((__m128i*)(dest+0));
359 __m128i v4 = _mm_load_si128((__m128i*)(dest+4));
360 _mm_store_si128((__m128i*)(dest+0), _mm_add_epi32(v3, _mm_madd_epi16(v0, v1)));
361 _mm_store_si128((__m128i*)(dest+4), _mm_add_epi32(v4, _mm_madd_epi16(v0, v2)));
362 dest+=8;
363 idx += increment;
364 }
365 }
366
367#elif defined HAVE_ALTIVEC
368 remain = todo&3;
369 {
370 SWORD s[8];
371 vector signed short r0 = vec_ld(0, vol);
372 vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, /* l */
373 0, 1, /* l */
374 2, 3, /* r */
375 2, 1, /* r */
376 0, 1, /* l */
377 0, 1, /* l */
378 2, 3, /* r */
379 2, 3 /* r */
380 ));
381
382 for(todo>>=2;todo; todo--)
383 {
384 vector short int r1;
385 vector signed short v1, v2;
386 vector signed int v3, v4, v5, v6;
387
388 /* Load constants */
389 s[0] = GetSample(srce, idx);
390 s[1] = GetSample(srce, idx += increment);
391 s[2] = GetSample(srce, idx += increment);
392 s[3] = GetSample(srce, idx += increment);
393 s[4] = 0;
394
395 r1 = vec_ld(0, s);
396 v1 = vec_perm(r1, r1, (vector unsigned char)
397 (0*2, 0*2+1, /* s0 */
398 4*2, 4*2+1, /* 0 */
399 0*2, 0*2+1, /* s0 */
400 4*2, 4*2+1, /* 0 */
401 1*2, 1*2+1, /* s1 */
402 4*2, 4*2+1, /* 0 */
403 1*2, 1*2+1, /* s1 */
404 4*2, 4*2+1 /* 0 */
405 ) );
406 v2 = vec_perm(r1, r1, (vector unsigned char)
407 (2*2, 2*2+1, /* s2 */
408 4*2, 4*2+1, /* 0 */
409 2*2, 2*2+1, /* s2 */
410 4*2, 4*2+1, /* 0 */
411 3*2, 3*2+1, /* s3 */
412 4*2, 4*2+1, /* 0 */
413 3*2, 3*2+1, /* s3 */
414 4*2, 4*2+1 /* 0 */
415 ) );
416
417 v3 = vec_ld(0, dest);
418 v4 = vec_ld(0x10, dest);
419 v5 = vec_mule(v0, v1);
420 v6 = vec_mule(v0, v2);
421
422 vec_st(vec_add(v3, v5), 0, dest);
423 vec_st(vec_add(v4, v6), 0x10, dest);
424
425 dest+=8;
426 idx += increment;
427 }
428 }
429#endif /* HAVE_ALTIVEC */
430
431 /* Remaining bits */
432 while(remain--) {
433 sample=GetSample(srce, idx);
434 idx+= increment;
435 *dest++ += vol[0] * sample;
436 *dest++ += vol[1] * sample;
437 }
438end:
439 vnf->lastvalL=vnf->lvolsel*sample;
440 vnf->lastvalR=vnf->rvolsel*sample;
441 return idx;
442}
443
444static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo)
445{
446 SWORD sample=0;
447 SLONGLONG i,f;
448
449 if (vnf->rampvol)
450 while(todo) {
451 todo--;
452 i=idx>>FRACBITS,f=idx&FRACMASK;
453 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
454 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS));
455 idx += increment;
456
457 *dest++ += (long)(
458 ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) +
459 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
460 ) * (SLONGLONG)sample ) >> CLICK_SHIFT );
461 *dest++ += (long)(
462 ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) +
463 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
464 ) * (SLONGLONG)sample ) >> CLICK_SHIFT );
465 vnf->rampvol--;
466
467 if (!vnf->rampvol)
468 break;
469 }
470
471 if (vnf->click)
472 while(todo) {
473 todo--;
474 i=idx>>FRACBITS,f=idx&FRACMASK;
475 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
476 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS));
477 idx += increment;
478
479 *dest++ += (long)(
480 ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
481 (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) )
482 >> CLICK_SHIFT );
483
484 *dest++ += (long)(
485 ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
486 (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) )
487 >> CLICK_SHIFT );
488 vnf->click--;
489
490 if (!vnf->click)
491 break;
492 }
493
494 if (todo)
495 {
496 if (md_mode & DMODE_SIMDMIXER) {
497 return MixSIMDStereoNormal(srce, dest, idx, increment, todo);
498 }
499 while(todo)
500 {
501 i=idx>>FRACBITS,
502 f=idx&FRACMASK;
503 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
504 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS));
505 idx += increment;
506
507 *dest++ +=vnf->lvolsel*sample;
508 *dest++ +=vnf->rvolsel*sample;
509 todo--;
510 }
511 }
512 vnf->lastvalL=vnf->lvolsel*sample;
513 vnf->lastvalR=vnf->rvolsel*sample;
514
515 return idx;
516}
517
518#else /* HAVE_SSE2 || HAVE_ALTIVEC */
519static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo)
520{
521 SWORD sample=0;
522 SLONGLONG i,f;
523
524 while(todo--) {
525 i=idx>>FRACBITS,f=idx&FRACMASK;
526 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
527 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS));
528 idx += increment;
529
530 if(vnf->rampvol) {
531 *dest++ += (long)(
532 ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) +
533 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
534 ) * (SLONGLONG)sample ) >> CLICK_SHIFT );
535 *dest++ += (long)(
536 ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) +
537 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
538 ) * (SLONGLONG)sample ) >> CLICK_SHIFT );
539 vnf->rampvol--;
540 } else
541 if(vnf->click) {
542 *dest++ += (long)(
543 ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
544 (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) )
545 >> CLICK_SHIFT );
546 *dest++ += (long)(
547 ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
548 (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) )
549 >> CLICK_SHIFT );
550 vnf->click--;
551 } else {
552 *dest++ +=vnf->lvolsel*sample;
553 *dest++ +=vnf->rvolsel*sample;
554 }
555 }
556 vnf->lastvalL=vnf->lvolsel*sample;
557 vnf->lastvalR=vnf->rvolsel*sample;
558
559 return idx;
560}
561#endif /* HAVE_SSE2 || HAVE_ALTIVEC */
562
563
564static SLONGLONG MixStereoSurround(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo)
565{
566 SWORD sample=0;
567 long whoop;
568 SLONGLONG i, f;
569
570 while(todo--) {
571 i=idx>>FRACBITS,f=idx&FRACMASK;
572 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
573 ((SLONGLONG)srce[i+1]*f)) >> FRACBITS));
574 idx+=increment;
575
576 if(vnf->rampvol) {
577 whoop=(long)(
578 ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) +
579 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
580 (SLONGLONG)sample) >> CLICK_SHIFT );
581 *dest++ +=whoop;
582 *dest++ -=whoop;
583 vnf->rampvol--;
584 } else
585 if(vnf->click) {
586 whoop = (long)(
587 ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
588 (SLONGLONG)sample) +
589 (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT );
590 *dest++ +=whoop;
591 *dest++ -=whoop;
592 vnf->click--;
593 } else {
594 *dest++ +=vnf->lvolsel*sample;
595 *dest++ -=vnf->lvolsel*sample;
596 }
597 }
598 vnf->lastvalL=vnf->lvolsel*sample;
599 vnf->lastvalR=vnf->lvolsel*sample;
600
601 return idx;
602}
603
604static void(*Mix32toFP)(float* dste,const SLONG *srce,NATIVE count);
605static void(*Mix32to16)(SWORD* dste,const SLONG *srce,NATIVE count);
606static void(*Mix32to8)(SBYTE* dste,const SLONG *srce,NATIVE count);
607static void(*MixReverb)(SLONG *srce,NATIVE count);
608
609/* Reverb macros */
610#define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n
611#define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7)
612#define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7)
613
614static void MixReverb_Normal(SLONG *srce,NATIVE count)
615{
616 NATIVE speedup;
617 int ReverbPct;
618 unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
619
620 ReverbPct=58+(md_reverb*4);
621
622 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
623 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
624
625 while(count--) {
626 /* Compute the left channel echo buffers */
627 speedup = *srce >> 3;
628
629 COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
630 COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
631
632 /* Prepare to compute actual finalized data */
633 RVRindex++;
634
635 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
636 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
637
638 /* left channel */
639 *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
640 RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
641 }
642}
643
644static void MixReverb_Stereo(SLONG *srce,NATIVE count)
645{
646 NATIVE speedup;
647 int ReverbPct;
648 unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
649
650 ReverbPct=58+(md_reverb*4);
651
652 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
653 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
654
655 while(count--) {
656 /* Compute the left channel echo buffers */
657 speedup = *srce >> 3;
658
659 COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
660 COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
661
662 /* Compute the right channel echo buffers */
663 speedup = srce[1] >> 3;
664
665 COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4);
666 COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8);
667
668 /* Prepare to compute actual finalized data */
669 RVRindex++;
670
671 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
672 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
673
674 /* left channel */
675 *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
676 RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
677
678 /* right channel */
679 *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
680 RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
681 }
682}
683
684static void (*MixLowPass)(SLONG* srce,NATIVE count);
685
686static int nLeftNR, nRightNR;
687
688static void MixLowPass_Stereo(SLONG* srce,NATIVE count)
689{
690 int n1 = nLeftNR, n2 = nRightNR;
691 SLONG *pnr = srce;
692 int nr=count;
693 for (; nr; nr--)
694 {
695 int vnr = pnr[0] >> 1;
696 pnr[0] = vnr + n1;
697 n1 = vnr;
698 vnr = pnr[1] >> 1;
699 pnr[1] = vnr + n2;
700 n2 = vnr;
701 pnr += 2;
702 }
703 nLeftNR = n1;
704 nRightNR = n2;
705}
706
707static void MixLowPass_Normal(SLONG* srce,NATIVE count)
708{
709 int n1 = nLeftNR;
710 SLONG *pnr = srce;
711 int nr=count;
712 for (; nr; nr--)
713 {
714 int vnr = pnr[0] >> 1;
715 pnr[0] = vnr + n1;
716 n1 = vnr;
717 pnr ++;
718 }
719 nLeftNR = n1;
720}
721
722/* Mixing macros */
723#define EXTRACT_SAMPLE_FP(var,attenuation) var=*srce++*((1.0f / 32768.0f) / (MAXVOL_FACTOR*attenuation))
724#define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var
725
726static void Mix32ToFP_Normal(float* dste,const SLONG *srce,NATIVE count)
727{
728 float x1,x2,tmpx;
729 int i;
730
731 for(count/=SAMPLING_FACTOR;count;count--) {
732 tmpx=0.0f;
733
734 for(i=SAMPLING_FACTOR/2;i;i--) {
735 EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f);
736
737 CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f);
738
739 tmpx+=x1+x2;
740 }
741 *dste++ =tmpx*(1.0f/SAMPLING_FACTOR);
742 }
743}
744
745static void Mix32ToFP_Stereo(float* dste,const SLONG *srce,NATIVE count)
746{
747 float x1,x2,x3,x4,tmpx,tmpy;
748 int i;
749
750 for(count/=SAMPLING_FACTOR;count;count--) {
751 tmpx=tmpy=0.0f;
752
753 for(i=SAMPLING_FACTOR/2;i;i--) {
754 EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f);
755 EXTRACT_SAMPLE_FP(x3,1.0f); EXTRACT_SAMPLE_FP(x4,1.0f);
756
757 CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f);
758 CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f);
759
760 tmpx+=x1+x3;
761 tmpy+=x2+x4;
762 }
763 *dste++ =tmpx*(1.0f/SAMPLING_FACTOR);
764 *dste++ =tmpy*(1.0f/SAMPLING_FACTOR);
765 }
766}
767
768/* Mixing macros */
769#define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation)
770#define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var
771
772static void Mix32To16_Normal(SWORD* dste,const SLONG *srce,NATIVE count)
773{
774 NATIVE x1,x2,tmpx;
775 int i;
776
777 for(count/=SAMPLING_FACTOR;count;count--) {
778 tmpx=0;
779
780 for(i=SAMPLING_FACTOR/2;i;i--) {
781 EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
782
783 CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
784
785 tmpx+=x1+x2;
786 }
787 *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR);
788 }
789}
790
791
792static void Mix32To16_Stereo(SWORD* dste,const SLONG *srce,NATIVE count)
793{
794 NATIVE x1,x2,x3,x4,tmpx,tmpy;
795 int i;
796
797 for(count/=SAMPLING_FACTOR;count;count--) {
798 tmpx=tmpy=0;
799
800 for(i=SAMPLING_FACTOR/2;i;i--) {
801 EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
802 EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1);
803
804 CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
805 CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
806
807 tmpx+=x1+x3;
808 tmpy+=x2+x4;
809 }
810 *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR);
811 *dste++ =(SWORD)(tmpy/SAMPLING_FACTOR);
812 }
813}
814
815static void Mix32To8_Normal(SBYTE* dste,const SLONG *srce,NATIVE count)
816{
817 NATIVE x1,x2,tmpx;
818 int i;
819
820 for(count/=SAMPLING_FACTOR;count;count--) {
821 tmpx = 0;
822
823 for(i=SAMPLING_FACTOR/2;i;i--) {
824 EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
825
826 CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
827
828 tmpx+=x1+x2;
829 }
830 *dste++ = (SBYTE)((tmpx/SAMPLING_FACTOR)+128);
831 }
832}
833
834static void Mix32To8_Stereo(SBYTE* dste,const SLONG *srce,NATIVE count)
835{
836 NATIVE x1,x2,x3,x4,tmpx,tmpy;
837 int i;
838
839 for(count/=SAMPLING_FACTOR;count;count--) {
840 tmpx=tmpy=0;
841
842 for(i=SAMPLING_FACTOR/2;i;i--) {
843 EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
844 EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256);
845
846 CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
847 CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
848
849 tmpx+=x1+x3;
850 tmpy+=x2+x4;
851 }
852 *dste++ =(SBYTE)((tmpx/SAMPLING_FACTOR)+128);
853 *dste++ =(SBYTE)((tmpy/SAMPLING_FACTOR)+128);
854 }
855}
856
857#if defined HAVE_SSE2
858#define SHIFT_MIX_TO_16 (BITSHIFT + 16 - 16)
859/* TEST: Ok */
860static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count)
861{
862 int remain = count;
863
864 /* Check unaligned dste buffer. srce is always aligned. */
865 while(!IS_ALIGNED_16(dste))
866 {
867 Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR);
868 dste+=2;
869 srce+=8;
870 count--;
871 if(!count) return;
872 }
873
874 /* dste and srce aligned. srce is always aligned. */
875 remain = count & 15;
876 /* count / 2 for 1 sample */
877
878 for(count>>=4;count;count--)
879 {
880 /* Load 32bit sample. 1st average */
881 __m128i v0 = _mm_add_epi32(
882 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+0)), SHIFT_MIX_TO_16),
883 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+4)), SHIFT_MIX_TO_16)
884 ); /* v0: s0.l+s2.l | s0.r+s2.r | s1.l+s3.l | s1.r+s3.r */
885
886 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */
887 __m128i v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2);
888 /* v1: s0.l+s2.l / 4 | s0.r+s2.r / 4 | s1.l+s3.l+s0.l+s2.l / 4 | s1.r+s3.r+s0.r+s2.r / 4 */
889
890 __m128i v2 = _mm_add_epi32(
891 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+8)), SHIFT_MIX_TO_16),
892 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+12)), SHIFT_MIX_TO_16)
893 ); /* v2: s4.l+s6.l | s4.r+s6.r | s5.l+s7.l | s5.r+s7.r */
894
895 __m128i v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */
896 /* v3: s4.l+s6.l /4 | s4.r+s6.r / 4| s5.l+s7.l+s4.l+s6.l / 4 | s5.r+s7.r+s4.r+s6.l / 4 */
897
898 /* pack two stereo samples in one */
899 __m128i v4 = _mm_unpacklo_epi64(v1, v3); /* v4 = avg(s0,s1,s2,s3) | avg(s4,s5,s6,s7) */
900
901 __m128i v6;
902
903 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */
904 v0 = _mm_add_epi32(
905 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+16)), SHIFT_MIX_TO_16),
906 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+20)), SHIFT_MIX_TO_16)
907 ); /* 128bit = 2 stereo samples */
908
909 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */
910 v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2);
911
912 v2 = _mm_add_epi32(
913 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+24)), SHIFT_MIX_TO_16),
914 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+28)), SHIFT_MIX_TO_16)
915 );
916
917 v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */
918
919 /* pack two stereo samples in one */
920 v6 = _mm_unpacklo_epi64(v1, v3); /* v6 = avg(s8,s9,s10,s11) | avg(s12,s13,s14,s15) */
921
922 _mm_store_si128((__m128i*)dste, _mm_packs_epi32(v4, v6)); /* 4 interpolated stereo sample 32bit to 4 */
923
924 dste+=8;
925 srce+=32; /* 32 = 4 * 8 */
926 }
927
928 /* FIXME: THIS PART WRITES PAST DST !! */
929 if (remain)
930 {
931 Mix32To16_Stereo(dste, srce, remain);
932 }
933}
934
935#elif defined HAVE_ALTIVEC
936#define SHIFT_MIX_TO_16 vec_splat_u32(BITSHIFT + 16 - 16)
937/* TEST: Ok */
938static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count)
939{
940 int remain = count;
941
942 /* Check unaligned dste buffer. srce is always aligned. */
943 while(!IS_ALIGNED_16(dste))
944 {
945 Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR);
946 dste+=2;
947 srce+=8;
948 count--;
949 if(!count) return;
950 }
951
952 /* dste and srce aligned. srce is always aligned. */
953 remain = count & 15;
954 for(count>>=4;count;count--)
955 {
956 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */
957 vector signed int v0 = vec_add(
958 vec_sra(vec_ld(0, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */
959 vec_sra(vec_ld(0x10, srce), SHIFT_MIX_TO_16)
960 ); /* 128bit = 2 stereo samples */
961
962 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */
963 vector signed int v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2));
964
965 vector signed int v2 = vec_add(
966 vec_sra(vec_ld(0x20, srce), SHIFT_MIX_TO_16),
967 vec_sra(vec_ld(0x30, srce), SHIFT_MIX_TO_16)
968 );
969
970 vector signed int v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */
971
972 /* pack two stereo samples in one */
973 vector signed int v6, v4 = vec_unpacklo(v1, v3); /* v4 = lo64(v1) | lo64(v3) */
974
975 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */
976 v0 = vec_add(
977 vec_sra(vec_ld(0x40, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */
978 vec_sra(vec_ld(0x50, srce), SHIFT_MIX_TO_16)
979 ); /* 128bit = 2 stereo samples */
980
981 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */
982 v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2));
983
984 v2 = vec_add(
985 vec_sra(vec_ld(0x60, srce), SHIFT_MIX_TO_16),
986 vec_sra(vec_ld(0x70, srce), SHIFT_MIX_TO_16)
987 );
988
989 v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */
990
991 /* pack two stereo samples in one */
992 v6 = vec_unpacklo(v1, v3);
993
994 vec_st(vec_packs(v4, v6), 0, dste); /* 4 interpolated stereo sample 32bit to 4 interpolated stereo sample 16bit + saturation */
995
996 dste+=8;
997 srce+=32; /* 32 = 4 * 8 */
998 }
999
1000 if (remain)
1001 {
1002 Mix32To16_Stereo(dste, srce, remain);
1003 }
1004}
1005
1006#endif
1007
1008
1009static void AddChannel(SLONG* ptr,NATIVE todo)
1010{
1011 SLONGLONG end,done;
1012 SWORD *s;
1013
1014 if(!(s=Samples[vnf->handle])) {
1015 vnf->current = vnf->active = 0;
1016 vnf->lastvalL = vnf->lastvalR = 0;
1017 return;
1018 }
1019
1020 /* update the 'current' index so the sample loops, or stops playing if it
1021 reached the end of the sample */
1022 while(todo>0) {
1023 SLONGLONG endpos;
1024
1025 if(vnf->flags & SF_REVERSE) {
1026 /* The sample is playing in reverse */
1027 if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) {
1028 /* the sample is looping and has reached the loopstart index */
1029 if(vnf->flags & SF_BIDI) {
1030 /* sample is doing bidirectional loops, so 'bounce' the
1031 current index against the idxlpos */
1032 vnf->current = idxlpos+(idxlpos-vnf->current);
1033 vnf->flags &= ~SF_REVERSE;
1034 vnf->increment = -vnf->increment;
1035 } else
1036 /* normal backwards looping, so set the current position to
1037 loopend index */
1038 vnf->current=idxlend-(idxlpos-vnf->current);
1039 } else {
1040 /* the sample is not looping, so check if it reached index 0 */
1041 if(vnf->current < 0) {
1042 /* playing index reached 0, so stop playing this sample */
1043 vnf->current = vnf->active = 0;
1044 break;
1045 }
1046 }
1047 } else {
1048 /* The sample is playing forward */
1049 if((vnf->flags & SF_LOOP) &&
1050 (vnf->current >= idxlend)) {
1051 /* the sample is looping, check the loopend index */
1052 if(vnf->flags & SF_BIDI) {
1053 /* sample is doing bidirectional loops, so 'bounce' the
1054 current index against the idxlend */
1055 vnf->flags |= SF_REVERSE;
1056 vnf->increment = -vnf->increment;
1057 vnf->current = idxlend-(vnf->current-idxlend);
1058 } else
1059 /* normal backwards looping, so set the current position
1060 to loopend index */
1061 vnf->current=idxlpos+(vnf->current-idxlend);
1062 } else {
1063 /* sample is not looping, so check if it reached the last
1064 position */
1065 if(vnf->current >= idxsize) {
1066 /* yes, so stop playing this sample */
1067 vnf->current = vnf->active = 0;
1068 break;
1069 }
1070 }
1071 }
1072
1073 end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
1074 (vnf->flags&SF_LOOP)?idxlend:idxsize;
1075
1076 /* if the sample is not blocked... */
1077 if((end==vnf->current)||(!vnf->increment))
1078 done=0;
1079 else {
1080 done=MIN((end-vnf->current)/vnf->increment+1,todo);
1081 if(done<0) done=0;
1082 }
1083
1084 if(!done) {
1085 vnf->active = 0;
1086 break;
1087 }
1088
1089 endpos=vnf->current+done*vnf->increment;
1090
1091 if(vnf->vol || vnf->rampvol) {
1092#ifndef NATIVE_64BIT_INT
1093 /* use the 32 bit mixers as often as we can (they're much faster) */
1094 if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) {
1095 if(vc_mode & DMODE_STEREO) {
1096 if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND))
1097 vnf->current=(SLONGLONG)Mix32StereoSurround
1098 (s,ptr,vnf->current,vnf->increment,done);
1099 else
1100 vnf->current=Mix32StereoNormal
1101 (s,ptr,vnf->current,vnf->increment,done);
1102 } else
1103 vnf->current=Mix32MonoNormal
1104 (s,ptr,vnf->current,vnf->increment,done);
1105 }
1106 else
1107#endif
1108 {
1109 if(vc_mode & DMODE_STEREO) {
1110 if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND))
1111 vnf->current=MixStereoSurround
1112 (s,ptr,vnf->current,vnf->increment,done);
1113 else
1114 vnf->current=MixStereoNormal
1115 (s,ptr,vnf->current,vnf->increment,done);
1116 } else
1117 vnf->current=MixMonoNormal
1118 (s,ptr,vnf->current,vnf->increment,done);
1119 }
1120 } else {
1121 vnf->lastvalL = vnf->lastvalR = 0;
1122 /* update sample position */
1123 vnf->current=endpos;
1124 }
1125
1126 todo -= done;
1127 ptr += (vc_mode & DMODE_STEREO)?(done<<1):done;
1128 }
1129}
1130
1131#define _IN_VIRTCH_
1132
1133#define VC1_SilenceBytes VC2_SilenceBytes
1134#define VC1_WriteSamples VC2_WriteSamples
1135#define VC1_WriteBytes VC2_WriteBytes
1136#define VC1_Exit VC2_Exit
1137#define VC1_VoiceSetVolume VC2_VoiceSetVolume
1138#define VC1_VoiceGetVolume VC2_VoiceGetVolume
1139#define VC1_VoiceSetPanning VC2_VoiceSetPanning
1140#define VC1_VoiceGetPanning VC2_VoiceGetPanning
1141#define VC1_VoiceSetFrequency VC2_VoiceSetFrequency
1142#define VC1_VoiceGetFrequency VC2_VoiceGetFrequency
1143#define VC1_VoicePlay VC2_VoicePlay
1144#define VC1_VoiceStop VC2_VoiceStop
1145#define VC1_VoiceStopped VC2_VoiceStopped
1146#define VC1_VoiceGetPosition VC2_VoiceGetPosition
1147#define VC1_SampleUnload VC2_SampleUnload
1148#define VC1_SampleLoad VC2_SampleLoad
1149#define VC1_SampleSpace VC2_SampleSpace
1150#define VC1_SampleLength VC2_SampleLength
1151#define VC1_VoiceRealVolume VC2_VoiceRealVolume
1152
1153#include "virtch_common.c"
1154#undef _IN_VIRTCH_
1155
1156void VC2_WriteSamples(SBYTE* buf,ULONG todo)
1157{
1158 int left,portion=0;
1159 SBYTE *buffer;
1160 int t,pan,vol;
1161
1162 todo*=SAMPLING_FACTOR;
1163
1164 while(todo) {
1165 if(!tickleft) {
1166 if(vc_mode & DMODE_SOFT_MUSIC) md_player();
1167 tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L);
1168 tickleft&=~(SAMPLING_FACTOR-1);
1169 }
1170 left = MIN(tickleft, (int)todo);
1171 buffer = buf;
1172 tickleft -= left;
1173 todo -= left;
1174 buf += samples2bytes(left)/SAMPLING_FACTOR;
1175
1176 while(left) {
1177 portion = MIN(left, samplesthatfit);
1178 memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2));
1179 for(t=0;t<vc_softchn;t++) {
1180 vnf = &vinf[t];
1181
1182 if(vnf->kick) {
1183 vnf->current=((SLONGLONG)(vnf->start))<<FRACBITS;
1184 vnf->kick = 0;
1185 vnf->active = 1;
1186 vnf->click = CLICK_BUFFER;
1187 vnf->rampvol = 0;
1188 }
1189
1190 if(!vnf->frq) vnf->active = 0;
1191
1192 if(vnf->active) {
1193 vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT))
1194 /md_mixfreq;
1195 if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment;
1196 vol = vnf->vol; pan = vnf->pan;
1197
1198 vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel;
1199 if(vc_mode & DMODE_STEREO) {
1200 if(pan!=PAN_SURROUND) {
1201 vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8;
1202 vnf->rvolsel=(vol*pan)>>8;
1203 } else {
1204 vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480;
1205 }
1206 } else
1207 vnf->lvolsel=vol;
1208
1209 idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<<FRACBITS)-1:0;
1210 idxlend=(vnf->repend)?((SLONGLONG)(vnf->repend)<<FRACBITS)-1:0;
1211 idxlpos=(SLONGLONG)(vnf->reppos)<<FRACBITS;
1212 AddChannel(vc_tickbuf,portion);
1213 }
1214 }
1215
1216 if(md_mode & DMODE_NOISEREDUCTION) {
1217 MixLowPass(vc_tickbuf, portion);
1218 }
1219
1220 if(md_reverb) {
1221 if(md_reverb>15) md_reverb=15;
1222 MixReverb(vc_tickbuf,portion);
1223 }
1224
1225 if (vc_callback) {
1226 vc_callback((unsigned char*)vc_tickbuf, portion);
1227 }
1228
1229 if(vc_mode & DMODE_FLOAT)
1230 Mix32toFP((float*)buffer,vc_tickbuf,portion);
1231 else if(vc_mode & DMODE_16BITS)
1232 Mix32to16((SWORD*)buffer,vc_tickbuf,portion);
1233 else
1234 Mix32to8((SBYTE*)buffer,vc_tickbuf,portion);
1235
1236 buffer += samples2bytes(portion) / SAMPLING_FACTOR;
1237 left -= portion;
1238 }
1239 }
1240}
1241
1242int VC2_Init(void)
1243{
1244 VC_SetupPointers();
1245
1246 if (!(md_mode&DMODE_HQMIXER))
1247 return VC1_Init();
1248
1249 if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) {
1250 _mm_errno = MMERR_INITIALIZING_MIXER;
1251 return 1;
1252 }
1253 if(!vc_tickbuf) {
1254 if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) {
1255 _mm_errno = MMERR_INITIALIZING_MIXER;
1256 return 1;
1257 }
1258 }
1259
1260 if(md_mode & DMODE_STEREO) {
1261 Mix32toFP = Mix32ToFP_Stereo;
1262#if ((defined HAVE_ALTIVEC || defined HAVE_SSE2) && (SAMPLING_FACTOR == 4))
1263 if (md_mode & DMODE_SIMDMIXER)
1264 Mix32to16 = Mix32To16_Stereo_SIMD_4Tap;
1265 else
1266#endif
1267 Mix32to16 = Mix32To16_Stereo;
1268 Mix32to8 = Mix32To8_Stereo;
1269 MixReverb = MixReverb_Stereo;
1270 MixLowPass = MixLowPass_Stereo;
1271 } else {
1272 Mix32toFP = Mix32ToFP_Normal;
1273 Mix32to16 = Mix32To16_Normal;
1274 Mix32to8 = Mix32To8_Normal;
1275 MixReverb = MixReverb_Normal;
1276 MixLowPass = MixLowPass_Normal;
1277 }
1278
1279 md_mode |= DMODE_INTERP;
1280 vc_mode = md_mode;
1281 return 0;
1282}
1283
1284int VC2_PlayStart(void)
1285{
1286 md_mode|=DMODE_INTERP;
1287
1288 samplesthatfit = TICKLSIZE;
1289 if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
1290 tickleft = 0;
1291
1292 RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10);
1293 RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10);
1294 RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10);
1295 RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10);
1296 RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10);
1297 RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10);
1298 RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10);
1299 RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10);
1300
1301 if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1;
1302 if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1;
1303 if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1;
1304 if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1;
1305 if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1;
1306 if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1;
1307 if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1;
1308 if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1;
1309
1310 /* allocate reverb buffers for the right channel if in stereo mode only. */
1311 if (vc_mode & DMODE_STEREO) {
1312 if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1;
1313 if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1;
1314 if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1;
1315 if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1;
1316 if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1;
1317 if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1;
1318 if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1;
1319 if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1;
1320 }
1321
1322 RVRindex = 0;
1323 return 0;
1324}
1325
1326void VC2_PlayStop(void)
1327{
1328 MikMod_free(RVbufL1);
1329 MikMod_free(RVbufL2);
1330 MikMod_free(RVbufL3);
1331 MikMod_free(RVbufL4);
1332 MikMod_free(RVbufL5);
1333 MikMod_free(RVbufL6);
1334 MikMod_free(RVbufL7);
1335 MikMod_free(RVbufL8);
1336 MikMod_free(RVbufR1);
1337 MikMod_free(RVbufR2);
1338 MikMod_free(RVbufR3);
1339 MikMod_free(RVbufR4);
1340 MikMod_free(RVbufR5);
1341 MikMod_free(RVbufR6);
1342 MikMod_free(RVbufR7);
1343 MikMod_free(RVbufR8);
1344
1345 RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL;
1346 RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL;
1347}
1348
1349int VC2_SetNumVoices(void)
1350{
1351 int t;
1352
1353 md_mode|=DMODE_INTERP;
1354
1355 if(!(vc_softchn=md_softchn)) return 0;
1356
1357 MikMod_free(vinf);
1358 if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1;
1359
1360 for(t=0;t<vc_softchn;t++) {
1361 vinf[t].frq=10000;
1362 vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;
1363 }
1364
1365 return 0;
1366}
1367
1368#endif /* ! NO_HQMIXER */
1369
1370/* ex:set ts=4: */