Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/virtch2.c @ 4:5d614bcc4287
Initial entry of mikmod into the CVS tree.
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:71e20a32bd84 | 4:5d614bcc4287 |
---|---|
1 /* | |
2 | |
3 Name: VIRTCH2.C | |
4 | |
5 Description: | |
6 All-c sample mixing routines, using a 32 bits mixing buffer, interpolation, | |
7 and sample smoothing [improves sound quality and removes clicks]. | |
8 | |
9 Future Additions: | |
10 Low-Pass filter to remove annoying staticy buzz. | |
11 | |
12 | |
13 C Mixer Portability: | |
14 All Systems -- All compilers. | |
15 | |
16 Assembly Mixer Portability: | |
17 | |
18 MSDOS: BC(?) Watcom(y) DJGPP(y) | |
19 Win95: ? | |
20 Os2: ? | |
21 Linux: y | |
22 | |
23 (y) - yes | |
24 (n) - no (not possible or not useful) | |
25 (?) - may be possible, but not tested | |
26 | |
27 */ | |
28 | |
29 #include <stddef.h> | |
30 #include <string.h> | |
31 #include "mikmod.h" | |
32 | |
33 | |
34 // REVERBERATION : Larger numbers result in shorter reverb duration. | |
35 // Longer reverb durations can cause unwanted static and make the | |
36 // reverb sound more like an echo. | |
37 | |
38 #define REVERBERATION 28000l | |
39 | |
40 // SAMPLING_SHIFT : Specified the shift multiplier which controls by how | |
41 // much the mixing rate is multiplied while mixing. Higher values | |
42 // can improve quality by smoothing the soudn and reducing pops and | |
43 // clicks. Note, this is a shift value, so a value of 2 becomes a | |
44 // mixing-rate multiplier of 4, and a value of 3 = 8, etc. | |
45 | |
46 #define SAMPLING_SHIFT 2 | |
47 #define SAMPLING_FACTOR (SLONG)(1<<SAMPLING_SHIFT) | |
48 | |
49 | |
50 // FRACBITS : the number of bits per integer devoted to the fractional | |
51 // part of the number. This value HAS to be changed if the compiler | |
52 // does not support 64 bit integers. If 32 bit integers are used, | |
53 // FRACBITS _must_ be 9 or smaller. | |
54 | |
55 #define FRACBITS 28 | |
56 #define FRACMASK ((1l<<FRACBITS)-1) | |
57 | |
58 #define TICKLSIZE 4096 | |
59 #define TICKWSIZE (TICKLSIZE*2) | |
60 #define TICKBSIZE (TICKWSIZE*2) | |
61 | |
62 #ifndef MIN | |
63 #define MIN(a,b) (((a)<(b)) ? (a) : (b)) | |
64 #endif | |
65 | |
66 #ifndef MAX | |
67 #define MAX(a,b) (((a)>(b))?(a):(b)) | |
68 #endif | |
69 | |
70 | |
71 typedef struct | |
72 { UBYTE kick; // =1 -> sample has to be restarted | |
73 UBYTE active; // =1 -> sample is playing | |
74 UWORD flags; // 16/8 bits looping/one-shot | |
75 SWORD handle; // identifies the sample | |
76 ULONG start; // start index | |
77 ULONG size; // samplesize | |
78 ULONG reppos; // loop start | |
79 ULONG repend; // loop end | |
80 ULONG frq; // current frequency | |
81 UWORD vol; // current volume | |
82 UWORD pan; // current panning position | |
83 SDOUBLE current; // current index in the sample | |
84 SDOUBLE increment; // fixed-point increment value | |
85 } VINFO; | |
86 | |
87 | |
88 static SWORD **Samples; | |
89 | |
90 static VINFO *vinf = NULL; | |
91 static VINFO *vnf; | |
92 static ULONG samplesthatfit; | |
93 static int vc_memory, vc_softchn; | |
94 static SDOUBLE idxsize,idxlpos,idxlend; | |
95 static SLONG TICKLEFT; | |
96 static SLONG *VC2_TICKBUF = NULL; | |
97 static UWORD vc_mode; | |
98 static int bitshift; // Amplification shift (amount to decrease 32 bit mixing buffer by!) | |
99 static SLONG lvolsel, rvolsel; // Volume factor .. range 0-255 | |
100 | |
101 | |
102 // Reverb control variables | |
103 // ======================== | |
104 | |
105 static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; | |
106 static ULONG RVRindex; | |
107 | |
108 // For Mono or Left Channel | |
109 static SLONG *RVbuf1 = NULL, *RVbuf2 = NULL, *RVbuf3 = NULL, | |
110 *RVbuf4 = NULL, *RVbuf5 = NULL, *RVbuf6 = NULL, | |
111 *RVbuf7 = NULL, *RVbuf8 = NULL; | |
112 | |
113 // For Stereo only (Right Channel) | |
114 static SLONG *RVbuf9 = NULL, *RVbuf10 = NULL, *RVbuf11 = NULL, | |
115 *RVbuf12 = NULL, *RVbuf13 = NULL, *RVbuf14 = NULL, | |
116 *RVbuf15 = NULL, *RVbuf16 = NULL; | |
117 | |
118 | |
119 // ============================================================== | |
120 // 16 bit sample mixers! | |
121 | |
122 static SDOUBLE MixStereoNormal(SWORD *srce, SLONG *dest, SDOUBLE index, SDOUBLE increment, ULONG todo) | |
123 { | |
124 SWORD sample; | |
125 | |
126 for(; todo; todo--) | |
127 { sample = (index & FRACBITS) ? | |
128 (((srce[index >> FRACBITS] * (FRACBITS - (index & FRACBITS))) + | |
129 (srce[(index >> FRACBITS)+1] * (index & FRACBITS))) / FRACBITS) | |
130 : srce[index >> FRACBITS]; | |
131 index += increment; | |
132 | |
133 *dest++ += lvolsel * sample; | |
134 *dest++ += rvolsel * sample; | |
135 } | |
136 | |
137 return index; | |
138 } | |
139 | |
140 | |
141 static SDOUBLE MixStereoSurround(SWORD *srce, SLONG *dest, SDOUBLE index, SDOUBLE increment, ULONG todo) | |
142 { | |
143 SWORD sample; | |
144 | |
145 for(dest--; todo; todo--) | |
146 { sample = (index & FRACBITS) ? | |
147 (((srce[index >> FRACBITS] * (FRACBITS - (index & FRACBITS))) + | |
148 (srce[(index >> FRACBITS)+1] * (index & FRACBITS))) / FRACBITS) | |
149 : srce[index >> FRACBITS]; | |
150 index += increment; | |
151 | |
152 *dest++ += lvolsel * sample; | |
153 *dest++ -= lvolsel * sample; | |
154 } | |
155 | |
156 return index; | |
157 } | |
158 | |
159 | |
160 static SDOUBLE MixMonoNormal(SWORD *srce, SLONG *dest, SDOUBLE index, SDOUBLE increment, SLONG todo) | |
161 { | |
162 SWORD sample; | |
163 | |
164 for(; todo; todo--) | |
165 { sample = (index & FRACBITS) ? | |
166 (((srce[index >> FRACBITS] * (FRACBITS - (index & FRACBITS))) + | |
167 (srce[(index >> FRACBITS)+1] * (index & FRACBITS))) / FRACBITS) | |
168 : srce[index >> FRACBITS]; | |
169 index += increment; | |
170 | |
171 *dest++ += lvolsel * sample; | |
172 } | |
173 | |
174 return index; | |
175 } | |
176 | |
177 | |
178 static void (*Mix32to16)(SWORD *dste, SLONG *srce, SLONG count); | |
179 static void (*Mix32to8)(SBYTE *dste, SLONG *srce, SLONG count); | |
180 static void (*MixReverb)(SLONG *srce, SLONG count); | |
181 | |
182 | |
183 static void MixReverb_Normal(SLONG *srce, SLONG count) | |
184 { | |
185 SLONG speedup; | |
186 int ReverbPct; | |
187 unsigned int loc1, loc2, loc3, loc4, | |
188 loc5, loc6, loc7, loc8; | |
189 | |
190 ReverbPct = 63 + (md_reverb*4); | |
191 | |
192 loc1 = RVRindex % RVc1; | |
193 loc2 = RVRindex % RVc2; | |
194 loc3 = RVRindex % RVc3; | |
195 loc4 = RVRindex % RVc4; | |
196 loc5 = RVRindex % RVc5; | |
197 loc6 = RVRindex % RVc6; | |
198 loc7 = RVRindex % RVc7; | |
199 loc8 = RVRindex % RVc8; | |
200 | |
201 for(; count; count--) | |
202 { | |
203 // Compute the LEFT CHANNEL echo buffers! | |
204 | |
205 speedup = *srce >> 3; | |
206 | |
207 RVbuf1[loc1] = speedup + ((ReverbPct * RVbuf1[loc1]) / 128); | |
208 RVbuf2[loc2] = speedup + ((ReverbPct * RVbuf2[loc2]) / 128); | |
209 RVbuf3[loc3] = speedup + ((ReverbPct * RVbuf3[loc3]) / 128); | |
210 RVbuf4[loc4] = speedup + ((ReverbPct * RVbuf4[loc4]) / 128); | |
211 RVbuf5[loc5] = speedup + ((ReverbPct * RVbuf5[loc5]) / 128); | |
212 RVbuf6[loc6] = speedup + ((ReverbPct * RVbuf6[loc6]) / 128); | |
213 RVbuf7[loc7] = speedup + ((ReverbPct * RVbuf7[loc7]) / 128); | |
214 RVbuf8[loc8] = speedup + ((ReverbPct * RVbuf8[loc8]) / 128); | |
215 | |
216 // Prepare to compute actual finalized data! | |
217 | |
218 RVRindex++; | |
219 loc1 = RVRindex % RVc1; | |
220 loc2 = RVRindex % RVc2; | |
221 loc3 = RVRindex % RVc3; | |
222 loc4 = RVRindex % RVc4; | |
223 loc5 = RVRindex % RVc5; | |
224 loc6 = RVRindex % RVc6; | |
225 loc7 = RVRindex % RVc7; | |
226 loc8 = RVRindex % RVc8; | |
227 | |
228 // Left Channel! | |
229 | |
230 *srce++ += (RVbuf1[loc1] - RVbuf2[loc2] + RVbuf3[loc3] - RVbuf4[loc4] + | |
231 RVbuf5[loc5] - RVbuf6[loc6] + RVbuf7[loc7] - RVbuf8[loc8]); | |
232 } | |
233 } | |
234 | |
235 | |
236 static void MixReverb_Stereo(SLONG *srce, SLONG count) | |
237 { | |
238 SLONG speedup; | |
239 int ReverbPct; | |
240 unsigned int loc1, loc2, loc3, loc4, | |
241 loc5, loc6, loc7, loc8; | |
242 | |
243 ReverbPct = 63 + (md_reverb*4); | |
244 | |
245 loc1 = RVRindex % RVc1; | |
246 loc2 = RVRindex % RVc2; | |
247 loc3 = RVRindex % RVc3; | |
248 loc4 = RVRindex % RVc4; | |
249 loc5 = RVRindex % RVc5; | |
250 loc6 = RVRindex % RVc6; | |
251 loc7 = RVRindex % RVc7; | |
252 loc8 = RVRindex % RVc8; | |
253 | |
254 for(; count; count--) | |
255 { | |
256 // Compute the LEFT CHANNEL echo buffers! | |
257 | |
258 speedup = *srce >> 3; | |
259 | |
260 RVbuf1[loc1] = speedup + ((ReverbPct * RVbuf1[loc1]) / 128); | |
261 RVbuf2[loc2] = speedup + ((ReverbPct * RVbuf2[loc2]) / 128); | |
262 RVbuf3[loc3] = speedup + ((ReverbPct * RVbuf3[loc3]) / 128); | |
263 RVbuf4[loc4] = speedup + ((ReverbPct * RVbuf4[loc4]) / 128); | |
264 RVbuf5[loc5] = speedup + ((ReverbPct * RVbuf5[loc5]) / 128); | |
265 RVbuf6[loc6] = speedup + ((ReverbPct * RVbuf6[loc6]) / 128); | |
266 RVbuf7[loc7] = speedup + ((ReverbPct * RVbuf7[loc7]) / 128); | |
267 RVbuf8[loc8] = speedup + ((ReverbPct * RVbuf8[loc8]) / 128); | |
268 | |
269 // Compute the RIGHT CHANNEL echo buffers! | |
270 | |
271 speedup = srce[1] >> 3; | |
272 | |
273 RVbuf9[loc1] = speedup + ((ReverbPct * RVbuf9[loc1]) / 128); | |
274 RVbuf10[loc2] = speedup + ((ReverbPct * RVbuf11[loc2]) / 128); | |
275 RVbuf11[loc3] = speedup + ((ReverbPct * RVbuf12[loc3]) / 128); | |
276 RVbuf12[loc4] = speedup + ((ReverbPct * RVbuf12[loc4]) / 128); | |
277 RVbuf13[loc5] = speedup + ((ReverbPct * RVbuf13[loc5]) / 128); | |
278 RVbuf14[loc6] = speedup + ((ReverbPct * RVbuf14[loc6]) / 128); | |
279 RVbuf15[loc7] = speedup + ((ReverbPct * RVbuf15[loc7]) / 128); | |
280 RVbuf16[loc8] = speedup + ((ReverbPct * RVbuf16[loc8]) / 128); | |
281 | |
282 // Prepare to compute actual finalized data! | |
283 | |
284 RVRindex++; | |
285 loc1 = RVRindex % RVc1; | |
286 loc2 = RVRindex % RVc2; | |
287 loc3 = RVRindex % RVc3; | |
288 loc4 = RVRindex % RVc4; | |
289 loc5 = RVRindex % RVc5; | |
290 loc6 = RVRindex % RVc6; | |
291 loc7 = RVRindex % RVc7; | |
292 loc8 = RVRindex % RVc8; | |
293 | |
294 // Left Channel! | |
295 | |
296 *srce++ += (RVbuf1[loc1] - RVbuf2[loc2] + RVbuf3[loc3] - RVbuf4[loc4] + | |
297 RVbuf5[loc5] - RVbuf6[loc6] + RVbuf7[loc7] - RVbuf8[loc8]); | |
298 | |
299 // Right Channel! | |
300 | |
301 *srce++ += (RVbuf9[loc1] - RVbuf10[loc2] + RVbuf11[loc3] - RVbuf12[loc4] + | |
302 RVbuf13[loc5] - RVbuf14[loc6] + RVbuf15[loc7] - RVbuf16[loc8]); | |
303 } | |
304 } | |
305 | |
306 | |
307 static void Mix32To16_Normal(SWORD *dste, SLONG *srce, SLONG count) | |
308 { | |
309 SLONG x1, x2, tmpx; | |
310 int i; | |
311 | |
312 for(count/=SAMPLING_FACTOR; count; count--) | |
313 { tmpx = 0; | |
314 | |
315 for(i=SAMPLING_FACTOR/2; i; i--) | |
316 { x1 = *srce++ / bitshift; | |
317 x2 = *srce++ / bitshift; | |
318 | |
319 x1 = (x1 > 32767) ? 32767 : (x1 < -32768) ? -32768 : x1; | |
320 x2 = (x2 > 32767) ? 32767 : (x2 < -32768) ? -32768 : x2; | |
321 | |
322 tmpx += x1 + x2; | |
323 } | |
324 | |
325 *dste++ = tmpx / SAMPLING_FACTOR; | |
326 } | |
327 } | |
328 | |
329 | |
330 static void Mix32To16_Stereo(SWORD *dste, SLONG *srce, SLONG count) | |
331 { | |
332 SLONG x1, x2, x3, x4, tmpx, tmpy; | |
333 int i; | |
334 | |
335 for(count/=SAMPLING_FACTOR; count; count--) | |
336 { tmpx = tmpy = 0; | |
337 | |
338 for(i=SAMPLING_FACTOR/2; i; i--) | |
339 { x1 = *srce++ / bitshift; | |
340 x2 = *srce++ / bitshift; | |
341 x3 = *srce++ / bitshift; | |
342 x4 = *srce++ / bitshift; | |
343 | |
344 x1 = (x1 > 32767) ? 32767 : (x1 < -32768) ? -32768 : x1; | |
345 x2 = (x2 > 32767) ? 32767 : (x2 < -32768) ? -32768 : x2; | |
346 x3 = (x3 > 32767) ? 32767 : (x3 < -32768) ? -32768 : x3; | |
347 x4 = (x4 > 32767) ? 32767 : (x4 < -32768) ? -32768 : x4; | |
348 | |
349 tmpx += x1 + x3; | |
350 tmpy += x2 + x4; | |
351 } | |
352 | |
353 *dste++ = tmpx / SAMPLING_FACTOR; | |
354 *dste++ = tmpy / SAMPLING_FACTOR; | |
355 } | |
356 } | |
357 | |
358 | |
359 static void Mix32To8_Normal(SBYTE *dste, SLONG *srce, SLONG count) | |
360 { | |
361 int x1, x2; | |
362 int i, tmpx; | |
363 | |
364 for(count/=SAMPLING_FACTOR; count; count--) | |
365 { tmpx = 0; | |
366 | |
367 for(i=SAMPLING_FACTOR/2; i; i--) | |
368 { x1 = *srce++ / bitshift; | |
369 x2 = *srce++ / bitshift; | |
370 | |
371 x1 = (x1 > 127) ? 127 : (x1 < -128) ? -128 : x1; | |
372 x2 = (x2 > 127) ? 127 : (x2 < -128) ? -128 : x2; | |
373 | |
374 tmpx += x1 + x2; | |
375 } | |
376 | |
377 *dste++ = (tmpx / SAMPLING_FACTOR) + 128; | |
378 } | |
379 } | |
380 | |
381 | |
382 static void Mix32To8_Stereo(SBYTE *dste, SLONG *srce, SLONG count) | |
383 { | |
384 int x1, x2, x3, x4; | |
385 int i, tmpx, tmpy; | |
386 | |
387 for(count/=SAMPLING_FACTOR; count; count--) | |
388 { tmpx = tmpy = 0; | |
389 | |
390 for(i=SAMPLING_FACTOR/2; i; i--) | |
391 { x1 = *srce++ / bitshift; | |
392 x2 = *srce++ / bitshift; | |
393 x3 = *srce++ / bitshift; | |
394 x4 = *srce++ / bitshift; | |
395 | |
396 x1 = (x1 > 127) ? 127 : (x1 < -128) ? -128 : x1; | |
397 x2 = (x2 > 127) ? 127 : (x2 < -128) ? -128 : x2; | |
398 x3 = (x3 > 127) ? 127 : (x3 < -128) ? -128 : x3; | |
399 x4 = (x4 > 127) ? 127 : (x4 < -128) ? -128 : x4; | |
400 | |
401 tmpx += x1 + x3; | |
402 tmpy += x2 + x4; | |
403 } | |
404 | |
405 *dste++ = (tmpx / SAMPLING_FACTOR) + 128; | |
406 *dste++ = (tmpy / SAMPLING_FACTOR) + 128; | |
407 } | |
408 } | |
409 | |
410 | |
411 static ULONG samples2bytes(ULONG samples) | |
412 { | |
413 if(vc_mode & DMODE_16BITS) samples <<= 1; | |
414 if(vc_mode & DMODE_STEREO) samples <<= 1; | |
415 | |
416 return samples; | |
417 } | |
418 | |
419 | |
420 static ULONG bytes2samples(ULONG bytes) | |
421 { | |
422 if(vc_mode & DMODE_16BITS) bytes >>= 1; | |
423 if(vc_mode & DMODE_STEREO) bytes >>= 1; | |
424 | |
425 return bytes; | |
426 } | |
427 | |
428 | |
429 static void AddChannel(SLONG *ptr, SLONG todo) | |
430 { | |
431 SDOUBLE end; | |
432 SLONG done; | |
433 SWORD *s; | |
434 | |
435 while(todo > 0) | |
436 { // update the 'current' index so the sample loops, or | |
437 // stops playing if it reached the end of the sample | |
438 | |
439 if(vnf->flags & SF_REVERSE) | |
440 { | |
441 // The sample is playing in reverse | |
442 | |
443 if((vnf->flags & SF_LOOP) && (vnf->current < idxlpos)) | |
444 { | |
445 // the sample is looping, and it has | |
446 // reached the loopstart index | |
447 | |
448 if(vnf->flags & SF_BIDI) | |
449 { | |
450 // sample is doing bidirectional loops, so 'bounce' | |
451 // the current index against the idxlpos | |
452 | |
453 vnf->current = idxlpos + (idxlpos - vnf->current); | |
454 vnf->flags &= ~SF_REVERSE; | |
455 vnf->increment = -vnf->increment; | |
456 } else | |
457 // normal backwards looping, so set the | |
458 // current position to loopend index | |
459 | |
460 vnf->current = idxlend - (idxlpos-vnf->current); | |
461 } else | |
462 { | |
463 // the sample is not looping, so check | |
464 // if it reached index 0 | |
465 | |
466 if(vnf->current < 0) | |
467 { | |
468 // playing index reached 0, so stop | |
469 // playing this sample | |
470 | |
471 vnf->current = 0; | |
472 vnf->active = 0; | |
473 break; | |
474 } | |
475 } | |
476 } else | |
477 { | |
478 // The sample is playing forward | |
479 | |
480 if((vnf->flags & SF_LOOP) && (vnf->current > idxlend)) | |
481 { | |
482 // the sample is looping, so check if | |
483 // it reached the loopend index | |
484 | |
485 if(vnf->flags & SF_BIDI) | |
486 { | |
487 // sample is doing bidirectional loops, so 'bounce' | |
488 // the current index against the idxlend | |
489 | |
490 vnf->flags |= SF_REVERSE; | |
491 vnf->increment = -vnf->increment; | |
492 vnf->current = idxlend-(vnf->current-idxlend); | |
493 } else | |
494 // normal backwards looping, so set the | |
495 // current position to loopend index | |
496 | |
497 vnf->current = idxlpos + (vnf->current-idxlend); | |
498 } else | |
499 { | |
500 // sample is not looping, so check | |
501 // if it reached the last position | |
502 | |
503 if(vnf->current > idxsize) | |
504 { | |
505 // yes, so stop playing this sample | |
506 | |
507 vnf->current = 0; | |
508 vnf->active = 0; | |
509 break; | |
510 } | |
511 } | |
512 } | |
513 | |
514 if(!(s=Samples[vnf->handle])) | |
515 { vnf->current = 0; | |
516 vnf->active = 0; | |
517 break; | |
518 } | |
519 | |
520 end = (vnf->flags & SF_REVERSE) ? | |
521 (vnf->flags & SF_LOOP) ? idxlpos : 0 : | |
522 (vnf->flags & SF_LOOP) ? idxlend : idxsize; | |
523 | |
524 done = MIN((end - vnf->current) / vnf->increment + 1, todo); | |
525 | |
526 if(!done) | |
527 { vnf->active = 0; | |
528 break; | |
529 } | |
530 | |
531 if(vnf->vol) | |
532 { if(vc_mode & DMODE_STEREO) | |
533 if(vnf->pan == PAN_SURROUND && vc_mode&DMODE_SURROUND) | |
534 vnf->current = MixStereoSurround(s,ptr,vnf->current,vnf->increment,done); | |
535 else | |
536 vnf->current = MixStereoNormal(s,ptr,vnf->current,vnf->increment,done); | |
537 else | |
538 vnf->current = MixMonoNormal(s,ptr,vnf->current,vnf->increment,done); | |
539 } | |
540 todo -= done; | |
541 ptr += (vc_mode & DMODE_STEREO) ? (done<<1) : done; | |
542 } | |
543 } | |
544 | |
545 | |
546 void VC2_WriteSamples(SBYTE *buf, ULONG todo) | |
547 { | |
548 int left, portion = 0; | |
549 SBYTE *buffer; | |
550 int t; | |
551 int pan, vol; | |
552 | |
553 todo *= SAMPLING_FACTOR; | |
554 | |
555 while(todo) | |
556 { if(TICKLEFT==0) | |
557 { if(vc_mode & DMODE_SOFT_MUSIC) md_player(); | |
558 TICKLEFT = (md_mixfreq*125l*SAMPLING_FACTOR) / (md_bpm*50l); | |
559 TICKLEFT &= ~(SAMPLING_FACTOR-1); | |
560 } | |
561 | |
562 left = MIN(TICKLEFT, todo); | |
563 | |
564 buffer = buf; | |
565 TICKLEFT -= left; | |
566 todo -= left; | |
567 | |
568 buf += samples2bytes(left) / SAMPLING_FACTOR; | |
569 | |
570 while(left) | |
571 { portion = MIN(left, samplesthatfit); | |
572 memset(VC2_TICKBUF, 0, portion << ((vc_mode & DMODE_STEREO) ? 3 : 2)); | |
573 | |
574 for(t=0; t<vc_softchn; t++) | |
575 { vnf = &vinf[t]; | |
576 | |
577 if(vnf->kick) | |
578 { vnf->current = (SDOUBLE)(vnf->start) << FRACBITS; | |
579 vnf->kick = 0; | |
580 vnf->active = 1; | |
581 } | |
582 | |
583 if(vnf->frq == 0) vnf->active = 0; | |
584 | |
585 if(vnf->active) | |
586 { vnf->increment = ((SDOUBLE)(vnf->frq) << (FRACBITS-SAMPLING_SHIFT)) / (SDOUBLE)md_mixfreq; | |
587 if(vnf->flags & SF_REVERSE) vnf->increment=-vnf->increment; | |
588 | |
589 vol = vnf->vol; pan = vnf->pan; | |
590 | |
591 if((vc_mode & DMODE_STEREO) && (pan!=PAN_SURROUND)) | |
592 { lvolsel = (vol * (255-pan)) >> 8; | |
593 rvolsel = (vol * pan) >> 8; | |
594 } else | |
595 lvolsel = (vol*256l) / 480; | |
596 | |
597 idxsize = (vnf->size) ? ((SDOUBLE)(vnf->size) << FRACBITS)-1 : 0; | |
598 idxlend = (vnf->repend) ? ((SDOUBLE)(vnf->repend) << FRACBITS)-1 : 0; | |
599 idxlpos = (SDOUBLE)(vnf->reppos) << FRACBITS; | |
600 AddChannel(VC2_TICKBUF, portion); | |
601 } | |
602 } | |
603 | |
604 if(md_reverb) MixReverb(VC2_TICKBUF, portion); | |
605 | |
606 if(vc_mode & DMODE_16BITS) | |
607 Mix32to16((SWORD *) buffer, VC2_TICKBUF, portion); | |
608 else | |
609 Mix32to8((SBYTE *) buffer, VC2_TICKBUF, portion); | |
610 | |
611 buffer += samples2bytes(portion) / SAMPLING_FACTOR; | |
612 left -= portion; | |
613 } | |
614 } | |
615 } | |
616 | |
617 | |
618 void VC2_SilenceBytes(SBYTE *buf, ULONG todo) | |
619 | |
620 // Fill the buffer with 'todo' bytes of silence (it depends on the mixing | |
621 // mode how the buffer is filled) | |
622 | |
623 { | |
624 // clear the buffer to zero (16 bits | |
625 // signed ) or 0x80 (8 bits unsigned) | |
626 | |
627 if(vc_mode & DMODE_16BITS) | |
628 memset(buf,0,todo); | |
629 else | |
630 memset(buf,0x80,todo); | |
631 } | |
632 | |
633 | |
634 ULONG VC2_WriteBytes(SBYTE *buf, ULONG todo) | |
635 | |
636 // Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of | |
637 // SBYTES actually written to 'buf' (which is rounded to number of samples | |
638 // that fit into 'todo' bytes). | |
639 | |
640 { | |
641 if(vc_softchn == 0) | |
642 { VC2_SilenceBytes(buf,todo); | |
643 return todo; | |
644 } | |
645 | |
646 todo = bytes2samples(todo); | |
647 VC2_WriteSamples(buf,todo); | |
648 | |
649 return samples2bytes(todo); | |
650 } | |
651 | |
652 | |
653 BOOL VC2_PlayStart(void) | |
654 { | |
655 if(vc_softchn > 0) | |
656 { bitshift = vc_softchn + 257; | |
657 if(!(vc_mode & DMODE_16BITS)) | |
658 bitshift *= 256; | |
659 if(md_reverb) bitshift++; | |
660 } | |
661 | |
662 samplesthatfit = TICKLSIZE; | |
663 if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; | |
664 TICKLEFT = 0; | |
665 | |
666 /* Original Reverb Code! | |
667 The stuff I use avoids floating point (below). | |
668 | |
669 RVc1 = (SLONG)(500 * md_mixfreq) / 11000; | |
670 RVc2 = (SLONG)(507.8125 * md_mixfreq) / 11000; | |
671 RVc3 = (SLONG)(531.25 * md_mixfreq) / 11000; | |
672 RVc4 = (SLONG)(570.3125 * md_mixfreq) / 11000; | |
673 RVc5 = (SLONG)(625 * md_mixfreq) / 11000; | |
674 RVc6 = (SLONG)(695.3125 * md_mixfreq) / 11000; | |
675 RVc7 = (SLONG)(781.25 * md_mixfreq) / 11000; | |
676 RVc8 = (SLONG)(882.8125 * md_mixfreq) / 11000; | |
677 ReverbPct = 99 - (md_reverb*2); | |
678 */ | |
679 | |
680 RVc1 = (5000L * md_mixfreq) / REVERBERATION; | |
681 RVc2 = (5078L * md_mixfreq) / REVERBERATION; | |
682 RVc3 = (5313L * md_mixfreq) / REVERBERATION; | |
683 RVc4 = (5703L * md_mixfreq) / REVERBERATION; | |
684 RVc5 = (6250L * md_mixfreq) / REVERBERATION; | |
685 RVc6 = (6953L * md_mixfreq) / REVERBERATION; | |
686 RVc7 = (7813L * md_mixfreq) / REVERBERATION; | |
687 RVc8 = (8828L * md_mixfreq) / REVERBERATION; | |
688 | |
689 if((RVbuf1 = (SLONG *)_mm_calloc((RVc1+1),sizeof(SLONG))) == NULL) return 1; | |
690 if((RVbuf2 = (SLONG *)_mm_calloc((RVc2+1),sizeof(SLONG))) == NULL) return 1; | |
691 if((RVbuf3 = (SLONG *)_mm_calloc((RVc3+1),sizeof(SLONG))) == NULL) return 1; | |
692 if((RVbuf4 = (SLONG *)_mm_calloc((RVc4+1),sizeof(SLONG))) == NULL) return 1; | |
693 if((RVbuf5 = (SLONG *)_mm_calloc((RVc5+1),sizeof(SLONG))) == NULL) return 1; | |
694 if((RVbuf6 = (SLONG *)_mm_calloc((RVc6+1),sizeof(SLONG))) == NULL) return 1; | |
695 if((RVbuf7 = (SLONG *)_mm_calloc((RVc7+1),sizeof(SLONG))) == NULL) return 1; | |
696 if((RVbuf8 = (SLONG *)_mm_calloc((RVc8+1),sizeof(SLONG))) == NULL) return 1; | |
697 | |
698 if(vc_mode & DMODE_STEREO) | |
699 { if((RVbuf9 = (SLONG *)_mm_calloc((RVc1+1),sizeof(SLONG))) == NULL) return 1; | |
700 if((RVbuf10 = (SLONG *)_mm_calloc((RVc2+1),sizeof(SLONG))) == NULL) return 1; | |
701 if((RVbuf11 = (SLONG *)_mm_calloc((RVc3+1),sizeof(SLONG))) == NULL) return 1; | |
702 if((RVbuf12 = (SLONG *)_mm_calloc((RVc4+1),sizeof(SLONG))) == NULL) return 1; | |
703 if((RVbuf13 = (SLONG *)_mm_calloc((RVc5+1),sizeof(SLONG))) == NULL) return 1; | |
704 if((RVbuf14 = (SLONG *)_mm_calloc((RVc6+1),sizeof(SLONG))) == NULL) return 1; | |
705 if((RVbuf15 = (SLONG *)_mm_calloc((RVc7+1),sizeof(SLONG))) == NULL) return 1; | |
706 if((RVbuf16 = (SLONG *)_mm_calloc((RVc8+1),sizeof(SLONG))) == NULL) return 1; | |
707 } | |
708 | |
709 RVRindex = 0; | |
710 return 0; | |
711 } | |
712 | |
713 | |
714 void VC2_PlayStop(void) | |
715 { | |
716 if(RVbuf1 != NULL) free(RVbuf1); | |
717 if(RVbuf2 != NULL) free(RVbuf2); | |
718 if(RVbuf3 != NULL) free(RVbuf3); | |
719 if(RVbuf4 != NULL) free(RVbuf4); | |
720 if(RVbuf5 != NULL) free(RVbuf5); | |
721 if(RVbuf6 != NULL) free(RVbuf6); | |
722 if(RVbuf7 != NULL) free(RVbuf7); | |
723 if(RVbuf8 != NULL) free(RVbuf8); | |
724 if(RVbuf9 != NULL) free(RVbuf9); | |
725 if(RVbuf10 != NULL) free(RVbuf10); | |
726 if(RVbuf11 != NULL) free(RVbuf11); | |
727 if(RVbuf12 != NULL) free(RVbuf12); | |
728 if(RVbuf13 != NULL) free(RVbuf13); | |
729 if(RVbuf14 != NULL) free(RVbuf14); | |
730 if(RVbuf15 != NULL) free(RVbuf15); | |
731 if(RVbuf16 != NULL) free(RVbuf16); | |
732 | |
733 RVbuf1 = NULL; RVbuf2 = NULL; RVbuf3 = NULL; RVbuf4 = NULL; | |
734 RVbuf5 = NULL; RVbuf6 = NULL; RVbuf7 = NULL; RVbuf8 = NULL; | |
735 RVbuf9 = NULL; RVbuf10 = NULL; RVbuf11 = NULL; RVbuf12 = NULL; | |
736 RVbuf13 = NULL; RVbuf14 = NULL; RVbuf15 = NULL; RVbuf16 = NULL; | |
737 } | |
738 | |
739 | |
740 BOOL VC2_Init(void) | |
741 { | |
742 _mm_errno = MMERR_INITIALIZING_MIXER; | |
743 if((Samples = (SWORD **)calloc(MAXSAMPLEHANDLES, sizeof(SWORD *))) == NULL) return 1; | |
744 if(VC2_TICKBUF==NULL) if((VC2_TICKBUF=(SLONG *)malloc((TICKLSIZE+32) * sizeof(SLONG))) == NULL) return 1; | |
745 | |
746 if(md_mode & DMODE_STEREO) | |
747 { Mix32to16 = Mix32To16_Stereo; | |
748 Mix32to8 = Mix32To8_Stereo; | |
749 MixReverb = MixReverb_Stereo; | |
750 } else | |
751 { Mix32to16 = Mix32To16_Normal; | |
752 Mix32to8 = Mix32To8_Normal; | |
753 MixReverb = MixReverb_Normal; | |
754 } | |
755 | |
756 vc_mode = md_mode; | |
757 | |
758 _mm_errno = 0; | |
759 return 0; | |
760 } | |
761 | |
762 | |
763 void VC2_Exit(void) | |
764 | |
765 // Yay, he joys and fruits of C and C++ - | |
766 // Deallocation of arrays! | |
767 | |
768 { | |
769 //if(VC2_TICKBUF!=NULL) free(VC2_TICKBUF); | |
770 if(vinf!=NULL) free(vinf); | |
771 if(Samples!=NULL) free(Samples); | |
772 | |
773 // VC2_TICKBUF = NULL; | |
774 vinf = NULL; | |
775 Samples = NULL; | |
776 } | |
777 | |
778 | |
779 BOOL VC2_SetNumVoices(void) | |
780 { | |
781 int t; | |
782 | |
783 if((vc_softchn = md_softchn) == 0) return 0; | |
784 | |
785 if(vinf!=NULL) free(vinf); | |
786 if((vinf = _mm_calloc(sizeof(VINFO),vc_softchn)) == NULL) return 1; | |
787 | |
788 for(t=0; t<vc_softchn; t++) | |
789 { vinf[t].frq = 10000; | |
790 vinf[t].pan = (t & 1) ? 0 : 255; | |
791 } | |
792 | |
793 return 0; | |
794 } | |
795 | |
796 | |
797 void VC2_VoiceSetVolume(UBYTE voice, UWORD vol) | |
798 { | |
799 vinf[voice].vol = vol; | |
800 } | |
801 | |
802 | |
803 void VC2_VoiceSetFrequency(UBYTE voice, ULONG frq) | |
804 { | |
805 vinf[voice].frq = frq; | |
806 } | |
807 | |
808 | |
809 void VC2_VoiceSetPanning(UBYTE voice, ULONG pan) | |
810 { | |
811 vinf[voice].pan = pan; | |
812 } | |
813 | |
814 | |
815 void VC2_VoicePlay(UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags) | |
816 { | |
817 vinf[voice].flags = flags; | |
818 vinf[voice].handle = handle; | |
819 vinf[voice].start = start; | |
820 vinf[voice].size = size; | |
821 vinf[voice].reppos = reppos; | |
822 vinf[voice].repend = repend; | |
823 vinf[voice].kick = 1; | |
824 } | |
825 | |
826 | |
827 void VC2_VoiceStop(UBYTE voice) | |
828 { | |
829 vinf[voice].active = 0; | |
830 } | |
831 | |
832 | |
833 BOOL VC2_VoiceStopped(UBYTE voice) | |
834 { | |
835 return(vinf[voice].active==0); | |
836 } | |
837 | |
838 | |
839 void VC2_VoiceReleaseSustain(UBYTE voice) | |
840 { | |
841 | |
842 } | |
843 | |
844 | |
845 SLONG VC2_VoiceGetPosition(UBYTE voice) | |
846 { | |
847 return(vinf[voice].current>>FRACBITS); | |
848 } | |
849 | |
850 | |
851 /************************************************** | |
852 *************************************************** | |
853 *************************************************** | |
854 **************************************************/ | |
855 | |
856 | |
857 void VC2_SampleUnload(SWORD handle) | |
858 { | |
859 void *sampleadr = Samples[handle]; | |
860 | |
861 free(sampleadr); | |
862 Samples[handle] = NULL; | |
863 } | |
864 | |
865 | |
866 SWORD VC2_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) | |
867 { | |
868 SAMPLE *s = sload->sample; | |
869 int handle; | |
870 ULONG t, length,loopstart,loopend; | |
871 | |
872 if(type==MD_HARDWARE) return -1; | |
873 | |
874 // Find empty slot to put sample address in | |
875 for(handle=0; handle<MAXSAMPLEHANDLES; handle++) | |
876 if(Samples[handle]==NULL) break; | |
877 | |
878 if(handle==MAXSAMPLEHANDLES) | |
879 { _mm_errno = MMERR_OUT_OF_HANDLES; | |
880 return -1; | |
881 } | |
882 | |
883 length = s->length; | |
884 loopstart = s->loopstart; | |
885 loopend = s->loopend; | |
886 | |
887 SL_SampleSigned(sload); | |
888 | |
889 SL_Sample8to16(sload); | |
890 if((Samples[handle]=(SWORD *)malloc((length+16)<<1))==NULL) | |
891 { _mm_errno = MMERR_SAMPLE_TOO_BIG; | |
892 return -1; | |
893 } | |
894 // read sample into buffer. | |
895 SL_Load(Samples[handle],sload,length); | |
896 | |
897 // Unclick samples: | |
898 | |
899 if(s->flags & SF_LOOP) | |
900 { if(s->flags & SF_BIDI) | |
901 for(t=0; t<16; t++) Samples[handle][loopend+t] = Samples[handle][(loopend-t)-1]; | |
902 else | |
903 for(t=0; t<16; t++) Samples[handle][loopend+t] = Samples[handle][t+loopstart]; | |
904 } else | |
905 for(t=0; t<16; t++) Samples[handle][t+length] = 0; | |
906 | |
907 return handle; | |
908 } | |
909 | |
910 | |
911 ULONG VC2_SampleSpace(int type) | |
912 { | |
913 return vc_memory; | |
914 } | |
915 | |
916 | |
917 ULONG VC2_SampleLength(int type, SAMPLE *s) | |
918 { | |
919 return (s->length * ((s->flags & SF_16BITS) ? 2 : 1)) + 16; | |
920 } | |
921 | |
922 | |
923 /************************************************** | |
924 *************************************************** | |
925 *************************************************** | |
926 **************************************************/ | |
927 |