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