Goto: [ Program Documentation ]

//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: 23 January 1998
// Last Modified: Sat Jan 16 15:08:32 PST 1999
// 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 [20050403]