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