//
// 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]