00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "pent_include.h"
00023
00024 #ifdef USE_TIMIDITY_MIDI
00025
00026 #include <cstdio>
00027 #include <cstdlib>
00028 #include <cstring>
00029
00030 #ifndef _WIN32_WCE
00031 #include <cerrno>
00032 #else
00033 static int errno = 0;
00034 static char *strerror(int _errno) {
00035 return "";
00036 }
00037 #endif
00038
00039 #include "timidity.h"
00040 #include "timidity_common.h"
00041 #include "timidity_instrum.h"
00042 #include "timidity_playmidi.h"
00043 #include "timidity_readmidi.h"
00044 #include "timidity_output.h"
00045 #include "timidity_controls.h"
00046
00047 #ifdef NS_TIMIDITY
00048 namespace NS_TIMIDITY {
00049 #endif
00050
00051 sint32 quietchannels=0;
00052
00053
00054 static MidiEventList *evlist;
00055 static sint32 event_count;
00056 static FILE *fp;
00057 static sint32 at;
00058
00059
00060
00061 static sint32 sample_increment, sample_correction;
00062
00063
00064 static void compute_sample_increment(sint32 tempo, sint32 divisions)
00065 {
00066 double a;
00067 a = (double) (tempo) * (double) (play_mode->rate) * (65536.0/1000000.0) /
00068 (double)(divisions);
00069
00070 sample_correction = (sint32)(a) & 0xFFFF;
00071 sample_increment = (sint32)(a) >> 16;
00072
00073 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Samples per delta-t: %d (correction %d)",
00074 sample_increment, sample_correction);
00075 }
00076
00077
00078 static sint32 getvl(void)
00079 {
00080 sint32 l=0;
00081 uint8 c;
00082 for (;;)
00083 {
00084 fread(&c,1,1,fp);
00085 l += (c & 0x7f);
00086 if (!(c & 0x80)) return l;
00087 l<<=7;
00088 }
00089 }
00090
00091
00092
00093 static int dumpstring(sint32 len, char *label)
00094 {
00095 signed char *s=safe_Malloc<signed char>(len+1);
00096 if (len != (sint32)fread(s, 1, len, fp))
00097 {
00098 free(s);
00099 return -1;
00100 }
00101 s[len]='\0';
00102 while (len--)
00103 {
00104 if (s[len]<32)
00105 s[len]='.';
00106 }
00107 ctl->cmsg(CMSG_TEXT, VERB_VERBOSE, "%s%s", label, s);
00108 free(s);
00109 return 0;
00110 }
00111
00112 #define MIDIEVENT(at,t,ch,pa,pb) \
00113 event=safe_Malloc<MidiEventList>(); \
00114 event->event.time=at; event->event.type=t; event->event.channel=ch; \
00115 event->event.a=pa; event->event.b=pb; event->next=0;\
00116 return event;
00117
00118 #define MAGIC_EOT ((MidiEventList *)(-1))
00119
00120
00121
00122 static MidiEventList *read_midi_event(void)
00123 {
00124 static uint8 laststatus, lastchan;
00125 static uint8 nrpn=0, rpn_msb[16], rpn_lsb[16];
00126 uint8 me, type, a,b,c;
00127 sint32 len;
00128 MidiEventList *event;
00129
00130 for (;;)
00131 {
00132 at+=getvl();
00133 if (fread(&me,1,1,fp)!=1)
00134 {
00135 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: read_midi_event: %s",
00136 current_filename, strerror(errno));
00137 return 0;
00138 }
00139
00140 if(me==0xF0 || me == 0xF7)
00141 {
00142 len=getvl();
00143 skip(fp, len);
00144 }
00145 else if(me==0xFF)
00146 {
00147 fread(&type,1,1,fp);
00148 len=getvl();
00149 if (type>0 && type<16)
00150 {
00151 static char *label[]={
00152 "Text event: ", "Text: ", "Copyright: ", "Track name: ",
00153 "Instrument: ", "Lyric: ", "Marker: ", "Cue point: "};
00154 dumpstring(len, label[(type>7) ? 0 : type]);
00155 }
00156 else
00157 switch(type)
00158 {
00159 case 0x2F:
00160 return MAGIC_EOT;
00161
00162 case 0x51:
00163 fread(&a,1,1,fp); fread(&b,1,1,fp); fread(&c,1,1,fp);
00164 MIDIEVENT(at, ME_TEMPO, c, a, b);
00165
00166 default:
00167 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
00168 "(Meta event type 0x%02x, length %ld)", type, len);
00169 skip(fp, len);
00170 break;
00171 }
00172 }
00173 else
00174 {
00175 a=me;
00176 if (a & 0x80)
00177 {
00178 lastchan=a & 0x0F;
00179 laststatus=(a>>4) & 0x07;
00180 fread(&a, 1,1, fp);
00181 a &= 0x7F;
00182 }
00183 switch(laststatus)
00184 {
00185 case 0:
00186 fread(&b, 1,1, fp);
00187 b &= 0x7F;
00188 MIDIEVENT(at, ME_NOTEOFF, lastchan, a,b);
00189
00190 case 1:
00191 fread(&b, 1,1, fp);
00192 b &= 0x7F;
00193 MIDIEVENT(at, ME_NOTEON, lastchan, a,b);
00194
00195 case 2:
00196 fread(&b, 1,1, fp);
00197 b &= 0x7F;
00198 MIDIEVENT(at, ME_KEYPRESSURE, lastchan, a, b);
00199
00200 case 3:
00201 fread(&b, 1,1, fp);
00202 b &= 0x7F;
00203 {
00204 int control=255;
00205 switch(a)
00206 {
00207 case 7: control=ME_MAINVOLUME; break;
00208 case 10: control=ME_PAN; break;
00209 case 11: control=ME_EXPRESSION; break;
00210 case 64: control=ME_SUSTAIN; break;
00211 case 120: control=ME_ALL_SOUNDS_OFF; break;
00212 case 121: control=ME_RESET_CONTROLLERS; break;
00213 case 123: control=ME_ALL_NOTES_OFF; break;
00214
00215
00216
00217
00218
00219
00220
00221 case 0: control=ME_TONE_BANK; break;
00222 case 32:
00223 if (b!=0)
00224 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
00225 "(Strange: tone bank change 0x20%02x)", b);
00226 else
00227 control=ME_TONE_BANK;
00228 break;
00229
00230 case 100: nrpn=0; rpn_msb[lastchan]=b; break;
00231 case 101: nrpn=0; rpn_lsb[lastchan]=b; break;
00232 case 99: nrpn=1; rpn_msb[lastchan]=b; break;
00233 case 98: nrpn=1; rpn_lsb[lastchan]=b; break;
00234
00235 case 6:
00236 if (nrpn)
00237 {
00238 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
00239 "(Data entry (MSB) for NRPN %02x,%02x: %ld)",
00240 rpn_msb[lastchan], rpn_lsb[lastchan],
00241 b);
00242 break;
00243 }
00244
00245 switch((rpn_msb[lastchan]<<8) | rpn_lsb[lastchan])
00246 {
00247 case 0x0000:
00248 control=ME_PITCH_SENS;
00249 break;
00250
00251 case 0x7F7F:
00252
00253 MIDIEVENT(at, ME_PITCH_SENS, lastchan, 2, 0);
00254
00255 default:
00256 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
00257 "(Data entry (MSB) for RPN %02x,%02x: %ld)",
00258 rpn_msb[lastchan], rpn_lsb[lastchan],
00259 b);
00260 break;
00261 }
00262 break;
00263
00264 default:
00265 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
00266 "(Control %d: %d)", a, b);
00267 break;
00268 }
00269 if (control != 255)
00270 {
00271 MIDIEVENT(at, control, lastchan, b, 0);
00272 }
00273 }
00274 break;
00275
00276 case 4:
00277 a &= 0x7f;
00278 MIDIEVENT(at, ME_PROGRAM, lastchan, a, 0);
00279
00280 case 5:
00281 break;
00282
00283 case 6:
00284 fread(&b, 1,1, fp);
00285 b &= 0x7F;
00286 MIDIEVENT(at, ME_PITCHWHEEL, lastchan, a, b);
00287
00288 default:
00289 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00290 "*** Can't happen: status 0x%02X, channel 0x%02X",
00291 laststatus, lastchan);
00292 break;
00293 }
00294 }
00295 }
00296
00297 return event;
00298 }
00299
00300 #undef MIDIEVENT
00301
00302
00303
00304 static int read_track(int append)
00305 {
00306 MidiEventList *meep;
00307 MidiEventList *next, *new_event;
00308 sint32 len;
00309 char tmp[4];
00310
00311 meep=evlist;
00312 if (append && meep)
00313 {
00314
00315 for (; meep->next; meep=meep->next)
00316 ;
00317 at=meep->event.time;
00318 }
00319 else
00320 at=0;
00321
00322
00323
00324 if ((fread(tmp,1,4,fp) != 4) || (fread(&len,4,1,fp) != 1))
00325 {
00326 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00327 "%s: Can't read track header.", current_filename);
00328 return -1;
00329 }
00330 len=BE_LONG(len);
00331 if (memcmp(tmp, "MTrk", 4))
00332 {
00333 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00334 "%s: Corrupt MIDI file.", current_filename);
00335 return -2;
00336 }
00337
00338 for (;;)
00339 {
00340 if (!(new_event=read_midi_event()))
00341 return -2;
00342
00343 if (new_event==MAGIC_EOT)
00344 {
00345 return 0;
00346 }
00347
00348 next=meep->next;
00349 while (next && (next->event.time < new_event->event.time))
00350 {
00351 meep=next;
00352 next=meep->next;
00353 }
00354
00355 new_event->next=next;
00356 meep->next=new_event;
00357
00358 event_count++;
00359 meep=new_event;
00360 }
00361 }
00362
00363
00364 static void free_midi_list(void)
00365 {
00366 MidiEventList *meep, *next;
00367 if (!(meep=evlist)) return;
00368 while (meep)
00369 {
00370 next=meep->next;
00371 free(meep);
00372 meep=next;
00373 }
00374 evlist=0;
00375 }
00376
00377
00378
00379
00380
00381 static MidiEvent *groom_list(sint32 divisions,sint32 *eventsp,sint32 *samplesp)
00382 {
00383 MidiEvent *groomed_list, *lp;
00384 MidiEventList *meep;
00385 sint32 i, our_event_count, tempo, skip_this_event, new_value;
00386 sint32 sample_cum, samples_to_do, at, st, dt, counting_time;
00387
00388 int current_bank[16], current_set[16], current_program[16];
00389
00390
00391 for (i=0; i<16; i++)
00392 {
00393 current_bank[i]=0;
00394 current_set[i]=0;
00395 current_program[i]=default_program;
00396 }
00397
00398 tempo=500000;
00399 compute_sample_increment(tempo, divisions);
00400
00401
00402 groomed_list=lp=safe_Malloc<MidiEvent>(event_count+1);
00403 meep=evlist;
00404
00405 our_event_count=0;
00406 st=at=sample_cum=0;
00407 counting_time=2;
00408
00409 for (i=0; i<event_count; i++)
00410 {
00411 skip_this_event=0;
00412 ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
00413 "%6d: ch %2d: event %d (%d,%d)",
00414 meep->event.time, meep->event.channel + 1,
00415 meep->event.type, meep->event.a, meep->event.b);
00416
00417 if (meep->event.type==ME_TEMPO)
00418 {
00419 tempo=
00420 meep->event.channel + meep->event.b * 256 + meep->event.a * 65536;
00421 compute_sample_increment(tempo, divisions);
00422 skip_this_event=1;
00423 }
00424 else if ((quietchannels & (1<<meep->event.channel)))
00425 skip_this_event=1;
00426 else switch (meep->event.type)
00427 {
00428 case ME_PROGRAM:
00429 if (ISDRUMCHANNEL(meep->event.channel))
00430 {
00431 if (drumset[meep->event.a])
00432 new_value=meep->event.a;
00433 else
00434 {
00435 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
00436 "Drum set %d is undefined", meep->event.a);
00437 new_value=meep->event.a=0;
00438 }
00439 if (current_set[meep->event.channel] != new_value)
00440 current_set[meep->event.channel]=new_value;
00441 else
00442 skip_this_event=1;
00443 }
00444 else
00445 {
00446 new_value=meep->event.a;
00447 if ((current_program[meep->event.channel] != SPECIAL_PROGRAM)
00448 && (current_program[meep->event.channel] != new_value))
00449 current_program[meep->event.channel] = new_value;
00450 else
00451 skip_this_event=1;
00452 }
00453 break;
00454
00455 case ME_NOTEON:
00456 if (counting_time)
00457 counting_time=1;
00458 if (ISDRUMCHANNEL(meep->event.channel))
00459 {
00460
00461 if (!(drumset[current_set[meep->event.channel]]
00462 ->tone[meep->event.a].instrument))
00463 drumset[current_set[meep->event.channel]]
00464 ->tone[meep->event.a].instrument=
00465 MAGIC_LOAD_INSTRUMENT;
00466 }
00467 else
00468 {
00469 if (current_program[meep->event.channel]==SPECIAL_PROGRAM)
00470 break;
00471
00472 if (!(tonebank[current_bank[meep->event.channel]]
00473 ->tone[current_program[meep->event.channel]].instrument))
00474 tonebank[current_bank[meep->event.channel]]
00475 ->tone[current_program[meep->event.channel]].instrument=
00476 MAGIC_LOAD_INSTRUMENT;
00477 }
00478 break;
00479
00480 case ME_TONE_BANK:
00481 if (ISDRUMCHANNEL(meep->event.channel))
00482 {
00483 skip_this_event=1;
00484 break;
00485 }
00486 if (tonebank[meep->event.a])
00487 new_value=meep->event.a;
00488 else
00489 {
00490 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
00491 "Tone bank %d is undefined", meep->event.a);
00492 new_value=meep->event.a=0;
00493 }
00494 if (current_bank[meep->event.channel]!=new_value)
00495 current_bank[meep->event.channel]=new_value;
00496 else
00497 skip_this_event=1;
00498 break;
00499 }
00500
00501
00502 if ((dt=meep->event.time - at) && !counting_time)
00503 {
00504 samples_to_do=sample_increment * dt;
00505 sample_cum += sample_correction * dt;
00506 if (sample_cum & 0xFFFF0000)
00507 {
00508 samples_to_do += ((sample_cum >> 16) & 0xFFFF);
00509 sample_cum &= 0x0000FFFF;
00510 }
00511 st += samples_to_do;
00512 }
00513 else if (counting_time==1) counting_time=0;
00514 if (!skip_this_event)
00515 {
00516
00517 *lp=meep->event;
00518 lp->time=st;
00519 lp++;
00520 our_event_count++;
00521 }
00522 at=meep->event.time;
00523 meep=meep->next;
00524 }
00525
00526 lp->time=st;
00527 lp->type=ME_EOT;
00528 our_event_count++;
00529 free_midi_list();
00530
00531 *eventsp=our_event_count;
00532 *samplesp=st;
00533 return groomed_list;
00534 }
00535
00536 MidiEvent *read_midi_file(FILE *mfp, sint32 *count, sint32 *sp)
00537 {
00538 sint32 len, divisions;
00539 sint16 format, tracks, divisions_tmp;
00540 int i;
00541 char tmp[4];
00542
00543 fp=mfp;
00544 event_count=0;
00545 at=0;
00546 evlist=0;
00547
00548 if ((fread(tmp,1,4,fp) != 4) || (fread(&len,4,1,fp) != 1))
00549 {
00550 if (ferror(fp))
00551 {
00552 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", current_filename,
00553 strerror(errno));
00554 }
00555 else
00556 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00557 "%s: Not a MIDI file!", current_filename);
00558 return 0;
00559 }
00560 len=BE_LONG(len);
00561 if (memcmp(tmp, "MThd", 4) || len < 6)
00562 {
00563 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00564 "%s: Not a MIDI file!", current_filename);
00565 return 0;
00566 }
00567
00568 fread(&format, 2, 1, fp);
00569 fread(&tracks, 2, 1, fp);
00570 fread(&divisions_tmp, 2, 1, fp);
00571 format=BE_SHORT(format);
00572 tracks=BE_SHORT(tracks);
00573 divisions_tmp=BE_SHORT(divisions_tmp);
00574
00575 if (divisions_tmp<0)
00576 {
00577
00578 divisions=
00579 (sint32)(-(divisions_tmp/256)) * (sint32)(divisions_tmp & 0xFF);
00580 }
00581 else divisions=(sint32)(divisions_tmp);
00582
00583 if (len > 6)
00584 {
00585 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
00586 "%s: MIDI file header size %ld bytes",
00587 current_filename, len);
00588 skip(fp, len-6);
00589 }
00590 if (format<0 || format >2)
00591 {
00592 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
00593 "%s: Unknown MIDI file format %d", current_filename, format);
00594 return 0;
00595 }
00596 ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
00597 "Format: %d Tracks: %d Divisions: %d", format, tracks, divisions);
00598
00599
00600 evlist=safe_Malloc<MidiEventList>();
00601 evlist->event.time=0;
00602 evlist->event.type=ME_NONE;
00603 evlist->next=0;
00604 event_count++;
00605
00606 switch(format)
00607 {
00608 case 0:
00609 if (read_track(0))
00610 {
00611 free_midi_list();
00612 return 0;
00613 }
00614 break;
00615
00616 case 1:
00617 for (i=0; i<tracks; i++)
00618 if (read_track(0))
00619 {
00620 free_midi_list();
00621 return 0;
00622 }
00623 break;
00624
00625 case 2:
00626 for (i=0; i<tracks; i++)
00627 if (read_track(1))
00628 {
00629 free_midi_list();
00630 return 0;
00631 }
00632 break;
00633 }
00634 return groom_list(divisions, count, sp);
00635 }
00636
00637 #ifdef NS_TIMIDITY
00638 };
00639 #endif
00640
00641 #endif //USE_TIMIDITY_MIDI