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