Mercurial > audlegacy-plugins
comparison src/Input/timidity/libtimidity/mix.c @ 0:13389e613d67 trunk
[svn] - initial import of audacious-plugins tree (lots to do)
| author | nenolod |
|---|---|
| date | Mon, 18 Sep 2006 01:11:49 -0700 |
| parents | |
| children | 088092a52fea |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:13389e613d67 |
|---|---|
| 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 "libaudacious/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 } |
