summaryrefslogtreecommitdiff
path: root/support/mid2tex/src/readmidi.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/mid2tex/src/readmidi.c
Initial commit
Diffstat (limited to 'support/mid2tex/src/readmidi.c')
-rw-r--r--support/mid2tex/src/readmidi.c1040
1 files changed, 1040 insertions, 0 deletions
diff --git a/support/mid2tex/src/readmidi.c b/support/mid2tex/src/readmidi.c
new file mode 100644
index 0000000000..4d272ac670
--- /dev/null
+++ b/support/mid2tex/src/readmidi.c
@@ -0,0 +1,1040 @@
+/***************************/
+/* readmidi.c */
+/***************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "midi.h"
+#include "maintypes.h"
+#include "defines.h"
+#include "readmidi.h"
+
+#ifdef DEBUG
+static void ausgabe()
+{
+ printf("MThd = %s, chunk_length = %d\n", head.MThd , head.chunk_length);
+ printf("format = %d, tracks = %d, per_quarter = %x\n",
+ head.format, head.tracks, head.per_quarter);
+
+ printf("Mtrk = %s, Track_chunk_length = %d\n",
+ THead.MTrk, THead.chunk_length);
+}
+#endif
+
+static unsigned long get_valid_time(ti)
+ unsigned long ti;
+{
+ if (ti < bartime) {
+ if (ti < lastbartime) {
+ converter = 0;
+ sequencecounter = 0;
+ }
+ else {
+ converter = lastbartime;
+ sequencecounter = (double) lastbartime;
+ }
+ }
+ else {
+ converter = bartime;
+ sequencecounter = (double) bartime;
+ }
+ while (ti > converter) {
+ lastsc = sequencecounter;
+ sequencecounter += one64tel;
+ converter = (unsigned long) sequencecounter;
+ }
+ if (ti < converter) ti = (unsigned long) lastsc;
+ return(ti);
+}
+
+static char midi_getc(fpointer)
+ FILE *fpointer;
+{
+ if (THead.chunk_length-- < 0) {
+ fprintf(stderr, "midi_getc: Length Underflow\n");
+ exit(10);
+ }
+ return(getc(fpointer));
+}
+
+static void midi_ungetc(c, fpointer)
+ FILE *fpointer;
+ char c;
+{
+ THead.chunk_length++;
+ ungetc(c, fpointer);
+}
+
+static unsigned int ReadVarLen()
+{
+ unsigned int value;
+ unsigned char c;
+
+ if ((value = midi_getc(fp)) & 0x80) {
+ value &= 0x7f;
+ do {
+ value = (value << 7) + ((c = midi_getc(fp)) & 0x7f);
+ }
+ while (c & 0x80);
+ }
+
+ return(value);
+}
+
+
+static void ReadMidiTrackName(delta)
+ int delta;
+{
+ int len, i;
+
+ len = ReadVarLen();
+ for (i = 0; i < len; i++) {
+ if (i < 80 - 1) TrackName[Track_Nr][i] = midi_getc(fp);
+ else midi_getc(fp);
+ }
+ if (i<80) TrackName[Track_Nr][i] = '\0';
+ else TrackName[Track_Nr][79] = '\0';
+
+#ifdef DEBUG
+ printf("MIDI_TRACK_NAME (%s) at %d\n", TrackName[Track_Nr], delta);
+#endif
+
+}
+
+static void ReadMidiSequSpec(delta)
+ int delta;
+{
+ int len, i;
+ char Str[80];
+#ifdef DEBUG
+ int j;
+#endif
+
+ len = ReadVarLen();
+ for (i = 0; i < len; i++) {
+ if (i < 80 - 1) Str[i] = midi_getc(fp);
+ }
+ Str[i] = '\0';
+#ifdef DEBUG
+ printf("MIDI_SEQUENCER_SPECIFIC at %d:\n", delta);
+ for (j = 0; j < i; j++)
+ printf("\t0x%x\n", Str[j]);
+#endif
+}
+
+#ifdef DEBUG
+static char *p2str(oct, pit)
+ int oct, pit;
+{
+ static char Str[10];
+ static char *p_table[12] = {"C", "Cis", "D", "Dis",
+ "E", "F", "Fis", "G",
+ "Gis", "A", "B", "H"};
+
+ sprintf(Str, "%s%d", p_table[pit], oct);
+ return(Str);
+}
+#endif
+
+static void ReadMidiToneVal(oct, pit, laut)
+ int *oct, *pit, *laut;
+{
+ int w;
+ unsigned char inthelp;
+
+ w = midi_getc(fp);
+ *laut = midi_getc(fp);
+
+ /* allow only octaves 0 - 5 */
+ if ((w>24) && (w<95)) {
+ *oct = (w / 12) - 2;
+ *pit = (w % 12);
+ }
+ else {
+ *oct = 6;
+ *pit = 0;
+ }
+
+ inthelp = 12 * (*oct) + (*pit);
+ if (max[Track_Nr] < inthelp) max[Track_Nr] = inthelp;
+ if (min[Track_Nr] > inthelp) min[Track_Nr] = inthelp;
+}
+
+static void erzeuge_note(octave, pitch, laut, begin, dauer, channel)
+ int octave, pitch, laut, dauer, channel;
+ unsigned long int begin;
+{
+ if (firstnotetimeflag == -1) {
+ firstnotetime = begin;
+ firstnotetimeflag = 0;
+ }
+ /* if there were no TimeSig */
+ if ((valid == 0) && (begin > firstnotetime)) {
+ valid++;
+ if ((!printonly) || (Track_Nr == (printonly -1))) {
+ if ((!notes_flag) && (nom0) && (Track_Nr))
+ ins_dyn_event(Track_Nr, 't', 0, nom0, denom0, 0, 0, 0, 0, 0);
+ else
+ ins_dyn_event(Track_Nr, 't', 0, 4, 4, 0, 0, 0, 0, 0);
+ }
+ }
+
+ /* if there were no KeySig */
+ if ((valid2 == 0) && (begin > firstnotetime)) {
+ valid2++;
+ if ((!printonly) || (Track_Nr == (printonly -1))) {
+ if ((!notes_flag) && (key0) && (Track_Nr))
+ ins_dyn_event(Track_Nr, 'k', 0, key0, 0, 0, 0, 0, 0, 0);
+ else
+ ins_dyn_event(Track_Nr, 'k', 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "NOTE into dyn_event_list inserted\n");
+ fprintf(stdout, "oct: %d\t pit: %d\t laut: %x\t beg: %lx\t durat: %x\n",
+ octave, pitch, laut, begin, dauer);
+#endif
+ /* notes_flag shows that notes of first track were read */
+ /* */
+ /* because f.e. rosegarden writes empty first track */
+ /* with takt and key info for all other tracks */
+
+ if (Track_Nr == 0) notes_flag = 1;
+
+ if (((!printonly) || (Track_Nr == (printonly -1))) && (octave != 6))
+ ins_dyn_event(Track_Nr, 'n', 0, 0, 0, octave, pitch, laut, get_valid_time(begin), dauer);
+}
+
+static void ReadMidiNoteOff(channel, delta)
+ int channel, delta;
+{
+ int dauer, octave, pitch, laut, la;
+ unsigned long int begin;
+
+ ReadMidiToneVal(&octave, &pitch, &laut);
+
+#ifdef DEBUG
+ printf("MIDI_NOTE_OFF at %d(%ld): Channel: %d, pitch = %s, laut = 0x%x\n",
+ delta, zeit, channel, p2str(octave, pitch), laut);
+#endif
+ dauer = note_delete(octave, pitch, &la, zeit, &begin, channel);
+#ifdef DEBUG
+ printf("Generate_Note with begin = %ld, absolute time = %ld, duration = %d\n",
+ begin, zeit, dauer);
+#endif
+ erzeuge_note(octave, pitch, la, begin, dauer, channel);
+}
+
+static void ReadMidiNoteOn(channel, delta)
+ int channel, delta;
+{
+ int dauer, octave, pitch, laut, la;
+ unsigned long int begin;
+
+ ReadMidiToneVal(&octave, &pitch, &laut);
+
+ if (laut) {
+ note_insert(octave, pitch, laut, zeit, channel);
+ }
+ else {
+ dauer = note_delete(octave, pitch, &la, zeit, &begin, channel);
+#ifdef DEBUG
+ printf("Generate_Note with begin = %ld, absolute time = %ld, duration = %d\n",
+ begin, zeit, dauer);
+#endif
+ erzeuge_note(octave, pitch, la, begin, dauer, channel);
+ }
+#ifdef DEBUG
+ printf("MIDI_NOTE_ON at %d(%ld): Channel: %d, pitch = %s, laut = 0x%x\n",
+ delta, zeit, channel, p2str(octave, pitch), laut);
+#endif
+}
+
+static void ReadMidiPolyAftertouch(channel, delta)
+ int channel, delta;
+{
+ char dum1, dum2;
+
+ dum1 = midi_getc(fp); dum2 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_POLY_AFTERTOUCH: 0x%x, 0x%x, 0x%x\n", channel, dum1, dum2);
+#endif
+}
+
+static void ReadMidiCtrlChange(channel, delta)
+ int channel, delta;
+{
+ char dum1, dum2;
+
+ dum1 = midi_getc(fp); dum2 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_CTRL_CHANGE: 0x%x, 0x%x, 0x%x\n", channel, dum1, dum2);
+#endif
+}
+
+static void ReadMidiProgChange(channel, delta)
+ int channel, delta;
+{
+ char dum1;
+
+ dum1 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_PROG_CHANGE: 0x%x, 0x%x\n", channel, dum1);
+#endif
+}
+
+static void ReadMidiChnlAftertouch(channel, delta)
+ int channel, delta;
+{
+ char dum1;
+
+ dum1 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_CHNL_AFTERTOUCH: 0x%x, 0x%x\n", channel, dum1);
+#endif
+}
+
+static void ReadMidiPitchBend(channel, delta)
+ int channel, delta;
+{
+ char dum1, dum2;
+
+ dum1 = midi_getc(fp); dum2 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_PITCH_BEND: 0x%x, 0x%x, 0x%x\n", channel, dum1, dum2);
+#endif
+}
+
+static void ReadMidiSongPositionPtr(delta)
+ int delta;
+{
+ char dum1, dum2;
+
+ dum1 = midi_getc(fp); dum2 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_SONG_POSITION_PTR: 0x%x, 0x%x\n", dum1, dum2);
+#endif
+}
+
+static void ReadMidiSongSelect(delta)
+ int delta;
+{
+ char dum1;
+
+ dum1 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_SONG_SELECT: 0x%x\n", dum1);
+#endif
+}
+
+static void ReadMidiSystemExclusive()
+{
+ int dum;
+ unsigned int value;
+
+ dum = ReadVarLen();
+ while ((value = midi_getc(fp)) != MIDI_EOX);
+#ifdef DEBUG
+ printf("MIDI_SYSTEM_EXCLUSIVE\n");
+#endif
+}
+
+static void ReadMidiSetTempo(delta)
+ int delta;
+{
+ unsigned int len, tempo;
+
+ len = midi_getc(fp);
+ if (len == 0x03) {
+ tempo = 0;
+ while(len--) {
+ tempo *= 0x100;
+ tempo += (unsigned int) (0xff & midi_getc(fp));
+ }
+#ifdef DEBUG
+ D_Tempo = (double) tempo / 1000000.0;
+ printf("MIDI_SET_TEMPO at %d: Tempo = %d(%f)\n", delta, tempo, D_Tempo);
+#endif
+ }
+ else { /* system reset detect */
+ midi_ungetc(len, fp);
+ midi_ungetc(0x51, fp);
+ }
+}
+
+static void ReadMidiTimeSig(delta)
+ int delta;
+{
+ int dummy, nn, dd, cc, bb, dominator;
+
+ dummy = midi_getc(fp);
+ if (dummy == 0x04) {
+ valid = 1; /* means: TimeSig detected */
+ nn = midi_getc(fp);
+ dd = midi_getc(fp);
+ cc = midi_getc(fp);
+ bb = midi_getc(fp);
+ dominator = (1 << dd);
+ help = taktzeit;
+ taktzeit = head.per_quarter * nn * 4 / dominator;
+ diskrete_tz = diskrete_tz + taktzeit - help;
+ if ((!Track_Nr) && (!nom0)) {
+ nom0 = nn;
+ denom0 = dominator;
+ }
+ if ((!printonly) || (Track_Nr == (printonly -1)))
+ ins_dyn_event(Track_Nr, 't', 0, nn, dominator, 0, 0, 0, get_valid_time(zeit), 0);
+
+#ifdef DEBUG
+ printf("Takt: %x\n",taktzeit);
+ printf("MIDI_TIME_SIGNATURE at %d: Takt:%d/%d\nMIDI-clocks per Metronom: %d,",
+ delta, nn, dominator, cc);
+ printf("%d 32nd per MIDI-Quarter\n", bb);
+#endif
+ }
+ else { /* system reset detect */
+ midi_ungetc(dummy, fp);
+ midi_ungetc(0x58, fp);
+ }
+}
+
+static void ReadMidiTextEvent(delta)
+ int delta;
+{
+ unsigned int len;
+ int value;
+
+ len = ReadVarLen();
+ while (len--) value = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_TEXT_EVENT\n");
+#endif
+}
+
+static void ReadMidiCopyrightNotice(delta)
+ int delta;
+{
+ unsigned int len;
+ int value;
+
+ len = ReadVarLen();
+ while (len--) value = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_COPYRIGHT_NOTICE\n");
+#endif
+}
+
+static void ReadMidiInstrumentName(delta)
+ int delta;
+{
+ unsigned int len;
+ int value=0;
+
+ len = ReadVarLen();
+ while (len--) Staffs[Track_Nr][value++] = midi_getc(fp);
+ Staffs[Track_Nr][value] = 0;
+#ifdef DEBUG
+ printf("MIDI_INSTRUMENT_NAME: %s\n",Staffs[Track_Nr]);
+#endif
+}
+
+static void ReadMidiLyrik(delta)
+ int delta;
+{
+ unsigned int len;
+ char *ptr, *ptrhelp;
+
+ len = ReadVarLen();
+ if ((ptr = (char *) malloc (len+1)) == NULL) {
+ fprintf(stderr, "mallocC error\n");
+ exit(10);
+ }
+ ptrhelp = ptr;
+ while (len--) {
+ *ptrhelp = midi_getc(fp);
+ ptrhelp++;
+ }
+ *ptrhelp = 0;
+#ifdef DEBUG
+ printf("MIDI_LYRIC\n");
+#endif
+ if ((!printonly) || (Track_Nr == (printonly -1)))
+ ins_dyn_event(Track_Nr, 'l', ptr, 0, 0, 0, 0, 0, get_valid_time(zeit), 0);
+}
+
+static void ReadMidiTextMarker(delta)
+ int delta;
+{
+ unsigned int len;
+ int value;
+
+ len = ReadVarLen();
+ while (len--) value = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_TEXT_MARKER\n");
+#endif
+}
+
+static void ReadMidiCuePoint(delta)
+ int delta;
+{
+ unsigned int len;
+ int value;
+
+ len = ReadVarLen();
+ while (len--) value = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_CUE_POINT\n");
+#endif
+}
+
+static void ReadMidiChannelPrefix(delta)
+ int delta;
+{
+ int dum1, dum2;
+ dum1 = midi_getc(fp);
+ if (dum1 == 0x01) {
+ dum2 = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_CHANNEL_PREFIX\n");
+#endif
+ }
+ else { /* system reset detect */
+ midi_ungetc(dum1, fp);
+ midi_ungetc(0x20, fp);
+ }
+}
+
+static void ReadMidiSmpteOffset(delta)
+ int delta;
+{
+ int dum;
+
+ if (delta != 0) { /* system reset detect */
+ midi_ungetc(0x54, fp);
+ }
+ else {
+ dum = midi_getc(fp);
+ if (dum == 0x05) {
+ midi_getc(fp); midi_getc(fp); midi_getc(fp);
+ midi_getc(fp); midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_SMPTE_OFFSET\n");
+#endif
+ }
+ else { /* system reset detect */
+ midi_ungetc(dum, fp);
+ midi_ungetc(0x54, fp);
+ }
+ }
+}
+
+static void ReadMidiSequenceNumber(MetaEvent, delta)
+ int delta;
+ unsigned char MetaEvent;
+{
+ int value;
+
+ value = midi_getc(fp);
+ if (value != 0x02) { /* system reset detect */
+ midi_ungetc(value, fp);
+ midi_ungetc(0x00, fp);
+ }
+ else {
+ value = midi_getc(fp); value = midi_getc(fp);
+ value = midi_getc(fp); value = midi_getc(fp);
+#ifdef DEBUG
+ printf("MIDI_SEQUENCE_NUMBER\n");
+#endif
+ }
+}
+
+static void ReadMidiKeySig(delta)
+ int delta;
+{
+ int dum, sign;
+
+ dum = midi_getc(fp);
+ if (dum != 0x02) { /* system reset detect */
+ midi_ungetc(dum, fp);
+ midi_ungetc(0x59, fp);
+ }
+ else {
+ valid2 = 1; /* KeySig detected */
+ sign = midi_getc(fp);
+ /* manipulate sign */
+ if ((sign & 0x80) && (sign & 0x08)) {
+ sign = sign ^ 0xf;
+ sign++;
+ }
+ if ((!Track_Nr) && (!key0)) key0 = sign;
+ if ((!printonly) || (Track_Nr == (printonly -1)))
+ ins_dyn_event(Track_Nr, 'k', 0, sign, 0, 0, 0, 0, get_valid_time(zeit), 0);
+ T_genus = (0xff & sign);
+ Signature = (0xff & midi_getc(fp));
+#ifdef DEBUG
+ printf("MIDI_KEY_SIGNATURE at %d: T_genus = ", delta);
+ switch (T_genus) {
+ case MINOR: printf("MINOR"); break;
+ case MAJOR: printf("MAJOR"); break;
+ default: printf("unknown"); break;
+ }
+ printf(" Signature = %d\n", Signature);
+#endif
+ }
+}
+
+static void ReadMidiEndOfTrack(delta)
+ int delta;
+{
+ int dum, dauer, octave, pitch, laut, channel;
+ unsigned long int begin;
+
+ dum = midi_getc(fp);
+ if (dum == 0) {
+ dum = midi_getc(fp); /* read - deltatime */
+ while (dum == 0) { /* falls nach EOTrack noch Folgeelement */
+ midi_ungetc(dum, fp);
+ ReadEvent();
+ dum = midi_getc(fp);
+ }
+ midi_ungetc(dum, fp);
+ while ((dauer = search_note(&octave, &pitch, &laut, zeit, &begin, &channel)) != -1) {
+#ifdef DEBUG
+ printf("erzeuge_note mit begin = %ld, zeit = %ld, dauer = %d\n",
+ begin, zeit, dauer);
+#endif
+ erzeuge_note(octave, pitch, laut, begin, dauer, channel);
+ }
+
+ if (THead.chunk_length) {
+ fprintf(stderr, "Warning: ReadMidiEndOfTrack: Sync_Error THead.chunk_length = %d\n",
+ THead.chunk_length);
+ while (THead.chunk_length >= 0) midi_getc(fp);
+ }
+#ifdef DEBUG
+ printf("MIDI_END_OF_TRACK at %d\n", delta);
+#endif
+ }
+ else { /* system reset detect */
+ midi_ungetc(dum, fp);
+ midi_ungetc(0x2f, fp);
+ }
+}
+
+static int ReadMidiMetaEvent(delta)
+ int delta;
+{
+ unsigned char MetaEvent;
+ int not_eot = 1;
+
+ switch(MetaEvent = midi_getc(fp)) {
+ case MIDI_SEQUENCE_NUMBER: ReadMidiSequenceNumber(MetaEvent,delta); break;
+ case MIDI_TEXT_EVENT: ReadMidiTextEvent(delta); break;
+ case MIDI_TRACK_NAME: ReadMidiTrackName(delta); break;
+ case MIDI_SET_TEMPO: ReadMidiSetTempo(delta); break;
+ case MIDI_TIME_SIGNATURE: ReadMidiTimeSig(delta); break;
+ case MIDI_END_OF_TRACK: ReadMidiEndOfTrack(delta); not_eot = 0; break;
+ case MIDI_KEY_SIGNATURE: ReadMidiKeySig(delta); break;
+ case MIDI_SEQUENCER_SPECIFIC: ReadMidiSequSpec(delta); break;
+ case MIDI_CHANNEL_PREFIX: ReadMidiChannelPrefix(delta); break;
+ case MIDI_SMPTE_OFFSET: ReadMidiSmpteOffset(delta); break;
+ case MIDI_COPYRIGHT_NOTICE: ReadMidiCopyrightNotice(delta); break;
+ case MIDI_INSTRUMENT_NAME: ReadMidiInstrumentName(delta); break;
+ case MIDI_LYRIC: ReadMidiLyrik(delta); break;
+ case MIDI_TEXT_MARKER: ReadMidiTextMarker(delta); break;
+ case MIDI_CUE_POINT: ReadMidiCuePoint(delta); break;
+ default: /* system reset detect */
+ midi_ungetc(MetaEvent, fp); break;
+ }
+ return(not_eot);
+}
+
+static int ReadEvent()
+{
+ unsigned char Event_Type;
+ int delta, not_eot = 1;
+
+ delta = ReadVarLen();
+ zeit += delta;
+
+ while (zeit >= diskrete_tz) {
+ if ((!printonly) || (Track_Nr == (printonly -1))) {
+ lastbartime = bartime;
+ bartime = diskrete_tz;
+ ins_dyn_event(Track_Nr, 'b', 0, 0, 0, 0, 0, 0, diskrete_tz, taktzeit);
+ }
+ diskrete_tz += taktzeit;
+ }
+
+ Event_Type = midi_getc(fp);
+r_event:
+ if ((0xf0 & Event_Type) == MIDI_NOTE_OFF) {
+ ReadMidiNoteOff((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_NOTE_ON) {
+ ReadMidiNoteOn((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_POLY_AFTERTOUCH) {
+ ReadMidiPolyAftertouch((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_CTRL_CHANGE) {
+ ReadMidiCtrlChange((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_PROG_CHANGE) {
+ ReadMidiProgChange((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_CHNL_AFTERTOUCH) {
+ ReadMidiChnlAftertouch((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_PITCH_BEND) {
+ ReadMidiPitchBend((Event_Type & 0xf), delta);
+ }
+ else if ((0xf0 & Event_Type) == MIDI_SYSTEM_MSG) {
+ if (Event_Type == MIDI_FILE_META_EVENT) {
+ not_eot = ReadMidiMetaEvent(delta);
+ }
+ else {
+ /* treatment of all other 0xfx-events */
+ switch (0xf & Event_Type) {
+ case MIDI_SONG_POSITION_PTR: /* 0xf2 */
+ ReadMidiSongPositionPtr(delta);
+ break;
+ case MIDI_SONG_SELECT: /* 0xf3 */
+ ReadMidiSongSelect(delta);
+ break;
+ case MIDI_SYSTEM_EXCLUSIVE: /* 0xf0 */
+ ReadMidiSystemExclusive();
+ break;
+ case MIDI_TUNE_REQUEST: /* 0xf6 */
+ case MIDI_TIMING_CLOCK: /* 0xf8 */
+ case MIDI_START: /* 0xfa */
+ case MIDI_CONTINUE: /* 0xfb */
+ case MIDI_STOP: /* 0xfc */
+ case MIDI_ACTIVE_SENSING: /* 0xfe */
+ midi_getc(fp);
+ break;
+ default:
+ fprintf(stderr, "Event: 0x%x unknown\n", Event_Type);
+ fprintf(stderr, "Fileoffset: %lu\n", ftell(fp));
+ exit(10);
+ }
+ }
+ }
+ else if (Running_Event) {
+#ifdef DEBUG
+ printf("Running Event\n");
+#endif
+ midi_ungetc(Event_Type, fp);
+
+ Event_Type = Running_Event;
+ goto r_event;
+ }
+ else {
+ fprintf(stderr, "Event: 0x%x unknown\n", Event_Type);
+ fprintf(stderr, "Fileoffset: %lu\n", ftell(fp));
+ exit(10);
+ }
+ Running_Event = Event_Type;
+ return(not_eot);
+}
+
+
+static void read_track()
+{
+ zeit = 0;
+ THead.MTrk[0] = getc(fp); THead.MTrk[1] = getc(fp);
+ THead.MTrk[2] = getc(fp); THead.MTrk[3] = getc(fp);
+ THead.MTrk[4] = '\0';
+ if (strcmp(THead.MTrk, MIDI_TRACK_HEADER)) {
+ fprintf(stderr, "read_track: Sync_error(%s)\n", THead.MTrk);
+ exit(10);
+ }
+ THead.chunk_length = 0x1000000 * getc(fp);
+ THead.chunk_length += 0x10000 * getc(fp);
+ THead.chunk_length += 0x100 * getc(fp);
+ THead.chunk_length += getc(fp);
+#ifdef DEBUG
+ ausgabe();
+#endif
+ Running_Event = 0;
+ while (ReadEvent());
+}
+
+static void usage(conststrg)
+ char *conststrg;
+{
+ fprintf(stderr,"usage:\t%s [-<nr>] <midifile> [<texfile>]\n", conststrg);
+ fprintf(stderr,"\t%s -c <midifile>\n", conststrg);
+ exit(10);
+}
+
+void main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int lenhelp;
+ char opthelp;
+
+ if (argc < 2) usage(argv[0]);
+
+ if ((argc == 3) && (!strcmp(argv[1],"-c"))) {
+ if ((fp = fopen(argv[2], "r")) == NULL) {
+ fprintf(stderr, "cannot open %s\n", argv[1]);
+ exit(10);
+ }
+ count = 1;
+ }
+ else {
+ count = 0;
+ if (*argv[1] == '-') {
+ if ((argc == 2) || (*argv[2] == '-') || (argc > 4)) usage(argv[0]);
+ opthelp = 1;
+ printonly = (char) atoi((argv[1])+1);
+ if (!printonly) printonly = 20;
+ }
+ else {
+ if (argc > 3) usage(argv[0]);
+ printonly = 0; /* print every track */
+ opthelp = 0;
+ }
+
+ if ((fp = fopen(argv[1+opthelp], "r")) == NULL) {
+ fprintf(stderr, "cannot open %s\n", argv[1+opthelp]);
+ exit(10);
+ }
+
+ /* fill the array for the name of tex file */
+ if (argc == (3+opthelp)) {
+ if (!strcmp(argv[1+opthelp], argv[2+opthelp])) {
+ fprintf(stderr, "cannot process one file to itself\n");
+ exit(10);
+ }
+ strcpy(texfilename, argv[2+opthelp]);
+ }
+ else { /* mainmark1: try to select a nice name for texfile */
+ strcpy(texfilename, argv[1+opthelp]);
+ lenhelp = strlen(texfilename) - 4;
+
+ /* delete midi file extension */
+ if ((!strcmp(&(texfilename[lenhelp]),".mid")) ||
+ (!strcmp(&(texfilename[lenhelp]),".MID")))
+ texfilename[lenhelp] = 0;
+ else {
+ if ((!strcmp(&(texfilename[lenhelp+1]),".mf")) ||
+ (!strcmp(&(texfilename[lenhelp+1]),".MF")))
+ texfilename[lenhelp+1] = 0;
+ }
+ if ((texfilename[0] > 64) && (texfilename[0] < 91))
+ strcat(texfilename, ".TEX");
+ else
+ strcat(texfilename, ".tex");
+ }
+
+ }
+
+ /* mainmark2 */
+ head.MThd[0] = getc(fp); head.MThd[1] = getc(fp);
+ head.MThd[2] = getc(fp); head.MThd[3] = getc(fp); head.MThd[4] = '\0';
+ if (strcmp(head.MThd, MIDI_FILE_HEADER)) {
+ fprintf(stderr, "specified file probably not a midi-file or corrupted\n");
+ exit(10);
+ }
+
+ head.chunk_length = 0x1000000 * getc(fp);
+ head.chunk_length += 0x10000 * getc(fp);
+ head.chunk_length += 0x100 * getc(fp);
+ head.chunk_length += getc(fp);
+
+ if (head.chunk_length != 6) {
+ fprintf(stderr, "wrong header chunk length\n");
+ exit(10);
+ }
+
+ head.format = 0x100 * getc(fp); head.format += getc(fp);
+ head.tracks = 0x100 * getc(fp); head.tracks += getc(fp);
+
+ /* mainmark3 */
+ if (count) {
+ printf("%d tracks detected\n", head.tracks);
+ exit(0);
+ }
+
+ if (printonly && (printonly > head.tracks)) {
+ printf("can't build tex-file of specified track \n");
+ exit(0);
+ }
+
+ if ((!printonly) && ((head.tracks) > 9))
+ fprintf(stderr, "Warning: printing out so many tracks together may look very ugly\n");
+
+ head.per_quarter = 0x100 * (0xff & getc(fp));
+ head.per_quarter += (0xff & getc(fp));
+ if (head.format != 1) {
+ fprintf(stderr, "Format %d not supported\n", head.format);
+ exit(10);
+ }
+
+ if (head.per_quarter & 0x8000) {
+ fprintf(stderr, "SMPTE-Time Code not supported\n");
+ exit(10);
+ }
+
+ /* mainmark4 */
+ one64tel = (double) head.per_quarter / 16;
+
+ /* mainmark5 */
+ nom0 = 0;
+ key0 = 0;
+ notes_flag = 0;
+ for (lenhelp = 0; lenhelp < MAXTRACKS; lenhelp++) {
+ Staffs[lenhelp][0]=0;
+ max[lenhelp]=0;
+ min[lenhelp]=255;
+ }
+ taktzeit = 4 * head.per_quarter;
+ dyn_init();
+
+ /* mainmark6 */
+ if (!printonly)
+ for (Track_Nr = 0; Track_Nr < head.tracks; Track_Nr++) {
+ valid = 0; /* no TimeSig */
+ valid2 = 0; /* no KeySig */
+
+ /* following variables allow event begin only at fixed time-points */
+ lastbartime = 0;
+ bartime = 0;
+
+ firstnotetimeflag = -1;
+ diskrete_tz = taktzeit;
+ read_track();
+ if (min[Track_Nr] > 0x1f) region[Track_Nr] = 1;
+ else if (max[Track_Nr] < 0x2a) region[Track_Nr] = 2;
+ else region[Track_Nr] = 0;
+#ifdef DEBUG
+ printf("region: %x min: %x max: %x\n", region[Track_Nr], min[Track_Nr], max[Track_Nr]);
+ printf("call now split_notes()\n");
+#endif
+ split_notes(Track_Nr, head.per_quarter);
+#ifdef DEBUG
+ printf("call now detect_accords()\n");
+#endif
+ detect_accords(region[Track_Nr], Track_Nr);
+#ifdef DEBUG
+ printf("call now insert_notetimes_and_slurs()\n");
+#endif
+ insert_notetimes_and_slurs(region[Track_Nr], Track_Nr, head.per_quarter);
+#ifdef DEBUG
+ printf("call now detect_note_positions_with_signs()\n");
+#endif
+ detect_note_positions_with_signs(Track_Nr);
+#ifdef DEBUG
+ printf("call now set_slur_regions()\n");
+#endif
+ set_slur_regions(Track_Nr);
+#ifdef DEBUG
+ printf("call now reset_treat_info()\n");
+#endif
+ reset_treat_info(Track_Nr);
+#ifdef DEBUG
+ printf("call now beam_detect()\n");
+#endif
+ beam_detect(region[Track_Nr], Track_Nr);
+#ifdef DEBUG
+ printf("call now set_beam_regions()\n");
+#endif
+ set_beam_regions(Track_Nr);
+#ifdef DEBUG
+ printf("call now reset_treat_info()\n");
+#endif
+ reset_treat_info(Track_Nr);
+#ifdef DEBUG
+ printf("call now slur_geometry()\n");
+#endif
+ slur_geometry(Track_Nr);
+#ifdef DEBUG
+ printf("call now detect_rests()\n");
+#endif
+ detect_rests(Track_Nr, region[Track_Nr], head.per_quarter);
+#ifdef DEBUG
+ printf("call now reset_treat_info()\n");
+#endif
+ reset_treat_info(Track_Nr);
+#ifdef DEBUG
+ printf("call now beam_geometry()\n");
+#endif
+ beam_geometry(Track_Nr);
+#ifdef DEBUG
+ printf("call now reset_treat_info()\n");
+#endif
+ reset_treat_info(Track_Nr);
+#ifdef DEBUG
+ printf("call now calculate_rest_positions()\n");
+#endif
+ calculate_rest_positions(Track_Nr);
+#ifdef DEBUG
+ printf("call now set_loudness_infos()\n");
+#endif
+ set_loudness_infos(Track_Nr);
+ }
+ else {
+ for (Track_Nr = 0; Track_Nr < printonly; Track_Nr++) {
+ valid = 0; /* no TimeSig */
+ valid2 = 0; /* no KeySig */
+
+ /* following variables allow event begin only at fixed time-points */
+ lastbartime = 0;
+ bartime = 0;
+
+ firstnotetimeflag = -1;
+ diskrete_tz = taktzeit;
+ read_track();
+ }
+ if ((printonly == 1) && (notes_flag == 0)) {
+ fprintf(stderr, "sorry, first track is empty\n");
+ }
+ else {
+ Track_Nr--;
+ if (min[Track_Nr] > 0x1f) region[Track_Nr] = 1;
+ else if (max[Track_Nr] < 0x2a) region[Track_Nr] = 2;
+ else region[Track_Nr] = 0;
+#ifdef DEBUG
+ printf("region: %x min: %x max: %x\n", region[Track_Nr], min[Track_Nr], max[Track_Nr]);
+#endif
+ split_notes(Track_Nr, head.per_quarter);
+ detect_accords(region[Track_Nr], Track_Nr);
+ insert_notetimes_and_slurs(region[Track_Nr], Track_Nr, head.per_quarter);
+ detect_note_positions_with_signs(Track_Nr);
+ set_slur_regions(Track_Nr);
+ reset_treat_info(Track_Nr);
+ beam_detect(region[Track_Nr], Track_Nr);
+ set_beam_regions(Track_Nr);
+ reset_treat_info(Track_Nr);
+ slur_geometry(Track_Nr);
+ detect_rests(Track_Nr, region[Track_Nr], head.per_quarter);
+ reset_treat_info(Track_Nr);
+ beam_geometry(Track_Nr);
+ reset_treat_info(Track_Nr);
+ calculate_rest_positions(Track_Nr);
+ set_loudness_infos(Track_Nr);
+ }
+ }
+
+#ifdef DEBUG
+ debug_out();
+#endif
+ /* mainmark7 */
+ if ((tfp = fopen(texfilename, "w")) == NULL) {
+ fprintf(stderr, "cannot open %s\n", texfilename);
+ exit(10);
+ }
+
+#ifdef DEBUG
+ printf("writing texfile\n");
+#endif
+ write_texfile();
+ fclose(fp); /* close MIDI-file */
+ fclose(tfp); /* close TEX-file */
+}