//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: 9 January 1998
// Last Modified: 9 January 1998
// Filename: ...sig/doc/examples/improv/synthImprov/shadow2/shadow2.cpp
// Syntax: C++; synthImprov 2.0
//
// Description: echos a note played on the synthesizer keyboard
// Unlike shadow.cpp, this program also imitates the duration
// of the echoing note and is polyphonic.
#include "synthImprov.h"
/*----------------- beginning of improvization algorithms ---------------*/
int shadowDistance = 12; // number of half-steps to place shadow at
int shadowSide = 1; // 1 = higher, -1 = lower
MidiMessage noteMessage; // for reading keyno and velocity (and time)
int shadowNote = 0; // note to play as a shadow
int keyray[128] = {0}; // keyboard array which keeps track of notes
/*--------------------- maintenance algorithms --------------------------*/
void description(void) {
printboxtop();
psl(
" Shadow2 -- by Craig Stuart Sapp <craig@ccrma.stanford.edu> -- 5 Jan 1998");
psl("");
psl(
" This program will echo the input notes at a certain distance from the");
psl(
" original notes. The range of the shadow is from 1 to 24 half-steps on");
psl(" either side of the original note.");
printintermediateline();
psl(" User commands:");
psl(" \"-\" = decrease shadow length \"=\" = increase shadow length");
psl(" \"\\\" = switch shadow side");
printboxbottom();
}
void initialization(void) { }
void finishup(void) { }
/*-------------------- main loop algorithms -----------------------------*/
void interpretNote(MidiMessage message);
void mainloopalgorithms(void) {
while (synth.getNoteCount() > 0) {
interpretNote(synth.extractNote());
}
}
void interpretNote(MidiMessage message) {
int newNote = message.p1();
int newVelocity = message.p2();
if (newVelocity != 0) {
// pick a shadow note
shadowNote = newNote + shadowSide * shadowDistance;
// ignore the shadow note if it is out of keyboard range:
if (shadowNote > 0 && shadowNote < 128) {
// turn off any old note (should never happen, but be safe):
if (keyray[newNote] != 0) {
synth.play(0, keyray[newNote], 0);
}
keyray[newNote] = shadowNote;
synth.play(0, shadowNote, newVelocity);
}
} else {
// a note off command
if (keyray[newNote] != 0) {
synth.play(0, keyray[newNote], 0);
keyray[newNote] = 0;
}
}
}
/*-------------------- triggered algorithms -----------------------------*/
void keyboardchar(int key) {
switch (key) {
case '-':
shadowDistance--;
if (shadowDistance < 1) shadowDistance = 1;
cout << "Shadow = " << shadowSide * shadowDistance << endl;
break;
case '=':
shadowDistance++;
if (shadowDistance > 24) shadowDistance = 24;
cout << "Shadow = " << shadowSide * shadowDistance << endl;
break;
case '\\':
shadowSide *= -1;
cout << "Shadow = " << shadowSide * shadowDistance << endl;
break;
default:
charsynth(key);
}
}
/*------------------ end improvization algorithms -----------------------*/
/* some functions and variables provided by the support program
program_change(channel, instrument); -------- sets the timbre for a channel
control_change(channel, controller, value); - sends a continuous controller
note_on(channel, keynumber, keyvelocity); --- plays a MIDI note
note_off(channel, keynumber); --------------- same as note_on with 0 vel.
raw_send(channel, command, data1, data2); --- send some midi command
long t_time; -------------------------------- current time in milliseconds
*/
// md5sum: 6c9160fd4f09124be14ede7eec7ecbe9 shadow2.cpp [20050403]