timidity/mix.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 17 Oct 2017 21:54:04 -0700
changeset 782 e7d3a8f73e88
parent 518 8bc9b5fd2aae
child 807 974d914af9e4
permissions -rw-r--r--
Merged over timidity from SDL_sound
This has changes to make it safe to load MIDI files as sound chunks and adds the ability to seek in MIDI files
Also cherry picked some patches from the original SDL_mixer timidity to fix buffer overruns and so forth.
     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     return recompute_envelope(song, v);
    60   song->voice[v].envelope_target = song->voice[v].sample->envelope_offset[stage];
    61   song->voice[v].envelope_increment = song->voice[v].sample->envelope_rate[stage];
    62   if (song->voice[v].envelope_target < song->voice[v].envelope_volume)
    63     song->voice[v].envelope_increment = -song->voice[v].envelope_increment;
    64   return 0;
    65 }
    66 
    67 void apply_envelope_to_amp(MidiSong *song, int v)
    68 {
    69   float lamp = song->voice[v].left_amp, ramp;
    70   Sint32 la,ra;
    71   if (song->voice[v].panned == PANNED_MYSTERY)
    72     {
    73       ramp = song->voice[v].right_amp;
    74       if (song->voice[v].tremolo_phase_increment)
    75 	{
    76 	  lamp *= song->voice[v].tremolo_volume;
    77 	  ramp *= song->voice[v].tremolo_volume;
    78 	}
    79       if (song->voice[v].sample->modes & MODES_ENVELOPE)
    80 	{
    81 	  lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
    82 	  ramp *= (float)vol_table[song->voice[v].envelope_volume>>23];
    83 	}
    84 
    85       la = (Sint32)FSCALE(lamp,AMP_BITS);
    86       
    87       if (la>MAX_AMP_VALUE)
    88 	la=MAX_AMP_VALUE;
    89 
    90       ra = (Sint32)FSCALE(ramp,AMP_BITS);
    91       if (ra>MAX_AMP_VALUE)
    92 	ra=MAX_AMP_VALUE;
    93       
    94       song->voice[v].left_mix = la;
    95       song->voice[v].right_mix = ra;
    96     }
    97   else
    98     {
    99       if (song->voice[v].tremolo_phase_increment)
   100 	lamp *= song->voice[v].tremolo_volume;
   101       if (song->voice[v].sample->modes & MODES_ENVELOPE)
   102 	lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
   103 
   104       la = (Sint32)FSCALE(lamp,AMP_BITS);
   105 
   106       if (la>MAX_AMP_VALUE)
   107 	la=MAX_AMP_VALUE;
   108 
   109       song->voice[v].left_mix = la;
   110     }
   111 }
   112 
   113 static int update_envelope(MidiSong *song, int v)
   114 {
   115   song->voice[v].envelope_volume += song->voice[v].envelope_increment;
   116   /* Why is there no ^^ operator?? */
   117   if (((song->voice[v].envelope_increment < 0) &&
   118        (song->voice[v].envelope_volume <= song->voice[v].envelope_target)) ||
   119       ((song->voice[v].envelope_increment > 0) &&
   120 	   (song->voice[v].envelope_volume >= song->voice[v].envelope_target)))
   121     {
   122       song->voice[v].envelope_volume = song->voice[v].envelope_target;
   123       if (recompute_envelope(song, v))
   124 	return 1;
   125     }
   126   return 0;
   127 }
   128 
   129 static void update_tremolo(MidiSong *song, int v)
   130 {
   131   Sint32 depth = song->voice[v].sample->tremolo_depth << 7;
   132 
   133   if (song->voice[v].tremolo_sweep)
   134     {
   135       /* Update sweep position */
   136 
   137       song->voice[v].tremolo_sweep_position += song->voice[v].tremolo_sweep;
   138       if (song->voice[v].tremolo_sweep_position >= (1 << SWEEP_SHIFT))
   139 	song->voice[v].tremolo_sweep=0; /* Swept to max amplitude */
   140       else
   141 	{
   142 	  /* Need to adjust depth */
   143 	  depth *= song->voice[v].tremolo_sweep_position;
   144 	  depth >>= SWEEP_SHIFT;
   145 	}
   146     }
   147 
   148   song->voice[v].tremolo_phase += song->voice[v].tremolo_phase_increment;
   149 
   150   /* if (song->voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
   151      song->voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT;  */
   152 
   153   song->voice[v].tremolo_volume = (float) 
   154     (1.0 - FSCALENEG((sine(song->voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)
   155 		    * depth * TREMOLO_AMPLITUDE_TUNING,
   156 		    17));
   157 
   158   /* I'm not sure about the +1.0 there -- it makes tremoloed voices'
   159      volumes on average the lower the higher the tremolo amplitude. */
   160 }
   161 
   162 /* Returns 1 if the note died */
   163 static int update_signal(MidiSong *song, int v)
   164 {
   165   if (song->voice[v].envelope_increment && update_envelope(song, v))
   166     return 1;
   167 
   168   if (song->voice[v].tremolo_phase_increment)
   169     update_tremolo(song, v);
   170 
   171   apply_envelope_to_amp(song, v);
   172   return 0;
   173 }
   174 
   175 #define MIXATION(a)	*lp++ += (a)*s;
   176 
   177 static void mix_mystery_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
   178 			       int count)
   179 {
   180   Voice *vp = song->voice + v;
   181   final_volume_t 
   182     left=vp->left_mix, 
   183     right=vp->right_mix;
   184   int cc;
   185   sample_t s;
   186 
   187   if (!(cc = vp->control_counter))
   188     {
   189       cc = song->control_ratio;
   190       if (update_signal(song, v))
   191 	return;	/* Envelope ran out */
   192       left = vp->left_mix;
   193       right = vp->right_mix;
   194     }
   195   
   196   while (count)
   197     if (cc < count)
   198       {
   199 	count -= cc;
   200 	while (cc--)
   201 	  {
   202 	    s = *sp++;
   203 	    MIXATION(left);
   204 	    MIXATION(right);
   205 	  }
   206 	cc = song->control_ratio;
   207 	if (update_signal(song, v))
   208 	  return;	/* Envelope ran out */
   209 	left = vp->left_mix;
   210 	right = vp->right_mix;
   211       }
   212     else
   213       {
   214 	vp->control_counter = cc - count;
   215 	while (count--)
   216 	  {
   217 	    s = *sp++;
   218 	    MIXATION(left);
   219 	    MIXATION(right);
   220 	  }
   221 	return;
   222       }
   223 }
   224 
   225 static void mix_center_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
   226 			      int count)
   227 {
   228   Voice *vp = song->voice + v;
   229   final_volume_t 
   230     left=vp->left_mix;
   231   int cc;
   232   sample_t s;
   233 
   234   if (!(cc = vp->control_counter))
   235     {
   236       cc = song->control_ratio;
   237       if (update_signal(song, v))
   238 	return;	/* Envelope ran out */
   239       left = vp->left_mix;
   240     }
   241   
   242   while (count)
   243     if (cc < count)
   244       {
   245 	count -= cc;
   246 	while (cc--)
   247 	  {
   248 	    s = *sp++;
   249 	    MIXATION(left);
   250 	    MIXATION(left);
   251 	  }
   252 	cc = song->control_ratio;
   253 	if (update_signal(song, v))
   254 	  return;	/* Envelope ran out */
   255 	left = vp->left_mix;
   256       }
   257     else
   258       {
   259 	vp->control_counter = cc - count;
   260 	while (count--)
   261 	  {
   262 	    s = *sp++;
   263 	    MIXATION(left);
   264 	    MIXATION(left);
   265 	  }
   266 	return;
   267       }
   268 }
   269 
   270 static void mix_single_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
   271 			      int count)
   272 {
   273   Voice *vp = song->voice + v;
   274   final_volume_t 
   275     left=vp->left_mix;
   276   int cc;
   277   sample_t s;
   278   
   279   if (!(cc = vp->control_counter))
   280     {
   281       cc = song->control_ratio;
   282       if (update_signal(song, v))
   283 	return;	/* Envelope ran out */
   284       left = vp->left_mix;
   285     }
   286   
   287   while (count)
   288     if (cc < count)
   289       {
   290 	count -= cc;
   291 	while (cc--)
   292 	  {
   293 	    s = *sp++;
   294 	    MIXATION(left);
   295 	    lp++;
   296 	  }
   297 	cc = song->control_ratio;
   298 	if (update_signal(song, v))
   299 	  return;	/* Envelope ran out */
   300 	left = vp->left_mix;
   301       }
   302     else
   303       {
   304 	vp->control_counter = cc - count;
   305 	while (count--)
   306 	  {
   307 	    s = *sp++;
   308 	    MIXATION(left);
   309 	    lp++;
   310 	  }
   311 	return;
   312       }
   313 }
   314 
   315 static void mix_mono_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
   316 			    int count)
   317 {
   318   Voice *vp = song->voice + v;
   319   final_volume_t 
   320     left=vp->left_mix;
   321   int cc;
   322   sample_t s;
   323   
   324   if (!(cc = vp->control_counter))
   325     {
   326       cc = song->control_ratio;
   327       if (update_signal(song, v))
   328 	return;	/* Envelope ran out */
   329       left = vp->left_mix;
   330     }
   331   
   332   while (count)
   333     if (cc < count)
   334       {
   335 	count -= cc;
   336 	while (cc--)
   337 	  {
   338 	    s = *sp++;
   339 	    MIXATION(left);
   340 	  }
   341 	cc = song->control_ratio;
   342 	if (update_signal(song, v))
   343 	  return;	/* Envelope ran out */
   344 	left = vp->left_mix;
   345       }
   346     else
   347       {
   348 	vp->control_counter = cc - count;
   349 	while (count--)
   350 	  {
   351 	    s = *sp++;
   352 	    MIXATION(left);
   353 	  }
   354 	return;
   355       }
   356 }
   357 
   358 static void mix_mystery(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
   359 {
   360   final_volume_t 
   361     left = song->voice[v].left_mix, 
   362     right = song->voice[v].right_mix;
   363   sample_t s;
   364   
   365   while (count--)
   366     {
   367       s = *sp++;
   368       MIXATION(left);
   369       MIXATION(right);
   370     }
   371 }
   372 
   373 static void mix_center(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
   374 {
   375   final_volume_t 
   376     left = song->voice[v].left_mix;
   377   sample_t s;
   378   
   379   while (count--)
   380     {
   381       s = *sp++;
   382       MIXATION(left);
   383       MIXATION(left);
   384     }
   385 }
   386 
   387 static void mix_single(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
   388 {
   389   final_volume_t 
   390     left = song->voice[v].left_mix;
   391   sample_t s;
   392   
   393   while (count--)
   394     {
   395       s = *sp++;
   396       MIXATION(left);
   397       lp++;
   398     }
   399 }
   400 
   401 static void mix_mono(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
   402 {
   403   final_volume_t 
   404     left = song->voice[v].left_mix;
   405   sample_t s;
   406   
   407   while (count--)
   408     {
   409       s = *sp++;
   410       MIXATION(left);
   411     }
   412 }
   413 
   414 /* Ramp a note out in c samples */
   415 static void ramp_out(MidiSong *song, sample_t *sp, Sint32 *lp, int v, Sint32 c)
   416 {
   417 
   418   /* should be final_volume_t, but Uint8 gives trouble. */
   419   Sint32 left, right, li, ri;
   420 
   421   sample_t s=0; /* silly warning about uninitialized s */
   422 
   423   /* Fix by James Caldwell */
   424   if ( c == 0 ) c = 1;
   425   
   426   left=song->voice[v].left_mix;
   427   li=-(left/c);
   428   if (!li) li=-1;
   429 
   430   /* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
   431 
   432   if (!(song->encoding & PE_MONO))
   433     {
   434       if (song->voice[v].panned==PANNED_MYSTERY)
   435 	{
   436 	  right=song->voice[v].right_mix;
   437 	  ri=-(right/c);
   438 	  while (c--)
   439 	    {
   440 	      left += li;
   441 	      if (left<0)
   442 		left=0;
   443 	      right += ri;
   444 	      if (right<0)
   445 		right=0;
   446 	      s=*sp++;
   447 	      MIXATION(left);
   448 	      MIXATION(right);
   449 	    }
   450 	}
   451       else if (song->voice[v].panned==PANNED_CENTER)
   452 	{
   453 	  while (c--)
   454 	    {
   455 	      left += li;
   456 	      if (left<0)
   457 		return;
   458 	      s=*sp++;	
   459 	      MIXATION(left);
   460 	      MIXATION(left);
   461 	    }
   462 	}
   463       else if (song->voice[v].panned==PANNED_LEFT)
   464 	{
   465 	  while (c--)
   466 	    {
   467 	      left += li;
   468 	      if (left<0)
   469 		return;
   470 	      s=*sp++;
   471 	      MIXATION(left);
   472 	      lp++;
   473 	    }
   474 	}
   475       else if (song->voice[v].panned==PANNED_RIGHT)
   476 	{
   477 	  while (c--)
   478 	    {
   479 	      left += li;
   480 	      if (left<0)
   481 		return;
   482 	      s=*sp++;
   483 	      lp++;
   484 	      MIXATION(left);
   485 	    }
   486 	}
   487     }
   488   else
   489     {
   490       /* Mono output.  */
   491       while (c--)
   492 	{
   493 	  left += li;
   494 	  if (left<0)
   495 	    return;
   496 	  s=*sp++;
   497 	  MIXATION(left);
   498 	}
   499     }
   500 }
   501 
   502 
   503 /**************** interface function ******************/
   504 
   505 void mix_voice(MidiSong *song, Sint32 *buf, int v, Sint32 c)
   506 {
   507   Voice *vp = song->voice + v;
   508   sample_t *sp;
   509   if (vp->status==VOICE_DIE)
   510     {
   511       if (c>=MAX_DIE_TIME)
   512 	c=MAX_DIE_TIME;
   513       sp=resample_voice(song, v, &c);
   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 }