comparison decoders/timidity/mix.c @ 199:2d887640d300

Initial add.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 04 Jan 2002 06:49:49 +0000
parents
children
comparison
equal deleted inserted replaced
198:f9a752f41ab6 199:2d887640d300
1 /*
2
3 TiMidity -- Experimental MIDI to WAVE converter
4 Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
5
6 Suddenly, you realize that this program is free software; you get
7 an overwhelming urge to redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received another copy of the GNU General Public
18 License along with this program; if not, write to the Free
19 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 I bet they'll be amazed.
21
22 mix.c */
23
24 #if HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "SDL_sound.h"
33
34 #define __SDL_SOUND_INTERNAL__
35 #include "SDL_sound_internal.h"
36
37 #include "timidity.h"
38 #include "options.h"
39 #include "instrum.h"
40 #include "playmidi.h"
41 #include "output.h"
42 #include "tables.h"
43 #include "resample.h"
44 #include "mix.h"
45
46 /* Returns 1 if envelope runs out */
47 int recompute_envelope(MidiSong *song, int v)
48 {
49 int stage;
50
51 stage = song->voice[v].envelope_stage;
52
53 if (stage>5)
54 {
55 /* Envelope ran out. */
56 song->voice[v].status = VOICE_FREE;
57 return 1;
58 }
59
60 if (song->voice[v].sample->modes & MODES_ENVELOPE)
61 {
62 if (song->voice[v].status==VOICE_ON || song->voice[v].status==VOICE_SUSTAINED)
63 {
64 if (stage>2)
65 {
66 /* Freeze envelope until note turns off. Trumpets want this. */
67 song->voice[v].envelope_increment=0;
68 return 0;
69 }
70 }
71 }
72 song->voice[v].envelope_stage=stage+1;
73
74 if (song->voice[v].envelope_volume==song->voice[v].sample->envelope_offset[stage])
75 return recompute_envelope(song, v);
76 song->voice[v].envelope_target = song->voice[v].sample->envelope_offset[stage];
77 song->voice[v].envelope_increment = song->voice[v].sample->envelope_rate[stage];
78 if (song->voice[v].envelope_target < song->voice[v].envelope_volume)
79 song->voice[v].envelope_increment = -song->voice[v].envelope_increment;
80 return 0;
81 }
82
83 void apply_envelope_to_amp(MidiSong *song, int v)
84 {
85 float lamp = song->voice[v].left_amp, ramp;
86 Sint32 la,ra;
87 if (song->voice[v].panned == PANNED_MYSTERY)
88 {
89 ramp = song->voice[v].right_amp;
90 if (song->voice[v].tremolo_phase_increment)
91 {
92 lamp *= song->voice[v].tremolo_volume;
93 ramp *= song->voice[v].tremolo_volume;
94 }
95 if (song->voice[v].sample->modes & MODES_ENVELOPE)
96 {
97 lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
98 ramp *= (float)vol_table[song->voice[v].envelope_volume>>23];
99 }
100
101 la = (Sint32)FSCALE(lamp,AMP_BITS);
102
103 if (la>MAX_AMP_VALUE)
104 la=MAX_AMP_VALUE;
105
106 ra = (Sint32)FSCALE(ramp,AMP_BITS);
107 if (ra>MAX_AMP_VALUE)
108 ra=MAX_AMP_VALUE;
109
110 song->voice[v].left_mix = la;
111 song->voice[v].right_mix = ra;
112 }
113 else
114 {
115 if (song->voice[v].tremolo_phase_increment)
116 lamp *= song->voice[v].tremolo_volume;
117 if (song->voice[v].sample->modes & MODES_ENVELOPE)
118 lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
119
120 la = (Sint32)FSCALE(lamp,AMP_BITS);
121
122 if (la>MAX_AMP_VALUE)
123 la=MAX_AMP_VALUE;
124
125 song->voice[v].left_mix = la;
126 }
127 }
128
129 static int update_envelope(MidiSong *song, int v)
130 {
131 song->voice[v].envelope_volume += song->voice[v].envelope_increment;
132 /* Why is there no ^^ operator?? */
133 if (((song->voice[v].envelope_increment < 0) &&
134 (song->voice[v].envelope_volume <= song->voice[v].envelope_target)) ||
135 ((song->voice[v].envelope_increment > 0) &&
136 (song->voice[v].envelope_volume >= song->voice[v].envelope_target)))
137 {
138 song->voice[v].envelope_volume = song->voice[v].envelope_target;
139 if (recompute_envelope(song, v))
140 return 1;
141 }
142 return 0;
143 }
144
145 static void update_tremolo(MidiSong *song, int v)
146 {
147 Sint32 depth = song->voice[v].sample->tremolo_depth << 7;
148
149 if (song->voice[v].tremolo_sweep)
150 {
151 /* Update sweep position */
152
153 song->voice[v].tremolo_sweep_position += song->voice[v].tremolo_sweep;
154 if (song->voice[v].tremolo_sweep_position >= (1 << SWEEP_SHIFT))
155 song->voice[v].tremolo_sweep=0; /* Swept to max amplitude */
156 else
157 {
158 /* Need to adjust depth */
159 depth *= song->voice[v].tremolo_sweep_position;
160 depth >>= SWEEP_SHIFT;
161 }
162 }
163
164 song->voice[v].tremolo_phase += song->voice[v].tremolo_phase_increment;
165
166 /* if (song->voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
167 song->voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT; */
168
169 song->voice[v].tremolo_volume = (float)
170 (1.0 - FSCALENEG((sine(song->voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)
171 * depth * TREMOLO_AMPLITUDE_TUNING,
172 17));
173
174 /* I'm not sure about the +1.0 there -- it makes tremoloed voices'
175 volumes on average the lower the higher the tremolo amplitude. */
176 }
177
178 /* Returns 1 if the note died */
179 static int update_signal(MidiSong *song, int v)
180 {
181 if (song->voice[v].envelope_increment && update_envelope(song, v))
182 return 1;
183
184 if (song->voice[v].tremolo_phase_increment)
185 update_tremolo(song, v);
186
187 apply_envelope_to_amp(song, v);
188 return 0;
189 }
190
191 #define MIXATION(a) *lp++ += (a)*s;
192
193 static void mix_mystery_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
194 int count)
195 {
196 Voice *vp = song->voice + v;
197 final_volume_t
198 left=vp->left_mix,
199 right=vp->right_mix;
200 int cc;
201 sample_t s;
202
203 if (!(cc = vp->control_counter))
204 {
205 cc = song->control_ratio;
206 if (update_signal(song, v))
207 return; /* Envelope ran out */
208 left = vp->left_mix;
209 right = vp->right_mix;
210 }
211
212 while (count)
213 if (cc < count)
214 {
215 count -= cc;
216 while (cc--)
217 {
218 s = *sp++;
219 MIXATION(left);
220 MIXATION(right);
221 }
222 cc = song->control_ratio;
223 if (update_signal(song, v))
224 return; /* Envelope ran out */
225 left = vp->left_mix;
226 right = vp->right_mix;
227 }
228 else
229 {
230 vp->control_counter = cc - count;
231 while (count--)
232 {
233 s = *sp++;
234 MIXATION(left);
235 MIXATION(right);
236 }
237 return;
238 }
239 }
240
241 static void mix_center_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
242 int count)
243 {
244 Voice *vp = song->voice + v;
245 final_volume_t
246 left=vp->left_mix;
247 int cc;
248 sample_t s;
249
250 if (!(cc = vp->control_counter))
251 {
252 cc = song->control_ratio;
253 if (update_signal(song, v))
254 return; /* Envelope ran out */
255 left = vp->left_mix;
256 }
257
258 while (count)
259 if (cc < count)
260 {
261 count -= cc;
262 while (cc--)
263 {
264 s = *sp++;
265 MIXATION(left);
266 MIXATION(left);
267 }
268 cc = song->control_ratio;
269 if (update_signal(song, v))
270 return; /* Envelope ran out */
271 left = vp->left_mix;
272 }
273 else
274 {
275 vp->control_counter = cc - count;
276 while (count--)
277 {
278 s = *sp++;
279 MIXATION(left);
280 MIXATION(left);
281 }
282 return;
283 }
284 }
285
286 static void mix_single_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
287 int count)
288 {
289 Voice *vp = song->voice + v;
290 final_volume_t
291 left=vp->left_mix;
292 int cc;
293 sample_t s;
294
295 if (!(cc = vp->control_counter))
296 {
297 cc = song->control_ratio;
298 if (update_signal(song, v))
299 return; /* Envelope ran out */
300 left = vp->left_mix;
301 }
302
303 while (count)
304 if (cc < count)
305 {
306 count -= cc;
307 while (cc--)
308 {
309 s = *sp++;
310 MIXATION(left);
311 lp++;
312 }
313 cc = song->control_ratio;
314 if (update_signal(song, v))
315 return; /* Envelope ran out */
316 left = vp->left_mix;
317 }
318 else
319 {
320 vp->control_counter = cc - count;
321 while (count--)
322 {
323 s = *sp++;
324 MIXATION(left);
325 lp++;
326 }
327 return;
328 }
329 }
330
331 static void mix_mono_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
332 int count)
333 {
334 Voice *vp = song->voice + v;
335 final_volume_t
336 left=vp->left_mix;
337 int cc;
338 sample_t s;
339
340 if (!(cc = vp->control_counter))
341 {
342 cc = song->control_ratio;
343 if (update_signal(song, v))
344 return; /* Envelope ran out */
345 left = vp->left_mix;
346 }
347
348 while (count)
349 if (cc < count)
350 {
351 count -= cc;
352 while (cc--)
353 {
354 s = *sp++;
355 MIXATION(left);
356 }
357 cc = song->control_ratio;
358 if (update_signal(song, v))
359 return; /* Envelope ran out */
360 left = vp->left_mix;
361 }
362 else
363 {
364 vp->control_counter = cc - count;
365 while (count--)
366 {
367 s = *sp++;
368 MIXATION(left);
369 }
370 return;
371 }
372 }
373
374 static void mix_mystery(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
375 {
376 final_volume_t
377 left = song->voice[v].left_mix,
378 right = song->voice[v].right_mix;
379 sample_t s;
380
381 while (count--)
382 {
383 s = *sp++;
384 MIXATION(left);
385 MIXATION(right);
386 }
387 }
388
389 static void mix_center(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
390 {
391 final_volume_t
392 left = song->voice[v].left_mix;
393 sample_t s;
394
395 while (count--)
396 {
397 s = *sp++;
398 MIXATION(left);
399 MIXATION(left);
400 }
401 }
402
403 static void mix_single(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
404 {
405 final_volume_t
406 left = song->voice[v].left_mix;
407 sample_t s;
408
409 while (count--)
410 {
411 s = *sp++;
412 MIXATION(left);
413 lp++;
414 }
415 }
416
417 static void mix_mono(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
418 {
419 final_volume_t
420 left = song->voice[v].left_mix;
421 sample_t s;
422
423 while (count--)
424 {
425 s = *sp++;
426 MIXATION(left);
427 }
428 }
429
430 /* Ramp a note out in c samples */
431 static void ramp_out(MidiSong *song, sample_t *sp, Sint32 *lp, int v, Sint32 c)
432 {
433
434 /* should be final_volume_t, but Uint8 gives trouble. */
435 Sint32 left, right, li, ri;
436
437 sample_t s=0; /* silly warning about uninitialized s */
438
439 /* Fix by James Caldwell */
440 if ( c == 0 ) c = 1;
441
442 left=song->voice[v].left_mix;
443 li=-(left/c);
444 if (!li) li=-1;
445
446 /* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
447
448 if (!(song->encoding & PE_MONO))
449 {
450 if (song->voice[v].panned==PANNED_MYSTERY)
451 {
452 right=song->voice[v].right_mix;
453 ri=-(right/c);
454 while (c--)
455 {
456 left += li;
457 if (left<0)
458 left=0;
459 right += ri;
460 if (right<0)
461 right=0;
462 s=*sp++;
463 MIXATION(left);
464 MIXATION(right);
465 }
466 }
467 else if (song->voice[v].panned==PANNED_CENTER)
468 {
469 while (c--)
470 {
471 left += li;
472 if (left<0)
473 return;
474 s=*sp++;
475 MIXATION(left);
476 MIXATION(left);
477 }
478 }
479 else if (song->voice[v].panned==PANNED_LEFT)
480 {
481 while (c--)
482 {
483 left += li;
484 if (left<0)
485 return;
486 s=*sp++;
487 MIXATION(left);
488 lp++;
489 }
490 }
491 else if (song->voice[v].panned==PANNED_RIGHT)
492 {
493 while (c--)
494 {
495 left += li;
496 if (left<0)
497 return;
498 s=*sp++;
499 lp++;
500 MIXATION(left);
501 }
502 }
503 }
504 else
505 {
506 /* Mono output. */
507 while (c--)
508 {
509 left += li;
510 if (left<0)
511 return;
512 s=*sp++;
513 MIXATION(left);
514 }
515 }
516 }
517
518
519 /**************** interface function ******************/
520
521 void mix_voice(MidiSong *song, Sint32 *buf, int v, Sint32 c)
522 {
523 Voice *vp = song->voice + v;
524 sample_t *sp;
525 if (vp->status==VOICE_DIE)
526 {
527 if (c>=MAX_DIE_TIME)
528 c=MAX_DIE_TIME;
529 sp=resample_voice(song, v, &c);
530 ramp_out(song, sp, buf, v, c);
531 vp->status=VOICE_FREE;
532 }
533 else
534 {
535 sp=resample_voice(song, v, &c);
536 if (song->encoding & PE_MONO)
537 {
538 /* Mono output. */
539 if (vp->envelope_increment || vp->tremolo_phase_increment)
540 mix_mono_signal(song, sp, buf, v, c);
541 else
542 mix_mono(song, sp, buf, v, c);
543 }
544 else
545 {
546 if (vp->panned == PANNED_MYSTERY)
547 {
548 if (vp->envelope_increment || vp->tremolo_phase_increment)
549 mix_mystery_signal(song, sp, buf, v, c);
550 else
551 mix_mystery(song, sp, buf, v, c);
552 }
553 else if (vp->panned == PANNED_CENTER)
554 {
555 if (vp->envelope_increment || vp->tremolo_phase_increment)
556 mix_center_signal(song, sp, buf, v, c);
557 else
558 mix_center(song, sp, buf, v, c);
559 }
560 else
561 {
562 /* It's either full left or full right. In either case,
563 every other sample is 0. Just get the offset right: */
564 if (vp->panned == PANNED_RIGHT) buf++;
565
566 if (vp->envelope_increment || vp->tremolo_phase_increment)
567 mix_single_signal(song, sp, buf, v, c);
568 else
569 mix_single(song, sp, buf, v, c);
570 }
571 }
572 }
573 }