Goto: [ Program Documentation ]

```//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: 23 January 1998
// Filename:      ...sig/doc/examples/improv/synthImprov/sinus/sinus.cpp
// Syntax:        C++; synthImprov 2.0
//
// Description: you press a key on the synthesizer keyboard, and a pitch
//	pattern shaped like a sinewave is generated.  Attack velocity give
//	amplitude of sine wave.  Alternatively, there is a synthesizer
//	keyboard mapped to the computer keyboard: the octave is controlled
//	by the numbers 0-9, and the chromatic pitches are on the bottom
//	two rows of the keyboard (e.g., 'z' is the note C).  '-' and '='
//	control the period size which controls how many notes to play
//	in one sinewave cycle.  '[' and ']' controls the tempo of the
//	sinewave notes in 100 millisecond increments.  If you play
//	a note loudly, then the sinewave pattern will be soft, and
//	if you play a note softly, then the pattern will be loud.
//	The pattern is played as long as you are holding down a note.
//	If you are playing notes from the computer keyboard, then
//	their attack velocities are assigned random values from 1 to
//	127 since computer keyboards don't record attack velocity.
//

#include "synthImprov.h"

/*----------------- beginning of improvization algorithms ---------------*/

#define TWOPI 6.283185307

int centernote = 0;          // played note which centers sinewave pattern
int amplitude = 0;           // greatest deviation amplitude of sine function
int sinenote = 0;            // current note of the sinewave
int sinevelocity = 0;        // current velocity of the sinewave
int period = 5;              // how many notes to play in the sinewave pattern
int counte = 0;               // which note of the period we are on
int duration = 200;          // duration of sine notes
int octave = 4;              // octave range for computer keyboard notes
int keyboardnote = 0;        // computer keyboard note
int lastoff = 0;             // last note which was turned off
int nextnotetime = 0;        // time for the next note
MidiMessage noteMessage;     // for reading keyno and velocity (and time)
Voice sinevoice;             // for handling note-offs

/*--------------------- maintenance algorithms --------------------------*/

void description(void) {
printboxtop();
psl("Sinus -- by Craig Stuart Sapp <craig@ccrma.stanford.edu>, 24 Jan 1998");
psl("");
psl(" Description: press a key on the synthesizer keyboard, and a pitch ");
psl(" pattern shaped like a sinewave is generated.  Attack velocity gives");
psl(" inverse amplitude of sine wave.  Computer keyboard keys are assigned");
psl(" random attack velocities");
printintermediateline();
psl("  User commands:");
psl("     \"-\" = decrease period length   \"=\" = increase period length ");
psl("     \"[\" = decrease duration        \"]\" = increase duration");
psl(" ");
psl("     \"0\"-\"9\" = octave number of computer keyboard notes");
psl("         Notes:           s   d      g    h   j   ");
psl("                        z   x   c   v   b   n   m  ");
printboxbottom();
}

void initialization(void) {
sinevoice.setPort(synth.getOutputPort());
sinevoice.setChannel(0);
}

void finishup(void) {
sinevoice.off();
}

/*-------------------- main loop algorithms -----------------------------*/

void mainloopalgorithms(void) {
while (synth.getNoteCount() > 0) {
noteMessage = synth.extractNote();
if (noteMessage.p2() != 0) {
sinevelocity = 127 - noteMessage.p2();
} else  {
break;
}
centernote = noteMessage.p1();
counte = 0;
amplitude = midiscale(noteMessage.p2(), 0, 24);
cout << "\rcenter = " << setw(4) << centernote
<< " amplitude = " << setw(4) << amplitude << "\t\t\t\t";
cout.flush();
}

if (nextnotetime <= t_time && sinevelocity != 0) {
nextnotetime = t_time + duration;
sinenote = (int)(centernote + amplitude *
sin(TWOPI * counte / period) + 0.5);
sinevoice.play(sinenote, sinevelocity);
counte++;
}
}

/*-------------------- triggered algorithms -----------------------------*/

void keyboard(int key) {
synth.play(0, keyboardnote, 0);
noteMessage.command() = 0x90;
noteMessage.p1() = keyboardnote;
noteMessage.p2() = 0;
synth.insert(noteMessage);
switch (key) {
case 'z': keyboardnote = 12 * octave + 0;  break;   // C
case 's': keyboardnote = 12 * octave + 1;  break;   // C#
case 'x': keyboardnote = 12 * octave + 2;  break;   // D
case 'd': keyboardnote = 12 * octave + 3;  break;   // D#
case 'c': keyboardnote = 12 * octave + 4;  break;   // E
case 'v': keyboardnote = 12 * octave + 5;  break;   // F
case 'g': keyboardnote = 12 * octave + 6;  break;   // F#
case 'b': keyboardnote = 12 * octave + 7;  break;   // G
case 'h': keyboardnote = 12 * octave + 8;  break;   // G#
case 'n': keyboardnote = 12 * octave + 9;  break;   // A
case 'j': keyboardnote = 12 * octave + 10;  break;   // A#
case 'm': keyboardnote = 12 * octave + 11;  break;   // B
case ',': keyboardnote = 12 * octave + 12;  break;   // C
default: return;
}
if (keyboardnote < 0)  keyboardnote = 0;
else if (keyboardnote > 127)  keyboardnote = 127;
noteMessage.command() = 0x90;
noteMessage.p1() = keyboardnote;
noteMessage.p2() = rand()%127 + 1;      // random int from 1 to 127
synth.play(0, noteMessage.p1(), noteMessage.p2());
synth.insert(noteMessage);
}

void keyboardchar(int key) {
if (isdigit((char)key)) {
octave = key - '0';
return;
}
switch (key) {
case '-':
period--;
if (period < 1)  period = 1;
cout << "\r period = " << period << "   \t\t\t\t\t";
cout.flush();
break;
case '=':
period++;
if (period > 50)  period = 50;
cout << "\r period = " << period << "   \t\t\t\t\t";
cout.flush();
break;
case '[':
duration -= 25;
if (duration < 25)  duration = 25;
break;
case ']':
duration += 25;
break;
default:
keyboard(key);
}
}

/*------------------ end improvization algorithms -----------------------*/

// md5sum: 50a059b97e63b61ce970727ba865e4fe sinus.cpp 
```