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