00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "track.h"
00028 #include <stdlib.h>
00029 #include "sndcard.h"
00030 #include "midispec.h"
00031 #include "midfile.h"
00032
00033 #ifndef TRUE
00034 #define TRUE 1
00035 #endif
00036 #ifndef FALSE
00037 #define FALSE 0
00038 #endif
00039
00040 #define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)tPCN)
00041
00042 #define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)tPCN)/((double)60000L))
00043
00044 #define PEDANTIC_TRACK
00045 #define CHANGETEMPO_ONLY_IN_TRACK0
00046
00047
00048
00049 MidiTrack::MidiTrack(FILE *file,int tpcn,int Id)
00050 {
00051 id=Id;
00052 tPCN=tpcn;
00053 currentpos=0;
00054 size=0;
00055 data=0L;
00056 tempo=1000000;
00057 if (feof(file))
00058 {
00059 clear();
00060 return;
00061 };
00062 size=readLong(file);
00063 #ifdef TRACKDEBUG
00064 printf("Track %d : Size %ld\n",id,size);
00065 #endif
00066 data=new uchar[size];
00067 if (data==NULL)
00068 {
00069 perror("track: Not enough memory ?");
00070 exit(-1);
00071 }
00072 ulong rsize=0;
00073 if ((rsize=fread(data,1,size,file))!=size)
00074 {
00075 fprintf(stderr,"track (%d): File is corrupt : Couldn't load track (%ld!=%ld) !!\n", id, rsize, size);
00076 size=rsize;
00077 };
00078
00079
00080
00081
00082
00083
00084
00085 init();
00086 }
00087
00088 MidiTrack::~MidiTrack()
00089 {
00090 delete data;
00091 endoftrack=1;
00092 currentpos=0;
00093 size=0;
00094 }
00095
00096 int MidiTrack::power2to(int i)
00097 {
00098 return 1<<i;
00099 }
00100
00101 ulong MidiTrack::readVariableLengthValue(void)
00102 {
00103 ulong dticks=0;
00104
00105 while ((*ptrdata) & 0x80)
00106 {
00107 #ifdef PEDANTIC_TRACK
00108 if (currentpos>=size)
00109 {
00110 endoftrack=1;
00111 fprintf(stderr, "track (%d) : EndofTrack found by accident !\n",id);
00112 delta_ticks = wait_ticks = ~0;
00113 time_at_next_event=10000 * 60000L;
00114 return 0;
00115 }
00116 else
00117 #endif
00118 {
00119 dticks=(dticks << 7) | (*ptrdata) & 0x7F;
00120 ptrdata++;currentpos++;
00121 }
00122
00123 }
00124 dticks=((dticks << 7) | (*ptrdata) & 0x7F);
00125 ptrdata++;currentpos++;
00126
00127 #ifdef PEDANTIC_TRACK
00128
00129 if (currentpos>=size)
00130 {
00131 endoftrack=1;
00132 fprintf(stderr,"track (%d): EndofTrack found by accident 2 !\n",id);
00133 dticks=0;
00134 delta_ticks = wait_ticks = ~0;
00135 time_at_next_event=10000 * 60000L;
00136 return 0;
00137 }
00138 #endif
00139 #ifdef TRACKDEBUG
00140 printfdebug("track(%d): DTICKS : %ld\n",id,dticks);
00141 usleep(10);
00142 #endif
00143 return dticks;
00144 }
00145
00146 int MidiTrack::ticksPassed (ulong ticks)
00147 {
00148 if (endoftrack==1) return 0;
00149 if (ticks>wait_ticks)
00150 {
00151 printfdebug("track (%d): ERROR : TICKS PASSED > WAIT TICKS\n", id);
00152 return 1;
00153 }
00154 wait_ticks-=ticks;
00155 return 0;
00156 }
00157
00158 int MidiTrack::msPassed (ulong ms)
00159 {
00160 if (endoftrack==1) return 0;
00161 current_time+=ms;
00162
00163 if ( current_time>time_at_next_event )
00164 {
00165 fprintf(stderr, "track (%d): ERROR : MS PASSED > WAIT MS\n", id);
00166 return 1;
00167 }
00168 #ifdef TRACKDEBUG
00169 if (current_time==time_at_next_event) printfdebug("track(%d): _OK_",id);
00170 #endif
00171 return 0;
00172 }
00173
00174 int MidiTrack::currentMs(double ms)
00175 {
00176 if (endoftrack==1) return 0;
00177 current_time=ms;
00178
00179 #ifdef PEDANTIC_TRACK
00180 if (current_time>time_at_next_event)
00181 {
00182 fprintf(stderr,"track(%d): ERROR : MS PASSED > WAIT MS\n", id);
00183 exit(-1);
00184 return 1;
00185 }
00186 #endif
00187 return 0;
00188 }
00189
00190 void MidiTrack::readEvent(MidiEvent *ev)
00191 {
00192 int i,j;
00193 if (endoftrack==1)
00194 {
00195 ev->command=0;
00196 return;
00197 }
00198
00199
00200
00201
00202
00203 int skip_event=0;
00204 current_time=time_at_next_event;
00205 if (((*ptrdata)&0x80)!=0)
00206 {
00207 ev->command=(*ptrdata);
00208 ptrdata++;currentpos++;
00209 lastcommand=ev->command;
00210 }
00211 else
00212 {
00213 ev->command=lastcommand;
00214 }
00215
00216 #ifdef PEDANTIC_TRACK
00217 if (currentpos>=size)
00218 {
00219 endoftrack=1;
00220 delta_ticks = wait_ticks = ~0;
00221 time_at_next_event=10000 * 60000L;
00222 ev->command=MIDI_SYSTEM_PREFIX;
00223 ev->chn=0xF;
00224 ev->d1=ME_END_OF_TRACK;
00225 fprintf(stderr, "track (%d): EndofTrack found by accident 3\n",id);
00226 return;
00227 }
00228 #endif
00229
00230 ev->chn=ev->command & 0xF;
00231 ev->command=ev->command & 0xF0;
00232 switch (ev->command)
00233 {
00234 case (MIDI_NOTEON) :
00235 ev->note = *ptrdata;ptrdata++;currentpos++;
00236 ev->vel = *ptrdata;ptrdata++;currentpos++;
00237 if (ev->vel==0)
00238 note[ev->chn][ev->note]=FALSE;
00239 else
00240 note[ev->chn][ev->note]=TRUE;
00241
00242 #ifdef TRACKDEBUG2
00243 if (ev->chn==6) {
00244 if (ev->vel==0) printfdebug("Note Onf\n");
00245 else printfdebug("Note On\n");
00246 };
00247 #endif
00248 break;
00249 case (MIDI_NOTEOFF) :
00250 #ifdef TRACKDEBUG2
00251 if (ev->chn==6) printfdebug("Note Off\n");
00252 #endif
00253 ev->note = *ptrdata;ptrdata++;currentpos++;
00254 ev->vel = *ptrdata;ptrdata++;currentpos++;
00255 note[ev->chn][ev->note]=FALSE;
00256
00257 break;
00258 case (MIDI_KEY_PRESSURE) :
00259 #ifdef TRACKDEBUG2
00260 if (ev->chn==6) printfdebug ("Key press\n");
00261 #endif
00262 ev->note = *ptrdata;ptrdata++;currentpos++;
00263 ev->vel = *ptrdata;ptrdata++;currentpos++;
00264 break;
00265 case (MIDI_PGM_CHANGE) :
00266 #ifdef TRACKDEBUG2
00267 if (ev->chn==6) printfdebug ("Pgm\n");
00268 #endif
00269 ev->patch = *ptrdata;ptrdata++;currentpos++;
00270 break;
00271 case (MIDI_CHN_PRESSURE) :
00272 #ifdef TRACKDEBUG2
00273 if (ev->chn==6) printfdebug ("Chn press\n");
00274 #endif
00275 ev->vel = *ptrdata;ptrdata++;currentpos++;
00276 break;
00277 case (MIDI_PITCH_BEND) :
00278 #ifdef TRACKDEBUG2
00279 if (ev->chn==6) printfdebug ("Pitch\n");
00280 #endif
00281 ev->d1 = *ptrdata;ptrdata++;currentpos++;
00282 ev->d2 = *ptrdata;ptrdata++;currentpos++;
00283 break;
00284 case (MIDI_CTL_CHANGE) :
00285 #ifdef TRACKDEBUG2
00286 if (ev->chn==6) printfdebug (stderr, "Ctl\n");
00287 #endif
00288 ev->ctl = *ptrdata;ptrdata++; currentpos++;
00289 ev->d1 = *ptrdata;ptrdata++;currentpos++;
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 break;
00302
00303 case (MIDI_SYSTEM_PREFIX) :
00304 #ifdef TRACKDEBUG2
00305 if (ev->chn==6) printfdebug ("Sys Prefix\n");
00306 #endif
00307 switch ((ev->command|ev->chn))
00308 {
00309 case (0xF0) :
00310 case (0xF7) :
00311 ev->length=readVariableLengthValue();
00312 #ifdef PEDANTIC_TRACK
00313 if (endoftrack)
00314 {
00315 ev->command=MIDI_SYSTEM_PREFIX;
00316 ev->chn=0xF;
00317 ev->d1=ME_END_OF_TRACK;
00318 }
00319 else
00320 #endif
00321 {
00322 ev->data=ptrdata;
00323 ptrdata+=ev->length;currentpos+=ev->length;
00324 }
00325 break;
00326 case (0xFE):
00327 case (0xF8):
00328
00329 break;
00330 case (META_EVENT) :
00331 ev->d1=*ptrdata;ptrdata++;currentpos++;
00332 switch (ev->d1)
00333 {
00334 case (ME_END_OF_TRACK) :
00335 i=0;
00336 j=0;
00337 while ((note[i][j]==FALSE)&&(i<16))
00338 {
00339 j++;
00340 if (j==128) { j=0; i++; };
00341 }
00342 if (i<16)
00343 {
00344 ptrdata--;currentpos--;
00345 ev->chn=i;
00346 ev->command=MIDI_NOTEOFF;
00347 ev->note = j;
00348 ev->vel = 0;
00349 note[ev->chn][ev->note]=FALSE;
00350 fprintf(stderr,"Note Off(simulated)\n");
00351 return;
00352 }
00353 else
00354 {
00355 endoftrack=1;
00356 delta_ticks = wait_ticks = ~0;
00357 time_at_next_event=10000 * 60000L;
00358 #ifdef TRACKDEBUG
00359 printfdebug("EndofTrack %d event\n",id);
00360 #endif
00361 }
00362 break;
00363 case (ME_SET_TEMPO):
00364 ev->length=readVariableLengthValue();
00365 #ifdef PEDANTIC_TRACK
00366 if (endoftrack)
00367 {
00368 ev->command=MIDI_SYSTEM_PREFIX;
00369 ev->chn=0xF;
00370 ev->d1=ME_END_OF_TRACK;
00371 }
00372 else
00373 #endif
00374 {
00375 ev->data=ptrdata;
00376 ptrdata+=ev->length;currentpos+=ev->length;
00377
00378
00379
00380 #ifdef TRACKDEBUG
00381 printfdebug("Track %d : Set Tempo : %ld\n",id,tempo);
00382 #endif
00383 #ifdef CHANGETEMPO_ONLY_IN_TRACK0
00384 if (id!=0) skip_event=1;
00385 #endif
00386 }
00387 break;
00388 case (ME_TIME_SIGNATURE) :
00389 ev->length=*ptrdata;ptrdata++;currentpos++;
00390 ev->d2=*ptrdata;ptrdata++;currentpos++;
00391 ev->d3=power2to(*ptrdata);ptrdata++;currentpos++;
00392 ev->d4=*ptrdata;ptrdata++;currentpos++;
00393 ev->d5=*ptrdata;ptrdata++;currentpos++;
00394 #ifdef TRACKDEBUG
00395 printfdebug("TIME SIGNATURE :\n");
00396 printfdebug("%d\n",ev->d2);
00397 printfdebug("---- %d metronome , %d number of 32nd notes per quarter note\n",ev->d4,ev->d5);
00398 printfdebug("%d\n",ev->d3);
00399 #endif
00400 break;
00401 case (ME_TRACK_SEQ_NUMBER) :
00402 case (ME_TEXT) :
00403 case (ME_COPYRIGHT) :
00404 case (ME_SEQ_OR_TRACK_NAME) :
00405 case (ME_TRACK_INSTR_NAME) :
00406 case (ME_LYRIC) :
00407 case (ME_MARKER) :
00408 case (ME_CUE_POINT) :
00409 case (ME_CHANNEL_PREFIX) :
00410 case (ME_MIDI_PORT) :
00411 case (ME_SMPTE_OFFSET) :
00412 case (ME_KEY_SIGNATURE) :
00413 ev->length=readVariableLengthValue();
00414 #ifdef PEDANTIC_TRACK
00415 if (endoftrack)
00416 {
00417 ev->command=MIDI_SYSTEM_PREFIX;
00418 ev->chn=0xF;
00419 ev->d1=ME_END_OF_TRACK;
00420 }
00421 else
00422 #endif
00423 {
00424 ev->data=ptrdata;
00425 ptrdata+=ev->length;currentpos+=ev->length;
00426 }
00427 break;
00428 default:
00429 #ifdef GENERAL_DEBUG_MESSAGES
00430 fprintf(stderr,"track (%d) : Default handler for meta event " \
00431 "0x%x\n", id, ev->d1);
00432 #endif
00433 ev->length=readVariableLengthValue();
00434 #ifdef PEDANTIC_TRACK
00435 if (endoftrack)
00436 {
00437 ev->command=MIDI_SYSTEM_PREFIX;
00438 ev->chn=0xF;
00439 ev->d1=ME_END_OF_TRACK;
00440 }
00441 else
00442 #endif
00443 {
00444 ev->data=ptrdata;
00445 ptrdata+=ev->length;currentpos+=ev->length;
00446 }
00447 break;
00448 }
00449 break;
00450 default :
00451 fprintf(stderr,"track (%d): Default handler for system event 0x%x\n",
00452 id, (ev->command|ev->chn));
00453 break;
00454 }
00455 break;
00456 default :
00457 fprintf(stderr,"track (%d): Default handler for event 0x%x\n",
00458 id, (ev->command|ev->chn));
00459 break;
00460 }
00461 #ifdef PEDANTIC_TRACK
00462 if (currentpos>=size)
00463 {
00464 endoftrack=1;
00465 delta_ticks = wait_ticks = ~0;
00466 time_at_next_event=10000 * 60000L;
00467 printfdebug("track (%d): EndofTrack reached\n",id);
00468 }
00469 #endif
00470 if (endoftrack==0)
00471 {
00472 current_ticks+=delta_ticks;
00473 delta_ticks=readVariableLengthValue();
00474 #ifdef PEDANTIC_TRACK
00475 if (endoftrack)
00476 {
00477 ev->command=MIDI_SYSTEM_PREFIX;
00478 ev->chn=0xF;
00479 ev->d1=ME_END_OF_TRACK;
00480 return;
00481 }
00482 #endif
00483 ticks_from_previous_tempochange+=delta_ticks;
00484
00485 time_at_next_event=T2MS(ticks_from_previous_tempochange)+time_at_previous_tempochange;
00486
00487
00488
00489
00490
00491 wait_ticks=delta_ticks;
00492
00493 }
00494 if (skip_event) readEvent(ev);
00495 }
00496
00497
00498 void MidiTrack::clear(void)
00499 {
00500 endoftrack=1;
00501 ptrdata=data;
00502 current_ticks=0;
00503 currentpos=0;
00504
00505 for (int i=0;i<16;i++)
00506 for (int j=0;j<128;j++)
00507 note[i][j]=FALSE;
00508
00509 delta_ticks = wait_ticks = ~0;
00510 time_at_previous_tempochange=0;
00511 current_time=0;
00512 ticks_from_previous_tempochange=0;
00513 tempo=1000000;
00514 time_at_next_event=10000 * 60000L;
00515
00516 }
00517
00518
00519 void MidiTrack::init(void)
00520 {
00521 if (data==0L) { clear(); return; };
00522 endoftrack=0;
00523 ptrdata=data;
00524 current_ticks=0;
00525 currentpos=0;
00526
00527 for (int i=0;i<16;i++)
00528 for (int j=0;j<128;j++)
00529 note[i][j]=FALSE;
00530
00531 delta_ticks=readVariableLengthValue();
00532 if (endoftrack) return;
00533 wait_ticks=delta_ticks;
00534
00535
00536 time_at_previous_tempochange=0;
00537 current_time=0;
00538 ticks_from_previous_tempochange=wait_ticks;
00539 tempo=1000000;
00540 time_at_next_event=T2MS(delta_ticks);
00541
00542 }
00543
00544 void MidiTrack::changeTempo(ulong t)
00545 {
00546 if (endoftrack==1) return;
00547 if (tempo==t) return;
00548 double ticks;
00549 time_at_previous_tempochange=current_time;
00550 ticks=MS2T(time_at_next_event-current_time);
00551 tempo=t;
00552 time_at_next_event=T2MS(ticks)+current_time;
00553 ticks_from_previous_tempochange=ticks;
00554
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 #undef T2MS
00566 #undef MS2T