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