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