timidity_playmidi.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     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020     playmidi.c -- random stuff in need of rearrangement
00021 
00022 */
00023 
00024 #include "pent_include.h"
00025 
00026 #ifdef USE_TIMIDITY_MIDI
00027 
00028 #include <cstdio>
00029 #include <cstdlib>
00030 #include <cstring>
00031 
00032 #include "timidity.h"
00033 #include "timidity_common.h"
00034 #include "timidity_instrum.h"
00035 #include "timidity_playmidi.h"
00036 #include "timidity_readmidi.h"
00037 #include "timidity_output.h"
00038 #include "timidity_mix.h"
00039 #include "timidity_controls.h"
00040 #include "timidity_tables.h"
00041 
00042 #ifdef NS_TIMIDITY
00043 namespace NS_TIMIDITY {
00044 #endif
00045 
00046 Channel channel[16];
00047 Voice voice[MAX_VOICES];
00048 
00049 int
00050     voices=DEFAULT_VOICES;
00051 
00052 sint32
00053     control_ratio=0,
00054     amplification=DEFAULT_AMPLIFICATION;
00055 
00056 float
00057     master_volume;
00058 
00059 sint32 drumchannels=DEFAULT_DRUMCHANNELS;
00060 int adjust_panning_immediately=1;
00061 
00062 struct MidiSong {
00063         sint32 samples;
00064         MidiEvent *events;
00065 };
00066 static int midi_playing = 0;
00067 static sint32 lost_notes, cut_notes;
00068 static sint32 *buffer_pointer;
00069 static sint32 buffered_count;
00070 extern sint32 *common_buffer;
00071 
00072 static MidiEvent *event_list, *current_event;
00073 static sint32 sample_count, current_sample;
00074 
00075 static void adjust_amplification(void)
00076 { 
00077   master_volume = (float)(amplification) / (float)100.0;
00078 }
00079 
00080 static void reset_voices(void)
00081 {
00082   int i;
00083   for (i=0; i<MAX_VOICES; i++)
00084     voice[i].status=VOICE_FREE;
00085 }
00086 
00087 /* Process the Reset All Controllers event */
00088 static void reset_controllers(int c)
00089 {
00090   channel[c].volume=90; /* Some standard says, although the SCC docs say 0. */
00091   channel[c].expression=127; /* SCC-1 does this. */
00092   channel[c].sustain=0;
00093   channel[c].pitchbend=0x2000;
00094   channel[c].pitchfactor=0; /* to be computed */
00095 }
00096 
00097 static void redraw_controllers(int c)
00098 {
00099   ctl->volume(c, channel[c].volume);
00100   ctl->expression(c, channel[c].expression);
00101   ctl->sustain(c, channel[c].sustain);
00102   ctl->pitch_bend(c, channel[c].pitchbend);
00103 }
00104 
00105 static void reset_midi(void)
00106 {
00107   int i;
00108   for (i=0; i<16; i++)
00109     {
00110       reset_controllers(i);
00111       /* The rest of these are unaffected by the Reset All Controllers event */
00112       channel[i].program=default_program;
00113       channel[i].panning=NO_PANNING;
00114       channel[i].pitchsens=2;
00115       channel[i].bank=0; /* tone bank or drum set */
00116     }
00117   reset_voices();
00118 }
00119 
00120 static void select_sample(int v, Instrument *ip)
00121 {
00122   sint32 f, cdiff, diff;
00123   int s,i;
00124   Sample *sp, *closest;
00125 
00126   s=ip->samples;
00127   sp=ip->sample;
00128 
00129   if (s==1)
00130     {
00131       voice[v].sample=sp;
00132       return;
00133     }
00134 
00135   f=voice[v].orig_frequency;
00136   for (i=0; i<s; i++)
00137     {
00138       if (sp->low_freq <= f && sp->high_freq >= f)
00139         {
00140           voice[v].sample=sp;
00141           return;
00142         }
00143       sp++;
00144     }
00145 
00146   /* 
00147      No suitable sample found! We'll select the sample whose root
00148      frequency is closest to the one we want. (Actually we should
00149      probably convert the low, high, and root frequencies to MIDI note
00150      values and compare those.) */
00151 
00152   cdiff=0x7FFFFFFF;
00153   closest=sp=ip->sample;
00154   for(i=0; i<s; i++)
00155     {
00156       diff=sp->root_freq - f;
00157       if (diff<0) diff=-diff;
00158       if (diff<cdiff)
00159         {
00160           cdiff=diff;
00161           closest=sp;
00162         }
00163       sp++;
00164     }
00165   voice[v].sample=closest;
00166   return;
00167 }
00168 
00169 static void recompute_freq(int v)
00170 {
00171   int 
00172     sign=(voice[v].sample_increment < 0), /* for bidirectional loops */
00173     pb=channel[voice[v].channel].pitchbend;
00174   double a;
00175   
00176   if (!voice[v].sample->sample_rate)
00177     return;
00178 
00179   if (voice[v].vibrato_control_ratio)
00180     {
00181       /* This instrument has vibrato. Invalidate any precomputed
00182          sample_increments. */
00183 
00184       int i=VIBRATO_SAMPLE_INCREMENTS;
00185       while (i--)
00186         voice[v].vibrato_sample_increment[i]=0;
00187     }
00188 
00189   if (pb==0x2000 || pb<0 || pb>0x3FFF)
00190     voice[v].frequency=voice[v].orig_frequency;
00191   else
00192     {
00193       pb-=0x2000;
00194       if (!(channel[voice[v].channel].pitchfactor))
00195         {
00196           /* Damn. Somebody bent the pitch. */
00197           sint32 i=pb*channel[voice[v].channel].pitchsens;
00198           if (pb<0)
00199             i=-i;
00200           channel[voice[v].channel].pitchfactor=
00201             (float)(bend_fine[(i>>5) & 0xFF] * bend_coarse[i>>13]);
00202         }
00203       if (pb>0)
00204         voice[v].frequency=
00205           (sint32)(channel[voice[v].channel].pitchfactor *
00206                   (double)(voice[v].orig_frequency));
00207       else
00208         voice[v].frequency=
00209           (sint32)((double)(voice[v].orig_frequency) /
00210                   channel[voice[v].channel].pitchfactor);
00211     }
00212 
00213   a = FSCALE(((double)(voice[v].sample->sample_rate) *
00214               (double)(voice[v].frequency)) /
00215              ((double)(voice[v].sample->root_freq) *
00216               (double)(play_mode->rate)),
00217              FRACTION_BITS);
00218 
00219   if (sign) 
00220     a = -a; /* need to preserve the loop direction */
00221 
00222   voice[v].sample_increment = (sint32)(a);
00223 }
00224 
00225 static void recompute_amp(int v)
00226 {
00227   sint32 tempamp;
00228 
00229   /* TODO: use fscale */
00230 
00231   tempamp= (voice[v].velocity *
00232             channel[voice[v].channel].volume * 
00233             channel[voice[v].channel].expression); /* 21 bits */
00234 
00235   if (!(play_mode->encoding & PE_MONO))
00236     {
00237       if (voice[v].panning > 60 && voice[v].panning < 68)
00238         {
00239           voice[v].panned=PANNED_CENTER;
00240 
00241           voice[v].left_amp=
00242             FSCALENEG((double)(tempamp) * voice[v].sample->volume * master_volume,
00243                       21);
00244         }
00245       else if (voice[v].panning<5)
00246         {
00247           voice[v].panned = PANNED_LEFT;
00248 
00249           voice[v].left_amp=
00250             FSCALENEG((double)(tempamp) * voice[v].sample->volume * master_volume,
00251                       20);
00252         }
00253       else if (voice[v].panning>123)
00254         {
00255           voice[v].panned = PANNED_RIGHT;
00256 
00257           voice[v].left_amp= /* left_amp will be used */
00258             FSCALENEG((double)(tempamp) * voice[v].sample->volume * master_volume,
00259                       20);
00260         }
00261       else
00262         {
00263           voice[v].panned = PANNED_MYSTERY;
00264 
00265           voice[v].left_amp=
00266             FSCALENEG((double)(tempamp) * voice[v].sample->volume * master_volume,
00267                       27);
00268           voice[v].right_amp=voice[v].left_amp * (voice[v].panning);
00269           voice[v].left_amp *= (float)(127-voice[v].panning);
00270         }
00271     }
00272   else
00273     {
00274       voice[v].panned=PANNED_CENTER;
00275 
00276       voice[v].left_amp=
00277         FSCALENEG((double)(tempamp) * voice[v].sample->volume * master_volume,
00278                   21);
00279     }
00280 }
00281 
00282 static void start_note(MidiEvent *e, int i)
00283 {
00284   Instrument *ip;
00285   int j;
00286 
00287   if (ISDRUMCHANNEL(e->channel))
00288     {
00289       if (!(ip=drumset[channel[e->channel].bank]->tone[e->a].instrument))
00290         {
00291           if (!(ip=drumset[0]->tone[e->a].instrument))
00292             return; /* No instrument? Then we can't play. */
00293         }
00294       if (ip->samples != 1)
00295         {
00296           ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, 
00297                "Strange: percussion instrument with %d samples!", ip->samples);
00298         }
00299 
00300       if (ip->sample->note_to_use) /* Do we have a fixed pitch? */
00301         voice[i].orig_frequency=freq_table[(int)(ip->sample->note_to_use)];
00302       else
00303         voice[i].orig_frequency=freq_table[e->a & 0x7F];
00304       
00305       /* drums are supposed to have only one sample */
00306       voice[i].sample=ip->sample;
00307     }
00308   else
00309     {
00310       if (channel[e->channel].program==SPECIAL_PROGRAM)
00311         ip=default_instrument;
00312       else if (!(ip=tonebank[channel[e->channel].bank]->
00313                  tone[channel[e->channel].program].instrument))
00314         {
00315           if (!(ip=tonebank[0]->tone[channel[e->channel].program].instrument))
00316             return; /* No instrument? Then we can't play. */
00317         }
00318 
00319       if (ip->sample->note_to_use) /* Fixed-pitch instrument? */
00320         voice[i].orig_frequency=freq_table[(int)(ip->sample->note_to_use)];
00321       else
00322         voice[i].orig_frequency=freq_table[e->a & 0x7F];
00323       select_sample(i, ip);
00324     }
00325 
00326   voice[i].status=VOICE_ON;
00327   voice[i].channel=e->channel;
00328   voice[i].note=e->a;
00329   voice[i].velocity=e->b;
00330   voice[i].sample_offset=0;
00331   voice[i].sample_increment=0; /* make sure it isn't negative */
00332 
00333   voice[i].tremolo_phase=0;
00334   voice[i].tremolo_phase_increment=voice[i].sample->tremolo_phase_increment;
00335   voice[i].tremolo_sweep=voice[i].sample->tremolo_sweep_increment;
00336   voice[i].tremolo_sweep_position=0;
00337 
00338   voice[i].vibrato_sweep=voice[i].sample->vibrato_sweep_increment;
00339   voice[i].vibrato_sweep_position=0;
00340   voice[i].vibrato_control_ratio=voice[i].sample->vibrato_control_ratio;
00341   voice[i].vibrato_control_counter=voice[i].vibrato_phase=0;
00342   for (j=0; j<VIBRATO_SAMPLE_INCREMENTS; j++)
00343     voice[i].vibrato_sample_increment[j]=0;
00344 
00345   if (channel[e->channel].panning != NO_PANNING)
00346     voice[i].panning=channel[e->channel].panning;
00347   else
00348     voice[i].panning=voice[i].sample->panning;
00349 
00350   recompute_freq(i);
00351   recompute_amp(i);
00352   if (voice[i].sample->modes & MODES_ENVELOPE)
00353     {
00354       /* Ramp up from 0 */
00355       voice[i].envelope_stage=0;
00356       voice[i].envelope_volume=0;
00357       voice[i].control_counter=0;
00358       recompute_envelope(i);
00359       apply_envelope_to_amp(i);
00360     }
00361   else
00362     {
00363       voice[i].envelope_increment=0;
00364       apply_envelope_to_amp(i);
00365     }
00366   ctl->note(i);
00367 }
00368 
00369 static void kill_note(int i)
00370 {
00371   voice[i].status=VOICE_DIE;
00372   ctl->note(i);
00373 }
00374 
00375 /* Only one instance of a note can be playing on a single channel. */
00376 static void note_on(MidiEvent *e)
00377 {
00378   int i=voices, lowest=-1; 
00379   sint32 lv=0x7FFFFFFF, v;
00380 
00381   while (i--)
00382     {
00383       if (voice[i].status == VOICE_FREE)
00384         lowest=i; /* Can't get a lower volume than silence */
00385       else if (voice[i].channel==e->channel && 
00386                (voice[i].note==e->a || channel[voice[i].channel].mono))
00387         kill_note(i);
00388     }
00389 
00390   if (lowest != -1)
00391     {
00392       /* Found a free voice. */
00393       start_note(e,lowest);
00394       return;
00395     }
00396   
00397   /* Look for the decaying note with the lowest volume */
00398   i=voices;
00399   while (i--)
00400     {
00401       if ((voice[i].status!=VOICE_ON) &&
00402           (voice[i].status!=VOICE_DIE))
00403         {
00404           v=voice[i].left_mix;
00405           if ((voice[i].panned==PANNED_MYSTERY) && (voice[i].right_mix>v))
00406             v=voice[i].right_mix;
00407           if (v<lv)
00408             {
00409               lv=v;
00410               lowest=i;
00411             }
00412         }
00413     }
00414 
00415   if (lowest != -1)
00416     {
00417       /* This can still cause a click, but if we had a free voice to
00418          spare for ramping down this note, we wouldn't need to kill it
00419          in the first place... Still, this needs to be fixed. Perhaps
00420          we could use a reserve of voices to play dying notes only. */
00421       
00422       cut_notes++;
00423       voice[lowest].status=VOICE_FREE;
00424       ctl->note(lowest);
00425       start_note(e,lowest);
00426     }
00427   else
00428     lost_notes++;
00429 }
00430 
00431 static void finish_note(int i)
00432 {
00433   if (voice[i].sample->modes & MODES_ENVELOPE)
00434     {
00435       /* We need to get the envelope out of Sustain stage */
00436       voice[i].envelope_stage=3;
00437       voice[i].status=VOICE_OFF;
00438       recompute_envelope(i);
00439       apply_envelope_to_amp(i);
00440       ctl->note(i);
00441     }
00442   else
00443     {
00444       /* Set status to OFF so resample_voice() will let this voice out
00445          of its loop, if any. In any case, this voice dies when it
00446          hits the end of its data (ofs>=data_length). */
00447       voice[i].status=VOICE_OFF;
00448     }
00449 }
00450 
00451 static void note_off(MidiEvent *e)
00452 {
00453   int i=voices;
00454   while (i--)
00455     if (voice[i].status==VOICE_ON &&
00456         voice[i].channel==e->channel &&
00457         voice[i].note==e->a)
00458       {
00459         if (channel[e->channel].sustain)
00460           {
00461             voice[i].status=VOICE_SUSTAINED;
00462             ctl->note(i);
00463           }
00464         else
00465           finish_note(i);
00466         return;
00467       }
00468 }
00469 
00470 /* Process the All Notes Off event */
00471 static void all_notes_off(int c)
00472 {
00473   int i=voices;
00474   ctl->cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c);
00475   while (i--)
00476     if (voice[i].status==VOICE_ON &&
00477         voice[i].channel==c)
00478       {
00479         if (channel[c].sustain) 
00480           {
00481             voice[i].status=VOICE_SUSTAINED;
00482             ctl->note(i);
00483           }
00484         else
00485           finish_note(i);
00486       }
00487 }
00488 
00489 /* Process the All Sounds Off event */
00490 static void all_sounds_off(int c)
00491 {
00492   int i=voices;
00493   while (i--)
00494     if (voice[i].channel==c && 
00495         voice[i].status != VOICE_FREE &&
00496         voice[i].status != VOICE_DIE)
00497       {
00498         kill_note(i);
00499       }
00500 }
00501 
00502 static void adjust_pressure(MidiEvent *e)
00503 {
00504   int i=voices;
00505   while (i--)
00506     if (voice[i].status==VOICE_ON &&
00507         voice[i].channel==e->channel &&
00508         voice[i].note==e->a)
00509       {
00510         voice[i].velocity=e->b;
00511         recompute_amp(i);
00512         apply_envelope_to_amp(i);
00513         return;
00514       }
00515 }
00516 
00517 static void adjust_panning(int c)
00518 {
00519   int i=voices;
00520   while (i--)
00521     if ((voice[i].channel==c) &&
00522         (voice[i].status==VOICE_ON || voice[i].status==VOICE_SUSTAINED))
00523       {
00524         voice[i].panning=channel[c].panning;
00525         recompute_amp(i);
00526         apply_envelope_to_amp(i);
00527       }
00528 }
00529 
00530 static void drop_sustain(int c)
00531 {
00532   int i=voices;
00533   while (i--)
00534     if (voice[i].status==VOICE_SUSTAINED && voice[i].channel==c)
00535       finish_note(i);
00536 }
00537 
00538 static void adjust_pitchbend(int c)
00539 {
00540   int i=voices;
00541   while (i--)
00542     if (voice[i].status!=VOICE_FREE && voice[i].channel==c)
00543       {
00544         recompute_freq(i);
00545       }
00546 }
00547 
00548 static void adjust_volume(int c)
00549 {
00550   int i=voices;
00551   while (i--)
00552     if (voice[i].channel==c &&
00553         (voice[i].status==VOICE_ON || voice[i].status==VOICE_SUSTAINED))
00554       {
00555         recompute_amp(i);
00556         apply_envelope_to_amp(i);
00557       }
00558 }
00559 
00560 static void seek_forward(sint32 until_time)
00561 {
00562   reset_voices();
00563   while (current_event->time < until_time)
00564     {
00565       switch(current_event->type)
00566         {
00567           /* All notes stay off. Just handle the parameter changes. */
00568 
00569         case ME_PITCH_SENS:
00570           channel[current_event->channel].pitchsens=
00571             current_event->a;
00572           channel[current_event->channel].pitchfactor=0;
00573           break;
00574           
00575         case ME_PITCHWHEEL:
00576           channel[current_event->channel].pitchbend=
00577             current_event->a + current_event->b * 128;
00578           channel[current_event->channel].pitchfactor=0;
00579           break;
00580           
00581         case ME_MAINVOLUME:
00582           channel[current_event->channel].volume=current_event->a;
00583           break;
00584           
00585         case ME_PAN:
00586           channel[current_event->channel].panning=current_event->a;
00587           break;
00588               
00589         case ME_EXPRESSION:
00590           channel[current_event->channel].expression=current_event->a;
00591           break;
00592           
00593         case ME_PROGRAM:
00594           if (ISDRUMCHANNEL(current_event->channel))
00595             /* Change drum set */
00596             channel[current_event->channel].bank=current_event->a;
00597           else
00598             channel[current_event->channel].program=current_event->a;
00599           break;
00600 
00601         case ME_SUSTAIN:
00602           channel[current_event->channel].sustain=current_event->a;
00603           break;
00604 
00605         case ME_RESET_CONTROLLERS:
00606           reset_controllers(current_event->channel);
00607           break;
00608               
00609         case ME_TONE_BANK:
00610           channel[current_event->channel].bank=current_event->a;
00611           break;
00612           
00613         case ME_EOT:
00614           current_sample=current_event->time;
00615           return;
00616         }
00617       current_event++;
00618     }
00619   /*current_sample=current_event->time;*/
00620   if (current_event != event_list)
00621     current_event--;
00622   current_sample=until_time;
00623 }
00624 
00625 static void skip_to(sint32 until_time)
00626 {
00627   if (current_sample > until_time)
00628     current_sample=0;
00629 
00630   reset_midi();
00631   buffered_count=0;
00632   buffer_pointer=common_buffer;
00633   current_event=event_list;
00634   
00635   if (until_time)
00636     seek_forward(until_time);
00637   ctl->reset();
00638 }
00639 
00640 static int apply_controls(void)
00641 {
00642   int rc, i, did_skip=0;
00643   sint32 val;
00644   /* ASCII renditions of CD player pictograms indicate approximate effect */
00645   do
00646     switch(rc=ctl->read(&val))
00647       {
00648       case TM_RC_QUIT: /* [] */
00649       case TM_RC_LOAD_FILE:       
00650       case TM_RC_NEXT: /* >>| */
00651       case TM_RC_REALLY_PREVIOUS: /* |<< */
00652         return rc;
00653         
00654       case TM_RC_CHANGE_VOLUME:
00655         if (val>0 || amplification > -val)
00656           amplification += val;
00657         else 
00658           amplification=0;
00659         if (amplification > MAX_AMPLIFICATION)
00660           amplification=MAX_AMPLIFICATION;
00661         adjust_amplification();
00662         for (i=0; i<voices; i++)
00663           if (voice[i].status != VOICE_FREE)
00664             {
00665               recompute_amp(i);
00666               apply_envelope_to_amp(i);
00667             }
00668         ctl->master_volume(amplification);
00669         break;
00670 
00671       case TM_RC_PREVIOUS: /* |<< */
00672         if (current_sample < 2*play_mode->rate)
00673           return TM_RC_REALLY_PREVIOUS;
00674         return TM_RC_RESTART;
00675 
00676       case TM_RC_RESTART: /* |<< */
00677         skip_to(0);
00678         did_skip=1;
00679         break;
00680         
00681       case TM_RC_JUMP:
00682         if (val >= sample_count)
00683           return TM_RC_NEXT;
00684         skip_to(val);
00685         return rc;
00686         
00687       case TM_RC_FORWARD: /* >> */
00688         if (val+current_sample >= sample_count)
00689           return TM_RC_NEXT;
00690         skip_to(val+current_sample);
00691         did_skip=1;
00692         break;
00693         
00694       case TM_RC_BACK: /* << */
00695         if (current_sample > val)
00696           skip_to(current_sample-val);
00697         else
00698           skip_to(0); /* We can't seek to end of previous song. */
00699         did_skip=1;
00700         break;
00701       }
00702   while (rc!= TM_RC_NONE);
00703  
00704   /* Advertise the skip so that we stop computing the audio buffer */
00705   if (did_skip)
00706     return TM_RC_JUMP; 
00707   else
00708     return rc;
00709 }
00710 
00711 static void do_compute_data(sint32 count)
00712 {
00713   int i;
00714   memset(buffer_pointer, 0, 
00715          (play_mode->encoding & PE_MONO) ? (count * 4) : (count * 8));
00716   for (i=0; i<voices; i++)
00717     {
00718       if(voice[i].status != VOICE_FREE)
00719         mix_voice(buffer_pointer, i, count);
00720     }
00721   current_sample += count;
00722 }
00723 
00724 /* count=0 means flush remaining buffered data to output device, then
00725    flush the device itself */
00726 static int compute_data(void *stream, sint32 count)
00727 {
00728   int rc, channels;
00729 
00730   if ( play_mode->encoding & PE_MONO )
00731     channels = 1;
00732   else
00733     channels = 2;
00734 
00735   if (!count)
00736     {
00737       if (buffered_count)
00738           s32tobuf(stream, common_buffer, channels*buffered_count);
00739       buffer_pointer=common_buffer;
00740       buffered_count=0;
00741       return TM_RC_NONE;
00742     }
00743 
00744   while ((count+buffered_count) >= AUDIO_BUFFER_SIZE)
00745     {
00746       do_compute_data(AUDIO_BUFFER_SIZE-buffered_count);
00747       count -= AUDIO_BUFFER_SIZE-buffered_count;
00748       s32tobuf(stream, common_buffer, channels*AUDIO_BUFFER_SIZE);
00749       buffer_pointer=common_buffer;
00750       buffered_count=0;
00751       
00752       ctl->current_time(current_sample);
00753       if ((rc=apply_controls())!=TM_RC_NONE)
00754         return rc;
00755     }
00756   if (count>0)
00757     {
00758       do_compute_data(count);
00759       buffered_count += count;
00760       buffer_pointer += (play_mode->encoding & PE_MONO) ? count : count*2;
00761     }
00762   return TM_RC_NONE;
00763 }
00764 
00765 int Timidity_PlaySome(void *stream, int samples)
00766 {
00767   int rc = TM_RC_NONE;
00768   sint32 end_sample;
00769   
00770   if ( ! midi_playing ) {
00771     return TM_RC_NONE;
00772   }
00773   end_sample = current_sample+samples;
00774   while ( current_sample < end_sample ) {
00775     /* Handle all events that should happen at this time */
00776     while (current_event->time <= current_sample) {
00777       switch(current_event->type) {
00778 
00779         /* Effects affecting a single note */
00780 
00781         case ME_NOTEON:
00782           if (!(current_event->b)) /* Velocity 0? */
00783             note_off(current_event);
00784           else
00785             note_on(current_event);
00786           break;
00787   
00788         case ME_NOTEOFF:
00789           note_off(current_event);
00790           break;
00791   
00792         case ME_KEYPRESSURE:
00793           adjust_pressure(current_event);
00794           break;
00795   
00796           /* Effects affecting a single channel */
00797   
00798         case ME_PITCH_SENS:
00799           channel[current_event->channel].pitchsens=current_event->a;
00800           channel[current_event->channel].pitchfactor=0;
00801           break;
00802           
00803         case ME_PITCHWHEEL:
00804           channel[current_event->channel].pitchbend=
00805             current_event->a + current_event->b * 128;
00806           channel[current_event->channel].pitchfactor=0;
00807           /* Adjust pitch for notes already playing */
00808           adjust_pitchbend(current_event->channel);
00809           ctl->pitch_bend(current_event->channel, 
00810               channel[current_event->channel].pitchbend);
00811           break;
00812           
00813         case ME_MAINVOLUME:
00814           channel[current_event->channel].volume=current_event->a;
00815           adjust_volume(current_event->channel);
00816           ctl->volume(current_event->channel, current_event->a);
00817           break;
00818           
00819         case ME_PAN:
00820           channel[current_event->channel].panning=current_event->a;
00821           if (adjust_panning_immediately)
00822             adjust_panning(current_event->channel);
00823           ctl->panning(current_event->channel, current_event->a);
00824           break;
00825           
00826         case ME_EXPRESSION:
00827           channel[current_event->channel].expression=current_event->a;
00828           adjust_volume(current_event->channel);
00829           ctl->expression(current_event->channel, current_event->a);
00830           break;
00831   
00832         case ME_PROGRAM:
00833           if (ISDRUMCHANNEL(current_event->channel)) {
00834             /* Change drum set */
00835             channel[current_event->channel].bank=current_event->a;
00836           }
00837           else
00838           {
00839             channel[current_event->channel].program=current_event->a;
00840           }
00841           ctl->program(current_event->channel, current_event->a);
00842           break;
00843   
00844         case ME_SUSTAIN:
00845           channel[current_event->channel].sustain=current_event->a;
00846           if (!current_event->a)
00847             drop_sustain(current_event->channel);
00848           ctl->sustain(current_event->channel, current_event->a);
00849           break;
00850           
00851         case ME_RESET_CONTROLLERS:
00852           reset_controllers(current_event->channel);
00853           redraw_controllers(current_event->channel);
00854           break;
00855   
00856         case ME_ALL_NOTES_OFF:
00857           all_notes_off(current_event->channel);
00858           break;
00859           
00860         case ME_ALL_SOUNDS_OFF:
00861           all_sounds_off(current_event->channel);
00862           break;
00863           
00864         case ME_TONE_BANK:
00865           channel[current_event->channel].bank=current_event->a;
00866           break;
00867   
00868         case ME_EOT:
00869           /* Give the last notes a couple of seconds to decay  */
00870           ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
00871             "Playing time: ~%d seconds", current_sample/play_mode->rate+2);
00872           ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
00873             "Notes cut: %d", cut_notes);
00874           ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
00875           "Notes lost totally: %d", lost_notes);
00876           midi_playing = 0;
00877           return TM_RC_TUNE_END;
00878         }
00879       current_event++;
00880     }
00881     if (current_event->time > end_sample)
00882       rc=compute_data(stream, end_sample-current_sample);
00883     else
00884       rc=compute_data(stream, current_event->time-current_sample);
00885     ctl->refresh();
00886     if ( (rc!=TM_RC_NONE) && (rc!=TM_RC_JUMP))
00887       break;
00888   }
00889   return rc;
00890 }
00891 
00892 
00893 void Timidity_SetVolume(int volume)
00894 {
00895   int i;
00896   if (volume > MAX_AMPLIFICATION)
00897     amplification=MAX_AMPLIFICATION;
00898   else
00899   if (volume < 0)
00900     amplification=0;
00901   else
00902     amplification=volume;
00903   adjust_amplification();
00904   for (i=0; i<voices; i++)
00905     if (voice[i].status != VOICE_FREE)
00906       {
00907         recompute_amp(i);
00908         apply_envelope_to_amp(i);
00909       }
00910   ctl->master_volume(amplification);
00911 }
00912 
00913 MidiSong *Timidity_LoadSong(char *midifile)
00914 {
00915   MidiSong *song;
00916   sint32 events;
00917   FILE *fp;
00918 
00919   /* Allocate memory for the song */
00920   song = safe_Malloc<MidiSong>();
00921   memset(song, 0, sizeof(*song));
00922 
00923   /* Open the file */
00924   fp = open_file(midifile, 1, OF_VERBOSE);
00925   if ( fp != NULL ) {
00926     song->events=read_midi_file(fp, &events, &song->samples);
00927     close_file(fp);
00928   }
00929   
00930   /* Make sure everything is okay */
00931   if (!song->events) {
00932     free(song);
00933     song = NULL;
00934   }
00935   return(song);
00936 }
00937 
00938 void Timidity_Start(MidiSong *song)
00939 {
00940   load_missing_instruments();
00941   adjust_amplification();
00942   sample_count = song->samples;
00943   event_list = song->events;
00944   lost_notes=cut_notes=0;
00945 
00946   skip_to(0);
00947   midi_playing = 1;
00948 }
00949 
00950 int Timidity_Active(void)
00951 {
00952         return(midi_playing);
00953 }
00954 
00955 void Timidity_Stop(void)
00956 {
00957   midi_playing = 0;
00958 }
00959 
00960 void Timidity_FreeSong(MidiSong *song)
00961 {
00962   if (free_instruments_afterwards)
00963       free_instruments();
00964   
00965   free(song->events);
00966   free(song);
00967 }
00968 
00969 /* Pentagram Extensions to Timidity Lib */
00970 
00971 #define MIDIEVENT(t,ch,pa,pb) \
00972   event.time=0; event.type=t; event.channel=ch; \
00973   event.a=(uint8)pa; event.b=(uint8)pb; 
00974 
00975 void Timidity_PlayEvent(unsigned char status, int a, int b)
00976 {
00977         MidiEvent event;
00978         uint8 chan=status & 0x0F;
00979 
00980         switch((status>>4) & 0x07)
00981         {
00982         case 0: /* Note off */
00983                 MIDIEVENT(ME_NOTEOFF, chan, a,b);
00984                 note_off(&event);
00985                 return;
00986 
00987         case 1: /* Note on */
00988                 MIDIEVENT(ME_NOTEON, chan, a,b);
00989         if (b) note_on(&event);
00990         else note_off(&event);
00991                 return;
00992 
00993         case 2: /* Key Pressure */
00994                 MIDIEVENT(ME_KEYPRESSURE, chan, a, b);
00995                 adjust_pressure(&event);
00996                 return;
00997 
00998         case 3: /* Control change */
00999                 switch(a)
01000                 {
01001                 case 0:                 /* Bank - This is not needed for Pentagram */
01002                         return;
01003 
01004                 case 7:                 /* Volume */
01005                         channel[chan].volume=b;
01006                         adjust_volume(chan);
01007                         ctl->volume(chan, b);
01008                         return;
01009 
01010                 case 10:                /* Pan */
01011                         channel[chan].panning=b;
01012                         if (adjust_panning_immediately)
01013                                 adjust_panning(chan);
01014                         ctl->panning(chan, b);
01015                         return;
01016 
01017                 case 11:                /* Expression */
01018                         channel[chan].expression=b;
01019                         adjust_volume(chan);
01020                         ctl->expression(chan, b);
01021                         return;
01022 
01023                 case 64:                /* Sustain*/
01024                         channel[chan].sustain=b;
01025                         if (!b) drop_sustain(chan);
01026                         ctl->sustain(chan, b);
01027                         return;
01028 
01029                 case 120:               /* All Sounds Off */
01030                 all_sounds_off(chan);
01031                         return;
01032                                 
01033                 case 121:               /* Reset Controllers */
01034                     reset_controllers(chan);
01035                 redraw_controllers(chan);
01036                         return;
01037 
01038                 case 123:               /* All notes off */
01039                         all_notes_off(chan);
01040                         return;
01041 
01042                 default:
01043                         return;
01044                 }
01045 
01046         case 4: /* Program change */
01047         if (chan!=9) {
01048                 channel[chan].program=a;
01049                 ctl->program(chan, a);
01050                 }
01051         return;
01052 
01053         case 5: /* Channel pressure - NOT IMPLEMENTED */
01054                 return;
01055 
01056         case 6: /* Pitch wheel */
01057         channel[chan].pitchbend= a + b * 128;
01058         channel[chan].pitchfactor=0;
01059         /* Adjust pitch for notes already playing */
01060         adjust_pitchbend(chan);
01061         ctl->pitch_bend(chan, channel[chan].pitchbend);
01062                 return;
01063 
01064         default: 
01065                 return;
01066         }
01067 }
01068 
01069 void Timidity_GenerateSamples(void *stream, int samples)
01070 {
01071         int channels;
01072 
01073         if ( play_mode->encoding & PE_MONO )
01074                 channels = 1;
01075         else
01076                 channels = 2;
01077 
01078         int sample_size = channels;
01079 
01080         if ( play_mode->encoding & PE_16BIT )
01081                 sample_size *= 2;
01082 
01083         buffer_pointer=common_buffer;
01084         buffered_count=0;
01085 
01086         while (samples >= AUDIO_BUFFER_SIZE)
01087         {
01088                 do_compute_data(AUDIO_BUFFER_SIZE);
01089                 samples -= AUDIO_BUFFER_SIZE;
01090                 s32tobuf(stream, common_buffer, channels*AUDIO_BUFFER_SIZE);
01091                 stream = AUDIO_BUFFER_SIZE*sample_size + (uint8*)stream;
01092                 buffer_pointer=common_buffer;
01093                 buffered_count=0;
01094         }
01095 
01096         if (samples)
01097         {
01098                 do_compute_data(samples);
01099                 s32tobuf(stream, common_buffer, channels*samples);
01100                 buffer_pointer=common_buffer;
01101                 buffered_count=0;
01102         }
01103 }
01104 
01105 void Timidity_FinalInit(bool patches[128], bool drums[128])
01106 {
01107         for (int i = 0; i < 128; i++)
01108         {
01109                 if (patches[i])
01110                 {
01111                         /* Mark this instrument to be loaded */
01112                         if (!(tonebank[0]->tone[i].instrument))
01113                                 tonebank[0]->tone[i].instrument=MAGIC_LOAD_INSTRUMENT;
01114                 }
01115                 if (drums[i])
01116                 {
01117                         /* Mark this instrument to be loaded */
01118                         if (!(drumset[0]->tone[i].instrument))
01119                                 drumset[0]->tone[i].instrument=MAGIC_LOAD_INSTRUMENT;
01120                 }
01121         }
01122 
01123         load_missing_instruments();
01124         adjust_amplification();
01125         sample_count = 0x7FFFFFF;
01126         event_list = 0;
01127         lost_notes=cut_notes=0;
01128         skip_to(0);
01129         midi_playing = 1;
01130 }
01131 
01132 #ifdef NS_TIMIDITY
01133 };
01134 #endif
01135 
01136 #endif //USE_TIMIDITY_MIDI

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