// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Sun Dec 19 13:52:11 PST 1999 // Last Modified: Wed Jan 12 15:21:15 PST 2000 // Filename: ...improv/examples/synthImprov/testgliss.cpp // Syntax: C++; synthImprov 2.0 // // Description: This program is designed for testing the speed of MIDI // transfers and for checking the throughput of various // microcontrollers. The program sends a continuous // stream of MIDI notes in a glissando pattern. You // can control the speed of the glissando with the // "[" and "]" keys. The range of the notes for the // glissando are controlled by the "-" and "=" keys. // The space bar toggles the program on/off. // // MIDI data can be returned to this program and it will be // compared to the output. If any differences occur // between the input and the output, an error message // will be printed to the screen with the input and // output messages which were not similar. At that point // the program will send out the MIDI command [0xaa 0x7f // 0x00] and stop sending out the glissando data. // // There are also some neat ideas for controlling // glissandos in this program. // // This program also demonstrates how to disable the // Synthesizer input buffer for directly receiving // MIDI input data (since a lower-level MIDI input // interpretation might be more useful in the future). // #include "synthImprov.h" // #include <iomanip.h> typedef unsigned char uchar; /*----------------- beginning of improvization algorithms ---------------*/ SigTimer notetimer; // timer for timing period between MIDI messages double period = 200.0; // time in ms to wait between MIDI output messages int lowestnote = 60; // lowest note in the glissando int highestnote = 72; // highest note in the glissando int note = lowestnote; // current note being played in the glissando int notestate = -1; // note is either on=1, or off=0. int direction = 1; // 1=gliss going up, -1 = gliss going down int step = 1; // half-note step amount int comparestate = 0; // boolean for comparing input to output MIDI uchar checkin[3] = {0}; // temporary comparison storage for MIDI input uchar checkout[3] = {0}; // temporary comparison storage for MIDI output uchar data = 0; // dummy holder for data before inserting to buffer MidiMessage message; // for reading in MIDI data. MidiInput midiinput; // raw MIDI input interface. CircularBuffer<uchar> sentout; // storage copy of MIDI output data CircularBuffer<uchar> receivedin; // storage of MIDI input data to compare // function declarations: void help(void); void start(void); void stop(void); /*--------------------- maintenance algorithms --------------------------*/ void description(void) { printboxtop(); psl(" TESTGLISS - by Craig Stuart Sapp <craig@ccrma.stanford.edu>" " - 11 Jan 2000"); psl(""); printintermediateline(); psl(" User commands:"); psl(" \"[\" = speed up. \"]\" = slow down. "); psl(" \"{\" = speed up by 5. \"}\" = slow down by 5. "); psl(" \"1\" = lower bottom of range. \"2\" = raise bottom of range. "); psl(" \"3\" = lower range. \"4\" = raise range. "); psl(" \"5\" = lower step. \"6\" = raise step. "); psl(" \"-\" = lower top of range. \"=\" = raise top of range. "); psl(" \"u\" = gliss up. \"d = gliss down. "); psl(" "); psl(" Type 'h' for more information "); printboxbottom(); } void initialization(void) { notetimer.setPeriod(period); // set the period in ms between MIDI events. notetimer.reset(); sentout.setSize(1024); // store up to 1024 MIDI output bytes receivedin.setSize(1024); // store up to 1024 MIDI input bytes description(); synth.makeOrphanBuffer(); start(); } void finishup(void) { } /*-------------------- main loop algorithms -----------------------------*/ void mainloopalgorithms(void) { if (comparestate && notetimer.expired()) { if (notetimer.expired() > 2) { notetimer.reset(); } else { notetimer.update(); } notestate = !notestate; if (notestate == 1 || notestate == -1) { synth.play(0, note, 64); data = 0x90; sentout.insert(data); data = note; sentout.insert(data); data = 64; sentout.insert(data); } else { synth.play(0, note, 0); data = 0x90; sentout.insert(data); data = note; sentout.insert(data); data = 0; sentout.insert(data); note += step * direction; if (note > highestnote) { note = lowestnote; } if (note < lowestnote) { note = highestnote; } } } if (midiinput.getCount() > 0) { message = midiinput.extract(); receivedin.insert(message.p0()); receivedin.insert(message.p1()); receivedin.insert(message.p2()); // check that the messages are identical if (receivedin.getCount() < 3) { cout << "Error: not enough received data" << endl; } else { checkin[0] = receivedin.extract(); checkin[1] = receivedin.extract(); checkin[2] = receivedin.extract(); } if (sentout.getCount() < 3) { cout << "Error: not enough sent data" << endl; } else { checkout[0] = sentout.extract(); checkout[1] = sentout.extract(); checkout[2] = sentout.extract(); } if ((checkout[0] != checkin[0]) || (checkout[1] != checkin[1]) || (checkout[2] != checkin[2])) { synth.rawsend(0xaa, 0x7f, 0x00); cout << "Error " << "output was = (" << hex << (int)checkout[0] << ") " << dec << (int)checkout[1] << " " << dec << (int)checkout[2] << "\tbut input is = (" << hex << (int)checkin[0] << ") " << dec << (int)checkin[1] << " " << dec << (int)checkin[2] << " " << endl; // assume that a note message was missed. if (sentout.getCount() < 3) { cout << "Error: not enough sent data during error" << endl; } else { checkout[0] = sentout.extract(); checkout[1] = sentout.extract(); checkout[2] = sentout.extract(); } stop(); cout << "Press space to restart testing, " "or press 'S' to silence synth" << endl; } } } /*-------------------- triggered algorithms -----------------------------*/ void keyboardchar(int key) { switch (key) { case 'h': // more help help(); break; case '[': // slow tempo period--; if (period < 1) { period = 1; } cout << "Period: " << period << endl; notetimer.setPeriod(period); break; case '{': // slow tempo by 5 period -= 5; if (period < 1) { period = 1; } cout << "Period: " << period << endl; notetimer.setPeriod(period); break; case ']': // speed tempo period++; cout << "Period: " << period << endl; notetimer.setPeriod(period); break; case '}': // speed tempo by 5 period += 5; cout << "Period: " << period << endl; notetimer.setPeriod(period); break; case 'u': // make glissando go up direction = 1; cout << "Glissandoing up" << endl; break; case 'd': // make glissando go down direction = -1; cout << "Glissandoing down" << endl; break; case '1': // lower bottom of glissando range if (lowestnote > 0) { lowestnote--; cout << "lowest note set to: " << lowestnote << endl; } break; case '2': // raise bottom of glissando range if (lowestnote < highestnote - 1) { lowestnote++; cout << "lowest note set to " << lowestnote << endl; } break; case '3': // lower both the top and the bottom of range if (lowestnote > 0) { lowestnote--; highestnote--; cout << "Range lowered" << endl; } break; case '4': // lower both the top and the bottom of range if (highestnote < 127) { lowestnote++; highestnote++; cout << "Range raised" << endl; } break; case '5': // lower step amount step--; if (step < 1) { step = 1; } cout << "Step size = " << step << endl; break; case '6': // raise step amount step++; cout << "Step size = " << step << endl; break; case '-': // lower top of glissando range if (highestnote > lowestnote + 1) { highestnote--; cout << "highest note set to: " << highestnote << endl; } break; case '=': // raise top or glissando range if (highestnote < 127) { highestnote++; cout << "highestnote note set to: " << highestnote << endl; } break; case ' ': // toggle sending/comparing of data if (comparestate) { stop(); cout << "Stopped data transmission/comparison" << endl; } else { cout << "Starting data transmission/comparison" << endl; start(); } } } /*------------------ end improvization algorithms -----------------------*/ ////////////////////////////// // // start -- start sending gliss data and start recording/comparing. // void start(void) { comparestate = 1; sentout.reset(); // initialize the MIDI output storage receivedin.reset(); // initialize the MIDI input storage midiinput.setPort(synth.getInputPort()); midiinput.open(); } ////////////////////////////// // // stop -- stop comparing gliss data and stop comparing input to output. // void stop(void) { if (notestate) { synth.play(0, note, 0); notestate = 0; } comparestate = 0; } ////////////////////////////// // // help -- print more information about the program // void help(void) { cout << "\n\nThis program is designed for testing the speed of MIDI transfers and\n" "for checking the throughput of various microcontrollers. The program\n" "sends a continuous stream of MIDI notes in a glissando pattern. You can\n" "control the speed of the glissando with the '[' and ']' keys. The range\n" "of the notes for the glissando are controlled by the '1/-' and '2/=' keys.\n" "The space bar toggles the program on/off.\n\n" "MIDI data can be returned to this program and it will be compared to\n" "the output. If any differences occur between the input and the output,\n" "an error message will be printed to the screen with the input and output\n" "messages which were not similar. At that point the program will send out\n" "the MIDI command [0xaa 0x7f 0x00] and stop sending out the glissando data.\n" << endl; } // md5sum: de57ee927bb8a05ec5fca7dab2c7728d testgliss.cpp [20050403]