DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

mix.cpp (11159B)


      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 #include <math.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 
     28 #include "config.h"
     29 #include "common.h"
     30 #include "instrum.h"
     31 #include "playmidi.h"
     32 #include "output.h"
     33 #include "controls.h"
     34 #include "tables.h"
     35 #include "resample.h"
     36 #include "mix.h"
     37 
     38 /* Returns 1 if envelope runs out */
     39 int recompute_envelope(int v)
     40 {
     41 	int stage;
     42 
     43 	stage = voice[v].envelope_stage;
     44 
     45 	if (stage>5)
     46 	{
     47 		/* Envelope ran out. */
     48 		int tmp=(voice[v].status == VOICE_DIE); /* Already displayed as dead */
     49 		voice[v].status = VOICE_FREE;
     50 		if(!tmp)
     51 			ctl->note(v);
     52 		return 1;
     53 	}
     54 
     55 	if (voice[v].sample->modes & MODES_ENVELOPE)
     56 	{
     57 		if (voice[v].status==VOICE_ON || voice[v].status==VOICE_SUSTAINED)
     58 		{
     59 			if (stage>2)
     60 			{
     61 				/* Freeze envelope until note turns off. Trumpets want this. */
     62 				voice[v].envelope_increment=0;
     63 				return 0;
     64 			}
     65 		}
     66 	}
     67 	voice[v].envelope_stage=stage+1;
     68 
     69 	if (voice[v].envelope_volume==voice[v].sample->envelope_offset[stage])
     70 		return recompute_envelope(v);
     71 	voice[v].envelope_target=voice[v].sample->envelope_offset[stage];
     72 	voice[v].envelope_increment = voice[v].sample->envelope_rate[stage];
     73 	if (voice[v].envelope_target<voice[v].envelope_volume)
     74 		voice[v].envelope_increment = -voice[v].envelope_increment;
     75 	return 0;
     76 }
     77 
     78 void apply_envelope_to_amp(int v)
     79 {
     80 	float lamp=voice[v].left_amp, ramp;
     81 	 int32_t  la,ra;
     82 	if (voice[v].panned == PANNED_MYSTERY)
     83 	{
     84 		ramp=voice[v].right_amp;
     85 		if (voice[v].tremolo_phase_increment)
     86 		{
     87 			lamp *= voice[v].tremolo_volume;
     88 			ramp *= voice[v].tremolo_volume;
     89 		}
     90 		if (voice[v].sample->modes & MODES_ENVELOPE)
     91 		{
     92 			lamp *= (float)vol_table[voice[v].envelope_volume>>23];
     93 			ramp *= (float)vol_table[voice[v].envelope_volume>>23];
     94 		}
     95 
     96 		la = (int32_t)FSCALE(lamp,AMP_BITS);
     97 
     98 		if (la>MAX_AMP_VALUE)
     99 			la=MAX_AMP_VALUE;
    100 
    101 		ra = (int32_t)FSCALE(ramp,AMP_BITS);
    102 		if (ra>MAX_AMP_VALUE)
    103 			ra=MAX_AMP_VALUE;
    104 
    105 
    106 		voice[v].left_mix=FINAL_VOLUME(la);
    107 		voice[v].right_mix=FINAL_VOLUME(ra);
    108 	}
    109 	else
    110 	{
    111 		if (voice[v].tremolo_phase_increment)
    112 			lamp *= voice[v].tremolo_volume;
    113 		if (voice[v].sample->modes & MODES_ENVELOPE)
    114 			lamp *= (float)vol_table[voice[v].envelope_volume>>23];
    115 
    116 		la = (int32_t)FSCALE(lamp,AMP_BITS);
    117 
    118 		if (la>MAX_AMP_VALUE)
    119 			la=MAX_AMP_VALUE;
    120 
    121 		voice[v].left_mix=FINAL_VOLUME(la);
    122 	}
    123 }
    124 
    125 static int update_envelope(int v)
    126 {
    127 	voice[v].envelope_volume += voice[v].envelope_increment;
    128 	/* Why is there no ^^ operator?? */
    129 	if (((voice[v].envelope_increment < 0) &&
    130 		(voice[v].envelope_volume <= voice[v].envelope_target)) ||
    131 		((voice[v].envelope_increment > 0) &&
    132 		(voice[v].envelope_volume >= voice[v].envelope_target)))
    133 	{
    134 		voice[v].envelope_volume = voice[v].envelope_target;
    135 		if (recompute_envelope(v))
    136 			return 1;
    137 	}
    138 	return 0;
    139 }
    140 
    141 static void update_tremolo(int v)
    142 {
    143 	 int32_t depth=voice[v].sample->tremolo_depth<<7;
    144 
    145 	if (voice[v].tremolo_sweep)
    146 	{
    147 		/* Update sweep position */
    148 
    149 		voice[v].tremolo_sweep_position += voice[v].tremolo_sweep;
    150 		if (voice[v].tremolo_sweep_position>=(1<<SWEEP_SHIFT))
    151 			voice[v].tremolo_sweep=0; /* Swept to max amplitude */
    152 		else
    153 		{
    154 			/* Need to adjust depth */
    155 			depth *= voice[v].tremolo_sweep_position;
    156 			depth >>= SWEEP_SHIFT;
    157 		}
    158 	}
    159 
    160 	voice[v].tremolo_phase += voice[v].tremolo_phase_increment;
    161 
    162 	/* if (voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
    163 	voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT;  */
    164 
    165 	voice[v].tremolo_volume = (float) 
    166 		(1.0 - FSCALENEG((sine(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(int v)
    176 {
    177 	if (voice[v].envelope_increment && update_envelope(v))
    178 		return 1;
    179 
    180 	if (voice[v].tremolo_phase_increment)
    181 		update_tremolo(v);
    182 
    183 	apply_envelope_to_amp(v);
    184 	return 0;
    185 }
    186 
    187 #ifdef LOOKUP_HACK
    188 #  define MIXATION(a)	*lp++ += mixup[(a<<8) | (uint8)s];
    189 #else
    190 #  define MIXATION(a)	*lp++ += (a)*s;
    191 #endif
    192 
    193 static void mix_mystery_signal(sample_t *sp,  int32_t *lp, int v, int count)
    194 {
    195 	Voice *vp = voice + v;
    196 	final_volume_t 
    197 		left=vp->left_mix, 
    198 		right=vp->right_mix;
    199 	int cc;
    200 	sample_t s;
    201 
    202 	if (!(cc = vp->control_counter))
    203 	{
    204 		cc = control_ratio;
    205 		if (update_signal(v))
    206 			return;	/* Envelope ran out */
    207 		left = vp->left_mix;
    208 		right = vp->right_mix;
    209 	}
    210 
    211 	while (count)
    212 		if (cc < count)
    213 		{
    214 			count -= cc;
    215 			while (cc--)
    216 			{
    217 				s = *sp++;
    218 				MIXATION(left);
    219 				MIXATION(right);
    220 			}
    221 			cc = control_ratio;
    222 			if (update_signal(v))
    223 				return;	/* Envelope ran out */
    224 			left = vp->left_mix;
    225 			right = vp->right_mix;
    226 		}
    227 		else
    228 		{
    229 			vp->control_counter = cc - count;
    230 			while (count--)
    231 			{
    232 				s = *sp++;
    233 				MIXATION(left);
    234 				MIXATION(right);
    235 			}
    236 			return;
    237 		}
    238 }
    239 
    240 static void mix_center_signal(sample_t *sp,  int32_t *lp, int v, int count)
    241 {
    242 	Voice *vp = voice + v;
    243 	final_volume_t 
    244 		left=vp->left_mix;
    245 	int cc;
    246 	sample_t s;
    247 
    248 	if (!(cc = vp->control_counter))
    249 	{
    250 		cc = control_ratio;
    251 		if (update_signal(v))
    252 			return;	/* Envelope ran out */
    253 		left = vp->left_mix;
    254 	}
    255 
    256 	while (count)
    257 		if (cc < count)
    258 		{
    259 			count -= cc;
    260 			while (cc--)
    261 			{
    262 				s = *sp++;
    263 				MIXATION(left);
    264 				MIXATION(left);
    265 			}
    266 			cc = control_ratio;
    267 			if (update_signal(v))
    268 				return;	/* Envelope ran out */
    269 			left = vp->left_mix;
    270 		}
    271 		else
    272 		{
    273 			vp->control_counter = cc - count;
    274 			while (count--)
    275 			{
    276 				s = *sp++;
    277 				MIXATION(left);
    278 				MIXATION(left);
    279 			}
    280 			return;
    281 		}
    282 }
    283 
    284 static void mix_single_signal(sample_t *sp,  int32_t *lp, int v, int count)
    285 {
    286 	Voice *vp = voice + v;
    287 	final_volume_t 
    288 		left=vp->left_mix;
    289 	int cc;
    290 	sample_t s;
    291 
    292 	if (!(cc = vp->control_counter))
    293 	{
    294 		cc = control_ratio;
    295 		if (update_signal(v))
    296 			return;	/* Envelope ran out */
    297 		left = vp->left_mix;
    298 	}
    299 
    300 	while (count)
    301 		if (cc < count)
    302 		{
    303 			count -= cc;
    304 			while (cc--)
    305 			{
    306 				s = *sp++;
    307 				MIXATION(left);
    308 				lp++;
    309 			}
    310 			cc = control_ratio;
    311 			if (update_signal(v))
    312 				return;	/* Envelope ran out */
    313 			left = vp->left_mix;
    314 		}
    315 		else
    316 		{
    317 			vp->control_counter = cc - count;
    318 			while (count--)
    319 			{
    320 				s = *sp++;
    321 				MIXATION(left);
    322 				lp++;
    323 			}
    324 			return;
    325 		}
    326 }
    327 
    328 static void mix_mono_signal(sample_t *sp,  int32_t *lp, int v, int count)
    329 {
    330 	Voice *vp = 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 = control_ratio;
    339 		if (update_signal(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 = control_ratio;
    354 			if (update_signal(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(sample_t *sp,  int32_t *lp, int v, int count)
    371 {
    372 	final_volume_t 
    373 		left=voice[v].left_mix, 
    374 		right=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(sample_t *sp,  int32_t *lp, int v, int count)
    386 {
    387 	final_volume_t 
    388 		left=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(sample_t *sp,  int32_t *lp, int v, int count)
    400 {
    401 	final_volume_t 
    402 		left=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(sample_t *sp,  int32_t *lp, int v, int count)
    414 {
    415 	final_volume_t 
    416 		left=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(sample_t *sp,  int32_t *lp, int v,  int32_t c)
    428 {
    429 
    430 	/* should be final_volume_t, but uint8_t gives trouble. */
    431 	 int32_t 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=voice[v].left_mix;
    439 	li=-(left/c);
    440 	if (!li) li=-1;
    441 
    442 	/* I_Printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
    443 
    444 	if (!(play_mode->encoding & PE_MONO))
    445 	{
    446 		if (voice[v].panned==PANNED_MYSTERY)
    447 		{
    448 			right=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 (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 (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 (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( int32_t *buf, int v,  int32_t c)
    518 {
    519 	Voice *vp=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(v, &c);
    526 		ramp_out(sp, buf, v, c);
    527 		vp->status=VOICE_FREE;
    528 	}
    529 	else
    530 	{
    531 		sp=resample_voice(v, &c);
    532 		if (play_mode->encoding & PE_MONO)
    533 		{
    534 			/* Mono output. */
    535 			if (vp->envelope_increment || vp->tremolo_phase_increment)
    536 				mix_mono_signal(sp, buf, v, c);
    537 			else
    538 				mix_mono(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(sp, buf, v, c);
    546 				else
    547 					mix_mystery(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(sp, buf, v, c);
    553 				else
    554 					mix_center(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(sp, buf, v, c);
    564 				else 
    565 					mix_single(sp, buf, v, c);
    566 			}
    567 		}
    568 	}
    569 }