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