Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/virtch.c @ 6:d14fd386d182
Initial entry of mikmod into the CVS tree.
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:09 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:42e11dc15457 | 6:d14fd386d182 |
---|---|
1 /* | |
2 | |
3 Name: VIRTCH.C | |
4 | |
5 Description: | |
6 Sample mixing routines, using a 32 bits mixing buffer. | |
7 | |
8 Optional features include: | |
9 (a) 4-step reverb (for 16 bit output only) | |
10 (b) Interpolation of sample data during mixing | |
11 (c) Dolby Surround Sound | |
12 (d) Optimized assembly mixers for the Intel platform | |
13 (e) Optional high-speed or high-quality modes | |
14 | |
15 C Mixer Portability: | |
16 All Systems -- All compilers. | |
17 | |
18 Assembly Mixer Portability: | |
19 | |
20 MSDOS: BC(?) Watcom(y) DJGPP(y) | |
21 Win95: ? | |
22 Os2: ? | |
23 Linux: y | |
24 | |
25 (y) - yes | |
26 (n) - no (not possible or not useful) | |
27 (?) - may be possible, but not tested | |
28 | |
29 */ | |
30 | |
31 #include <stddef.h> | |
32 #include <string.h> | |
33 #include "mikmod.h" | |
34 | |
35 // REVERBERATION : Larger numbers result in shorter reverb duration. | |
36 #define REVERBERATION 110000l | |
37 | |
38 | |
39 #ifdef __GNUC__ | |
40 #define __cdecl | |
41 #endif | |
42 | |
43 #ifdef __WATCOMC__ | |
44 #define inline | |
45 #endif | |
46 | |
47 | |
48 // for PC-assembly mixing | |
49 // ====================== | |
50 // | |
51 // Uncomment both lines below for assembly mixing under WATCOM or GCC for | |
52 // Linux. | |
53 // Note that there is no 16 bit mixers for assembly yet (C only), so | |
54 // defining __ASSEMBLY__ if not defining __FASTMIXER__ will lead to compiler | |
55 // errors. | |
56 | |
57 #define __FASTMIXER__ | |
58 //#define __ASSEMBLY__ | |
59 | |
60 #define FRACBITS 11 | |
61 #define FRACMASK ((1l<<FRACBITS)-1) | |
62 | |
63 #define TICKLSIZE 3600 | |
64 #define TICKWSIZE (TICKLSIZE*2) | |
65 #define TICKBSIZE (TICKWSIZE*2) | |
66 | |
67 #ifndef MIN | |
68 #define MIN(a,b) (((a)<(b)) ? (a) : (b)) | |
69 #endif | |
70 | |
71 #ifndef MAX | |
72 #define MAX(a,b) (((a)>(b))?(a):(b)) | |
73 #endif | |
74 | |
75 | |
76 typedef struct | |
77 { BOOL active; | |
78 UWORD infmt; | |
79 UWORD flags; | |
80 #ifdef __FASTMIXER__ | |
81 UBYTE *buffer; | |
82 #else | |
83 UWORD *buffer; | |
84 #endif | |
85 ULONG size; | |
86 ULONG speed; | |
87 ULONG speedfactor; | |
88 SLONG current; | |
89 SLONG increment; | |
90 SLONG writepos; | |
91 } VSTREAM; | |
92 | |
93 | |
94 typedef struct | |
95 { UBYTE kick; // =1 -> sample has to be restarted | |
96 UBYTE active; // =1 -> sample is playing | |
97 UWORD flags; // 16/8 bits looping/one-shot | |
98 SWORD handle; // identifies the sample | |
99 ULONG start; // start index | |
100 ULONG size; // samplesize | |
101 ULONG reppos; // loop start | |
102 ULONG repend; // loop end | |
103 ULONG frq; // current frequency | |
104 UWORD vol; // current volume | |
105 UWORD pan; // current panning position | |
106 SLONG current; // current index in the sample | |
107 SLONG increment; // fixed-point increment value | |
108 } VINFO; | |
109 | |
110 | |
111 #ifdef __FASTMIXER__ | |
112 static SBYTE **Samples; | |
113 #else | |
114 static SWORD **Samples; | |
115 #endif | |
116 | |
117 // Volume table for 8 bit sample mixing | |
118 #ifdef __FASTMIXER__ | |
119 static SLONG **voltab; | |
120 #endif | |
121 | |
122 static VINFO *vinf = NULL, *vnf; | |
123 static VSTREAM vstream; | |
124 static ULONG samplesthatfit; | |
125 static BOOL vc_stream = 0; | |
126 static int vc_memory, vc_softchn; | |
127 static SLONG idxsize,idxlpos,idxlend; | |
128 static SLONG TICKLEFT, *VC_TICKBUF = NULL; | |
129 static UWORD vc_mode; | |
130 | |
131 | |
132 // Reverb control variables | |
133 // ======================== | |
134 | |
135 static int RVc1, RVc2, RVc3, RVc4; | |
136 static ULONG RVRindex; | |
137 | |
138 | |
139 // For Mono or Left Channel | |
140 | |
141 static SLONG *RVbuf1 = NULL, *RVbuf2 = NULL, *RVbuf3 = NULL, | |
142 *RVbuf4 = NULL; | |
143 | |
144 // For Stereo only (Right Channel) | |
145 // Values start at 9 to leave room for expanding this to 8-step | |
146 // reverb in the future. | |
147 | |
148 static SLONG *RVbuf9 = NULL, *RVbuf10 = NULL, *RVbuf11 = NULL, | |
149 *RVbuf12 = NULL; | |
150 | |
151 | |
152 int bitshift; // Amplification shift (amount to decrease 32 bit mixing buffer by!) | |
153 | |
154 #ifdef __FASTMIXER__ | |
155 SLONG *lvoltab, *rvoltab; // Volume Table values for use by 8 bit mixers | |
156 #else | |
157 static SLONG lvolsel, rvolsel; // Volume Selectors for 16 bit mixers. | |
158 #endif | |
159 | |
160 | |
161 | |
162 // Define external Assembly Language Prototypes | |
163 // ============================================ | |
164 | |
165 #ifdef __ASSEMBLY__ | |
166 | |
167 #ifdef __cplusplus | |
168 extern "C" { | |
169 #endif | |
170 | |
171 #ifdef __GNUC__ | |
172 #define __cdecl | |
173 #endif | |
174 | |
175 void __cdecl AsmStereoNormal(SBYTE *srce,SLONG *dest,SLONG index,SLONG increment,SLONG todo); | |
176 void __cdecl AsmStereoSurround(SBYTE *srce,SLONG *dest,SLONG index,SLONG increment,SLONG todo); | |
177 void __cdecl AsmMonoNormal(SBYTE *srce,SLONG *dest,SLONG index,SLONG increment,SLONG todo); | |
178 | |
179 #ifdef __cplusplus | |
180 }; | |
181 #endif | |
182 | |
183 #else | |
184 | |
185 #ifdef __FASTMIXER__ | |
186 | |
187 // ============================================================== | |
188 // 8 bit sample mixers! | |
189 | |
190 static SLONG MixStereoNormal(SBYTE *srce, SLONG *dest, SLONG index, SLONG increment, SLONG todo) | |
191 { | |
192 UBYTE sample1, sample2, sample3, sample4; | |
193 int remain; | |
194 | |
195 remain = todo & 3; | |
196 | |
197 for(todo>>=2; todo; todo--) | |
198 { | |
199 sample1 = srce[index >> FRACBITS]; | |
200 index += increment; | |
201 sample2 = srce[index >> FRACBITS]; | |
202 index += increment; | |
203 sample3 = srce[index >> FRACBITS]; | |
204 index += increment; | |
205 sample4 = srce[index >> FRACBITS]; | |
206 index += increment; | |
207 | |
208 *dest++ += lvoltab[sample1]; | |
209 *dest++ += rvoltab[sample1]; | |
210 *dest++ += lvoltab[sample2]; | |
211 *dest++ += rvoltab[sample2]; | |
212 *dest++ += lvoltab[sample3]; | |
213 *dest++ += rvoltab[sample3]; | |
214 *dest++ += lvoltab[sample4]; | |
215 *dest++ += rvoltab[sample4]; | |
216 } | |
217 | |
218 for(; remain--; ) | |
219 { | |
220 sample1 = srce[index >> FRACBITS]; | |
221 index += increment; | |
222 *dest++ += lvoltab[sample1]; | |
223 *dest++ += rvoltab[sample1]; | |
224 } | |
225 | |
226 return index; | |
227 } | |
228 | |
229 | |
230 static SLONG MixStereoSurround(SBYTE *srce, SLONG *dest, SLONG index, SLONG increment, SLONG todo) | |
231 { | |
232 SLONG sample1, sample2, sample3, sample4; | |
233 int remain; | |
234 | |
235 remain = todo & 3; | |
236 | |
237 for(todo>>=2; todo; todo--) | |
238 { | |
239 sample1 = lvoltab[(UBYTE)srce[index >> FRACBITS]]; | |
240 index += increment; | |
241 sample2 = lvoltab[(UBYTE)srce[index >> FRACBITS]]; | |
242 index += increment; | |
243 sample3 = lvoltab[(UBYTE)srce[index >> FRACBITS]]; | |
244 index += increment; | |
245 sample4 = lvoltab[(UBYTE)srce[index >> FRACBITS]]; | |
246 index += increment; | |
247 | |
248 *dest++ += sample1; | |
249 *dest++ -= sample1; | |
250 *dest++ += sample2; | |
251 *dest++ -= sample2; | |
252 *dest++ += sample3; | |
253 *dest++ -= sample3; | |
254 *dest++ += sample4; | |
255 *dest++ -= sample4; | |
256 } | |
257 | |
258 for(; remain--; ) | |
259 { sample1 = lvoltab[(UBYTE)srce[index >> FRACBITS]]; | |
260 index += increment; | |
261 *dest++ += sample1; | |
262 *dest++ -= sample1; | |
263 } | |
264 | |
265 return index; | |
266 } | |
267 | |
268 | |
269 static SLONG MixMonoNormal(SBYTE *srce, SLONG *dest, SLONG index, SLONG increment, SLONG todo) | |
270 { | |
271 UBYTE sample1, sample2, sample3, sample4; | |
272 int remain; | |
273 | |
274 remain = todo & 3; | |
275 | |
276 for(todo>>=2; todo; todo--) | |
277 { | |
278 sample1 = srce[index >> FRACBITS]; | |
279 index += increment; | |
280 sample2 = srce[index >> FRACBITS]; | |
281 index += increment; | |
282 sample3 = srce[index >> FRACBITS]; | |
283 index += increment; | |
284 sample4 = srce[index >> FRACBITS]; | |
285 index += increment; | |
286 | |
287 *dest++ += lvoltab[sample1]; | |
288 *dest++ += lvoltab[sample2]; | |
289 *dest++ += lvoltab[sample3]; | |
290 *dest++ += lvoltab[sample4]; | |
291 } | |
292 | |
293 for(; remain--;) | |
294 { sample1 = srce[index >> FRACBITS]; | |
295 index += increment; | |
296 *dest++ -= lvoltab[sample1]; | |
297 } | |
298 | |
299 return index; | |
300 } | |
301 | |
302 #else // not __FASTMIXER__ | |
303 | |
304 // ============================================================== | |
305 // 16 bit sample mixers! | |
306 | |
307 static SLONG MixStereoNormal(SWORD *srce, SLONG *dest, SLONG index, SLONG increment, ULONG todo) | |
308 { | |
309 SWORD sample; | |
310 | |
311 for(; todo; todo--) | |
312 { | |
313 sample = srce[index >> FRACBITS]; | |
314 index += increment; | |
315 | |
316 *dest++ += lvolsel * sample; | |
317 *dest++ += rvolsel * sample; | |
318 } | |
319 | |
320 return index; | |
321 } | |
322 | |
323 | |
324 static SLONG MixStereoSurround(SWORD *srce, SLONG *dest, SLONG index, SLONG increment, ULONG todo) | |
325 { | |
326 SWORD sample; | |
327 | |
328 for (; todo; todo--) | |
329 { | |
330 sample = srce[index >> FRACBITS]; | |
331 index += increment; | |
332 | |
333 *dest++ += lvolsel * sample; | |
334 *dest++ -= lvolsel * sample; | |
335 } | |
336 | |
337 return index; | |
338 } | |
339 | |
340 | |
341 static SLONG MixMonoNormal(SWORD *srce, SLONG *dest, SLONG index, SLONG increment, SLONG todo) | |
342 { | |
343 SWORD sample; | |
344 | |
345 for(; todo; todo--) | |
346 { | |
347 sample = srce[index >> FRACBITS]; | |
348 index += increment; | |
349 | |
350 *dest++ += lvolsel * sample; | |
351 } | |
352 | |
353 return index; | |
354 } | |
355 | |
356 #endif // __FASTMIXER__ | |
357 #endif // __ASSEMBLY__ | |
358 | |
359 static void (*MixReverb16)(SLONG *srce, SLONG count); | |
360 | |
361 static void MixReverb16_Normal(SLONG *srce, SLONG count) | |
362 { | |
363 unsigned int speedup; | |
364 int ReverbPct; | |
365 unsigned int loc1, loc2, loc3, loc4; | |
366 | |
367 ReverbPct = 63 + (md_reverb*4); | |
368 | |
369 loc1 = RVRindex % RVc1; | |
370 loc2 = RVRindex % RVc2; | |
371 loc3 = RVRindex % RVc3; | |
372 loc4 = RVRindex % RVc4; | |
373 | |
374 for(; count; count--) | |
375 { | |
376 // Compute the LEFT CHANNEL echo buffers! | |
377 | |
378 speedup = *srce >> 3; | |
379 | |
380 RVbuf1[loc1] = speedup + ((ReverbPct * RVbuf1[loc1]) / 128l); | |
381 RVbuf2[loc2] = speedup + ((ReverbPct * RVbuf2[loc2]) / 128l); | |
382 RVbuf3[loc3] = speedup + ((ReverbPct * RVbuf3[loc3]) / 128l); | |
383 RVbuf4[loc4] = speedup + ((ReverbPct * RVbuf4[loc4]) / 128l); | |
384 | |
385 // Prepare to compute actual finalized data! | |
386 | |
387 RVRindex++; | |
388 loc1 = RVRindex % RVc1; | |
389 loc2 = RVRindex % RVc2; | |
390 loc3 = RVRindex % RVc3; | |
391 loc4 = RVRindex % RVc4; | |
392 | |
393 // Left Channel! | |
394 | |
395 *srce++ += RVbuf1[loc1] - RVbuf2[loc2] + RVbuf3[loc3] - RVbuf4[loc4]; | |
396 } | |
397 } | |
398 | |
399 | |
400 static void MixReverb16_Stereo(SLONG *srce, SLONG count) | |
401 { | |
402 unsigned int speedup; | |
403 int ReverbPct; | |
404 unsigned int loc1, loc2, loc3, loc4; | |
405 | |
406 ReverbPct = 63 + (md_reverb*4); | |
407 | |
408 loc1 = RVRindex % RVc1; | |
409 loc2 = RVRindex % RVc2; | |
410 loc3 = RVRindex % RVc3; | |
411 loc4 = RVRindex % RVc4; | |
412 | |
413 for(; count; count--) | |
414 { | |
415 // Compute the LEFT CHANNEL echo buffers! | |
416 | |
417 speedup = *srce >> 3; | |
418 | |
419 RVbuf1[loc1] = speedup + ((ReverbPct * RVbuf1[loc1]) / 128l); | |
420 RVbuf2[loc2] = speedup + ((ReverbPct * RVbuf2[loc2]) / 128l); | |
421 RVbuf3[loc3] = speedup + ((ReverbPct * RVbuf3[loc3]) / 128l); | |
422 RVbuf4[loc4] = speedup + ((ReverbPct * RVbuf4[loc4]) / 128l); | |
423 | |
424 // Compute the RIGHT CHANNEL echo buffers! | |
425 | |
426 speedup = srce[1] >> 3; | |
427 | |
428 RVbuf9[loc1] = speedup + ((ReverbPct * RVbuf9[loc1]) / 128l); | |
429 RVbuf10[loc2] = speedup + ((ReverbPct * RVbuf11[loc2]) / 128l); | |
430 RVbuf11[loc3] = speedup + ((ReverbPct * RVbuf12[loc3]) / 128l); | |
431 RVbuf12[loc4] = speedup + ((ReverbPct * RVbuf12[loc4]) / 128l); | |
432 | |
433 // Prepare to compute actual finalized data! | |
434 | |
435 RVRindex++; | |
436 loc1 = RVRindex % RVc1; | |
437 loc2 = RVRindex % RVc2; | |
438 loc3 = RVRindex % RVc3; | |
439 loc4 = RVRindex % RVc4; | |
440 | |
441 // Left Channel! | |
442 | |
443 *srce++ += RVbuf1[loc1] - RVbuf2[loc2] + RVbuf3[loc3] - RVbuf4[loc4]; | |
444 | |
445 // Right Channel! | |
446 | |
447 *srce++ += RVbuf9[loc1] - RVbuf10[loc2] + RVbuf11[loc3] - RVbuf12[loc4]; | |
448 } | |
449 } | |
450 | |
451 | |
452 static void Mix32To16(SWORD *dste, SLONG *srce, SLONG count) | |
453 { | |
454 SLONG x1, x2, x3, x4; | |
455 int remain; | |
456 | |
457 remain = count & 3; | |
458 | |
459 for(count>>=2; count; count--) | |
460 { x1 = *srce++ >> bitshift; | |
461 x2 = *srce++ >> bitshift; | |
462 x3 = *srce++ >> bitshift; | |
463 x4 = *srce++ >> bitshift; | |
464 x1 = (x1 > 32767) ? 32767 : (x1 < -32768) ? -32768 : x1; | |
465 x2 = (x2 > 32767) ? 32767 : (x2 < -32768) ? -32768 : x2; | |
466 x3 = (x3 > 32767) ? 32767 : (x3 < -32768) ? -32768 : x3; | |
467 x4 = (x4 > 32767) ? 32767 : (x4 < -32768) ? -32768 : x4; | |
468 *dste++ = x1; | |
469 *dste++ = x2; | |
470 *dste++ = x3; | |
471 *dste++ = x4; | |
472 } | |
473 | |
474 for(; remain; remain--) | |
475 { x1 = *srce++ >> bitshift; | |
476 x1 = (x1 > 32767) ? 32767 : (x1 < -32768) ? -32768 : x1; | |
477 *dste++ = x1; | |
478 } | |
479 } | |
480 | |
481 | |
482 static void Mix32To8(SBYTE *dste, SLONG *srce, SLONG count) | |
483 { | |
484 int x1, x2, x3, x4; | |
485 int remain; | |
486 | |
487 remain = count & 3; | |
488 | |
489 for(count>>=2; count; count--) | |
490 { x1 = *srce++ >> bitshift; | |
491 x2 = *srce++ >> bitshift; | |
492 x3 = *srce++ >> bitshift; | |
493 x4 = *srce++ >> bitshift; | |
494 | |
495 x1 = (x1 > 127) ? 127 : (x1 < -128) ? -128 : x1; | |
496 x2 = (x2 > 127) ? 127 : (x2 < -128) ? -128 : x2; | |
497 x3 = (x3 > 127) ? 127 : (x3 < -128) ? -128 : x3; | |
498 x4 = (x4 > 127) ? 127 : (x4 < -128) ? -128 : x4; | |
499 | |
500 *dste++ = x1 + 128; | |
501 *dste++ = x2 + 128; | |
502 *dste++ = x3 + 128; | |
503 *dste++ = x4 + 128; | |
504 } | |
505 | |
506 for(; remain; remain--) | |
507 { x1 = *srce++ >> bitshift; | |
508 x1 = (x1 > 127) ? 127 : (x1 < -128) ? -128 : x1; | |
509 *dste++ = x1 + 128; | |
510 } | |
511 } | |
512 | |
513 | |
514 static ULONG samples2bytes(ULONG samples) | |
515 { | |
516 if(vc_mode & DMODE_16BITS) samples <<= 1; | |
517 if(vc_mode & DMODE_STEREO) samples <<= 1; | |
518 return samples; | |
519 } | |
520 | |
521 | |
522 static ULONG bytes2samples(ULONG bytes) | |
523 { | |
524 if(vc_mode & DMODE_16BITS) bytes >>= 1; | |
525 if(vc_mode & DMODE_STEREO) bytes >>= 1; | |
526 return bytes; | |
527 } | |
528 | |
529 | |
530 static void AddChannel(SLONG *ptr, SLONG todo) | |
531 { | |
532 SLONG end, done; | |
533 #ifdef __FASTMIXER__ | |
534 SBYTE *s; | |
535 #else | |
536 SWORD *s; | |
537 #endif | |
538 | |
539 while(todo > 0) | |
540 { // update the 'current' index so the sample loops, or | |
541 // stops playing if it reached the end of the sample | |
542 | |
543 if(vnf->flags & SF_REVERSE) | |
544 { | |
545 // The sample is playing in reverse | |
546 | |
547 if((vnf->flags & SF_LOOP) && (vnf->current < idxlpos)) | |
548 { | |
549 // the sample is looping, and it has | |
550 // reached the loopstart index | |
551 | |
552 if(vnf->flags & SF_BIDI) | |
553 { | |
554 // sample is doing bidirectional loops, so 'bounce' | |
555 // the current index against the idxlpos | |
556 | |
557 vnf->current = idxlpos+(idxlpos-vnf->current); | |
558 vnf->flags &=~SF_REVERSE; | |
559 vnf->increment =-vnf->increment; | |
560 } else | |
561 // normal backwards looping, so set the | |
562 // current position to loopend index | |
563 | |
564 vnf->current = idxlend-(idxlpos-vnf->current); | |
565 } else | |
566 { | |
567 // the sample is not looping, so check | |
568 // if it reached index 0 | |
569 | |
570 if(vnf->current < 0) | |
571 { | |
572 // playing index reached 0, so stop | |
573 // playing this sample | |
574 | |
575 vnf->current = 0; | |
576 vnf->active = 0; | |
577 break; | |
578 } | |
579 } | |
580 } else | |
581 { | |
582 // The sample is playing forward | |
583 | |
584 if((vnf->flags & SF_LOOP) && (vnf->current > idxlend)) | |
585 { | |
586 // the sample is looping, so check if | |
587 // it reached the loopend index | |
588 | |
589 if(vnf->flags & SF_BIDI) | |
590 { | |
591 // sample is doing bidirectional loops, so 'bounce' | |
592 // the current index against the idxlend | |
593 | |
594 vnf->flags |=SF_REVERSE; | |
595 vnf->increment =-vnf->increment; | |
596 vnf->current =idxlend-(vnf->current-idxlend); | |
597 } else | |
598 // normal backwards looping, so set the | |
599 // current position to loopend index | |
600 | |
601 vnf->current = idxlpos + (vnf->current-idxlend); | |
602 } else | |
603 { | |
604 // sample is not looping, so check | |
605 // if it reached the last position | |
606 | |
607 if(vnf->current > idxsize) | |
608 { | |
609 // yes, so stop playing this sample | |
610 | |
611 vnf->current = 0; | |
612 vnf->active = 0; | |
613 break; | |
614 } | |
615 } | |
616 } | |
617 | |
618 if(!(s=Samples[vnf->handle])) | |
619 { vnf->current = 0; | |
620 vnf->active = 0; | |
621 break; | |
622 } | |
623 | |
624 end = (vnf->flags & SF_REVERSE) ? | |
625 (vnf->flags & SF_LOOP) ? idxlpos : 0 : | |
626 (vnf->flags & SF_LOOP) ? idxlend : idxsize; | |
627 | |
628 done = MIN((end - vnf->current) / vnf->increment + 1, todo); | |
629 | |
630 if(!done) | |
631 { vnf->active = 0; | |
632 break; | |
633 } | |
634 | |
635 if(vnf->vol) | |
636 { | |
637 #ifdef __ASSEMBLY__ | |
638 if(vc_mode & DMODE_STEREO) | |
639 if((vnf->pan == PAN_SURROUND) && (vc_mode & DMODE_SURROUND)) | |
640 AsmStereoSurround(s,ptr,vnf->current,vnf->increment,done); | |
641 else | |
642 AsmStereoNormal(s,ptr,vnf->current,vnf->increment,done); | |
643 else | |
644 AsmMonoNormal(s,ptr,vnf->current,vnf->increment,done); | |
645 vnf->current += (vnf->increment*done); | |
646 #else | |
647 if(vc_mode & DMODE_STEREO) | |
648 if((vnf->pan == PAN_SURROUND) && (vc_mode & DMODE_SURROUND)) | |
649 vnf->current = MixStereoSurround(s,ptr,vnf->current,vnf->increment,done); | |
650 else | |
651 vnf->current = MixStereoNormal(s,ptr,vnf->current,vnf->increment,done); | |
652 else | |
653 vnf->current = MixMonoNormal(s,ptr,vnf->current,vnf->increment,done); | |
654 #endif | |
655 } | |
656 todo -= done; | |
657 ptr += (vc_mode & DMODE_STEREO) ? (done<<1) : done; | |
658 } | |
659 } | |
660 | |
661 | |
662 void VC_WriteSamples(SBYTE *buf, ULONG todo) | |
663 { | |
664 int left, portion = 0, count; | |
665 SBYTE *buffer, *samplebuf; | |
666 int t; | |
667 int pan, vol; | |
668 int sampletodo; | |
669 | |
670 samplebuf = buf; | |
671 sampletodo = todo; | |
672 | |
673 while(todo) | |
674 { if(TICKLEFT==0) | |
675 { if(vc_mode & DMODE_SOFT_MUSIC) md_player(); | |
676 TICKLEFT = (md_mixfreq*125l) / (md_bpm*50L); | |
677 } | |
678 | |
679 left = MIN(TICKLEFT, todo); | |
680 | |
681 buffer = buf; | |
682 TICKLEFT -= left; | |
683 todo -= left; | |
684 | |
685 buf += samples2bytes(left); | |
686 | |
687 while(left) | |
688 { portion = MIN(left, samplesthatfit); | |
689 count = (vc_mode & DMODE_STEREO) ? (portion<<1) : portion; | |
690 | |
691 memset(VC_TICKBUF, 0, count<<2); | |
692 | |
693 for(t=0; t<vc_softchn; t++) | |
694 { vnf = &vinf[t]; | |
695 | |
696 if(vnf->kick) | |
697 { vnf->current = vnf->start << FRACBITS; | |
698 vnf->kick = 0; | |
699 vnf->active = 1; | |
700 } | |
701 | |
702 if(vnf->frq == 0) vnf->active = 0; | |
703 | |
704 if(vnf->active) | |
705 { vnf->increment = (vnf->frq<<FRACBITS) / md_mixfreq; | |
706 if(vnf->flags & SF_REVERSE) vnf->increment=-vnf->increment; | |
707 | |
708 vol = vnf->vol; pan = vnf->pan; | |
709 | |
710 if(vc_mode & DMODE_STEREO) | |
711 { if(pan != PAN_SURROUND) | |
712 { | |
713 #ifdef __FASTMIXER__ | |
714 lvoltab = voltab[(vol * (255-pan)) / 1024]; | |
715 rvoltab = voltab[(vol * pan) / 1024]; | |
716 #else | |
717 lvolsel = (vol * (255-pan)) >> 8; | |
718 rvolsel = (vol * pan) >> 8; | |
719 #endif | |
720 } else | |
721 { | |
722 #ifdef __FASTMIXER__ | |
723 lvoltab = voltab[(vol+1)>>3]; | |
724 #else | |
725 lvolsel = vol/2; | |
726 #endif | |
727 } | |
728 } else | |
729 { | |
730 #ifdef __FASTMIXER__ | |
731 lvoltab = voltab[(vol+1)>>2]; | |
732 #else | |
733 lvolsel = vol; | |
734 #endif | |
735 } | |
736 idxsize = (vnf->size) ? (vnf->size << FRACBITS)-1 : 0; | |
737 idxlend = (vnf->repend) ? (vnf->repend << FRACBITS)-1 : 0; | |
738 idxlpos = vnf->reppos << FRACBITS; | |
739 AddChannel(VC_TICKBUF, portion); | |
740 } | |
741 } | |
742 | |
743 if(md_reverb) MixReverb16(VC_TICKBUF, portion); | |
744 | |
745 if(vc_mode & DMODE_16BITS) | |
746 Mix32To16((SWORD *) buffer, VC_TICKBUF, count); | |
747 else | |
748 Mix32To8((SBYTE *) buffer, VC_TICKBUF, count); | |
749 | |
750 buffer += samples2bytes(portion); | |
751 left -= portion; | |
752 } | |
753 } | |
754 } | |
755 | |
756 | |
757 void VC_SilenceBytes(SBYTE *buf, ULONG todo) | |
758 | |
759 // Fill the buffer with 'todo' bytes of silence (it depends on the mixing | |
760 // mode how the buffer is filled) | |
761 | |
762 { | |
763 // clear the buffer to zero (16 bits | |
764 // signed ) or 0x80 (8 bits unsigned) | |
765 | |
766 if(vc_mode & DMODE_16BITS) | |
767 memset(buf,0,todo); | |
768 else | |
769 memset(buf,0x80,todo); | |
770 } | |
771 | |
772 | |
773 ULONG VC_WriteBytes(SBYTE *buf, ULONG todo) | |
774 | |
775 // Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of | |
776 // SBYTES actually written to 'buf' (which is rounded to number of samples | |
777 // that fit into 'todo' bytes). | |
778 | |
779 { | |
780 if(vc_softchn == 0) | |
781 { VC_SilenceBytes(buf,todo); | |
782 return todo; | |
783 } | |
784 | |
785 todo = bytes2samples(todo); | |
786 VC_WriteSamples(buf,todo); | |
787 | |
788 return samples2bytes(todo); | |
789 } | |
790 | |
791 | |
792 static UBYTE log2(ULONG x) | |
793 { | |
794 UBYTE result = 0; | |
795 while (x>>=1) result++; | |
796 | |
797 return result; | |
798 } | |
799 | |
800 | |
801 BOOL VC_PlayStart(void) | |
802 { | |
803 int t, numchn; | |
804 | |
805 numchn = md_softchn; | |
806 if(vc_stream) numchn++; | |
807 | |
808 if(numchn > 0) | |
809 { | |
810 #ifdef __FASTMIXER__ | |
811 int c; | |
812 SLONG maxvol, volmul; | |
813 | |
814 if(vc_stream) numchn++; | |
815 maxvol = 16777216L / (numchn+6); | |
816 | |
817 for(t=0; t<65; t++) | |
818 { volmul = (maxvol*t) / 64; | |
819 for(c=-128; c<128; c++) | |
820 voltab[t][(UBYTE)c] = (SLONG)c*volmul; | |
821 } | |
822 | |
823 bitshift = 16 - log2(numchn); | |
824 #else | |
825 bitshift = (log2(numchn)>>3) + 7; | |
826 | |
827 #endif | |
828 | |
829 if (!(vc_mode & DMODE_16BITS)) | |
830 bitshift += 8; | |
831 } | |
832 | |
833 samplesthatfit = TICKLSIZE; | |
834 if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; | |
835 TICKLEFT = 0; | |
836 | |
837 | |
838 RVc1 = (5000L * md_mixfreq) / REVERBERATION; | |
839 RVc2 = (5078L * md_mixfreq) / REVERBERATION; | |
840 RVc3 = (5313L * md_mixfreq) / REVERBERATION; | |
841 RVc4 = (5703L * md_mixfreq) / REVERBERATION; | |
842 | |
843 if((RVbuf1 = (SLONG *)_mm_calloc((RVc1+1),sizeof(SLONG))) == NULL) return 1; | |
844 if((RVbuf2 = (SLONG *)_mm_calloc((RVc2+1),sizeof(SLONG))) == NULL) return 1; | |
845 if((RVbuf3 = (SLONG *)_mm_calloc((RVc3+1),sizeof(SLONG))) == NULL) return 1; | |
846 if((RVbuf4 = (SLONG *)_mm_calloc((RVc4+1),sizeof(SLONG))) == NULL) return 1; | |
847 | |
848 if(vc_mode & DMODE_STEREO) | |
849 { if((RVbuf9 = (SLONG *)_mm_calloc((RVc1+1),sizeof(SLONG))) == NULL) return 1; | |
850 if((RVbuf10 = (SLONG *)_mm_calloc((RVc2+1),sizeof(SLONG))) == NULL) return 1; | |
851 if((RVbuf11 = (SLONG *)_mm_calloc((RVc3+1),sizeof(SLONG))) == NULL) return 1; | |
852 if((RVbuf12 = (SLONG *)_mm_calloc((RVc4+1),sizeof(SLONG))) == NULL) return 1; | |
853 } | |
854 | |
855 RVRindex = 0; | |
856 | |
857 return 0; | |
858 } | |
859 | |
860 | |
861 void VC_PlayStop(void) | |
862 { | |
863 if(RVbuf1 != NULL) free(RVbuf1); | |
864 if(RVbuf2 != NULL) free(RVbuf2); | |
865 if(RVbuf3 != NULL) free(RVbuf3); | |
866 if(RVbuf4 != NULL) free(RVbuf4); | |
867 if(RVbuf9 != NULL) free(RVbuf9); | |
868 if(RVbuf10 != NULL) free(RVbuf10); | |
869 if(RVbuf11 != NULL) free(RVbuf11); | |
870 if(RVbuf12 != NULL) free(RVbuf12); | |
871 | |
872 RVbuf1 = NULL; RVbuf2 = NULL; RVbuf3 = NULL; RVbuf4 = NULL; | |
873 RVbuf9 = NULL; RVbuf10 = NULL; RVbuf11 = NULL; RVbuf12 = NULL; | |
874 } | |
875 | |
876 | |
877 BOOL VC_Init(void) | |
878 { | |
879 | |
880 #ifdef __FASTMIXER__ | |
881 int t; | |
882 | |
883 _mm_errno = MMERR_INITIALIZING_MIXER; | |
884 if((voltab = (SLONG **)calloc(65,sizeof(SLONG *))) == NULL) return 1; | |
885 for(t=0; t<65; t++) | |
886 if((voltab[t] = (SLONG *)calloc(256,sizeof(SLONG))) == NULL) return 1; | |
887 | |
888 if((Samples = (SBYTE **)calloc(MAXSAMPLEHANDLES, sizeof(SBYTE *))) == NULL) return 1; | |
889 #else | |
890 _mm_errno = MMERR_INITIALIZING_MIXER; | |
891 if((Samples = (SWORD **)calloc(MAXSAMPLEHANDLES, sizeof(SWORD *))) == NULL) return 1; | |
892 #endif | |
893 | |
894 if(VC_TICKBUF==NULL) if((VC_TICKBUF=(SLONG *)malloc((TICKLSIZE+32) * sizeof(SLONG))) == NULL) return 1; | |
895 if(md_mode & DMODE_INTERP) md_mode &= ~DMODE_INTERP; | |
896 | |
897 MixReverb16 = (md_mode & DMODE_STEREO) ? MixReverb16_Stereo : MixReverb16_Normal; | |
898 vc_mode = md_mode; | |
899 | |
900 | |
901 _mm_errno = 0; | |
902 return 0; | |
903 } | |
904 | |
905 | |
906 void VC_Exit(void) | |
907 { | |
908 #ifdef __FASTMIXER__ | |
909 int t; | |
910 if(voltab!=NULL) | |
911 { for(t=0; t<65; t++) if(voltab[t]!=NULL) free(voltab[t]); | |
912 free(voltab); voltab = NULL; | |
913 } | |
914 #endif | |
915 | |
916 //if(VC_TICKBUF!=NULL) free(VC_TICKBUF); | |
917 if(vinf!=NULL) free(vinf); | |
918 if(Samples!=NULL) free(Samples); | |
919 | |
920 //VC_TICKBUF = NULL; | |
921 vinf = NULL; | |
922 Samples = NULL; | |
923 } | |
924 | |
925 | |
926 BOOL VC_SetNumVoices(void) | |
927 { | |
928 int t; | |
929 | |
930 if((vc_softchn = md_softchn) == 0) return 0; | |
931 | |
932 if(vinf!=NULL) free(vinf); | |
933 if((vinf = _mm_calloc(sizeof(VINFO),vc_softchn)) == NULL) return 1; | |
934 | |
935 for(t=0; t<vc_softchn; t++) | |
936 { vinf[t].frq = 10000; | |
937 vinf[t].pan = (t&1) ? 0 : 255; | |
938 } | |
939 | |
940 return 0; | |
941 } | |
942 | |
943 | |
944 void VC_VoiceSetVolume(UBYTE voice, UWORD vol) | |
945 { | |
946 vinf[voice].vol = vol; | |
947 } | |
948 | |
949 | |
950 void VC_VoiceSetFrequency(UBYTE voice, ULONG frq) | |
951 { | |
952 vinf[voice].frq = frq; | |
953 } | |
954 | |
955 | |
956 void VC_VoiceSetPanning(UBYTE voice, ULONG pan) | |
957 { | |
958 vinf[voice].pan = pan; | |
959 } | |
960 | |
961 | |
962 void VC_VoicePlay(UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags) | |
963 { | |
964 vinf[voice].flags = flags; | |
965 vinf[voice].handle = handle; | |
966 vinf[voice].start = start; | |
967 vinf[voice].size = size; | |
968 vinf[voice].reppos = reppos; | |
969 vinf[voice].repend = repend; | |
970 vinf[voice].kick = 1; | |
971 } | |
972 | |
973 | |
974 void VC_VoiceStop(UBYTE voice) | |
975 { | |
976 vinf[voice].active = 0; | |
977 } | |
978 | |
979 | |
980 BOOL VC_VoiceStopped(UBYTE voice) | |
981 { | |
982 return(vinf[voice].active==0); | |
983 } | |
984 | |
985 | |
986 void VC_VoiceReleaseSustain(UBYTE voice) | |
987 { | |
988 | |
989 } | |
990 | |
991 | |
992 SLONG VC_VoiceGetPosition(UBYTE voice) | |
993 { | |
994 return(vinf[voice].current>>FRACBITS); | |
995 } | |
996 | |
997 | |
998 /************************************************** | |
999 *************************************************** | |
1000 *************************************************** | |
1001 **************************************************/ | |
1002 | |
1003 | |
1004 void VC_SampleUnload(SWORD handle) | |
1005 { | |
1006 void *sampleadr = Samples[handle]; | |
1007 | |
1008 free(sampleadr); | |
1009 Samples[handle] = NULL; | |
1010 } | |
1011 | |
1012 | |
1013 SWORD VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) | |
1014 { | |
1015 SAMPLE *s = sload->sample; | |
1016 int handle; | |
1017 ULONG t, length,loopstart,loopend; | |
1018 | |
1019 if(type==MD_HARDWARE) return -1; | |
1020 | |
1021 // Find empty slot to put sample address in | |
1022 for(handle=0; handle<MAXSAMPLEHANDLES; handle++) | |
1023 if(Samples[handle]==NULL) break; | |
1024 | |
1025 if(handle==MAXSAMPLEHANDLES) | |
1026 { _mm_errno = MMERR_OUT_OF_HANDLES; | |
1027 return -1; | |
1028 } | |
1029 | |
1030 length = s->length; | |
1031 loopstart = s->loopstart; | |
1032 loopend = s->loopend; | |
1033 | |
1034 SL_SampleSigned(sload); | |
1035 | |
1036 #ifdef __FASTMIXER__ | |
1037 SL_Sample16to8(sload); | |
1038 if((Samples[handle]=(SBYTE *)malloc(length+16))==NULL) | |
1039 { _mm_errno = MMERR_SAMPLE_TOO_BIG; | |
1040 return -1; | |
1041 } | |
1042 // read sample into buffer. | |
1043 SL_Load(Samples[handle],sload,length); | |
1044 #else | |
1045 SL_Sample8to16(sload); | |
1046 if((Samples[handle]=(SWORD *)malloc((length+16)<<1))==NULL) | |
1047 { _mm_errno = MMERR_SAMPLE_TOO_BIG; | |
1048 return -1; | |
1049 } | |
1050 // read sample into buffer. | |
1051 SL_Load(Samples[handle],sload,length); | |
1052 #endif | |
1053 | |
1054 | |
1055 // Unclick samples: | |
1056 | |
1057 if(s->flags & SF_LOOP) | |
1058 { if(s->flags & SF_BIDI) | |
1059 for(t=0; t<16; t++) Samples[handle][loopend+t] = Samples[handle][(loopend-t)-1]; | |
1060 else | |
1061 for(t=0; t<16; t++) Samples[handle][loopend+t] = Samples[handle][t+loopstart]; | |
1062 } else | |
1063 for(t=0; t<16; t++) Samples[handle][t+length] = 0; | |
1064 | |
1065 return handle; | |
1066 } | |
1067 | |
1068 | |
1069 ULONG VC_SampleSpace(int type) | |
1070 { | |
1071 return vc_memory; | |
1072 } | |
1073 | |
1074 | |
1075 ULONG VC_SampleLength(int type, SAMPLE *s) | |
1076 { | |
1077 #ifdef __FASTMIXER__ | |
1078 return s->length + 16; | |
1079 #else | |
1080 return (s->length * ((s->flags&SF_16BITS) ? 2 : 1)) + 16; | |
1081 #endif | |
1082 } | |
1083 | |
1084 | |
1085 /************************************************** | |
1086 *************************************************** | |
1087 *************************************************** | |
1088 **************************************************/ | |
1089 | |
1090 | |
1091 ULONG VC_VoiceRealVolume(UBYTE voice) | |
1092 { | |
1093 ULONG i,s,size; | |
1094 int k,j; | |
1095 #ifdef __FASTMIXER__ | |
1096 SBYTE *smp; | |
1097 #else | |
1098 SWORD *smp; | |
1099 #endif | |
1100 SLONG t; | |
1101 | |
1102 t = vinf[voice].current>>FRACBITS; | |
1103 if(vinf[voice].active==0) return 0; | |
1104 | |
1105 s = vinf[voice].handle; | |
1106 size = vinf[voice].size; | |
1107 | |
1108 i=64; t-=64; k=0; j=0; | |
1109 if(i>size) i = size; | |
1110 if(t<0) t = 0; | |
1111 if(t+i > size) t = size-i; | |
1112 | |
1113 i &= ~1; // make sure it's EVEN. | |
1114 | |
1115 smp = &Samples[s][t]; | |
1116 for(; i; i--, smp++) | |
1117 { if(k<*smp) k = *smp; | |
1118 if(j>*smp) j = *smp; | |
1119 } | |
1120 | |
1121 #ifdef __FASTMIXER__ | |
1122 k = abs(k-j)<<8; | |
1123 #else | |
1124 k = abs(k-j); | |
1125 #endif | |
1126 | |
1127 return k; | |
1128 } | |
1129 | |
1130 | |
1131 BOOL VC_StreamInit(ULONG speed, UWORD flags) | |
1132 | |
1133 // flags - Disk Format - SF_STEREO, SF_16BITS, etc. | |
1134 // speed - speed at which to replay sample | |
1135 // | |
1136 // Returns - TRUE if init failed | |
1137 | |
1138 { | |
1139 ULONG tmp; | |
1140 | |
1141 #ifdef __FASTMIXER__ | |
1142 tmp = stream_bufsize * speed * (((flags & SF_STEREO) && (vc_mode & DMODE_STEREO)) ? 2 : 1); | |
1143 #else | |
1144 tmp = stream_bufsize * speed * (((flags & SF_STEREO) && (vc_mode & DMODE_STEREO)) ? 2 : 1) | |
1145 * ((flags & SF_16BITS) && (vc_mode & DMODE_16BITS)) ? 2 : 1; | |
1146 #endif | |
1147 if((flags & SF_STEREO) && (vc_mode & DMODE_STEREO)) tmp <<= 1; | |
1148 | |
1149 vstream.size = tmp; | |
1150 if((vstream.buffer=_mm_calloc(vstream.size,1024)) == NULL) return 1; | |
1151 | |
1152 vstream.speed = speed; | |
1153 vstream.speedfactor = (md_mixfreq / speed); | |
1154 if(!((vstream.speedfactor==2) || (vstream.speedfactor==4))) | |
1155 vstream.speedfactor = 1; | |
1156 | |
1157 vstream.infmt = flags; | |
1158 vstream.flags = flags; | |
1159 #ifdef __FASTMIXER__ | |
1160 vstream.flags = flags &= ~SF_16BITS; | |
1161 #else | |
1162 vstream.flags = flags |= SF_16BITS; | |
1163 #endif | |
1164 if(!(vc_mode&DMODE_STEREO)) vstream.flags &= ~SF_STEREO; | |
1165 | |
1166 vstream.active = 0; | |
1167 vstream.current = 0; | |
1168 vstream.increment = 0; | |
1169 | |
1170 vc_stream = 1; | |
1171 VC_PlayStart(); | |
1172 | |
1173 return 0; | |
1174 } | |
1175 | |
1176 | |
1177 void VC_StreamExit(void) | |
1178 { | |
1179 vstream.active = 0; | |
1180 if(vstream.buffer != NULL) free(vstream.buffer); | |
1181 vstream.buffer = NULL; | |
1182 vc_stream = 0; | |
1183 VC_PlayStart(); | |
1184 } | |
1185 | |
1186 | |
1187 void VC_StreamSetSpeed(ULONG speed) | |
1188 { | |
1189 vstream.speed = speed; | |
1190 vstream.speedfactor = (md_mixfreq/speed); | |
1191 if(!((vstream.speedfactor==2) || (vstream.speedfactor==4))) | |
1192 vstream.speedfactor = 1; | |
1193 } | |
1194 | |
1195 | |
1196 SLONG VC_StreamGetPosition(void) | |
1197 { | |
1198 return(vstream.current >> FRACBITS); | |
1199 } | |
1200 | |
1201 | |
1202 void VC_StreamStart(void) | |
1203 { | |
1204 if(vstream.buffer!=NULL) vstream.active = 1; | |
1205 } | |
1206 | |
1207 | |
1208 void VC_StreamStop(void) | |
1209 { | |
1210 vstream.active = 0; | |
1211 } | |
1212 | |
1213 | |
1214 void VC_StreamCommit(void *sample, ULONG size) | |
1215 | |
1216 // Read 'size' bytes from the specified buffer and commit them to | |
1217 // the streaming audio buffer. | |
1218 | |
1219 { | |
1220 //ULONG last, curr; | |
1221 //ULONG todo; | |
1222 | |
1223 if(vstream.buffer==NULL) return; | |
1224 | |
1225 } | |
1226 |