timidity_mix.cpp

Go to the documentation of this file.
00001 /*
00002 
00003     TiMidity -- Experimental MIDI to WAVE converter
00004     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
00005 
00006     Suddenly, you realize that this program is free software; you get
00007     an overwhelming urge to redistribute it and/or modify it under the
00008     terms of the GNU General Public License as published by the Free
00009     Software Foundation; either version 2 of the License, or (at your
00010     option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received another copy of the GNU General Public
00018     License along with this program; if not, write to the Free
00019     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020     I bet they'll be amazed.
00021 
00022     mix.c */
00023 
00024 #include "pent_include.h"
00025 
00026 #ifdef USE_TIMIDITY_MIDI
00027 
00028 #include <cmath>
00029 #include <cstdio>
00030 #include <cstdlib>
00031 
00032 #include "timidity.h"
00033 #include "timidity_common.h"
00034 #include "timidity_instrum.h"
00035 #include "timidity_playmidi.h"
00036 #include "timidity_output.h"
00037 #include "timidity_controls.h"
00038 #include "timidity_tables.h"
00039 #include "timidity_resample.h"
00040 #include "timidity_mix.h"
00041 
00042 #ifdef NS_TIMIDITY
00043 namespace NS_TIMIDITY {
00044 #endif
00045 
00046 /* Returns 1 if envelope runs out */
00047 int recompute_envelope(int v)
00048 {
00049   int stage;
00050 
00051   stage = voice[v].envelope_stage;
00052 
00053   if (stage>5)
00054     {
00055       /* Envelope ran out. */
00056       int tmp=(voice[v].status == VOICE_DIE); /* Already displayed as dead */
00057       voice[v].status = VOICE_FREE;
00058       if(!tmp)
00059         ctl->note(v);
00060       return 1;
00061     }
00062 
00063   if (voice[v].sample->modes & MODES_ENVELOPE)
00064     {
00065       if (voice[v].status==VOICE_ON || voice[v].status==VOICE_SUSTAINED)
00066         {
00067           if (stage>2)
00068             {
00069               /* Freeze envelope until note turns off. Trumpets want this. */
00070               voice[v].envelope_increment=0;
00071               return 0;
00072             }
00073         }
00074     }
00075   voice[v].envelope_stage=stage+1;
00076 
00077   if (voice[v].envelope_volume==voice[v].sample->envelope_offset[stage])
00078     return recompute_envelope(v);
00079   voice[v].envelope_target=voice[v].sample->envelope_offset[stage];
00080   voice[v].envelope_increment = voice[v].sample->envelope_rate[stage];
00081   if (voice[v].envelope_target<voice[v].envelope_volume)
00082     voice[v].envelope_increment = -voice[v].envelope_increment;
00083   return 0;
00084 }
00085 
00086 void apply_envelope_to_amp(int v)
00087 {
00088   float lamp=voice[v].left_amp, ramp;
00089   sint32 la,ra;
00090   if (voice[v].panned == PANNED_MYSTERY)
00091     {
00092       ramp=voice[v].right_amp;
00093       if (voice[v].tremolo_phase_increment)
00094         {
00095           lamp *= voice[v].tremolo_volume;
00096           ramp *= voice[v].tremolo_volume;
00097         }
00098       if (voice[v].sample->modes & MODES_ENVELOPE)
00099         {
00100           lamp *= (float)vol_table[voice[v].envelope_volume>>23];
00101           ramp *= (float)vol_table[voice[v].envelope_volume>>23];
00102         }
00103 
00104       la = (sint32)FSCALE(lamp,AMP_BITS);
00105       
00106       if (la>MAX_AMP_VALUE)
00107         la=MAX_AMP_VALUE;
00108 
00109       ra = (sint32)FSCALE(ramp,AMP_BITS);
00110       if (ra>MAX_AMP_VALUE)
00111         ra=MAX_AMP_VALUE;
00112 
00113       
00114       voice[v].left_mix=FINAL_VOLUME(la);
00115       voice[v].right_mix=FINAL_VOLUME(ra);
00116     }
00117   else
00118     {
00119       if (voice[v].tremolo_phase_increment)
00120         lamp *= voice[v].tremolo_volume;
00121       if (voice[v].sample->modes & MODES_ENVELOPE)
00122         lamp *= (float)vol_table[voice[v].envelope_volume>>23];
00123 
00124       la = (sint32)FSCALE(lamp,AMP_BITS);
00125 
00126       if (la>MAX_AMP_VALUE)
00127         la=MAX_AMP_VALUE;
00128 
00129       voice[v].left_mix=FINAL_VOLUME(la);
00130     }
00131 }
00132 
00133 static int update_envelope(int v)
00134 {
00135   voice[v].envelope_volume += voice[v].envelope_increment;
00136   /* Why is there no ^^ operator?? */
00137   if (((voice[v].envelope_increment < 0) &&
00138        (voice[v].envelope_volume <= voice[v].envelope_target)) ||
00139       ((voice[v].envelope_increment > 0) &&
00140            (voice[v].envelope_volume >= voice[v].envelope_target)))
00141     {
00142       voice[v].envelope_volume = voice[v].envelope_target;
00143       if (recompute_envelope(v))
00144         return 1;
00145     }
00146   return 0;
00147 }
00148 
00149 static void update_tremolo(int v)
00150 {
00151   sint32 depth=voice[v].sample->tremolo_depth<<7;
00152 
00153   if (voice[v].tremolo_sweep)
00154     {
00155       /* Update sweep position */
00156 
00157       voice[v].tremolo_sweep_position += voice[v].tremolo_sweep;
00158       if (voice[v].tremolo_sweep_position>=(1<<SWEEP_SHIFT))
00159         voice[v].tremolo_sweep=0; /* Swept to max amplitude */
00160       else
00161         {
00162           /* Need to adjust depth */
00163           depth *= voice[v].tremolo_sweep_position;
00164           depth >>= SWEEP_SHIFT;
00165         }
00166     }
00167 
00168   voice[v].tremolo_phase += voice[v].tremolo_phase_increment;
00169 
00170   /* if (voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
00171      voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT;  */
00172 
00173   voice[v].tremolo_volume = (float) 
00174     (1.0 - FSCALENEG((sine(voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)
00175                     * depth * TREMOLO_AMPLITUDE_TUNING,
00176                     17));
00177 
00178   /* I'm not sure about the +1.0 there -- it makes tremoloed voices'
00179      volumes on average the lower the higher the tremolo amplitude. */
00180 }
00181 
00182 /* Returns 1 if the note died */
00183 static int update_signal(int v)
00184 {
00185   if (voice[v].envelope_increment && update_envelope(v))
00186     return 1;
00187 
00188   if (voice[v].tremolo_phase_increment)
00189     update_tremolo(v);
00190 
00191   apply_envelope_to_amp(v);
00192   return 0;
00193 }
00194 
00195 #ifdef LOOKUP_HACK
00196 #  define MIXATION(a)   *lp++ += mixup[(a<<8) | (uint8)s];
00197 #else
00198 #  define MIXATION(a)   *lp++ += (a)*s;
00199 #endif
00200 
00201 static void mix_mystery_signal(sample_t *sp, sint32 *lp, int v, int count)
00202 {
00203   Voice *vp = voice + v;
00204   final_volume_t 
00205     left=vp->left_mix, 
00206     right=vp->right_mix;
00207   int cc;
00208   sample_t s;
00209 
00210   if (!(cc = vp->control_counter))
00211     {
00212       cc = control_ratio;
00213       if (update_signal(v))
00214         return; /* Envelope ran out */
00215       left = vp->left_mix;
00216       right = vp->right_mix;
00217     }
00218   
00219   while (count)
00220     if (cc < count)
00221       {
00222         count -= cc;
00223         while (cc--)
00224           {
00225             s = *sp++;
00226             MIXATION(left);
00227             MIXATION(right);
00228           }
00229         cc = control_ratio;
00230         if (update_signal(v))
00231           return;       /* Envelope ran out */
00232         left = vp->left_mix;
00233         right = vp->right_mix;
00234       }
00235     else
00236       {
00237         vp->control_counter = cc - count;
00238         while (count--)
00239           {
00240             s = *sp++;
00241             MIXATION(left);
00242             MIXATION(right);
00243           }
00244         return;
00245       }
00246 }
00247 
00248 static void mix_center_signal(sample_t *sp, sint32 *lp, int v, int count)
00249 {
00250   Voice *vp = voice + v;
00251   final_volume_t 
00252     left=vp->left_mix;
00253   int cc;
00254   sample_t s;
00255 
00256   if (!(cc = vp->control_counter))
00257     {
00258       cc = control_ratio;
00259       if (update_signal(v))
00260         return; /* Envelope ran out */
00261       left = vp->left_mix;
00262     }
00263   
00264   while (count)
00265     if (cc < count)
00266       {
00267         count -= cc;
00268         while (cc--)
00269           {
00270             s = *sp++;
00271             MIXATION(left);
00272             MIXATION(left);
00273           }
00274         cc = control_ratio;
00275         if (update_signal(v))
00276           return;       /* Envelope ran out */
00277         left = vp->left_mix;
00278       }
00279     else
00280       {
00281         vp->control_counter = cc - count;
00282         while (count--)
00283           {
00284             s = *sp++;
00285             MIXATION(left);
00286             MIXATION(left);
00287           }
00288         return;
00289       }
00290 }
00291 
00292 static void mix_single_signal(sample_t *sp, sint32 *lp, int v, int count)
00293 {
00294   Voice *vp = voice + v;
00295   final_volume_t 
00296     left=vp->left_mix;
00297   int cc;
00298   sample_t s;
00299   
00300   if (!(cc = vp->control_counter))
00301     {
00302       cc = control_ratio;
00303       if (update_signal(v))
00304         return; /* Envelope ran out */
00305       left = vp->left_mix;
00306     }
00307   
00308   while (count)
00309     if (cc < count)
00310       {
00311         count -= cc;
00312         while (cc--)
00313           {
00314             s = *sp++;
00315             MIXATION(left);
00316             lp++;
00317           }
00318         cc = control_ratio;
00319         if (update_signal(v))
00320           return;       /* Envelope ran out */
00321         left = vp->left_mix;
00322       }
00323     else
00324       {
00325         vp->control_counter = cc - count;
00326         while (count--)
00327           {
00328             s = *sp++;
00329             MIXATION(left);
00330             lp++;
00331           }
00332         return;
00333       }
00334 }
00335 
00336 static void mix_mono_signal(sample_t *sp, sint32 *lp, int v, int count)
00337 {
00338   Voice *vp = voice + v;
00339   final_volume_t 
00340     left=vp->left_mix;
00341   int cc;
00342   sample_t s;
00343   
00344   if (!(cc = vp->control_counter))
00345     {
00346       cc = control_ratio;
00347       if (update_signal(v))
00348         return; /* Envelope ran out */
00349       left = vp->left_mix;
00350     }
00351   
00352   while (count)
00353     if (cc < count)
00354       {
00355         count -= cc;
00356         while (cc--)
00357           {
00358             s = *sp++;
00359             MIXATION(left);
00360           }
00361         cc = control_ratio;
00362         if (update_signal(v))
00363           return;       /* Envelope ran out */
00364         left = vp->left_mix;
00365       }
00366     else
00367       {
00368         vp->control_counter = cc - count;
00369         while (count--)
00370           {
00371             s = *sp++;
00372             MIXATION(left);
00373           }
00374         return;
00375       }
00376 }
00377 
00378 static void mix_mystery(sample_t *sp, sint32 *lp, int v, int count)
00379 {
00380   final_volume_t 
00381     left=voice[v].left_mix, 
00382     right=voice[v].right_mix;
00383   sample_t s;
00384   
00385   while (count--)
00386     {
00387       s = *sp++;
00388       MIXATION(left);
00389       MIXATION(right);
00390     }
00391 }
00392 
00393 static void mix_center(sample_t *sp, sint32 *lp, int v, int count)
00394 {
00395   final_volume_t 
00396     left=voice[v].left_mix;
00397   sample_t s;
00398   
00399   while (count--)
00400     {
00401       s = *sp++;
00402       MIXATION(left);
00403       MIXATION(left);
00404     }
00405 }
00406 
00407 static void mix_single(sample_t *sp, sint32 *lp, int v, int count)
00408 {
00409   final_volume_t 
00410     left=voice[v].left_mix;
00411   sample_t s;
00412   
00413   while (count--)
00414     {
00415       s = *sp++;
00416       MIXATION(left);
00417       lp++;
00418     }
00419 }
00420 
00421 static void mix_mono(sample_t *sp, sint32 *lp, int v, int count)
00422 {
00423   final_volume_t 
00424     left=voice[v].left_mix;
00425   sample_t s;
00426   
00427   while (count--)
00428     {
00429       s = *sp++;
00430       MIXATION(left);
00431     }
00432 }
00433 
00434 /* Ramp a note out in c samples */
00435 static void ramp_out(sample_t *sp, sint32 *lp, int v, sint32 c)
00436 {
00437 
00438   /* should be final_volume_t, but uint8 gives trouble. */
00439   sint32 left, right, li, ri;
00440 
00441   sample_t s=0; /* silly warning about uninitialized s */
00442 
00443   /* Fix by James Caldwell */
00444   if ( c == 0 ) c = 1;
00445 
00446   left=voice[v].left_mix;
00447   li=-(left/c);
00448   if (!li) li=-1;
00449 
00450   /* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
00451 
00452   if (!(play_mode->encoding & PE_MONO))
00453     {
00454       if (voice[v].panned==PANNED_MYSTERY)
00455         {
00456           right=voice[v].right_mix;
00457           ri=-(right/c);
00458           while (c--)
00459             {
00460               left += li;
00461               if (left<0)
00462                 left=0;
00463               right += ri;
00464               if (right<0)
00465                 right=0;
00466               s=*sp++;
00467               MIXATION(left);
00468               MIXATION(right);
00469             }
00470         }
00471       else if (voice[v].panned==PANNED_CENTER)
00472         {
00473           while (c--)
00474             {
00475               left += li;
00476               if (left<0)
00477                 return;
00478               s=*sp++;  
00479               MIXATION(left);
00480               MIXATION(left);
00481             }
00482         }
00483       else if (voice[v].panned==PANNED_LEFT)
00484         {
00485           while (c--)
00486             {
00487               left += li;
00488               if (left<0)
00489                 return;
00490               s=*sp++;
00491               MIXATION(left);
00492               lp++;
00493             }
00494         }
00495       else if (voice[v].panned==PANNED_RIGHT)
00496         {
00497           while (c--)
00498             {
00499               left += li;
00500               if (left<0)
00501                 return;
00502               s=*sp++;
00503               lp++;
00504               MIXATION(left);
00505             }
00506         }
00507     }
00508   else
00509     {
00510       /* Mono output.  */
00511       while (c--)
00512         {
00513           left += li;
00514           if (left<0)
00515             return;
00516           s=*sp++;
00517           MIXATION(left);
00518         }
00519     }
00520 }
00521 
00522 
00523 /**************** interface function ******************/
00524 
00525 void mix_voice(sint32 *buf, int v, sint32 c)
00526 {
00527   Voice *vp=voice+v;
00528   sample_t *sp;
00529   if (vp->status==VOICE_DIE)
00530     {
00531       if (c>=MAX_DIE_TIME)
00532         c=MAX_DIE_TIME;
00533       sp=resample_voice(v, &c);
00534       ramp_out(sp, buf, v, c);
00535       vp->status=VOICE_FREE;
00536     }
00537   else
00538     {
00539       sp=resample_voice(v, &c);
00540       if (play_mode->encoding & PE_MONO)
00541         {
00542           /* Mono output. */
00543           if (vp->envelope_increment || vp->tremolo_phase_increment)
00544             mix_mono_signal(sp, buf, v, c);
00545           else
00546             mix_mono(sp, buf, v, c);
00547         }
00548       else
00549         {
00550           if (vp->panned == PANNED_MYSTERY)
00551             {
00552               if (vp->envelope_increment || vp->tremolo_phase_increment)
00553                 mix_mystery_signal(sp, buf, v, c);
00554               else
00555                 mix_mystery(sp, buf, v, c);
00556             }
00557           else if (vp->panned == PANNED_CENTER)
00558             {
00559               if (vp->envelope_increment || vp->tremolo_phase_increment)
00560                 mix_center_signal(sp, buf, v, c);
00561               else
00562                 mix_center(sp, buf, v, c);
00563             }
00564           else
00565             { 
00566               /* It's either full left or full right. In either case,
00567                  every other sample is 0. Just get the offset right: */
00568               if (vp->panned == PANNED_RIGHT) buf++;
00569               
00570               if (vp->envelope_increment || vp->tremolo_phase_increment)
00571                 mix_single_signal(sp, buf, v, c);
00572               else 
00573                 mix_single(sp, buf, v, c);
00574             }
00575         }
00576     }
00577 }
00578 
00579 #ifdef NS_TIMIDITY
00580 };
00581 #endif
00582 
00583 #endif //USE_TIMIDITY_MIDI

Generated on Fri Jul 27 22:27:44 2007 for pentagram by  doxygen 1.4.7