diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
commit | 26f2bfde03420edad4de1f22cb3d515dc063b20d (patch) | |
tree | 4a8c4abaf4795f38da70a4657c1a0fb3ba9debeb /apps/plugins/mikmod/virtch.c | |
parent | d192bdf11e06e50645ecb5726658d4b691480a9a (diff) | |
download | rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.gz rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.zip |
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mikmod/virtch.c')
-rw-r--r-- | apps/plugins/mikmod/virtch.c | 1319 |
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 | |||
86 | typedef 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 | |||
107 | static SWORD **Samples; | ||
108 | static VINFO *vinf=NULL,*vnf; | ||
109 | static long tickleft,samplesthatfit,vc_memory=0; | ||
110 | static int vc_softchn; | ||
111 | static SLONGLONG idxsize,idxlpos,idxlend; | ||
112 | static SLONG *vc_tickbuf=NULL; | ||
113 | static UWORD vc_mode; | ||
114 | |||
115 | /* Reverb control variables */ | ||
116 | |||
117 | static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; | ||
118 | static ULONG RVRindex; | ||
119 | |||
120 | /* For Mono or Left Channel */ | ||
121 | static 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) */ | ||
125 | static 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 | |||
135 | static 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 | |||
150 | static 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 | |||
260 | static 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 | ||
285 | static 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 | |||
310 | static 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 | |||
336 | static 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 | |||
371 | static 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 | |||
411 | static 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 | |||
463 | static 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 | |||
477 | static 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 | |||
493 | static 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 | |||
519 | static 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 | |||
554 | static 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 | |||
594 | static 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 | |||
642 | static 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 | |||
649 | static 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 | |||
680 | static 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 | |||
720 | static void (*MixLowPass)(SLONG* srce,NATIVE count); | ||
721 | |||
722 | static int nLeftNR, nRightNR; | ||
723 | |||
724 | static 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 | |||
743 | static 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 | |||
766 | static 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 | |||
795 | static 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 | |||
817 | static 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 | ||
844 | static 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 | ||
892 | static 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 | ||
927 | static 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 | |||
964 | static 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 | |||
1126 | void 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 | |||
1220 | int 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 | |||
1243 | int 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 | |||
1280 | void 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 | |||
1302 | int 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: */ | ||