1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
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.
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.
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
21 /*==============================================================================
25 Sample mixing routines, using a 32 bits mixing buffer.
27 ==============================================================================*/
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
46 #include "mikmod_internals.h"
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.
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
65 #define REVERBERATION 110000L
68 #define FRACMASK ((1L<<FRACBITS)-1L)
70 #define TICKLSIZE 8192
71 #define TICKWSIZE (TICKLSIZE<<1)
72 #define TICKBSIZE (TICKWSIZE<<1)
75 #define CLICK_BUFFER (1L<<CLICK_SHIFT)
78 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
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 */
95 int lvolsel,rvolsel; /* Volume factor in range 0-255 */
98 SLONGLONG current; /* current index in the sample */
99 SLONGLONG increment; /* increment value */
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;
110 /* Reverb control variables */
112 static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8;
113 static ULONG RVRindex;
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;
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;
123 #ifdef NATIVE_64BIT_INT
124 #define NATIVE SLONGLONG
129 #if defined HAVE_SSE2 || defined HAVE_ALTIVEC
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)
136 SLONG lvolsel = vnf->lvolsel;
139 sample = srce[idx >> FRACBITS];
142 *dest++ += lvolsel * sample;
146 # endif /* !NATIVE_64BIT_INT */
148 static SINTPTR_T MixSIMDStereoNormal(const SWORD* srce,SLONG* dest,SINTPTR_T idx,SINTPTR_T increment,SINTPTR_T todo)
150 SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel};
154 /* Dest can be misaligned */
155 while(!IS_ALIGNED_16(dest)) {
156 sample=srce[idx >> FRACBITS];
158 *dest++ += vol[0] * sample;
159 *dest++ += vol[1] * sample;
161 if(!todo) return idx;
164 /* Srce is always aligned */
166 #if defined HAVE_SSE2
169 __m128i v0 = _mm_set_epi16(0, vol[1],
173 for(todo>>=2;todo; todo--)
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)));
190 #elif defined HAVE_ALTIVEC
194 vector signed short r0 = vec_ld(0, vol);
195 vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, /* l */
205 for(todo>>=2;todo; todo--)
208 vector signed short v1, v2;
209 vector signed int v3, v4, v5, v6;
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];
219 v1 = vec_perm(r1, r1, (vector unsigned char)
220 (0*2, 0*2+1, /* s0 */
229 v2 = vec_perm(r1, r1, (vector unsigned char)
230 (2*2, 2*2+1, /* s2 */
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);
245 vec_st(vec_add(v3, v5), 0, dest);
246 vec_st(vec_add(v4, v6), 0x10, dest);
252 #endif /* HAVE_ALTIVEC */
256 sample=srce[idx >> FRACBITS];
259 *dest++ += vol[0] * sample;
260 *dest++ += vol[1] * sample;
266 /*========== 32 bit sample mixers - only for 32 bit platforms */
267 #ifndef NATIVE_64BIT_INT
269 static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
271 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
272 if (md_mode & DMODE_SIMDMIXER) {
273 return MixSIMDMonoNormal(srce, dest, idx, increment, todo);
279 SLONG lvolsel = vnf->lvolsel;
282 sample = srce[idx >> FRACBITS];
285 *dest++ += lvolsel * sample;
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)
295 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
296 if (md_mode & DMODE_SIMDMIXER) {
297 return MixSIMDStereoNormal(srce, dest, idx, increment, todo);
303 SLONG lvolsel = vnf->lvolsel;
304 SLONG rvolsel = vnf->rvolsel;
307 sample=srce[idx >> FRACBITS];
310 *dest++ += lvolsel * sample;
311 *dest++ += rvolsel * sample;
317 static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
320 SLONG lvolsel = vnf->lvolsel;
321 SLONG rvolsel = vnf->rvolsel;
323 if (lvolsel>=rvolsel) {
325 sample = srce[idx >> FRACBITS];
328 *dest++ += lvolsel*sample;
329 *dest++ -= lvolsel*sample;
334 sample = srce[idx >> FRACBITS];
337 *dest++ -= rvolsel*sample;
338 *dest++ += rvolsel*sample;
344 static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
347 SLONG lvolsel = vnf->lvolsel;
348 SLONG rampvol = vnf->rampvol;
351 SLONG oldlvol = vnf->oldlvol - lvolsel;
353 sample=(SLONG)srce[idx>>FRACBITS]+
354 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
355 *(idx&FRACMASK)>>FRACBITS);
358 *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
359 * sample >> CLICK_SHIFT;
363 vnf->rampvol = rampvol;
369 sample=(SLONG)srce[idx>>FRACBITS]+
370 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
371 *(idx&FRACMASK)>>FRACBITS);
374 *dest++ += lvolsel * sample;
379 static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
382 SLONG lvolsel = vnf->lvolsel;
383 SLONG rvolsel = vnf->rvolsel;
384 SLONG rampvol = vnf->rampvol;
387 SLONG oldlvol = vnf->oldlvol - lvolsel;
388 SLONG oldrvol = vnf->oldrvol - rvolsel;
390 sample=(SLONG)srce[idx>>FRACBITS]+
391 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
392 *(idx&FRACMASK)>>FRACBITS);
395 *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
396 * sample >> CLICK_SHIFT;
397 *dest++ += ((rvolsel << CLICK_SHIFT) + oldrvol * rampvol)
398 * sample >> CLICK_SHIFT;
402 vnf->rampvol = rampvol;
408 sample=(SLONG)srce[idx>>FRACBITS]+
409 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
410 *(idx&FRACMASK)>>FRACBITS);
413 *dest++ += lvolsel * sample;
414 *dest++ += rvolsel * sample;
419 static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
422 SLONG lvolsel = vnf->lvolsel;
423 SLONG rvolsel = vnf->rvolsel;
424 SLONG rampvol = vnf->rampvol;
427 if (lvolsel >= rvolsel) {
429 oldvol = vnf->oldlvol;
432 oldvol = vnf->oldrvol;
438 sample=(SLONG)srce[idx>>FRACBITS]+
439 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
440 *(idx&FRACMASK)>>FRACBITS);
443 sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
444 * sample >> CLICK_SHIFT;
451 vnf->rampvol = rampvol;
457 sample=(SLONG)srce[idx>>FRACBITS]+
458 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
459 *(idx&FRACMASK)>>FRACBITS);
462 *dest++ += vol*sample;
463 *dest++ -= vol*sample;
469 /*========== 64 bit sample mixers - all platforms */
471 static SLONGLONG MixMonoNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
474 SLONG lvolsel = vnf->lvolsel;
477 sample = srce[idx >> FRACBITS];
480 *dest++ += lvolsel * sample;
485 static SLONGLONG MixStereoNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
488 SLONG lvolsel = vnf->lvolsel;
489 SLONG rvolsel = vnf->rvolsel;
492 sample=srce[idx >> FRACBITS];
495 *dest++ += lvolsel * sample;
496 *dest++ += rvolsel * sample;
501 static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
504 SLONG lvolsel = vnf->lvolsel;
505 SLONG rvolsel = vnf->rvolsel;
507 if(vnf->lvolsel>=vnf->rvolsel) {
509 sample = srce[idx >> FRACBITS];
512 *dest++ += lvolsel*sample;
513 *dest++ -= lvolsel*sample;
518 sample = srce[idx >> FRACBITS];
521 *dest++ -= rvolsel*sample;
522 *dest++ += rvolsel*sample;
528 static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
531 SLONG lvolsel = vnf->lvolsel;
532 SLONG rampvol = vnf->rampvol;
535 SLONG oldlvol = vnf->oldlvol - lvolsel;
537 sample=(SLONG)srce[idx>>FRACBITS]+
538 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
539 *(idx&FRACMASK)>>FRACBITS);
542 *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
543 * sample >> CLICK_SHIFT;
547 vnf->rampvol = rampvol;
553 sample=(SLONG)srce[idx>>FRACBITS]+
554 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
555 *(idx&FRACMASK)>>FRACBITS);
558 *dest++ += lvolsel * sample;
563 static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
566 SLONG lvolsel = vnf->lvolsel;
567 SLONG rvolsel = vnf->rvolsel;
568 SLONG rampvol = vnf->rampvol;
571 SLONG oldlvol = vnf->oldlvol - lvolsel;
572 SLONG oldrvol = vnf->oldrvol - rvolsel;
574 sample=(SLONG)srce[idx>>FRACBITS]+
575 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
576 *(idx&FRACMASK)>>FRACBITS);
579 *dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
580 * sample >> CLICK_SHIFT;
581 *dest++ +=((rvolsel << CLICK_SHIFT) + oldrvol * rampvol)
582 * sample >> CLICK_SHIFT;
586 vnf->rampvol = rampvol;
592 sample=(SLONG)srce[idx>>FRACBITS]+
593 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
594 *(idx&FRACMASK)>>FRACBITS);
597 *dest++ += lvolsel * sample;
598 *dest++ += rvolsel * sample;
603 static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
606 SLONG lvolsel = vnf->lvolsel;
607 SLONG rvolsel = vnf->rvolsel;
608 SLONG rampvol = vnf->rampvol;
611 if (lvolsel >= rvolsel) {
613 oldvol = vnf->oldlvol;
616 oldvol = vnf->oldrvol;
622 sample=(SLONG)srce[idx>>FRACBITS]+
623 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
624 *(idx&FRACMASK)>>FRACBITS);
627 sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
628 * sample >> CLICK_SHIFT;
634 vnf->rampvol = rampvol;
640 sample=(SLONG)srce[idx>>FRACBITS]+
641 ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
642 *(idx&FRACMASK)>>FRACBITS);
645 *dest++ += vol*sample;
646 *dest++ -= vol*sample;
651 static void (*MixReverb)(SLONG* srce,NATIVE count);
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)
658 static void MixReverb_Normal(SLONG* srce,NATIVE count)
660 unsigned int speedup;
662 unsigned int loc1,loc2,loc3,loc4;
663 unsigned int loc5,loc6,loc7,loc8;
665 ReverbPct=58+(md_reverb<<2);
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);
671 /* Compute the left channel echo buffers */
672 speedup = *srce >> 3;
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);
677 /* Prepare to compute actual finalized data */
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);
684 *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
685 RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
689 static void MixReverb_Stereo(SLONG* srce,NATIVE count)
691 unsigned int speedup;
693 unsigned int loc1, loc2, loc3, loc4;
694 unsigned int loc5, loc6, loc7, loc8;
696 ReverbPct = 92+(md_reverb<<1);
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);
702 /* Compute the left channel echo buffers */
703 speedup = *srce >> 3;
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);
708 /* Compute the right channel echo buffers */
709 speedup = srce[1] >> 3;
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);
714 /* Prepare to compute actual finalized data */
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);
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];
724 *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
725 RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
729 static void (*MixLowPass)(SLONG* srce,NATIVE count);
731 static int nLeftNR, nRightNR;
733 static void MixLowPass_Stereo(SLONG* srce,NATIVE count)
735 int n1 = nLeftNR, n2 = nRightNR;
740 int vnr = pnr[0] >> 1;
752 static void MixLowPass_Normal(SLONG* srce,NATIVE count)
759 int vnr = pnr[0] >> 1;
767 /* shifting fudge factor for FP scaling, should be 0 < FP_SHIFT < BITSHIFT */
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
775 static void Mix32ToFP(float* dste,const SLONG *srce,NATIVE count)
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);
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);
788 PUT_SAMPLE_FP(x1); PUT_SAMPLE_FP(x2);
789 PUT_SAMPLE_FP(x3); PUT_SAMPLE_FP(x4);
792 EXTRACT_SAMPLE_FP(x1,FP_SHIFT);
793 CHECK_SAMPLE_FP(x1,1.0f);
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
804 static void Mix32To16(SWORD* dste,const SLONG *srce,NATIVE count)
810 for(count>>=2;count;count--) {
811 EXTRACT_SAMPLE(x1,16); EXTRACT_SAMPLE(x2,16);
812 EXTRACT_SAMPLE(x3,16); EXTRACT_SAMPLE(x4,16);
814 CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
815 CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
817 PUT_SAMPLE(x1); PUT_SAMPLE(x2); PUT_SAMPLE(x3); PUT_SAMPLE(x4);
820 EXTRACT_SAMPLE(x1,16);
821 CHECK_SAMPLE(x1,32768);
826 static void Mix32To8(SBYTE* dste,const SLONG *srce,NATIVE count)
832 for(count>>=2;count;count--) {
833 EXTRACT_SAMPLE(x1,8); EXTRACT_SAMPLE(x2,8);
834 EXTRACT_SAMPLE(x3,8); EXTRACT_SAMPLE(x4,8);
836 CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
837 CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
839 PUT_SAMPLE(x1+128); PUT_SAMPLE(x2+128);
840 PUT_SAMPLE(x3+128); PUT_SAMPLE(x4+128);
843 EXTRACT_SAMPLE(x1,8);
844 CHECK_SAMPLE(x1,128);
849 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
851 /* Mix 32bit input to floating point. 32 samples per iteration */
853 static void Mix32ToFP_SIMD(float* dste,const SLONG* srce,NATIVE count)
855 const float k = ((1.0f / 32768.0f) / (1 << FP_SHIFT));
857 simd_m128 x1, x2, xk;
859 while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce))
862 EXTRACT_SAMPLE_FP(xf,FP_SHIFT);
863 CHECK_SAMPLE_FP(xf,1.0f);
871 xk = LOAD_PS1_SIMD(&k); /* Scale factor */
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 */
883 EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); /* Load 4 samples */
884 PUT_SAMPLE_SIMD_F(dste, x1); /* Store 4 samples */
892 EXTRACT_SAMPLE_FP(xf,FP_SHIFT);
893 CHECK_SAMPLE_FP(xf,1.0f);
899 static void Mix32To16_SIMD(SWORD* dste,const SLONG* srce,NATIVE count)
903 while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce))
906 EXTRACT_SAMPLE(x1,16);
907 CHECK_SAMPLE(x1,32768);
915 for(count>>=3;count;count--)
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 */
926 Mix32To16(dste, srce, remain);
929 /* Mix 32bit input to 8bit. 128 samples per iteration */
931 static void Mix32To8_SIMD(SBYTE* dste,const SLONG* srce,NATIVE count)
935 while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce))
938 EXTRACT_SAMPLE(x1,8);
939 CHECK_SAMPLE(x1,128);
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 */
959 Mix32To8(dste, srce, remain);
965 static void AddChannel(SLONG* ptr,NATIVE todo)
970 if(!(s=Samples[vnf->handle])) {
971 vnf->current = vnf->active = 0;
975 /* update the 'current' index so the sample loops, or stops playing if it
976 reached the end of the sample */
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;
991 /* normal backwards looping, so set the current position to
993 vnf->current=idxlend-(idxlpos-vnf->current);
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;
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);
1014 /* normal backwards looping, so set the current position
1016 vnf->current=idxlpos+(vnf->current-idxlend);
1018 /* sample is not looping, so check if it reached the last
1020 if(vnf->current >= idxsize) {
1021 /* yes, so stop playing this sample */
1022 vnf->current = vnf->active = 0;
1028 end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
1029 (vnf->flags&SF_LOOP)?idxlend:idxsize;
1031 /* if the sample is not blocked... */
1032 if((end==vnf->current)||(!vnf->increment))
1035 done=MIN((end-vnf->current)/vnf->increment+1,todo);
1044 endpos=vnf->current+done*vnf->increment;
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);
1056 vnf->current=Mix32StereoInterp
1057 (s,ptr,vnf->current,vnf->increment,done);
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);
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);
1073 vnf->current=Mix32StereoNormal
1074 (s,ptr,vnf->current,vnf->increment,done);
1077 vnf->current=Mix32MonoNormal
1078 (s,ptr,vnf->current,vnf->increment,done);
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);
1089 vnf->current=MixStereoInterp
1090 (s,ptr,vnf->current,vnf->increment,done);
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);
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);
1106 vnf->current=MixStereoNormal
1107 (s,ptr,vnf->current,vnf->increment,done);
1110 vnf->current=MixMonoNormal
1111 (s,ptr,vnf->current,vnf->increment,done);
1114 /* update sample position */
1115 vnf->current=endpos;
1118 ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done;
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
1150 #include "virtch_common.c"
1153 void VC1_WriteSamples(SBYTE* buf,ULONG todo)
1155 int left,portion=0,count;
1161 if(vc_mode & DMODE_SOFT_MUSIC) md_player();
1162 tickleft=(md_mixfreq*125L)/(md_bpm*50L);
1164 left = MIN(tickleft, todo);
1168 buf += samples2bytes(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++) {
1178 vnf->current=((SLONGLONG)vnf->start)<<FRACBITS;
1183 if(!vnf->frq) vnf->active = 0;
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;
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;
1196 vnf->lvolsel=vnf->rvolsel=vol/2;
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);
1207 if(md_mode & DMODE_NOISEREDUCTION) {
1208 MixLowPass(vc_tickbuf, portion);
1212 if(md_reverb>15) md_reverb=15;
1213 MixReverb(vc_tickbuf, portion);
1217 vc_callback((unsigned char*)vc_tickbuf, portion);
1220 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
1221 if (md_mode & DMODE_SIMDMIXER)
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);
1228 Mix32To8_SIMD((SBYTE*) buffer, vc_tickbuf, count);
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);
1238 Mix32To8((SBYTE*) buffer, vc_tickbuf, count);
1240 buffer += samples2bytes(portion);
1251 if (md_mode&DMODE_HQMIXER)
1255 if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) {
1256 _mm_errno = MMERR_INITIALIZING_MIXER;
1260 if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) {
1261 _mm_errno = MMERR_INITIALIZING_MIXER;
1266 MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal;
1267 MixLowPass=(md_mode&DMODE_STEREO)?MixLowPass_Stereo:MixLowPass_Normal;
1272 int VC1_PlayStart(void)
1274 samplesthatfit=TICKLSIZE;
1275 if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
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;
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;
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;
1312 void VC1_PlayStop(void)
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;
1334 int VC1_SetNumVoices(void)
1338 if(!(vc_softchn=md_softchn)) return 0;
1341 if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1;
1343 for(t=0;t<vc_softchn;t++) {
1345 vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;