static void EchoAlgorithm(FunctionEvent& p, EventBuffer& midiOutput) { static NoteEvent note; // temporary note before placing in buffer // check if pausing if (decaystates[p.getKey()] < 0.0) { p.setOnTime(p.getOnTime() + p.getDur() + p.shortValue(14)); return; } // set the parameters for the output note: note.setOnDur(t_time, p.getOffTime()); // off time holds dur note.setVel(p.getVel()); note.setChan(p.getChan()); note.setKey(p.getKey()); // update the parameters for the function: decaystates[p.getKey()] *= decayrate; p.setVel((int)decaystates[p.getKey()]); // if note is too quiet, end the note if (p.getVel() <= 2) { p.off(midiOutput); decaystates[p.getKey()] = 0.0; } // next time includes a gap so that key can raise on keyboard p.setOnTime(p.getOnTime() + p.getDur() + p.shortValue(14)); note.activate(); note.action(midiOutput); // start right now, avoiding any buffer delay midiOutput.insert(note); // the note off message is being buffered }
static void TumbleNoteFunction(FunctionEvent& p, EventBuffer& midiOutput) { static NoteEvent note; // temporary note for placing in buffer TumbleParameters& param = tparam[p.charValue(0)]; int newnote = limit(param.current + param.dir * param.n[param.pos], 0, 127); // turn off algorithm if someone turned the algorithm off externally // or if the current note is too large or too small. if (param.active == 0 || newnote < A0 || newnote > C7) { param.active = 0; p.off(midiOutput); return; } // set the parameters of the output note: note.setOnDur(t_time, param.d[param.pos]); // off time holds dur note.setVel(param.v[param.pos]); note.setChan(p.getChan()); note.setKey(newnote); note.activate(); note.action(midiOutput); // start right now, avoiding any buffer delay midiOutput.insert(note); // store the note for turning off later // update the parameters for the tumble algorithm p.setOnTime(p.getOnTime() + param.i[param.pos]); param.current = newnote; param.pos++; if (param.pos > param.n.getSize()) { param.pos = 0; } }
static void EnhanceFunction(FunctionEvent& p, EventBuffer& midiOutput) { static NoteEvent note; // temporary note before placing in buffer // set the parameters for the output note: note.setOnDur(t_time, p.getOffTime()); // off time holds dur note.setVel(p.getVel()); note.setChan(p.getChan()); note.setKey(p.getKey()); // if note is too quiet if (p.getVel() <= 5) { p.off(midiOutput); } // update the parameters for the function: p.setKey(p.getKey()+p.shortValue(14)); p.setVel(p.getVel()-5); p.setOnTime(p.getOnTime() + p.getDur()); // OffTime stores duration note.activate(); note.action(midiOutput); // start right now, avoiding any buffer delay midiOutput.insert(note); // the note off message is being buffered // check wether to kill the algorithm or not: // if note is off the range of the keyboard if (p.getKey() > C8 || p.getKey() < A0) { p.off(midiOutput); } }
void playNextPattern(EventBuffer& eventbuffer, NoteScore& score, int pattern, int subpattern, double tempo) { if (pattern == 0 && subpattern == 3) { subpattern = 2; } if (pattern == 6 && subpattern == 3) { subpattern = 2; } int p = pattern; int sp = subpattern; cout << "playing pattern " << pattern << (char)('a' + subpattern) << endl; NoteEvent note; // temporary note for placing in buffer int i; for (i=0; i<score[pattern][subpattern].getSize(); i++) { if (!activevoice[score[pattern][subpattern][i].voice]) { continue; } note.setOnDur((int)(t_time + score[p][sp][i].start * 1000 * 60 / tempo + 0.5), (int)(score[p][sp][i].dur * 1000 * 60 / tempo + 0.5)); note.setChan(CH_10); note.setKey(voicetokey[score[p][sp][i].voice]); note.setVel(score[p][sp][i].vel); note.activate(); if (score[p][sp][i].start == 0.0) { note.action(eventbuffer); // play starting notes now, avoiding delay } eventbuffer.insert(note); } }
void PianorollEditor::tickLenChanged(int val) { QList<QGraphicsItem*> items = gv->scene()->selectedItems(); if (items.size() != 1) return; QGraphicsItem* item = items[0]; if (item->type() != PianoItemType) return; PianoItem* pi = static_cast<PianoItem*>(item); Note* note = pi->note(); NoteEvent* event = pi->event(); if (event->len() == val) return; NoteEvent ne = *event; ne.setLen(val); _score->startCmd(); _score->undo(new ChangeNoteEvent(note, event, ne)); _score->endCmd(); }
void PianorollEditor::updateSelection() { QList<QGraphicsItem*> items = gv->scene()->selectedItems(); if (items.size() == 1) { PianoItem* item = static_cast<PianoItem*>(items[0]); if (item->type() == PianoItemType) { Note* note = item->note(); NoteEvent* event = item->event(); pitch->setEnabled(true); pitch->setValue(note->pitch()); onTime->setValue(event->ontime()); tickLen->setValue(event->len()); updateVelocity(note); } } bool b = items.size() != 0; velocity->setEnabled(b); pitch->setEnabled(b); veloType->setEnabled(b); onTime->setEnabled(b); tickLen->setEnabled(b); }
static void TrillAlgorithm(FunctionEvent& p, EventBuffer& midiOutput) { static NoteEvent note; // temporary note before placing in buffer int key1 = p.getKey(); // lower key of trill int key2 = p.charValue(14); // upper key of trill int state = p.charValue(15); // which note to play next int starttime = p.intValue(10); // when trill was started int i; // turn off the trill if there is a note played inside the trill int range1 = key1; int range2 = key2; if (range2 - range1 == 1) { range1--; range2++; } for (i=range1; i<=range2; i++) { if (noteontimes[i] > starttime) { p.off(midiOutput); return; } } // set the next note to play int key = state ? key2 : key1; state = !state; p.charValue(15) = state; // set the parameters for the output note: note.setOnDur(t_time, p.getDur()); note.setVel(p.getVel()); note.setChan(p.getChan()); note.setKey(key); // update the parameters for the gliss function: p.setOnTime(p.getOnTime() + p.getDur()); int value = p.getVel() + velcorrection; if (value < 100 && value > 3) { p.setVel(value); } if (p.getDur() + trillcorrection > MINTRIGTIME) { p.setDur(p.getDur() + trillcorrection); } note.activate(); note.action(midiOutput); // start right now, avoiding any buffer delay midiOutput.insert(note); // the note off message is being buffered }
void playchord(MidiEvent aMessage, int chordQuality, int* rhythm, int* dur) { int numNotes = 0; // the number of notes to play NoteEvent tempNote; // temporary Note for copying into eventBuffer int chordNote[4]; // the notes of the chord to be calculated int rootNote = aMessage.getP1(); // root of chord to be created chordNote[0] = rootNote; switch (chordQuality) { case DIMINISHED_TRIAD: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 6; numNotes = 3; break; case MINOR_TRIAD: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 7; numNotes = 3; break; case MAJOR_TRIAD: chordNote[1] = rootNote + 4; chordNote[2] = rootNote + 7; numNotes = 3; break; case AUGMENTED_TRIAD: chordNote[1] = rootNote + 4; chordNote[2] = rootNote + 8; numNotes = 3; break; case FULLY_DIM_7TH: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 6; chordNote[3] = rootNote + 9; numNotes = 4; break; case HALF_DIM_7TH: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 6; chordNote[3] = rootNote + 10; numNotes = 4; break; case mm_7TH: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 7; chordNote[3] = rootNote + 10; numNotes = 4; break; case mM_7TH: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 7; chordNote[3] = rootNote + 11; numNotes = 4; break; case Mm_7TH: chordNote[1] = rootNote + 3; chordNote[2] = rootNote + 4; chordNote[3] = rootNote + 10; numNotes = 4; break; case MM_7TH: chordNote[1] = rootNote + 4; chordNote[2] = rootNote + 7; chordNote[3] = rootNote + 10; numNotes = 4; break; default: // invalid quality return; } cout << "Chord: ("; for (int i=0; i<numNotes; i++) { tempNote.setKeyno(chordNote[i]); if (tempNote.getKeyno() < 0 || tempNote.getKeyno() > 127) continue; if (attack[i] == 0) { tempNote.setVelocity(aMessage.getP2()); } else { tempNote.setVelocity(attack[i]); } tempNote.setOnDur(t_time+rhythm[i]+offset, dur[i]); tempNote.setStatus(0); // note hasn't been played yet eventBuffer.insert(&tempNote); cout << tempNote.getKeyno(); if (i != numNotes-1) cout << ","; } cout << ")" << endl; }
void processNotes(HumdrumRecord& record) { NoteEvent note; int pitch = 0; double duration = 0.0; int staccatoQ = 0; int accentQ = 0; int sforzandoQ = 0; int i, j; int notecount = 0; char buffer[128] = {0}; for (i=0; i<record.getFieldCount(); i++) { if ((record.getPrimaryTrack(i) < (int)trackmute.size()) && trackmute[record.getPrimaryTrack(i)]) { continue; } if (record.getExInterpNum(i) == E_KERN_EXINT) { notecount = record.getTokenCount(i); if (strcmp(record[i], ".") == 0) { continue; } for (j=0; j<notecount; j++) { record.getToken(buffer, i, j); if (strchr(buffer, '[')) { // total tied note durations duration = data.getTiedDuration(linenum, i, j); } else { duration = Convert::kernToDuration(buffer); } pitch = Convert::kernToMidiNoteNumber(buffer); // skip rests if (pitch < 0) { continue; } pitch += transpose; // don't play note which is transposed too extremely if (pitch < 0) { continue; } if (pitch > 127) { continue; } // skip tied notes if (strchr(buffer, '_') || strchr(buffer, ']')) { continue; } accentQ = strchr(buffer, '^') == NULL? 0 : 1; sforzandoQ = strchr(buffer, 'z') == NULL? 0 : 1; staccatoQ = strchr(buffer, '\'') == NULL? 0 : 1; note.setChannel(0); note.setKey(pitch); note.setOnTime(t_time); duration = duration * 60000 / tempo / tempoScale; if (shortenQ) { duration -= shortenamount; if (duration < mine) { duration = mine; } } note.setDur((int)duration); if (staccatoQ) { note.setDur((int)(0.5 * note.getDur())); } note.setKey(pitch); if (accentQ) { velocity *= 1.3; } if (sforzandoQ) { velocity *= 1.5; } if (velocity > 127) { velocity = 127; } note.setVelocity(velocity); note.activate(); note.action(eventBuffer); eventBuffer.insert(note); } } } }
void KeyboardWidget::PlayNote(int key, int e, int vel) { if (selectInstr == NULL || theProject == NULL) return; if (e == KEY_CHANGE && changeNew) { // stop last note PlayNote(key, KEY_UP, vel); e = KEY_DOWN; } // activeInstr keeps track of which instrument started the note. // We need to keep playing on the same instrument until a Key up happens, // even if the selected instrument changes. if (!activeInstr) activeInstr = selectInstr; NoteEvent *evt = (NoteEvent*) theProject->mgr.ManufEvent(activeInstr); evt->SetChannel(curChnl); evt->SetStart(0); evt->SetDuration((bsInt32) (synthParams.sampleRate * curDur)); evt->SetVolume(curVol); evt->SetPitch(key); evt->SetVelocity(vel); switch (e) { case KEY_CHANGE: // change current note evt->SetType(SEQEVT_PARAM); break; case KEY_DOWN: evtID = (evtID + 1) & 0x7FFFFFFF; evt->SetType(SEQEVT_START); break; case KEY_UP: evt->SetType(SEQEVT_STOP); activeInstr = 0; break; default: //OutputDebugString("Kbd event is unknown...\r\n"); evt->Destroy(); return; } evt->SetID(evtID); theProject->PlayEvent(evt); // NB: player will delete event. Don't touch it after calling PlayEvent! if (recording && e == KEY_DOWN) { RecNote *note = new RecNote(key, curRhythm, (int)(curVol*100.0)); recTail->InsertBefore(note); } }