/***************************/
/* 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 */
}