// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: 24 January 1998 // Last Modofied: 9 November 1998 // Filename: ...sig/doc/examples/improv/synthImprov/switch2/switch2.cpp // Syntax: C++; synthImprov 2.0 // // Description: Inverts pitch and attack parameters of keys played on // the synthesizer keyboard. On the computer keyboard, the // keys "-" and "=" will change the timbre of the notes which // are being switched. On the computer keyboard, the notes // z x c v b n m , . / represent the notes C D E F G A B C D E // and the notes s d g h j l ; represent the black notes // associated with the lower row of notes. // #include "synthImprov.h" /*----------------- beginning of improvization algorithms ---------------*/ int channel = 0; // MIDI channel (offset 0) on which to play notes MidiMessage message; // for reading keyno and velocity (and time) int offNote[128] = {0}; // for keeping track of note-offs int instrument = GM_VIBRAPHONE; // initial timbre of output notes int sustain = 0; // for sustain control // function declarations: void sillyKeyboard(int key, int chan = 0); /*--------------------- maintenance algorithms --------------------------*/ void description(void) { printboxtop(); psl( " SWITCH2 - by Craig Stuart Sapp <craig@ccrma.stanford.edu> - 9 Nov 1998"); psl(""); psl(" Description: Inverts pitch and attack parameters of keys "); psl(" played on the synthesizer keyboard."); printintermediateline(); psl(" User commands:"); psl(" \"-\" = decrement timbre no. \"=\" = increment timbre no. "); psl(" tab = sustain toggle."); psl(" \"0\"-\"9\" = octave number of computer keyboard notes"); psl(" Computer notes: s d g h j l ;"); psl(" z x c v b n m , . /"); printboxbottom(); } void initialization(void) { synth.pc(channel, instrument); // send patch change to synthesizer } void finishup(void) { } /*-------------------- main loop algorithms -----------------------------*/ void mainloopalgorithms(void) { // process all of the note messages waiting in the input buffer: while (synth.getNoteCount() > 0) { message = synth.extractNote(); if (message.p2() == 0) { // incoming note-off message synth.play(channel, offNote[message.p1()], 0); } else { // incoming note-on message synth.play(channel, message.p2(), message.p1()); offNote[message.p1()] = message.p2(); } } } /*-------------------- triggered algorithms -----------------------------*/ void keyboardchar(int key) { switch (key) { case '-': // decrement timbre instrument = (instrument - 1 + 127) % 128; cout << "Instrument: " << instrument << endl; synth.pc(channel, instrument); break; case '=': // increment timbre instrument = (instrument + 1) % 128; cout << "Instrument: " << instrument << endl; synth.pc(channel, instrument); break; case '\t': // sustain pedal on/off sustain = !sustain; synth.sustain(channel, sustain); cout << "Sustain: " << sustain << endl; break; default: sillyKeyboard(key); } } ////////////////////////////// // // sillyKeyboard -- converts the bottom two rows of the // computer keyboard into a synthesizer keyboard. The attack // velocities are not controllable, so they are randomly generated. // The octave number is controlled by the characters 0 through 9. // This function will send out the specified note to the // external synthsizer for playing and also put the note into the // synth's input MIDI buffer (so that the synth object thinks that // a note from an external MIDI synthesizer keyboard has been pressed. // 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 } // prevent any invalid key numbers: if (newkey < 0) { newkey = 0; } else if (newkey > 127) { newkey = 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); } /*------------------ end improvization algorithms -----------------------*/ // md5sum: 38dabcb1469bd417459c7140fdc79010 switch2.cpp [20050403]