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