#include "LoadMidi.h" #include "MidiData.h" #include #include LoadMidi::LoadMidi(entry_ref *ref): midi_parse(), mErr(0), mFile(0), mList(0), name(0), tList(0), trackNo(0) { mFile = new BFile(ref, B_READ_ONLY); mList = new TrackListList; name = new BString(ref->name); } LoadMidi::~LoadMidi() { #define DELETE(x) if (x) delete x // DELETE(mList); NO NO NO - can't delete!!!! DELETE(mFile); } TrackListList *LoadMidi::Load(void) { status_t err; BString S; BAlert *b; /* Check that the file was opened... */ err = mFile->InitCheck(); if (err != B_OK) { S = "Error opening file "; S += *name; S += "."; b = new BAlert("bad file", S.String(), "Bummer", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); b->Go(NULL); return NULL; } // parse the file err = Run(); if (err) { if (err == BAD_HEADER) { S = "The file "; S += *name; S += " is not a MIDI file."; delete mList; mList = NULL; } else { S = "Warning: file "; S += *name; S += " terminated early."; } b = new BAlert("weird midi", S.String(), "Ok", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); b->Go(NULL); //asynchronous } return mList; } uint8 LoadMidi::Read8(void) { uint8 val; if (mErr) throw(-1); if (!mFile) throw(-1); if (mFile->Read((void *)&val, 1) != 1) { mErr = 1; throw(-1); } return val & 0xff; //be safe... } // these are called when an event is parsed... #include void LoadMidi::M_header(int format, int trackCount, int qnDivision) { printf("format = %d, trackCount = %d, qnDivision = %d\n", format, trackCount, qnDivision); mList->SetDivision(qnDivision); mList->SetFormat(format); Division = qnDivision; } void LoadMidi::M_trackstart(uint32 trackLength) { printf("Track length is %d\n", trackLength); tList = new TrackList(100); mList->AddItem(tList); tList->SetTrackNumber(trackNo++); } void LoadMidi::M_text(int type, int length, const char *msg) { BString *tmp = new BString; Text *txt; tmp->SetTo(msg, length); switch (type) { case COPYRIGHT_NOTICE: mList->SetCopyright(*tmp); case SEQUENCE_NAME: //trackname tList->SetName(*tmp); break; case INSTRUMENT_NAME: //instrument name tList->SetInstrument(*tmp); break; case LYRIC: break; default: ; //printf("type is %d, message is %s\n", type, tmp->String()); } txt = new Text; txt->SetType(type); txt->SetText(*tmp); txt->SetTime(CurrentTime()); tList->AddItem(txt); delete tmp; } void LoadMidi::M_tempo(long tempo) { Tempo *t = new Tempo; t->SetTime(CurrentTime()); t->SetValue(tempo); tList->AddItem(t); } void LoadMidi::M_programChange(int channel, int instrument) { ProgramChange *pc = new ProgramChange; pc->SetTime(CurrentTime()); pc->SetChannel(channel); pc->SetValue(instrument); tList->AddItem(pc); } void LoadMidi::M_noteOn(int channel, int note, int velocity) { Note *n; if (velocity == 0) M_noteOff(channel, note, velocity); else { n = new Note; n->SetTime(CurrentTime()); n->SetChannel(channel); n->SetNote(note); n->SetOnVelocity(velocity); n->SetNoteLength(-1); // don't know (yet); n->SetOffVelocity(-1); //ditto tList->AddItem(n); } } void LoadMidi::M_noteOff(int channel, int note, int velocity) { Note *n; int i; //loop back through until we find a corresponding note on for (i = tList->CountItems(); i; i--) { n = (Note *)tList->ItemAt(i-1); if (n->GetKind() == NOTE_ON) { if ((n->GetChannel() == channel) && (n->GetNote() == note) && (n->GetNoteLength() == -1)) { n->SetNoteLength(CurrentTime() - n->GetTime()); n->SetOffVelocity(velocity); // check to see that it has a length ... :) if (n->GetNoteLength() < 0.01) n->SetNoteLength(0.01); return; } } } printf("warning: note couldn't be matched!!!\n"); } void LoadMidi::M_pitchBend(int channel, int value) { PitchBend *p; value -= 8192; //convert unsigned -> signed p = new PitchBend; p->SetTime(CurrentTime()); p->SetChannel(channel); p->SetValue(value); tList->AddItem(p); } void LoadMidi::M_keysig(int sharp_flat, int minor) { KeySignature *k; k = new KeySignature; k->SetTime(CurrentTime()); k->SetKey(sharp_flat); k->SetMinor(minor); tList->AddItem(k); } void LoadMidi::M_controlChange(int channel, int controller, int value) { ControlChange *C = new ControlChange; C->SetTime(CurrentTime()); C->SetChannel(channel); C->SetController(controller); C->SetValue(value); tList->AddItem(C); } void LoadMidi::M_timesig(int num, int den, int click, int clock) { TimeSig *T; T = new TimeSig; T->SetTime(CurrentTime()); T->SetNumerator(num); T->SetDenominator(den); T->SetClick(click); T->SetClock(clock); tList->AddItem(T); } void LoadMidi::M_trackEnd(void) { return; #if 0 int i; MidiData *d; for (i = tList->CountItems(); i; i--) { d = (MidiData *)tList->ItemAt(i-1); if (d) printf("kind = %x\n", d->GetKind()); } #endif } float LoadMidi::CurrentTime(void) { return (float)midi_parse::CurrentTime() / Division; }