void mainloopalgorithms(void) { eventBuffer.checkPoll(); while (synth.getNoteCount() > 0) { message = synth.extractNote(); if (message.isNoteOn() && message.getP1() == A0) { direction = -direction; cout << "Direction = " << direction << endl; } else if (message.isNoteOn() && message.getP1() == C7) { // add one to the length of the tumble sequence length = limit(length+1, 2, 200); cout << "Sequence length = " << length << endl; } else if (message.isNoteOn() && message.getP1() == B6) { // subtract one from the length of the tumble sequence length = limit(length-1, 2, 200); cout << "Sequence length = " << length << endl; } else { processNote(message, length, direction); } } }
void MidiSession::read() { while(active) { auto available = Pm_Poll(midiStream); if(available) { numEvents = Pm_Read(midiStream, events, 1); buffer.events.resize(numEvents); for(auto i = 0; i < numEvents; i++) { write(&events[i]); MidiEvent event; event.status = Pm_MessageStatus(events[i].message); event.note = Pm_MessageData1(events[i].message); event.velocity = Pm_MessageData2(events[i].message); event.timeStamp = events[i].timestamp; if(event.isNoteOff()) { event.channel = event.status - 127; } if(event.isNoteOn()) event.channel = event.status - 143; if (event.isPolyAftertouch()) event.channel = event.status = 159; buffer.events[i] = event; } for(auto& listener: listeners) listener->addBuffer(buffer); } } }
void processNote(MidiEvent message, int seqLength, int direction) { static Array<char> notes; static Array<char> velocities; static Array<int> durations; static Array<int> iois; static Array<int> ontimes; static CircularBuffer<int> attacktimes; static int init = 0; static TumbleParameters temparam; char vel; if (!init) { attacktimes.setSize(256); attacktimes.reset(); notes.setSize(0); velocities.setSize(0); durations.setSize(0); iois.setSize(0); ontimes.setSize(128); ontimes.zero(); init = 1; } char note; int deltatime; int ioi0; int ioix; if (message.isNoteOn()) { attacktimes.insert(message.tick); // check to see if the ioi is in the correct range if (notes.getSize() == 0) { // no notes yet, so don't know the first ioi } else { deltatime = attacktimes[0] - attacktimes[1]; iois.append(deltatime); } if (iois.getSize() > 1) { ioi0 = iois[0]; ioix = iois[iois.getSize()-1]; if ((ioix < ioi0 * tolerance) || (ioix > ioi0 / tolerance)) { goto resettrigger; } } // at this point the note can be added to the sequence if (notes.getSize() + 1 >= seqLength) { // time to trigger an algorithm if (durations.getSize() < notes.getSize()) { // if the last note has not yet been turned off, approximate dur. deltatime = iois[iois.getSize()-1]; durations.append(deltatime); } int i; for (i=0; i<seqLength; i++) { temparam.v[i] = velocities[i]; temparam.i[i] = iois[i]; temparam.d[i] = durations[i]; temparam.n[i] = notes[i] - notes[0]; } temparam.n[0] = message.getP1() - notes[0]; temparam.current = message.getP1(); temparam.pos = 1; temparam.max = seqLength; temparam.active = 1; startAlgorithm(temparam); goto resettrigger; } else { // add the note info to the algorithm pile note = message.getP1(); notes.append(note); vel = message.getP2(); velocities.append(vel); attacktimes[message.getP1()] = message.tick; } } else if (message.isNoteOff()) { if (notes.getSize() > 0) { if (notes[notes.getSize()-1] == message.getP1()) { deltatime = message.tick - ontimes[message.getP1()]; durations.append(deltatime); } else { cout << "A funny error ocurred" << endl; } } return; resettrigger: attacktimes.setSize(0); notes.setSize(0); velocities.setSize(0); durations.setSize(0); iois.setSize(0); if (message.isNoteOn()) { note = message.getP1(); notes.append(note); ontimes[message.getP1()] = message.tick; vel = message.getP2(); velocities.append(vel); } } ////////////////////////////// // // startAlgorithm -- start playing the tumble algorithm. Inserts a // FunctionEvent into the eventBuffer which plays the tumble // algorithm sequence. The algorithm will die after the notes // fall off of the 88-note keyboard. // }
int main(int argc, char** argv) { options.setOptions(argc, argv); checkOptions(options); int status; MidiFile midifile; if (options.getArgCount()) { status = midifile.read(options.getArg(1)); } else { status = midifile.read(cin); } if (status == 0) { cerr << "Error: could not read MIDI file" << endl; exit(1); } int tpq = midifile.getTicksPerQuarterNote(); midifile.linkNotePairs(); if (joinQ) { midifile.joinTracks(); } MidiEvent* mev; double duration; if (secondsQ) { midifile.doTimeAnalysis(); } if (secondsQ) { cout << "SEC\tDUR\tTRACK\tNOTE\n"; } else if (quarterQ) { cout << "QTRS\tDUR\tTRACK\tNOTE\n"; } else { cout << "TICKS\tDUR\tTRACK\tNOTE\n"; } cout << "============================\n"; for (int track=0; track < midifile.getTrackCount(); track++) { for (int i=0; i<midifile[track].size(); i++) { mev = &midifile[track][i]; if (!mev->isNoteOn()) { continue; } if (secondsQ) { duration = mev->getDurationInSeconds(); } else { duration = mev->getTickDuration(); } if (secondsQ) { cout << mev->seconds << '\t'; cout << duration << '\t'; } else if (quarterQ) { cout << mev->tick/tpq << '\t'; cout << duration/tpq << '\t'; } else { cout << mev->tick << '\t'; cout << duration << '\t'; } cout << mev->track << '\t'; cout << mev->getKeyNumber(); cout << endl; } if (midifile.getTrackCount() > 1) { cout << endl; } } return 0; }
void PCH_ChartManager::LoadMidiToDB(PCH_CString filePath,PCH_CString fileHash, bool update) { std::ifstream in2(filePath, std::ios::in | std::ios::binary); MidiFile midifile(in2); if (!midifile.status()) { printf("Error reading MIDI file %s\n",filePath); return; } printf("Loading midi file data...\n"); if(update) { printf("Deleting existing data...\n"); _db->DeleteChart(filePath); } midifile.absoluteTicks(); midifile.linkNotePairs(); midifile.doTimeAnalysis(); printf("Analysis complete...\n"); int totalTracks =midifile.size(); MidiEvent* mev; int chartID = _db->AddChart(filePath, fileHash); int trackID = 0; int trackItemCount = 0; #ifndef PCH_USE_HEAP PCH_ControllerEvent newEvent; PCH_ChartInstrument newInst; PCH_ChartTrackNote newNote; PCH_PitchBend newBend; #endif for (int track=0; track < totalTracks; track++) { trackItemCount = midifile[track].size(); if(trackItemCount == 0) continue; trackID = _db->AddTrack(chartID,track); printf("Track #%d added...\n",trackID); _db->BeginTransaction(); for (int i=0; i<trackItemCount; i++) { mev = &midifile[track][i]; if(mev->isTimbre()) { #ifdef PCH_USE_HEAP PCH_ChartInstrument* newInst = new PCH_ChartInstrument(); newInst->Channel = mev->getChannel(); newInst->Seconds = mev->seconds; newInst->InstrumentID = mev->getP1(); _db->AddInstrument(trackID,newInst); delete newInst; newInst = NULL; #else newInst.Channel = mev->getChannel(); newInst.Seconds = mev->seconds; newInst.InstrumentID = mev->getP1(); _db->AddInstrument(trackID,&newInst); #endif } if(mev->getCommandByte() == 0xFF && mev->getP1() == 0x03)//Title { printf("Title found\n"); unsigned char* title = &midifile[track][i][3];//CMD + p1 + p2 are omitted int titleSize = mev->getP2(); if(titleSize > 0) { char* strTitle = new char[titleSize+1]; memcpy(strTitle,title,titleSize); strTitle[titleSize] = '\0'; _db->SetTrackTitle(trackID, strTitle); } printf("Title end\n"); } if(mev->isNote()) //if(false) { if(mev->isNoteOn()) { #ifdef PCH_USE_HEAP PCH_ChartTrackNote* newNote = new PCH_ChartTrackNote(); newNote->Seconds = mev->seconds; newNote->SecondsDuration = mev->getDurationInSeconds(); newNote->Channel = mev->getChannel(); newNote->KeyNumber = mev->getKeyNumber(); newNote->Velocity = mev->getVelocity(); _db->AddNote(trackID, newNote); delete newNote; newNote = NULL; #else newNote.Seconds = mev->seconds; newNote.SecondsDuration = mev->getDurationInSeconds(); newNote.Channel = mev->getChannel(); newNote.KeyNumber = mev->getKeyNumber(); newNote.Velocity = mev->getVelocity(); _db->AddNote(trackID, &newNote); #endif } } if(mev->isController()) { #ifdef PCH_USE_HEAP PCH_ControllerEvent* newEvent = new PCH_ControllerEvent(); newEvent->Seconds = mev->seconds; newEvent->Channel = mev->getChannel(); newEvent->ControllerID = mev->getP1(); newEvent->Value = mev->getP2(); _db->AddEvent(trackID, newEvent); delete newEvent; newEvent = NULL; #else newEvent.Seconds = mev->seconds; newEvent.Channel = mev->getChannel(); newEvent.ControllerID = mev->getP1(); newEvent.Value = mev->getP2(); _db->AddEvent(trackID, &newEvent); #endif } if(mev->isPitchbend()) { #ifdef PCH_USE_HEAP PCH_PitchBend* newBend = new PCH_PitchBend(); newBend->Seconds = mev->seconds; newBend->Channel = mev->getChannel(); newBend->PitchBend = mev->getP1() + (mev->getP2() << 7); _db->AddPitchBend(trackID, newBend); delete newBend; newBend = NULL; #else newBend.Seconds = mev->seconds; newBend.Channel = mev->getChannel(); newBend.PitchBend = mev->getP1() + (mev->getP2() << 7); _db->AddPitchBend(trackID, &newBend); #endif } } _db->CommitTransaction(); } }