diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2020-08-08 21:56:15 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-08-11 03:29:12 +0000 |
commit | b4e70422a3455e327433a7471c929ef100ef3b10 (patch) | |
tree | e96c5431a1b22af1fcbc628322b79fb8c3162427 /apps/plugins/mikmod/virtch2.c | |
parent | 8c7780bafc9eabac6b92cfe5a5a00831c3d5fd9d (diff) | |
download | rockbox-b4e70422a3455e327433a7471c929ef100ef3b10.tar.gz rockbox-b4e70422a3455e327433a7471c929ef100ef3b10.zip |
mikmod: Upgrade mikmod core from v3.2.0 to v3.3.11
* Get rid of the non-functional GT2 loader
* Add the UMX loader
* Add HQ mixer routines (and make it configurable)
* Allow samplerate to be configured at run/playtime
* Support >64KHz mixing/playback
* Correctly restore non-boost status
(The diff to upstream is much smaller now too!)
Change-Id: Iaa4ac901ba9cd4123bb225656976e78271353a72
Diffstat (limited to 'apps/plugins/mikmod/virtch2.c')
-rw-r--r-- | apps/plugins/mikmod/virtch2.c | 1370 |
1 files changed, 1370 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/virtch2.c b/apps/plugins/mikmod/virtch2.c new file mode 100644 index 0000000000..d512833bbe --- /dev/null +++ b/apps/plugins/mikmod/virtch2.c | |||
@@ -0,0 +1,1370 @@ | |||
1 | /* MikMod sound library | ||
2 | (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for | ||
3 | complete list. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Library General Public License as | ||
7 | published by the Free Software Foundation; either version 2 of | ||
8 | the License, or (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
18 | 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /*============================================================================== | ||
22 | |||
23 | $Id$ | ||
24 | |||
25 | High-quality sample mixing routines, using a 32 bits mixing buffer, | ||
26 | interpolation, and sample smoothing to improve sound quality and remove | ||
27 | clicks. | ||
28 | |||
29 | ==============================================================================*/ | ||
30 | |||
31 | /* | ||
32 | |||
33 | Future Additions: | ||
34 | Low-Pass filter to remove annoying staticy buzz. | ||
35 | |||
36 | */ | ||
37 | |||
38 | #ifdef HAVE_CONFIG_H | ||
39 | #include "config.h" | ||
40 | #endif | ||
41 | |||
42 | #include "mikmod.h" | ||
43 | |||
44 | #ifndef NO_HQMIXER | ||
45 | |||
46 | #ifdef HAVE_MEMORY_H | ||
47 | #include <memory.h> | ||
48 | #endif | ||
49 | #include <string.h> | ||
50 | |||
51 | #include "mikmod_internals.h" | ||
52 | |||
53 | /* | ||
54 | Constant Definitions | ||
55 | ==================== | ||
56 | |||
57 | MAXVOL_FACTOR (was BITSHIFT in virtch.c) | ||
58 | Controls the maximum volume of the output data. All mixed data is | ||
59 | divided by this number after mixing, so larger numbers result in | ||
60 | quieter mixing. Smaller numbers will increase the likeliness of | ||
61 | distortion on loud modules. | ||
62 | |||
63 | REVERBERATION | ||
64 | Larger numbers result in shorter reverb duration. Longer reverb | ||
65 | durations can cause unwanted static and make the reverb sound more | ||
66 | like a crappy echo. | ||
67 | |||
68 | SAMPLING_SHIFT | ||
69 | Specified the shift multiplier which controls by how much the mixing | ||
70 | rate is multiplied while mixing. Higher values can improve quality by | ||
71 | smoothing the sound and reducing pops and clicks. Note, this is a shift | ||
72 | value, so a value of 2 becomes a mixing-rate multiplier of 4, and a | ||
73 | value of 3 = 8, etc. | ||
74 | |||
75 | FRACBITS | ||
76 | The number of bits per integer devoted to the fractional part of the | ||
77 | number. Generally, this number should not be changed for any reason. | ||
78 | |||
79 | !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0 | ||
80 | |||
81 | */ | ||
82 | |||
83 | #define BITSHIFT 9 | ||
84 | #define MAXVOL_FACTOR (1<<BITSHIFT) | ||
85 | #define REVERBERATION 11000L | ||
86 | |||
87 | #define SAMPLING_SHIFT 2 | ||
88 | #define SAMPLING_FACTOR (1UL<<SAMPLING_SHIFT) | ||
89 | |||
90 | #define FRACBITS 28 | ||
91 | #define FRACMASK ((1UL<<FRACBITS)-1UL) | ||
92 | |||
93 | #define TICKLSIZE 8192 | ||
94 | #define TICKWSIZE (TICKLSIZE * 2) | ||
95 | #define TICKBSIZE (TICKWSIZE * 2) | ||
96 | |||
97 | #define CLICK_SHIFT_BASE 6 | ||
98 | #define CLICK_SHIFT (CLICK_SHIFT_BASE + SAMPLING_SHIFT) | ||
99 | #define CLICK_BUFFER (1L << CLICK_SHIFT) | ||
100 | |||
101 | #ifndef MIN | ||
102 | #define MIN(a,b) (((a)<(b)) ? (a) : (b)) | ||
103 | #endif | ||
104 | |||
105 | typedef struct VINFO { | ||
106 | UBYTE kick; /* =1 -> sample has to be restarted */ | ||
107 | UBYTE active; /* =1 -> sample is playing */ | ||
108 | UWORD flags; /* 16/8 bits looping/one-shot */ | ||
109 | SWORD handle; /* identifies the sample */ | ||
110 | ULONG start; /* start index */ | ||
111 | ULONG size; /* samplesize */ | ||
112 | ULONG reppos; /* loop start */ | ||
113 | ULONG repend; /* loop end */ | ||
114 | ULONG frq; /* current frequency */ | ||
115 | int vol; /* current volume */ | ||
116 | int pan; /* current panning position */ | ||
117 | |||
118 | int click; | ||
119 | int rampvol; | ||
120 | SLONG lastvalL,lastvalR; | ||
121 | int lvolsel,rvolsel; /* Volume factor in range 0-255 */ | ||
122 | int oldlvol,oldrvol; | ||
123 | |||
124 | SLONGLONG current; /* current index in the sample */ | ||
125 | SLONGLONG increment; /* increment value */ | ||
126 | } VINFO; | ||
127 | |||
128 | static SWORD **Samples; | ||
129 | static VINFO *vinf=NULL,*vnf; | ||
130 | static long tickleft,samplesthatfit,vc_memory=0; | ||
131 | static int vc_softchn; | ||
132 | static SLONGLONG idxsize,idxlpos,idxlend; | ||
133 | static SLONG *vc_tickbuf=NULL; | ||
134 | static UWORD vc_mode; | ||
135 | |||
136 | #ifdef _MSC_VER | ||
137 | /* Weird bug in compiler */ /* FIXME is this still needed? */ | ||
138 | typedef void (*MikMod_callback_t)(unsigned char *data, size_t len); | ||
139 | #endif | ||
140 | |||
141 | /* Reverb control variables */ | ||
142 | |||
143 | static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; | ||
144 | static ULONG RVRindex; | ||
145 | |||
146 | /* For Mono or Left Channel */ | ||
147 | static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL, | ||
148 | *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL; | ||
149 | |||
150 | /* For Stereo only (Right Channel) */ | ||
151 | static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, | ||
152 | *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL; | ||
153 | |||
154 | #ifdef NATIVE_64BIT_INT | ||
155 | #define NATIVE SLONGLONG | ||
156 | #else | ||
157 | #define NATIVE SLONG | ||
158 | #endif | ||
159 | |||
160 | /*========== 32 bit sample mixers - only for 32 bit platforms */ | ||
161 | #ifndef NATIVE_64BIT_INT | ||
162 | |||
163 | static SLONG Mix32MonoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo) | ||
164 | { | ||
165 | SWORD sample=0; | ||
166 | SLONG i,f; | ||
167 | |||
168 | while(todo--) { | ||
169 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
170 | sample=(SWORD)( (((SLONG)(srce[i]*(FRACMASK+1L-f)) + | ||
171 | ((SLONG)srce[i+1]*f)) >> FRACBITS)); | ||
172 | idx+=increment; | ||
173 | |||
174 | if(vnf->rampvol) { | ||
175 | *dest++ += (long)( | ||
176 | ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + | ||
177 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * | ||
178 | (SLONG)sample ) >> CLICK_SHIFT ); | ||
179 | vnf->rampvol--; | ||
180 | } else | ||
181 | if(vnf->click) { | ||
182 | *dest++ += (long)( | ||
183 | ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
184 | (SLONG)sample ) + | ||
185 | (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); | ||
186 | vnf->click--; | ||
187 | } else | ||
188 | *dest++ +=vnf->lvolsel*sample; | ||
189 | } | ||
190 | vnf->lastvalL=vnf->lvolsel * sample; | ||
191 | |||
192 | return idx; | ||
193 | } | ||
194 | |||
195 | static SLONG Mix32StereoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) | ||
196 | { | ||
197 | SWORD sample=0; | ||
198 | SLONG i,f; | ||
199 | |||
200 | while(todo--) { | ||
201 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
202 | sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + | ||
203 | ((SLONG)srce[i+1] * f)) >> FRACBITS)); | ||
204 | idx += increment; | ||
205 | |||
206 | if(vnf->rampvol) { | ||
207 | *dest++ += (long)( | ||
208 | ( ( ((SLONG)vnf->oldlvol*vnf->rampvol) + | ||
209 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
210 | ) * (SLONG)sample ) >> CLICK_SHIFT ); | ||
211 | *dest++ += (long)( | ||
212 | ( ( ((SLONG)vnf->oldrvol*vnf->rampvol) + | ||
213 | (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
214 | ) * (SLONG)sample ) >> CLICK_SHIFT ); | ||
215 | vnf->rampvol--; | ||
216 | } else | ||
217 | if(vnf->click) { | ||
218 | *dest++ += (long)( | ||
219 | ( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
220 | (SLONG)sample ) + (vnf->lastvalL * vnf->click) ) | ||
221 | >> CLICK_SHIFT ); | ||
222 | *dest++ += (long)( | ||
223 | ( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * | ||
224 | (SLONG)sample ) + (vnf->lastvalR * vnf->click) ) | ||
225 | >> CLICK_SHIFT ); | ||
226 | vnf->click--; | ||
227 | } else { | ||
228 | *dest++ +=vnf->lvolsel*sample; | ||
229 | *dest++ +=vnf->rvolsel*sample; | ||
230 | } | ||
231 | } | ||
232 | vnf->lastvalL=vnf->lvolsel*sample; | ||
233 | vnf->lastvalR=vnf->rvolsel*sample; | ||
234 | |||
235 | return idx; | ||
236 | } | ||
237 | |||
238 | static SLONG Mix32StereoSurround(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) | ||
239 | { | ||
240 | SWORD sample=0; | ||
241 | long whoop; | ||
242 | SLONG i, f; | ||
243 | |||
244 | while(todo--) { | ||
245 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
246 | sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + | ||
247 | ((SLONG)srce[i+1]*f)) >> FRACBITS)); | ||
248 | idx+=increment; | ||
249 | |||
250 | if(vnf->rampvol) { | ||
251 | whoop=(long)( | ||
252 | ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + | ||
253 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * | ||
254 | (SLONG)sample) >> CLICK_SHIFT ); | ||
255 | *dest++ +=whoop; | ||
256 | *dest++ -=whoop; | ||
257 | vnf->rampvol--; | ||
258 | } else | ||
259 | if(vnf->click) { | ||
260 | whoop = (long)( | ||
261 | ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
262 | (SLONG)sample) + | ||
263 | (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); | ||
264 | *dest++ +=whoop; | ||
265 | *dest++ -=whoop; | ||
266 | vnf->click--; | ||
267 | } else { | ||
268 | *dest++ +=vnf->lvolsel*sample; | ||
269 | *dest++ -=vnf->lvolsel*sample; | ||
270 | } | ||
271 | } | ||
272 | vnf->lastvalL=vnf->lvolsel*sample; | ||
273 | vnf->lastvalR=vnf->lvolsel*sample; | ||
274 | |||
275 | return idx; | ||
276 | } | ||
277 | #endif | ||
278 | |||
279 | /*========== 64 bit mixers */ | ||
280 | |||
281 | static SLONGLONG MixMonoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo) | ||
282 | { | ||
283 | SWORD sample=0; | ||
284 | SLONGLONG i,f; | ||
285 | |||
286 | while(todo--) { | ||
287 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
288 | sample=(SWORD)((((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) + | ||
289 | ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); | ||
290 | idx+=increment; | ||
291 | |||
292 | if(vnf->rampvol) { | ||
293 | *dest++ += (long)( | ||
294 | ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + | ||
295 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * | ||
296 | (SLONGLONG)sample ) >> CLICK_SHIFT ); | ||
297 | vnf->rampvol--; | ||
298 | } else | ||
299 | if(vnf->click) { | ||
300 | *dest++ += (long)( | ||
301 | ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
302 | (SLONGLONG)sample ) + | ||
303 | (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); | ||
304 | vnf->click--; | ||
305 | } else | ||
306 | *dest++ +=vnf->lvolsel*sample; | ||
307 | } | ||
308 | vnf->lastvalL=vnf->lvolsel * sample; | ||
309 | |||
310 | return idx; | ||
311 | } | ||
312 | |||
313 | /* Slowest part... */ | ||
314 | |||
315 | #if defined HAVE_SSE2 || defined HAVE_ALTIVEC | ||
316 | |||
317 | static __inline SWORD GetSample(const SWORD* const srce, SLONGLONG idx) | ||
318 | { | ||
319 | SLONGLONG i=idx>>FRACBITS; | ||
320 | SLONGLONG f=idx&FRACMASK; | ||
321 | return (SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
322 | ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); | ||
323 | } | ||
324 | |||
325 | static SLONGLONG MixSIMDStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) | ||
326 | { | ||
327 | SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel}; | ||
328 | SWORD sample=0; | ||
329 | SLONG remain = todo; | ||
330 | |||
331 | /* Dest can be misaligned */ | ||
332 | while(!IS_ALIGNED_16(dest)) { | ||
333 | sample=srce[idx >> FRACBITS]; | ||
334 | idx += increment; | ||
335 | *dest++ += vol[0] * sample; | ||
336 | *dest++ += vol[1] * sample; | ||
337 | todo--; | ||
338 | if(!todo) goto end; | ||
339 | } | ||
340 | |||
341 | /* Srce is always aligned */ | ||
342 | |||
343 | #if defined HAVE_SSE2 | ||
344 | remain = todo&3; | ||
345 | { | ||
346 | __m128i v0 = _mm_set_epi16(0, vol[1], | ||
347 | 0, vol[0], | ||
348 | 0, vol[1], | ||
349 | 0, vol[0]); | ||
350 | for(todo>>=2;todo; todo--) | ||
351 | { | ||
352 | SWORD s0 = GetSample(srce, idx); | ||
353 | SWORD s1 = GetSample(srce, idx += increment); | ||
354 | SWORD s2 = GetSample(srce, idx += increment); | ||
355 | SWORD s3 = GetSample(srce, idx += increment); | ||
356 | __m128i v1 = _mm_set_epi16(0, s1, 0, s1, 0, s0, 0, s0); | ||
357 | __m128i v2 = _mm_set_epi16(0, s3, 0, s3, 0, s2, 0, s2); | ||
358 | __m128i v3 = _mm_load_si128((__m128i*)(dest+0)); | ||
359 | __m128i v4 = _mm_load_si128((__m128i*)(dest+4)); | ||
360 | _mm_store_si128((__m128i*)(dest+0), _mm_add_epi32(v3, _mm_madd_epi16(v0, v1))); | ||
361 | _mm_store_si128((__m128i*)(dest+4), _mm_add_epi32(v4, _mm_madd_epi16(v0, v2))); | ||
362 | dest+=8; | ||
363 | idx += increment; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | #elif defined HAVE_ALTIVEC | ||
368 | remain = todo&3; | ||
369 | { | ||
370 | SWORD s[8]; | ||
371 | vector signed short r0 = vec_ld(0, vol); | ||
372 | vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, /* l */ | ||
373 | 0, 1, /* l */ | ||
374 | 2, 3, /* r */ | ||
375 | 2, 1, /* r */ | ||
376 | 0, 1, /* l */ | ||
377 | 0, 1, /* l */ | ||
378 | 2, 3, /* r */ | ||
379 | 2, 3 /* r */ | ||
380 | )); | ||
381 | |||
382 | for(todo>>=2;todo; todo--) | ||
383 | { | ||
384 | vector short int r1; | ||
385 | vector signed short v1, v2; | ||
386 | vector signed int v3, v4, v5, v6; | ||
387 | |||
388 | /* Load constants */ | ||
389 | s[0] = GetSample(srce, idx); | ||
390 | s[1] = GetSample(srce, idx += increment); | ||
391 | s[2] = GetSample(srce, idx += increment); | ||
392 | s[3] = GetSample(srce, idx += increment); | ||
393 | s[4] = 0; | ||
394 | |||
395 | r1 = vec_ld(0, s); | ||
396 | v1 = vec_perm(r1, r1, (vector unsigned char) | ||
397 | (0*2, 0*2+1, /* s0 */ | ||
398 | 4*2, 4*2+1, /* 0 */ | ||
399 | 0*2, 0*2+1, /* s0 */ | ||
400 | 4*2, 4*2+1, /* 0 */ | ||
401 | 1*2, 1*2+1, /* s1 */ | ||
402 | 4*2, 4*2+1, /* 0 */ | ||
403 | 1*2, 1*2+1, /* s1 */ | ||
404 | 4*2, 4*2+1 /* 0 */ | ||
405 | ) ); | ||
406 | v2 = vec_perm(r1, r1, (vector unsigned char) | ||
407 | (2*2, 2*2+1, /* s2 */ | ||
408 | 4*2, 4*2+1, /* 0 */ | ||
409 | 2*2, 2*2+1, /* s2 */ | ||
410 | 4*2, 4*2+1, /* 0 */ | ||
411 | 3*2, 3*2+1, /* s3 */ | ||
412 | 4*2, 4*2+1, /* 0 */ | ||
413 | 3*2, 3*2+1, /* s3 */ | ||
414 | 4*2, 4*2+1 /* 0 */ | ||
415 | ) ); | ||
416 | |||
417 | v3 = vec_ld(0, dest); | ||
418 | v4 = vec_ld(0x10, dest); | ||
419 | v5 = vec_mule(v0, v1); | ||
420 | v6 = vec_mule(v0, v2); | ||
421 | |||
422 | vec_st(vec_add(v3, v5), 0, dest); | ||
423 | vec_st(vec_add(v4, v6), 0x10, dest); | ||
424 | |||
425 | dest+=8; | ||
426 | idx += increment; | ||
427 | } | ||
428 | } | ||
429 | #endif /* HAVE_ALTIVEC */ | ||
430 | |||
431 | /* Remaining bits */ | ||
432 | while(remain--) { | ||
433 | sample=GetSample(srce, idx); | ||
434 | idx+= increment; | ||
435 | *dest++ += vol[0] * sample; | ||
436 | *dest++ += vol[1] * sample; | ||
437 | } | ||
438 | end: | ||
439 | vnf->lastvalL=vnf->lvolsel*sample; | ||
440 | vnf->lastvalR=vnf->rvolsel*sample; | ||
441 | return idx; | ||
442 | } | ||
443 | |||
444 | static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) | ||
445 | { | ||
446 | SWORD sample=0; | ||
447 | SLONGLONG i,f; | ||
448 | |||
449 | if (vnf->rampvol) | ||
450 | while(todo) { | ||
451 | todo--; | ||
452 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
453 | sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
454 | ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); | ||
455 | idx += increment; | ||
456 | |||
457 | *dest++ += (long)( | ||
458 | ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + | ||
459 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
460 | ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); | ||
461 | *dest++ += (long)( | ||
462 | ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + | ||
463 | (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
464 | ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); | ||
465 | vnf->rampvol--; | ||
466 | |||
467 | if (!vnf->rampvol) | ||
468 | break; | ||
469 | } | ||
470 | |||
471 | if (vnf->click) | ||
472 | while(todo) { | ||
473 | todo--; | ||
474 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
475 | sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
476 | ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); | ||
477 | idx += increment; | ||
478 | |||
479 | *dest++ += (long)( | ||
480 | ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
481 | (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) | ||
482 | >> CLICK_SHIFT ); | ||
483 | |||
484 | *dest++ += (long)( | ||
485 | ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * | ||
486 | (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) | ||
487 | >> CLICK_SHIFT ); | ||
488 | vnf->click--; | ||
489 | |||
490 | if (!vnf->click) | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | if (todo) | ||
495 | { | ||
496 | if (md_mode & DMODE_SIMDMIXER) { | ||
497 | return MixSIMDStereoNormal(srce, dest, idx, increment, todo); | ||
498 | } | ||
499 | while(todo) | ||
500 | { | ||
501 | i=idx>>FRACBITS, | ||
502 | f=idx&FRACMASK; | ||
503 | sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
504 | ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); | ||
505 | idx += increment; | ||
506 | |||
507 | *dest++ +=vnf->lvolsel*sample; | ||
508 | *dest++ +=vnf->rvolsel*sample; | ||
509 | todo--; | ||
510 | } | ||
511 | } | ||
512 | vnf->lastvalL=vnf->lvolsel*sample; | ||
513 | vnf->lastvalR=vnf->rvolsel*sample; | ||
514 | |||
515 | return idx; | ||
516 | } | ||
517 | |||
518 | #else /* HAVE_SSE2 || HAVE_ALTIVEC */ | ||
519 | static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) | ||
520 | { | ||
521 | SWORD sample=0; | ||
522 | SLONGLONG i,f; | ||
523 | |||
524 | while(todo--) { | ||
525 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
526 | sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
527 | ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); | ||
528 | idx += increment; | ||
529 | |||
530 | if(vnf->rampvol) { | ||
531 | *dest++ += (long)( | ||
532 | ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + | ||
533 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
534 | ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); | ||
535 | *dest++ += (long)( | ||
536 | ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + | ||
537 | (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) | ||
538 | ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); | ||
539 | vnf->rampvol--; | ||
540 | } else | ||
541 | if(vnf->click) { | ||
542 | *dest++ += (long)( | ||
543 | ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
544 | (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) | ||
545 | >> CLICK_SHIFT ); | ||
546 | *dest++ += (long)( | ||
547 | ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * | ||
548 | (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) | ||
549 | >> CLICK_SHIFT ); | ||
550 | vnf->click--; | ||
551 | } else { | ||
552 | *dest++ +=vnf->lvolsel*sample; | ||
553 | *dest++ +=vnf->rvolsel*sample; | ||
554 | } | ||
555 | } | ||
556 | vnf->lastvalL=vnf->lvolsel*sample; | ||
557 | vnf->lastvalR=vnf->rvolsel*sample; | ||
558 | |||
559 | return idx; | ||
560 | } | ||
561 | #endif /* HAVE_SSE2 || HAVE_ALTIVEC */ | ||
562 | |||
563 | |||
564 | static SLONGLONG MixStereoSurround(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) | ||
565 | { | ||
566 | SWORD sample=0; | ||
567 | long whoop; | ||
568 | SLONGLONG i, f; | ||
569 | |||
570 | while(todo--) { | ||
571 | i=idx>>FRACBITS,f=idx&FRACMASK; | ||
572 | sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + | ||
573 | ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); | ||
574 | idx+=increment; | ||
575 | |||
576 | if(vnf->rampvol) { | ||
577 | whoop=(long)( | ||
578 | ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + | ||
579 | (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * | ||
580 | (SLONGLONG)sample) >> CLICK_SHIFT ); | ||
581 | *dest++ +=whoop; | ||
582 | *dest++ -=whoop; | ||
583 | vnf->rampvol--; | ||
584 | } else | ||
585 | if(vnf->click) { | ||
586 | whoop = (long)( | ||
587 | ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * | ||
588 | (SLONGLONG)sample) + | ||
589 | (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); | ||
590 | *dest++ +=whoop; | ||
591 | *dest++ -=whoop; | ||
592 | vnf->click--; | ||
593 | } else { | ||
594 | *dest++ +=vnf->lvolsel*sample; | ||
595 | *dest++ -=vnf->lvolsel*sample; | ||
596 | } | ||
597 | } | ||
598 | vnf->lastvalL=vnf->lvolsel*sample; | ||
599 | vnf->lastvalR=vnf->lvolsel*sample; | ||
600 | |||
601 | return idx; | ||
602 | } | ||
603 | |||
604 | static void(*Mix32toFP)(float* dste,const SLONG *srce,NATIVE count); | ||
605 | static void(*Mix32to16)(SWORD* dste,const SLONG *srce,NATIVE count); | ||
606 | static void(*Mix32to8)(SBYTE* dste,const SLONG *srce,NATIVE count); | ||
607 | static void(*MixReverb)(SLONG *srce,NATIVE count); | ||
608 | |||
609 | /* Reverb macros */ | ||
610 | #define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n | ||
611 | #define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7) | ||
612 | #define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7) | ||
613 | |||
614 | static void MixReverb_Normal(SLONG *srce,NATIVE count) | ||
615 | { | ||
616 | NATIVE speedup; | ||
617 | int ReverbPct; | ||
618 | unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; | ||
619 | |||
620 | ReverbPct=58+(md_reverb*4); | ||
621 | |||
622 | COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); | ||
623 | COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); | ||
624 | |||
625 | while(count--) { | ||
626 | /* Compute the left channel echo buffers */ | ||
627 | speedup = *srce >> 3; | ||
628 | |||
629 | COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); | ||
630 | COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); | ||
631 | |||
632 | /* Prepare to compute actual finalized data */ | ||
633 | RVRindex++; | ||
634 | |||
635 | COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); | ||
636 | COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); | ||
637 | |||
638 | /* left channel */ | ||
639 | *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ | ||
640 | RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; | ||
641 | } | ||
642 | } | ||
643 | |||
644 | static void MixReverb_Stereo(SLONG *srce,NATIVE count) | ||
645 | { | ||
646 | NATIVE speedup; | ||
647 | int ReverbPct; | ||
648 | unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; | ||
649 | |||
650 | ReverbPct=58+(md_reverb*4); | ||
651 | |||
652 | COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); | ||
653 | COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); | ||
654 | |||
655 | while(count--) { | ||
656 | /* Compute the left channel echo buffers */ | ||
657 | speedup = *srce >> 3; | ||
658 | |||
659 | COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); | ||
660 | COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); | ||
661 | |||
662 | /* Compute the right channel echo buffers */ | ||
663 | speedup = srce[1] >> 3; | ||
664 | |||
665 | COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4); | ||
666 | COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(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 | /* right channel */ | ||
679 | *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ | ||
680 | RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; | ||
681 | } | ||
682 | } | ||
683 | |||
684 | static void (*MixLowPass)(SLONG* srce,NATIVE count); | ||
685 | |||
686 | static int nLeftNR, nRightNR; | ||
687 | |||
688 | static void MixLowPass_Stereo(SLONG* srce,NATIVE count) | ||
689 | { | ||
690 | int n1 = nLeftNR, n2 = nRightNR; | ||
691 | SLONG *pnr = srce; | ||
692 | int nr=count; | ||
693 | for (; nr; nr--) | ||
694 | { | ||
695 | int vnr = pnr[0] >> 1; | ||
696 | pnr[0] = vnr + n1; | ||
697 | n1 = vnr; | ||
698 | vnr = pnr[1] >> 1; | ||
699 | pnr[1] = vnr + n2; | ||
700 | n2 = vnr; | ||
701 | pnr += 2; | ||
702 | } | ||
703 | nLeftNR = n1; | ||
704 | nRightNR = n2; | ||
705 | } | ||
706 | |||
707 | static void MixLowPass_Normal(SLONG* srce,NATIVE count) | ||
708 | { | ||
709 | int n1 = nLeftNR; | ||
710 | SLONG *pnr = srce; | ||
711 | int nr=count; | ||
712 | for (; nr; nr--) | ||
713 | { | ||
714 | int vnr = pnr[0] >> 1; | ||
715 | pnr[0] = vnr + n1; | ||
716 | n1 = vnr; | ||
717 | pnr ++; | ||
718 | } | ||
719 | nLeftNR = n1; | ||
720 | } | ||
721 | |||
722 | /* Mixing macros */ | ||
723 | #define EXTRACT_SAMPLE_FP(var,attenuation) var=*srce++*((1.0f / 32768.0f) / (MAXVOL_FACTOR*attenuation)) | ||
724 | #define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var | ||
725 | |||
726 | static void Mix32ToFP_Normal(float* dste,const SLONG *srce,NATIVE count) | ||
727 | { | ||
728 | float x1,x2,tmpx; | ||
729 | int i; | ||
730 | |||
731 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
732 | tmpx=0.0f; | ||
733 | |||
734 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
735 | EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); | ||
736 | |||
737 | CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); | ||
738 | |||
739 | tmpx+=x1+x2; | ||
740 | } | ||
741 | *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | static void Mix32ToFP_Stereo(float* dste,const SLONG *srce,NATIVE count) | ||
746 | { | ||
747 | float x1,x2,x3,x4,tmpx,tmpy; | ||
748 | int i; | ||
749 | |||
750 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
751 | tmpx=tmpy=0.0f; | ||
752 | |||
753 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
754 | EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); | ||
755 | EXTRACT_SAMPLE_FP(x3,1.0f); EXTRACT_SAMPLE_FP(x4,1.0f); | ||
756 | |||
757 | CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); | ||
758 | CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f); | ||
759 | |||
760 | tmpx+=x1+x3; | ||
761 | tmpy+=x2+x4; | ||
762 | } | ||
763 | *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); | ||
764 | *dste++ =tmpy*(1.0f/SAMPLING_FACTOR); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | /* Mixing macros */ | ||
769 | #define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation) | ||
770 | #define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var | ||
771 | |||
772 | static void Mix32To16_Normal(SWORD* dste,const SLONG *srce,NATIVE count) | ||
773 | { | ||
774 | NATIVE x1,x2,tmpx; | ||
775 | int i; | ||
776 | |||
777 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
778 | tmpx=0; | ||
779 | |||
780 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
781 | EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); | ||
782 | |||
783 | CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); | ||
784 | |||
785 | tmpx+=x1+x2; | ||
786 | } | ||
787 | *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); | ||
788 | } | ||
789 | } | ||
790 | |||
791 | |||
792 | static void Mix32To16_Stereo(SWORD* dste,const SLONG *srce,NATIVE count) | ||
793 | { | ||
794 | NATIVE x1,x2,x3,x4,tmpx,tmpy; | ||
795 | int i; | ||
796 | |||
797 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
798 | tmpx=tmpy=0; | ||
799 | |||
800 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
801 | EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); | ||
802 | EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1); | ||
803 | |||
804 | CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); | ||
805 | CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768); | ||
806 | |||
807 | tmpx+=x1+x3; | ||
808 | tmpy+=x2+x4; | ||
809 | } | ||
810 | *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); | ||
811 | *dste++ =(SWORD)(tmpy/SAMPLING_FACTOR); | ||
812 | } | ||
813 | } | ||
814 | |||
815 | static void Mix32To8_Normal(SBYTE* dste,const SLONG *srce,NATIVE count) | ||
816 | { | ||
817 | NATIVE x1,x2,tmpx; | ||
818 | int i; | ||
819 | |||
820 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
821 | tmpx = 0; | ||
822 | |||
823 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
824 | EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); | ||
825 | |||
826 | CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); | ||
827 | |||
828 | tmpx+=x1+x2; | ||
829 | } | ||
830 | *dste++ = (SBYTE)((tmpx/SAMPLING_FACTOR)+128); | ||
831 | } | ||
832 | } | ||
833 | |||
834 | static void Mix32To8_Stereo(SBYTE* dste,const SLONG *srce,NATIVE count) | ||
835 | { | ||
836 | NATIVE x1,x2,x3,x4,tmpx,tmpy; | ||
837 | int i; | ||
838 | |||
839 | for(count/=SAMPLING_FACTOR;count;count--) { | ||
840 | tmpx=tmpy=0; | ||
841 | |||
842 | for(i=SAMPLING_FACTOR/2;i;i--) { | ||
843 | EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); | ||
844 | EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256); | ||
845 | |||
846 | CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); | ||
847 | CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128); | ||
848 | |||
849 | tmpx+=x1+x3; | ||
850 | tmpy+=x2+x4; | ||
851 | } | ||
852 | *dste++ =(SBYTE)((tmpx/SAMPLING_FACTOR)+128); | ||
853 | *dste++ =(SBYTE)((tmpy/SAMPLING_FACTOR)+128); | ||
854 | } | ||
855 | } | ||
856 | |||
857 | #if defined HAVE_SSE2 | ||
858 | #define SHIFT_MIX_TO_16 (BITSHIFT + 16 - 16) | ||
859 | /* TEST: Ok */ | ||
860 | static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) | ||
861 | { | ||
862 | int remain = count; | ||
863 | |||
864 | /* Check unaligned dste buffer. srce is always aligned. */ | ||
865 | while(!IS_ALIGNED_16(dste)) | ||
866 | { | ||
867 | Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); | ||
868 | dste+=2; | ||
869 | srce+=8; | ||
870 | count--; | ||
871 | if(!count) return; | ||
872 | } | ||
873 | |||
874 | /* dste and srce aligned. srce is always aligned. */ | ||
875 | remain = count & 15; | ||
876 | /* count / 2 for 1 sample */ | ||
877 | |||
878 | for(count>>=4;count;count--) | ||
879 | { | ||
880 | /* Load 32bit sample. 1st average */ | ||
881 | __m128i v0 = _mm_add_epi32( | ||
882 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+0)), SHIFT_MIX_TO_16), | ||
883 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+4)), SHIFT_MIX_TO_16) | ||
884 | ); /* v0: s0.l+s2.l | s0.r+s2.r | s1.l+s3.l | s1.r+s3.r */ | ||
885 | |||
886 | /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ | ||
887 | __m128i v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); | ||
888 | /* v1: s0.l+s2.l / 4 | s0.r+s2.r / 4 | s1.l+s3.l+s0.l+s2.l / 4 | s1.r+s3.r+s0.r+s2.r / 4 */ | ||
889 | |||
890 | __m128i v2 = _mm_add_epi32( | ||
891 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+8)), SHIFT_MIX_TO_16), | ||
892 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+12)), SHIFT_MIX_TO_16) | ||
893 | ); /* v2: s4.l+s6.l | s4.r+s6.r | s5.l+s7.l | s5.r+s7.r */ | ||
894 | |||
895 | __m128i v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ | ||
896 | /* v3: s4.l+s6.l /4 | s4.r+s6.r / 4| s5.l+s7.l+s4.l+s6.l / 4 | s5.r+s7.r+s4.r+s6.l / 4 */ | ||
897 | |||
898 | /* pack two stereo samples in one */ | ||
899 | __m128i v4 = _mm_unpacklo_epi64(v1, v3); /* v4 = avg(s0,s1,s2,s3) | avg(s4,s5,s6,s7) */ | ||
900 | |||
901 | __m128i v6; | ||
902 | |||
903 | /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ | ||
904 | v0 = _mm_add_epi32( | ||
905 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+16)), SHIFT_MIX_TO_16), | ||
906 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+20)), SHIFT_MIX_TO_16) | ||
907 | ); /* 128bit = 2 stereo samples */ | ||
908 | |||
909 | /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ | ||
910 | v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); | ||
911 | |||
912 | v2 = _mm_add_epi32( | ||
913 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+24)), SHIFT_MIX_TO_16), | ||
914 | _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+28)), SHIFT_MIX_TO_16) | ||
915 | ); | ||
916 | |||
917 | v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ | ||
918 | |||
919 | /* pack two stereo samples in one */ | ||
920 | v6 = _mm_unpacklo_epi64(v1, v3); /* v6 = avg(s8,s9,s10,s11) | avg(s12,s13,s14,s15) */ | ||
921 | |||
922 | _mm_store_si128((__m128i*)dste, _mm_packs_epi32(v4, v6)); /* 4 interpolated stereo sample 32bit to 4 */ | ||
923 | |||
924 | dste+=8; | ||
925 | srce+=32; /* 32 = 4 * 8 */ | ||
926 | } | ||
927 | |||
928 | /* FIXME: THIS PART WRITES PAST DST !! */ | ||
929 | if (remain) | ||
930 | { | ||
931 | Mix32To16_Stereo(dste, srce, remain); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | #elif defined HAVE_ALTIVEC | ||
936 | #define SHIFT_MIX_TO_16 vec_splat_u32(BITSHIFT + 16 - 16) | ||
937 | /* TEST: Ok */ | ||
938 | static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) | ||
939 | { | ||
940 | int remain = count; | ||
941 | |||
942 | /* Check unaligned dste buffer. srce is always aligned. */ | ||
943 | while(!IS_ALIGNED_16(dste)) | ||
944 | { | ||
945 | Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); | ||
946 | dste+=2; | ||
947 | srce+=8; | ||
948 | count--; | ||
949 | if(!count) return; | ||
950 | } | ||
951 | |||
952 | /* dste and srce aligned. srce is always aligned. */ | ||
953 | remain = count & 15; | ||
954 | for(count>>=4;count;count--) | ||
955 | { | ||
956 | /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ | ||
957 | vector signed int v0 = vec_add( | ||
958 | vec_sra(vec_ld(0, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ | ||
959 | vec_sra(vec_ld(0x10, srce), SHIFT_MIX_TO_16) | ||
960 | ); /* 128bit = 2 stereo samples */ | ||
961 | |||
962 | /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ | ||
963 | vector signed int v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); | ||
964 | |||
965 | vector signed int v2 = vec_add( | ||
966 | vec_sra(vec_ld(0x20, srce), SHIFT_MIX_TO_16), | ||
967 | vec_sra(vec_ld(0x30, srce), SHIFT_MIX_TO_16) | ||
968 | ); | ||
969 | |||
970 | vector signed int v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ | ||
971 | |||
972 | /* pack two stereo samples in one */ | ||
973 | vector signed int v6, v4 = vec_unpacklo(v1, v3); /* v4 = lo64(v1) | lo64(v3) */ | ||
974 | |||
975 | /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ | ||
976 | v0 = vec_add( | ||
977 | vec_sra(vec_ld(0x40, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ | ||
978 | vec_sra(vec_ld(0x50, srce), SHIFT_MIX_TO_16) | ||
979 | ); /* 128bit = 2 stereo samples */ | ||
980 | |||
981 | /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ | ||
982 | v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); | ||
983 | |||
984 | v2 = vec_add( | ||
985 | vec_sra(vec_ld(0x60, srce), SHIFT_MIX_TO_16), | ||
986 | vec_sra(vec_ld(0x70, srce), SHIFT_MIX_TO_16) | ||
987 | ); | ||
988 | |||
989 | v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ | ||
990 | |||
991 | /* pack two stereo samples in one */ | ||
992 | v6 = vec_unpacklo(v1, v3); | ||
993 | |||
994 | vec_st(vec_packs(v4, v6), 0, dste); /* 4 interpolated stereo sample 32bit to 4 interpolated stereo sample 16bit + saturation */ | ||
995 | |||
996 | dste+=8; | ||
997 | srce+=32; /* 32 = 4 * 8 */ | ||
998 | } | ||
999 | |||
1000 | if (remain) | ||
1001 | { | ||
1002 | Mix32To16_Stereo(dste, srce, remain); | ||
1003 | } | ||
1004 | } | ||
1005 | |||
1006 | #endif | ||
1007 | |||
1008 | |||
1009 | static void AddChannel(SLONG* ptr,NATIVE todo) | ||
1010 | { | ||
1011 | SLONGLONG end,done; | ||
1012 | SWORD *s; | ||
1013 | |||
1014 | if(!(s=Samples[vnf->handle])) { | ||
1015 | vnf->current = vnf->active = 0; | ||
1016 | vnf->lastvalL = vnf->lastvalR = 0; | ||
1017 | return; | ||
1018 | } | ||
1019 | |||
1020 | /* update the 'current' index so the sample loops, or stops playing if it | ||
1021 | reached the end of the sample */ | ||
1022 | while(todo>0) { | ||
1023 | SLONGLONG endpos; | ||
1024 | |||
1025 | if(vnf->flags & SF_REVERSE) { | ||
1026 | /* The sample is playing in reverse */ | ||
1027 | if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) { | ||
1028 | /* the sample is looping and has reached the loopstart index */ | ||
1029 | if(vnf->flags & SF_BIDI) { | ||
1030 | /* sample is doing bidirectional loops, so 'bounce' the | ||
1031 | current index against the idxlpos */ | ||
1032 | vnf->current = idxlpos+(idxlpos-vnf->current); | ||
1033 | vnf->flags &= ~SF_REVERSE; | ||
1034 | vnf->increment = -vnf->increment; | ||
1035 | } else | ||
1036 | /* normal backwards looping, so set the current position to | ||
1037 | loopend index */ | ||
1038 | vnf->current=idxlend-(idxlpos-vnf->current); | ||
1039 | } else { | ||
1040 | /* the sample is not looping, so check if it reached index 0 */ | ||
1041 | if(vnf->current < 0) { | ||
1042 | /* playing index reached 0, so stop playing this sample */ | ||
1043 | vnf->current = vnf->active = 0; | ||
1044 | break; | ||
1045 | } | ||
1046 | } | ||
1047 | } else { | ||
1048 | /* The sample is playing forward */ | ||
1049 | if((vnf->flags & SF_LOOP) && | ||
1050 | (vnf->current >= idxlend)) { | ||
1051 | /* the sample is looping, check the loopend index */ | ||
1052 | if(vnf->flags & SF_BIDI) { | ||
1053 | /* sample is doing bidirectional loops, so 'bounce' the | ||
1054 | current index against the idxlend */ | ||
1055 | vnf->flags |= SF_REVERSE; | ||
1056 | vnf->increment = -vnf->increment; | ||
1057 | vnf->current = idxlend-(vnf->current-idxlend); | ||
1058 | } else | ||
1059 | /* normal backwards looping, so set the current position | ||
1060 | to loopend index */ | ||
1061 | vnf->current=idxlpos+(vnf->current-idxlend); | ||
1062 | } else { | ||
1063 | /* sample is not looping, so check if it reached the last | ||
1064 | position */ | ||
1065 | if(vnf->current >= idxsize) { | ||
1066 | /* yes, so stop playing this sample */ | ||
1067 | vnf->current = vnf->active = 0; | ||
1068 | break; | ||
1069 | } | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0: | ||
1074 | (vnf->flags&SF_LOOP)?idxlend:idxsize; | ||
1075 | |||
1076 | /* if the sample is not blocked... */ | ||
1077 | if((end==vnf->current)||(!vnf->increment)) | ||
1078 | done=0; | ||
1079 | else { | ||
1080 | done=MIN((end-vnf->current)/vnf->increment+1,todo); | ||
1081 | if(done<0) done=0; | ||
1082 | } | ||
1083 | |||
1084 | if(!done) { | ||
1085 | vnf->active = 0; | ||
1086 | break; | ||
1087 | } | ||
1088 | |||
1089 | endpos=vnf->current+done*vnf->increment; | ||
1090 | |||
1091 | if(vnf->vol || vnf->rampvol) { | ||
1092 | #ifndef NATIVE_64BIT_INT | ||
1093 | /* use the 32 bit mixers as often as we can (they're much faster) */ | ||
1094 | if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) { | ||
1095 | if(vc_mode & DMODE_STEREO) { | ||
1096 | if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) | ||
1097 | vnf->current=(SLONGLONG)Mix32StereoSurround | ||
1098 | (s,ptr,vnf->current,vnf->increment,done); | ||
1099 | else | ||
1100 | vnf->current=Mix32StereoNormal | ||
1101 | (s,ptr,vnf->current,vnf->increment,done); | ||
1102 | } else | ||
1103 | vnf->current=Mix32MonoNormal | ||
1104 | (s,ptr,vnf->current,vnf->increment,done); | ||
1105 | } | ||
1106 | else | ||
1107 | #endif | ||
1108 | { | ||
1109 | if(vc_mode & DMODE_STEREO) { | ||
1110 | if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) | ||
1111 | vnf->current=MixStereoSurround | ||
1112 | (s,ptr,vnf->current,vnf->increment,done); | ||
1113 | else | ||
1114 | vnf->current=MixStereoNormal | ||
1115 | (s,ptr,vnf->current,vnf->increment,done); | ||
1116 | } else | ||
1117 | vnf->current=MixMonoNormal | ||
1118 | (s,ptr,vnf->current,vnf->increment,done); | ||
1119 | } | ||
1120 | } else { | ||
1121 | vnf->lastvalL = vnf->lastvalR = 0; | ||
1122 | /* update sample position */ | ||
1123 | vnf->current=endpos; | ||
1124 | } | ||
1125 | |||
1126 | todo -= done; | ||
1127 | ptr += (vc_mode & DMODE_STEREO)?(done<<1):done; | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | #define _IN_VIRTCH_ | ||
1132 | |||
1133 | #define VC1_SilenceBytes VC2_SilenceBytes | ||
1134 | #define VC1_WriteSamples VC2_WriteSamples | ||
1135 | #define VC1_WriteBytes VC2_WriteBytes | ||
1136 | #define VC1_Exit VC2_Exit | ||
1137 | #define VC1_VoiceSetVolume VC2_VoiceSetVolume | ||
1138 | #define VC1_VoiceGetVolume VC2_VoiceGetVolume | ||
1139 | #define VC1_VoiceSetPanning VC2_VoiceSetPanning | ||
1140 | #define VC1_VoiceGetPanning VC2_VoiceGetPanning | ||
1141 | #define VC1_VoiceSetFrequency VC2_VoiceSetFrequency | ||
1142 | #define VC1_VoiceGetFrequency VC2_VoiceGetFrequency | ||
1143 | #define VC1_VoicePlay VC2_VoicePlay | ||
1144 | #define VC1_VoiceStop VC2_VoiceStop | ||
1145 | #define VC1_VoiceStopped VC2_VoiceStopped | ||
1146 | #define VC1_VoiceGetPosition VC2_VoiceGetPosition | ||
1147 | #define VC1_SampleUnload VC2_SampleUnload | ||
1148 | #define VC1_SampleLoad VC2_SampleLoad | ||
1149 | #define VC1_SampleSpace VC2_SampleSpace | ||
1150 | #define VC1_SampleLength VC2_SampleLength | ||
1151 | #define VC1_VoiceRealVolume VC2_VoiceRealVolume | ||
1152 | |||
1153 | #include "virtch_common.c" | ||
1154 | #undef _IN_VIRTCH_ | ||
1155 | |||
1156 | void VC2_WriteSamples(SBYTE* buf,ULONG todo) | ||
1157 | { | ||
1158 | int left,portion=0; | ||
1159 | SBYTE *buffer; | ||
1160 | int t,pan,vol; | ||
1161 | |||
1162 | todo*=SAMPLING_FACTOR; | ||
1163 | |||
1164 | while(todo) { | ||
1165 | if(!tickleft) { | ||
1166 | if(vc_mode & DMODE_SOFT_MUSIC) md_player(); | ||
1167 | tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L); | ||
1168 | tickleft&=~(SAMPLING_FACTOR-1); | ||
1169 | } | ||
1170 | left = MIN(tickleft, (int)todo); | ||
1171 | buffer = buf; | ||
1172 | tickleft -= left; | ||
1173 | todo -= left; | ||
1174 | buf += samples2bytes(left)/SAMPLING_FACTOR; | ||
1175 | |||
1176 | while(left) { | ||
1177 | portion = MIN(left, samplesthatfit); | ||
1178 | memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2)); | ||
1179 | for(t=0;t<vc_softchn;t++) { | ||
1180 | vnf = &vinf[t]; | ||
1181 | |||
1182 | if(vnf->kick) { | ||
1183 | vnf->current=((SLONGLONG)(vnf->start))<<FRACBITS; | ||
1184 | vnf->kick = 0; | ||
1185 | vnf->active = 1; | ||
1186 | vnf->click = CLICK_BUFFER; | ||
1187 | vnf->rampvol = 0; | ||
1188 | } | ||
1189 | |||
1190 | if(!vnf->frq) vnf->active = 0; | ||
1191 | |||
1192 | if(vnf->active) { | ||
1193 | vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT)) | ||
1194 | /md_mixfreq; | ||
1195 | if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment; | ||
1196 | vol = vnf->vol; pan = vnf->pan; | ||
1197 | |||
1198 | vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel; | ||
1199 | if(vc_mode & DMODE_STEREO) { | ||
1200 | if(pan!=PAN_SURROUND) { | ||
1201 | vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8; | ||
1202 | vnf->rvolsel=(vol*pan)>>8; | ||
1203 | } else { | ||
1204 | vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480; | ||
1205 | } | ||
1206 | } else | ||
1207 | vnf->lvolsel=vol; | ||
1208 | |||
1209 | idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<<FRACBITS)-1:0; | ||
1210 | idxlend=(vnf->repend)?((SLONGLONG)(vnf->repend)<<FRACBITS)-1:0; | ||
1211 | idxlpos=(SLONGLONG)(vnf->reppos)<<FRACBITS; | ||
1212 | AddChannel(vc_tickbuf,portion); | ||
1213 | } | ||
1214 | } | ||
1215 | |||
1216 | if(md_mode & DMODE_NOISEREDUCTION) { | ||
1217 | MixLowPass(vc_tickbuf, portion); | ||
1218 | } | ||
1219 | |||
1220 | if(md_reverb) { | ||
1221 | if(md_reverb>15) md_reverb=15; | ||
1222 | MixReverb(vc_tickbuf,portion); | ||
1223 | } | ||
1224 | |||
1225 | if (vc_callback) { | ||
1226 | vc_callback((unsigned char*)vc_tickbuf, portion); | ||
1227 | } | ||
1228 | |||
1229 | if(vc_mode & DMODE_FLOAT) | ||
1230 | Mix32toFP((float*)buffer,vc_tickbuf,portion); | ||
1231 | else if(vc_mode & DMODE_16BITS) | ||
1232 | Mix32to16((SWORD*)buffer,vc_tickbuf,portion); | ||
1233 | else | ||
1234 | Mix32to8((SBYTE*)buffer,vc_tickbuf,portion); | ||
1235 | |||
1236 | buffer += samples2bytes(portion) / SAMPLING_FACTOR; | ||
1237 | left -= portion; | ||
1238 | } | ||
1239 | } | ||
1240 | } | ||
1241 | |||
1242 | int VC2_Init(void) | ||
1243 | { | ||
1244 | VC_SetupPointers(); | ||
1245 | |||
1246 | if (!(md_mode&DMODE_HQMIXER)) | ||
1247 | return VC1_Init(); | ||
1248 | |||
1249 | if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) { | ||
1250 | _mm_errno = MMERR_INITIALIZING_MIXER; | ||
1251 | return 1; | ||
1252 | } | ||
1253 | if(!vc_tickbuf) { | ||
1254 | if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) { | ||
1255 | _mm_errno = MMERR_INITIALIZING_MIXER; | ||
1256 | return 1; | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | if(md_mode & DMODE_STEREO) { | ||
1261 | Mix32toFP = Mix32ToFP_Stereo; | ||
1262 | #if ((defined HAVE_ALTIVEC || defined HAVE_SSE2) && (SAMPLING_FACTOR == 4)) | ||
1263 | if (md_mode & DMODE_SIMDMIXER) | ||
1264 | Mix32to16 = Mix32To16_Stereo_SIMD_4Tap; | ||
1265 | else | ||
1266 | #endif | ||
1267 | Mix32to16 = Mix32To16_Stereo; | ||
1268 | Mix32to8 = Mix32To8_Stereo; | ||
1269 | MixReverb = MixReverb_Stereo; | ||
1270 | MixLowPass = MixLowPass_Stereo; | ||
1271 | } else { | ||
1272 | Mix32toFP = Mix32ToFP_Normal; | ||
1273 | Mix32to16 = Mix32To16_Normal; | ||
1274 | Mix32to8 = Mix32To8_Normal; | ||
1275 | MixReverb = MixReverb_Normal; | ||
1276 | MixLowPass = MixLowPass_Normal; | ||
1277 | } | ||
1278 | |||
1279 | md_mode |= DMODE_INTERP; | ||
1280 | vc_mode = md_mode; | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | int VC2_PlayStart(void) | ||
1285 | { | ||
1286 | md_mode|=DMODE_INTERP; | ||
1287 | |||
1288 | samplesthatfit = TICKLSIZE; | ||
1289 | if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; | ||
1290 | tickleft = 0; | ||
1291 | |||
1292 | RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10); | ||
1293 | RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10); | ||
1294 | RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10); | ||
1295 | RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10); | ||
1296 | RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10); | ||
1297 | RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10); | ||
1298 | RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10); | ||
1299 | RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10); | ||
1300 | |||
1301 | if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; | ||
1302 | if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; | ||
1303 | if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; | ||
1304 | if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; | ||
1305 | if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; | ||
1306 | if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; | ||
1307 | if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; | ||
1308 | if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; | ||
1309 | |||
1310 | /* allocate reverb buffers for the right channel if in stereo mode only. */ | ||
1311 | if (vc_mode & DMODE_STEREO) { | ||
1312 | if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; | ||
1313 | if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; | ||
1314 | if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; | ||
1315 | if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; | ||
1316 | if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; | ||
1317 | if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; | ||
1318 | if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; | ||
1319 | if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; | ||
1320 | } | ||
1321 | |||
1322 | RVRindex = 0; | ||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | void VC2_PlayStop(void) | ||
1327 | { | ||
1328 | MikMod_free(RVbufL1); | ||
1329 | MikMod_free(RVbufL2); | ||
1330 | MikMod_free(RVbufL3); | ||
1331 | MikMod_free(RVbufL4); | ||
1332 | MikMod_free(RVbufL5); | ||
1333 | MikMod_free(RVbufL6); | ||
1334 | MikMod_free(RVbufL7); | ||
1335 | MikMod_free(RVbufL8); | ||
1336 | MikMod_free(RVbufR1); | ||
1337 | MikMod_free(RVbufR2); | ||
1338 | MikMod_free(RVbufR3); | ||
1339 | MikMod_free(RVbufR4); | ||
1340 | MikMod_free(RVbufR5); | ||
1341 | MikMod_free(RVbufR6); | ||
1342 | MikMod_free(RVbufR7); | ||
1343 | MikMod_free(RVbufR8); | ||
1344 | |||
1345 | RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; | ||
1346 | RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; | ||
1347 | } | ||
1348 | |||
1349 | int VC2_SetNumVoices(void) | ||
1350 | { | ||
1351 | int t; | ||
1352 | |||
1353 | md_mode|=DMODE_INTERP; | ||
1354 | |||
1355 | if(!(vc_softchn=md_softchn)) return 0; | ||
1356 | |||
1357 | MikMod_free(vinf); | ||
1358 | if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1; | ||
1359 | |||
1360 | for(t=0;t<vc_softchn;t++) { | ||
1361 | vinf[t].frq=10000; | ||
1362 | vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT; | ||
1363 | } | ||
1364 | |||
1365 | return 0; | ||
1366 | } | ||
1367 | |||
1368 | #endif /* ! NO_HQMIXER */ | ||
1369 | |||
1370 | /* ex:set ts=4: */ | ||