void sillyKeyboard(int key, int chan /* = 0 */) { static int octave = 4; static int newkey = 0; static Voice voice; static MidiMessage message; // check to see if adjusting the octave: if (isdigit(key)) { octave = key - '0'; return; } switch (key) { case 'z': newkey = 12 * octave + 0; break; // C case 's': newkey = 12 * octave + 1; break; // C# case 'x': newkey = 12 * octave + 2; break; // D case 'd': newkey = 12 * octave + 3; break; // D# case 'c': newkey = 12 * octave + 4; break; // E case 'v': newkey = 12 * octave + 5; break; // F case 'g': newkey = 12 * octave + 6; break; // F# case 'b': newkey = 12 * octave + 7; break; // G case 'h': newkey = 12 * octave + 8; break; // G# case 'n': newkey = 12 * octave + 9; break; // A case 'j': newkey = 12 * octave + 10; break; // A# case 'm': newkey = 12 * octave + 11; break; // B case ',': newkey = 12 * octave + 12; break; // C case 'l': newkey = 12 * octave + 12; break; // C# case '.': newkey = 12 * octave + 12; break; // D case '\'': newkey = 12 * octave + 12; break; // D# case '/': newkey = 12 * octave + 12; break; // E default: return; // don't do anything if not a key } newkey = limit(newkey, 0, 127); // put note-off message in synth's input buffer: message.time = t_time; message.p0() = 0x90 | voice.getChan(); message.p1() = voice.getKey(); message.p2() = 0; synth.insert(message); // turn off the last note: voice.off(); // set parameters for next note-on: voice.setChan(chan & 0x0f); // limit channel to range from 0 to 15 voice.setVel(rand() % 127 +1); // random attack in range from 1 to 127 voice.setKey(newkey); // use the newly selected key number // play the MIDI note: voice.play(); // insert the played note into synth's input MIDI buffer: message.command() = 0x90 | voice.getChan(); message.p1() = voice.getKey(); message.p2() = voice.getVel(); synth.insert(message); }
void mainloopalgorithms(void) { if (synth.getNoteCount() > 0) { message = synth.extractNote(); oldnote = checkForSquelch(message, memory, mintime, maxtime, t_time); if (!oldnote || sstate == 0) { cout << "New note from performer: " << message << endl; if (message.is_note_on()) { message.p1() += 7; outvel = message.p2() + veladd; if (outvel > 127) { outvel = 127; } synth.send(message.p0(), message.p1(), outvel); message.time = t_time; message.p2() = outvel; memory.insert(message); } else if (message.is_note_off()) { message.p1() += 7; synth.send(message.p0(), message.p1(), message.p2()); message.time = t_time; memory.insert(message); } } else { cout << "Feedback note from piano: " << message << endl; } } }
int main(void) { MidiInput midiin; MidiOutput midiout; midiout.setPort(0); midiout.open(); midiin.setPort(0); midiin.open(); MidiMessage message; int sysexloc; unsigned char *sysexdata = NULL; int sysexsize = 0; int i; int running = 1; cout << "sysexio -- display and echo SYSEX messages from MIDI input" << endl; cout << "Press Middle C to quit." << endl; while (running) { if (midiin.getCount() > 0) { message = midiin.extract(); if (message.p0() == 0xf0) { sysexloc = message.p1(); sysexdata = midiin.getSysex(sysexloc); sysexsize = midiin.getSysexSize(sysexloc); // print out the sysex data to the screen: for (i=0; i<sysexsize; i++) { cout << hex << (int)sysexdata[i] << " "; if ((i + 1) % 30 == 0) { cout << endl; } } cout << endl; // Now echo the messages to MIDI output (as a demo // for how to send Sysex outputs) midiout.rawsend(sysexdata, sysexsize); // As a courtesy, mark the midiin sysex buffer free // but this is not necessay (it will be erased when // more space is needed for storing a sysex. midiin.clearSysex(sysexloc); } else if ((message.p0() & 0xf0) == 0x90) { // Exit the program when a middle C note is pressed. if (message.p1() == 60 && message.p2() > 0) { running = 0; } } } } return 0; }
void mainloopalgorithms(void) { if (synth.getNoteCount() > 0) { nextActionTime = t_time; message = synth.extractNote(); if (message.p2() == 0) { // note off keyCount--; if (keyCount < 0) { keyCount = 0; } switch (message.p1()) { case C3: lastOffTime[1] = t_time; break; case D3: lastOffTime[2] = t_time; break; case E3: lastOffTime[3] = t_time; break; case F3: lastOffTime[4] = t_time; break; case G3: lastOffTime[5] = t_time; break; case C4: lastOffTime[6] = t_time; break; case D4: lastOffTime[7] = t_time; break; case E4: lastOffTime[8] = t_time; break; case F4: lastOffTime[9] = t_time; break; case G4: lastOffTime[10] = t_time; break; } } else { // note on keyCount++; keysOn.insert(message.p1()); onKey2 = onKey1; switch (message.p1()) { case C3: lastOnTime[1] = t_time; onKey1 = 1; break; case D3: lastOnTime[2] = t_time; onKey1 = 2; break; case E3: lastOnTime[3] = t_time; onKey1 = 3; break; case F3: lastOnTime[4] = t_time; onKey1 = 4; break; case G3: lastOnTime[5] = t_time; onKey1 = 5; break; case C4: lastOnTime[6] = t_time; onKey1 = 6; break; case D4: lastOnTime[7] = t_time; onKey1 = 7; break; case E4: lastOnTime[8] = t_time; onKey1 = 8; break; case F4: lastOnTime[9] = t_time; onKey1 = 9; break; case G4: lastOnTime[10] = t_time; onKey1 = 10; break; } } } if (nextActionTime + repeatRate <= t_time) { nextActionTime = t_time; } event = makeEventDecision(); if (event > 0) { if (shift) { event = toupper(event); } cout << (char)event << flush; } }
void processNote(MidiMessage& message) { int velocity = message.p2(); int key = message.p1(); int channel = message.p0() & 0x0f; int state = 1; int duration = 0; if (((message.p0() & 0xf0) == 0x80) || velocity == 0) { state = 0; } if (key == A0) { cout << "A0 Triggered" << endl; for (int i=0; i<decaystates.getSize(); i++) { decaystates[i] *= -1.0; } return; } if (state == 1) { notestates[key] = message.time; onvels[key] = velocity; } else { if (notestates[key] == 0) { // do nothing } else { duration = message.time - notestates[key]; if (decaystates[key] == 0.0) { createDecay(channel, key, duration, onvels[key]); } } notestates[key] = 0; } }
int main(int argc, char* argv[]) { int incount = MidiInPort::getNumPorts(); int outcount = MidiOutPort::getNumPorts(); Array<ArrayInt> connections; connections.setSize(incount); int i, j; for (i=0; i<incount; i++) { connections[i].setSize(outcount); connections[i].setAll(1); } // temporary connections for now: // connections[0][2] = 0; // connections[1][2] = 0; cout << "There are " << incount << " MIDI inputs" << endl; cout << "and " << outcount << " MIDI outputs" << endl; MidiMessage message; Array<MidiInput> midiins; for (i=0; i<incount; i++) { midiins[i].setPort(i); midiins[i].open(); } Array<MidiOutPort> midiouts; midiouts.setSize(outcount); for (i=0; i<outcount; i++) { midiouts[i].setPort(i); midiouts[i].open(); cout << "opened MIDI output number " << i << endl; } connections[0][3] = 0; displayPatchBay(connections); int done = 0; while (!done) { for (i=0; i<incount; i++) { while (midiins[i].getCount() > 0) { message = midiins[i].extract(); if (message.p1() == A0) { done = 1; } cout << "[" << i << ":"; for (j=0; j<outcount; j++) { if (connections[i][j]) { cout << j << " "; sendData(message, midiouts[j], midiins[i]); } } cout << "]" << flush; } } } return 0; }
void mainloopalgorithms(void) { eventBuffer.checkPoll(); // see if any notes to play while (synth.getNoteCount() > 0) { message = synth.extractNote(); if (message.p2() != 0) { lastnotes.insert(message.p1()); lasttimes.insert(message.time); distancee = lastnotes[0] - lastnotes[1]; duration = lasttimes[0] - lasttimes[1]; channel = 0x0f & message.p0(); if (distancee != 0) { playgliss(message.p1(), message.p2(), channel, duration, distancee); } } } }
void sendData(MidiMessage& m, MidiOutPort& output, MidiInput& input) { int count = m.getParameterCount(); if (count >= 0 && count <= 2) { if (count >= 0) output.rawsend(m.p0()); if (count >= 1) output.rawsend(m.p0(), m.p1()); if (count >= 2) output.rawsend(m.p0(), m.p1(), m.p2()); } }
void processMidiCommand(MidiMessage& message) { if (message.p0() != 0x90 || message.p2() == 0) { return; } switch (message.p1()) { case 60: // Middle C = beat keyboardchar(' '); break; case 61: // C# = amplitude control { double amp = performance.getAmp(); amp = amp * message.p2() / 64; if (amp < 0) { amp = 0; } else if (amp > 127) { amp = 127; } performance.setAmp((int)amp); } break; case 71: // B = 1 beat tempo follow keyboardchar('1'); break; case 72: // C = 2 beat tempo follow keyboardchar('2'); break; case 73: // C# = 3 beat tempo follow keyboardchar('3'); break; case 74: // D = 4 beat tempo follow keyboardchar('4'); break; case 79: // G = constant tempo follow keyboardchar('9'); break; case 80: // G# = automatic keyboardchar('0'); break; case 62: // amplitude decrease keyboardchar('['); break; case 63: // amplitude increase keyboardchar(']'); break; case 64: // tempo decrease keyboardchar('-'); break; case 65: // tempo increase keyboardchar('='); break; } }
void mainloopalgorithms(void) { eventBuffer.checkPoll(); while (synth.getNoteCount() > 0) { message = synth.extractNote(); if (message.is_note_on() && message.p1() == A0) { direction = -direction; cout << "Direction = " << direction << endl; } else if (message.is_note_on() && message.p1() == C7) { // add one to the length of the tumble sequence length = limit(length+1, 2, 200); cout << "Sequence length = " << length << endl; } else if (message.is_note_on() && message.p1() == 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 mainloopalgorithms(void) { while (synth.getNoteCount() > 0) { noteMessage = synth.extractNote(); if (noteMessage.p2() != 0) { // ignore note off commands synth.play(0, shadowNote, 0); // turn off last note shadowNote = noteMessage.p1() + shadowSide * shadowDistance; if (shadowNote > 0 && shadowNote < 128) { synth.play(0, shadowNote, noteMessage.p2()); } else { shadowNote = 0; } } } }
void mainloopalgorithms(void) { while (synth.getNoteCount() > 0) { message = synth.extractNote(); if (message.is_note_off()) { continue; } returnpitch = message.p1(); returnvelocity = message.p2(); // returntime = message.time; returntime = t_time; dtime = (short)(returntime - outtimes[returnpitch]); if (dtime > 500) { // ignore return times which take more than 0.5 sec continue; } vchange = returnvelocity - outvels[returnpitch]; velchange[returnpitch][outvels[returnpitch]].append(vchange); deltatimes[returnpitch][outvels[returnpitch]].append(dtime); } if (!playstate) { return; } if (nextnotetime <= t_time) { currentnote += 11; if (currentnote > 127) { currentnote -= 127; } if (currentnote < A0 || currentnote > C8) { return; } velocity = rand() % 127 + 1; // random velocity between 1 and 127 voices[currvoice].off(); outvels[currentnote] = velocity; outtimes[currentnote] = mainTimer.getTime(); voices[currvoice++].play(0, currentnote, velocity); if (currvoice >= maxvoices) { currvoice = 0; } notecount++; nextnotetime = t_time + duration; } }
void processKeyboard(void) { MidiMessage message; int key; int vel; int command; while (synth.getNoteCount() > 0) { message = synth.extractNote(); command = message.p0(); key = message.p1(); vel = message.p2(); if (vel == 0 || (command & 0xf0 == 0x80)) { // note-off command section long duration = t_time - performerNotes[key]; durations.insert(duration); durtimes.insert(t_time); performerNotes[key] = 0; performerPC[key%12]--; if (performerPC[key%12] < 0) { performerPC[key%12] = 0; } } else { // note-on command performerNotes[key] = t_time; performerPC[key%12]++; performerPCHistory[key%12]++; keys.insert(key); keytimes.insert(t_time); volumes.insert(vel); voltimes.insert(t_time); } // end of the note-on command section } // end of the while loop for processing notes from the performer // update the time that the performer last play a note on/off: lastPerformerTime = t_time; updatePerformRegions(); updateDuration(); updateVolume(); }
int checkForSquelch(MidiMessage& message, CircularBuffer<MidiMessage>& memory, int mintime, int maxtime, int curtime) { int i; if (memory.getSize() == 0) { return 0; } for (i=0; i<memory.getSize(); i++) { if ((curtime - (int)memory[i].time) < mintime) { continue; } if ((curtime - (int)memory[i].time) > maxtime) { break; } if ((memory[i].p0() == message.p0()) && (memory[i].p1() == message.p1())) { return 1; } } return 0; }
void initialization(void) { batonTimer.setPeriod(50); // time to get new state of baton offTimer.setPeriod(200); // time to check buffer for forgetting controlDisplayTimer.setPeriod(200); // time to check buffer for forgetting // set the voice channels all to be 0 for the disklavier and so // the channels do not have to be specified when playing the note. for (int i=0; i<MAXVOICES; i++) { voice[i].setChannel(0); } computer.setChannel(0); computerMessage.time = t_time; computerMessage.p0() = 0x90; computerMessage.p1() = 0; computerMessage.p2() = 0; keys.setSize(1000); // store keys for memory of previous notes keytimes.setSize(1000); // note times for keys buffer volumes.setSize(1000); // duration of notes being held by performer voltimes.setSize(1000); // duration of notes being held by performer durations.setSize(1000); // duration of notes being held by performer durtimes.setSize(1000); // duration of notes being held by performer }
void RadioBaton::interpretCommand(MidiMessage aMessage) { ushort value; // for the buff value receive commands if (aMessage.command() == BAT_MIDI_COMMAND) { switch (aMessage.p1()) { case BAT_STICK1_RESPONSE_X: // stick 1 responding to poll; x s1ps(aMessage.time); s1pd(DATA_X, aMessage.p2()); break; case BAT_STICK1_RESPONSE_Y: // stick 1 responding to poll; y s1pd(DATA_Y, aMessage.p2()); break; case BAT_STICK1_RESPONSE_Z: // stick 1 responding to poll; z s1pd(DATA_Z, aMessage.p2()); break; case BAT_STICK2_RESPONSE_X: // stick 2 responding to poll; x s2ps(aMessage.time); s2pd(DATA_X, aMessage.p2()); break; case BAT_STICK2_RESPONSE_Y: // stick 2 responding to poll; y s2pd(DATA_Y, aMessage.p2()); break; case BAT_STICK2_RESPONSE_Z: // stick 2 responding to poll; z s2pd(DATA_Z, aMessage.p2()); break; case BAT_POT1_RESPONSE: // pot 1 responding to poll d1p = aMessage.p2(); // update global state variable dial1position(); recordState(aMessage.time, DIAL1RECORD, d1p); d1pb.insert(aMessage.p2()); break; case BAT_POT2_RESPONSE: // pot 2 responding to poll d2p = aMessage.p2(); // update global state variable dial2position(); recordState(aMessage.time, DIAL2RECORD, d2p); d2pb.insert(aMessage.p2()); break; case BAT_POT3_RESPONSE: // pot 3 responding to poll d3p = aMessage.p2(); // update global state variable dial3position(); recordState(aMessage.time, DIAL3RECORD, d3p); d3pb.insert(aMessage.p2()); break; case BAT_POT4_RESPONSE: // pot 4 responding to poll d4p = aMessage.p2(); // update global state variable dial4position(); recordState(aMessage.time, DIAL4RECORD, d4p); d4pb.insert(aMessage.p2()); break; case BAT_STICK1_TRIGGER: // stick 1 got triggered s1ts(aMessage.time); s1td(DATA_W, aMessage.p2()); break; case BAT_STICK1_TRIG_X: // stick 1 got triggered s1td(DATA_X, aMessage.p2()); break; case BAT_STICK1_TRIG_Y: // stick 1 got triggered s1td(DATA_Y, aMessage.p2()); break; case BAT_STICK2_TRIGGER: // stick 2 got triggered s2ts(aMessage.time); s2td(DATA_W, aMessage.p2()); break; case BAT_STICK2_TRIG_X: // stick 2 got triggered s2td(DATA_X, aMessage.p2()); break; case BAT_STICK2_TRIG_Y: // stick 2 got triggered s2td(DATA_Y, aMessage.p2()); break; case BAT_BUTTON_FOOT_TRIGGER: // button or pedal was triggered switch (aMessage.p2()) { case BAT_B14p_TRIGGER: // B14+ button pressed b14pt = aMessage.time; b14ptb.insert(b14pt); recordState(aMessage.time, BUTTON1RECORD); b14plustrig(); break; case BAT_B15p_TRIGGER: // B15+ button pressed b15pt = aMessage.time; recordState(aMessage.time, BUTTON2RECORD); b15plustrig(); b15ptb.insert(b15pt); break; case BAT_B14m_DOWN_TRIGGER: // B14- pedal was depressed b14mdt = aMessage.time; b14mdtb.insert(b14mdt); recordState(b14mdt, FOOTPEDAL1RECORD, 1); b14minusdowntrig(); break; case BAT_B14m_UP_TRIGGER: // B14- pedal was released b14mut = aMessage.time; b14mutb.insert(b14mut); recordState(b14mut, FOOTPEDAL1RECORD, 0); b14minusuptrig(); break; case BAT_B15m_DOWN_TRIGGER: // B15- pedal was depressed b15mdt = aMessage.time; b15mdtb.insert(b15mdt); recordState(b15mut, FOOTPEDAL2RECORD, 1); b15minusdowntrig(); break; case BAT_B15m_UP_TRIGGER: // B15- pedal was released b15mut = aMessage.time; b15mutb.insert(b15mut); recordState(b15mut, FOOTPEDAL2RECORD, 0); b15minusuptrig(); break; } break; case BAT_SEND: // ignore this command break; default: if (errorQ) { cerr << "Baton command not recognized: 0x" << hex << (int)aMessage.command() << dec << ", param1 = " << (int)aMessage.p1() << ", param2 = " << (int)aMessage.p2() << endl; } } // end of switch (aMessage.command()) } // end of if a baton command (0xa0) else if (aMessage.command() == 0xa1) { // do nothing: old calibration message } else if (aMessage.command() == 0xa2) { // do nothing: old calibration message } else if (aMessage.command() == 0xa3) { // do nothing: old calibration message } else if (aMessage.command() == 0xa4) { // do nothing: old calibration message } // take care of buf data else if (aMessage.command() == 0xa5) { // if p1 is not in the range from 0 to 15 then ignore the error: if (aMessage.p1() > 15) return; completeBufQ[aMessage.p1()] = 0; value = (ushort)(aMessage.p2() & 0x000f); buf[aMessage.p1()] &= 0x0fff; buf[aMessage.p1()] |= (value << 12); } else if (aMessage.command() == 0xa6) { // if p1 is not in the range from 0 to 15 then ignore the error: if (aMessage.p1() > 15) return; value = (ushort)(aMessage.p2() & 0x000f); buf[aMessage.p1()] &= 0xf0ff; buf[aMessage.p1()] |= (value << 8); } else if (aMessage.command() == 0xa7) { // if p1 is not in the range from 0 to 15 then ignore the error: if (aMessage.p1() > 15) return; value = (ushort)(aMessage.p2() & 0x000f); buf[aMessage.p1()] &= 0xff0f; buf[aMessage.p1()] |= (value << 4); } else if (aMessage.command() == 0xa8) { // if p1 is not in the range from 0 to 15 then ignore the error: if (aMessage.p1() > 15) return; value = (ushort)(aMessage.p2() & 0x000f); buf[aMessage.p1()] &= 0xfff0; buf[aMessage.p1()] |= value; completeBufQ[aMessage.p1()] = 1; // record buffer element to file if recording // NOTE: have to figure out what to put in the time slots below; 0 for now. switch (aMessage.p1()) { case 0: recordState(timer.getTime(), ANTENNA0RECORD, buf[0]); break; case 1: recordState(timer.getTime(), ANTENNA1RECORD, buf[1]); break; case 2: recordState(timer.getTime(), ANTENNA2RECORD, buf[2]); break; case 3: recordState(timer.getTime(), ANTENNA3RECORD, buf[3]); break; case 4: recordState(timer.getTime(), ANTENNA4RECORD, buf[4]); break; case 5: recordState(timer.getTime(), POT4RECORD, buf[5]); break; case 6: recordState(timer.getTime(), ANTENNA5RECORD, buf[6]); break; case 7: recordState(timer.getTime(), ANTENNA6RECORD, buf[7]); break; case 8: recordState(timer.getTime(), ANTENNA7RECORD, buf[8]); break; case 9: recordState(timer.getTime(), ANTENNA8RECORD, buf[9]); break; case 10: recordState(timer.getTime(), ANTENNA9RECORD, buf[10]); break; case 11: recordState(timer.getTime(), POT1RECORD, buf[11]); break; case 12: recordState(timer.getTime(), POT2RECORD, buf[12]); break; case 13: recordState(timer.getTime(), POT3RECORD, buf[13]); break; case 14: recordState(timer.getTime(), B14RECORD, buf[14]); break; case 15: recordState(timer.getTime(), B15RECORD, buf[15]); break; } } else if (aMessage.command() == 0xaa) { // miditest currentmidi = aMessage.p2(); if (currentmidi != 0) { if (currentmidi != lastmidi + 1) { midierrors++; } lastmidi = currentmidi; miditests++; } } else if (aMessage.command() == 0xab) { // miditest currentmidi = aMessage.p2(); if (currentmidi != 0) { if (currentmidi != lastmidi+1) { midierrors++; } lastmidi = currentmidi; miditests++; } } // All other MIDI commands are ignored. Maybe they are // for/from a synthesizer or something like that. }
void mainloopalgorithms(void) { if (comparestate && notetimer.expired()) { if (notetimer.expired() > 2) { notetimer.reset(); } else { notetimer.update(); } notestate = !notestate; if (notestate == 1 || notestate == -1) { synth.play(0, note, 64); data = 0x90; sentout.insert(data); data = note; sentout.insert(data); data = 64; sentout.insert(data); } else { synth.play(0, note, 0); data = 0x90; sentout.insert(data); data = note; sentout.insert(data); data = 0; sentout.insert(data); note += step * direction; if (note > highestnote) { note = lowestnote; } if (note < lowestnote) { note = highestnote; } } } if (midiinput.getCount() > 0) { message = midiinput.extract(); receivedin.insert(message.p0()); receivedin.insert(message.p1()); receivedin.insert(message.p2()); // check that the messages are identical if (receivedin.getCount() < 3) { cout << "Error: not enough received data" << endl; } else { checkin[0] = receivedin.extract(); checkin[1] = receivedin.extract(); checkin[2] = receivedin.extract(); } if (sentout.getCount() < 3) { cout << "Error: not enough sent data" << endl; } else { checkout[0] = sentout.extract(); checkout[1] = sentout.extract(); checkout[2] = sentout.extract(); } if ((checkout[0] != checkin[0]) || (checkout[1] != checkin[1]) || (checkout[2] != checkin[2])) { synth.rawsend(0xaa, 0x7f, 0x00); cout << "Error " << "output was = (" << hex << (int)checkout[0] << ") " << dec << (int)checkout[1] << " " << dec << (int)checkout[2] << "\tbut input is = (" << hex << (int)checkin[0] << ") " << dec << (int)checkin[1] << " " << dec << (int)checkin[2] << " " << endl; // assume that a note message was missed. if (sentout.getCount() < 3) { cout << "Error: not enough sent data during error" << endl; } else { checkout[0] = sentout.extract(); checkout[1] = sentout.extract(); checkout[2] = sentout.extract(); } stop(); cout << "Press space to restart testing, " "or press 'S' to silence synth" << endl; } } }
void processNote(MidiMessage 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.is_note_on()) { attacktimes.insert(message.time); // 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.p1() - notes[0]; temparam.current = message.p1(); temparam.pos = 1; temparam.max = seqLength; temparam.active = 1; startAlgorithm(temparam); goto resettrigger; } else { // add the note info to the algorithm pile note = message.p1(); notes.append(note); vel = message.p2(); velocities.append(vel); attacktimes[message.p1()] = message.time; } } else if (message.is_note_off()) { if (notes.getSize() > 0) { if (notes[notes.getSize()-1] == message.p1()) { deltatime = message.time - ontimes[message.p1()]; 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.is_note_on()) { note = message.p1(); notes.append(note); ontimes[message.p1()] = message.time; vel = message.p2(); 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. // }
void keyboardchar(int key) { if (isdigit(key)) { int mkey = 5 * 12 + key - '0'; int mvel = (int)(drand48() * 40 + 40); //turn off old note from computer's point of view computerMessage.time = t_time; computerMessage.p2() = 0; synth.insert(computerMessage); cout << "played note: " << mkey << " with velocity: " << mvel << endl; computer.play(mkey, mvel); computerMessage.time = t_time; computerMessage.p0() = 0x90; // midi note-on command, channel 1 computerMessage.p1() = mkey; computerMessage.p2() = mvel; synth.insert(computerMessage); cout << "played note: " << mkey << " with velocity: " << mvel << endl; return; } switch (key) { case ' ': // turn output notes on/off activeQ = !activeQ; if (activeQ) { cout << "Program Activated" << endl; } else { cout << "Program Deactivated" << endl; } break; case 'c': // toggle baton control display controlDisplayQ = !controlDisplayQ; if (controlDisplayQ == 0) { cout << endl; } break; case 'd': // display baton's output notes displayOutput = !displayOutput; if (displayOutput) { cout << "Baton output notes display turned ON" << endl; } else { cout << "Baton output notes display turned OFF" << endl; } break; case 'n': // display performerPCHistory pitches { cout << "Piano notes: "; for (int i=0; i<11; i++) { cout << performerPCHistory[i] << ", "; } cout << performerPCHistory[11] << endl; } break; case 'm': // display performerPC pitches { cout << "Notes on: "; for (int i=0; i<11; i++) { cout << performerPC[i] << ", "; } cout << performerPC[11] << endl; } break; case 'r': // display the register information { cout << "Register: " << performerRegion[0] << performerRegion[1] << performerRegion[2] << endl; } break; case 'v': // display the active voice count for baton { cout << endl << "Active voices = " << countActiveVoices(); cout << ": "; for (int z=0; z<MAXVOICES; z++) { if (voiceState[z]) { cout << " " << (int)voice[z].getKey(); } else { cout << " 0"; } } cout << endl; } break; case 'z': // forget the current piano's key history { for (int z=0; z<12; z++) { performerPCHistory[z] = 0; } keys.reset(); keytimes.reset(); } break; case '[': // decrease the note memory time keyDuration -= 1000; if (keyDuration < 1000) { keyDuration = 1000; } cout << "Note memory time set to : " << keyDuration/1000 << " seconds" << endl; break; case ']': // increase the note memory time keyDuration += 1000; if (keyDuration > 60000) { keyDuration = 60000; } cout << "Note memory time set to : " << keyDuration/1000 << " seconds" << endl; break; case '-': // turn off computer keyboard note // turn off old note from computer's point of view computerMessage.time = t_time; computerMessage.p2() = 0; synth.insert(computerMessage); // turn off old note from synthesizer's point of view computer.off(); break; } }