annotate projects/basic_midi/render.cpp @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents af1e662400fc
children
rev   line source
giuliomoro@181 1 /*
giuliomoro@181 2 * render.cpp
giuliomoro@181 3 *
giuliomoro@181 4 * Created on: Oct 24, 2014
giuliomoro@181 5 * Author: parallels
giuliomoro@181 6 */
giuliomoro@181 7
giuliomoro@181 8 #include <BeagleRT.h>
giuliomoro@181 9 #include <Midi.h>
giuliomoro@187 10 #include <Utilities.h>
giuliomoro@181 11 #include <stdlib.h>
giuliomoro@181 12 #include <rtdk.h>
giuliomoro@181 13 #include <cmath>
giuliomoro@181 14
giuliomoro@224 15 float gFreq;
giuliomoro@224 16 float gPhaseIncrement = 0;
giuliomoro@224 17 bool gIsNoteOn = 0;
giuliomoro@224 18 int gVelocity = 0;
giuliomoro@224 19 float gSamplingPeriod = 0;
giuliomoro@224 20
giuliomoro@226 21 void midiMessageCallback(MidiChannelMessage message, void* arg){
giuliomoro@226 22 if(arg != NULL){
giuliomoro@226 23 rt_printf("Message from midi port %d: ", *(int*)arg);
giuliomoro@226 24 }
giuliomoro@224 25 message.prettyPrint();
giuliomoro@224 26 if(message.getType() == kmmNoteOn){
giuliomoro@224 27 gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
giuliomoro@224 28 gVelocity = message.getDataByte(1);
giuliomoro@224 29 gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod;
giuliomoro@224 30 gIsNoteOn = gVelocity > 0;
giuliomoro@224 31 rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity);
giuliomoro@224 32 }
giuliomoro@224 33 }
giuliomoro@181 34 // setup() is called once before the audio rendering starts.
giuliomoro@181 35 // Use it to perform any initialisation and allocation which is dependent
giuliomoro@181 36 // on the period size or sample rate.
giuliomoro@181 37 //
giuliomoro@181 38 // userData holds an opaque pointer to a data structure that was passed
giuliomoro@181 39 // in from the call to initAudio().
giuliomoro@181 40 //
giuliomoro@181 41 // Return true on success; returning false halts the program.
giuliomoro@181 42 Midi midi;
giuliomoro@226 43 int gMidiPort0 = 0;
giuliomoro@181 44 bool setup(BeagleRTContext *context, void *userData)
giuliomoro@181 45 {
giuliomoro@226 46 midi.readFrom(gMidiPort0);
giuliomoro@226 47 midi.writeTo(gMidiPort0);
giuliomoro@224 48 midi.enableParser(true);
giuliomoro@226 49 midi.setParserCallback(midiMessageCallback, &gMidiPort0);
giuliomoro@181 50 if(context->analogFrames == 0) {
giuliomoro@226 51 rt_printf("Error: this example needs the analog I/O to be enabled\n");
giuliomoro@181 52 return false;
giuliomoro@181 53 }
giuliomoro@224 54 gSamplingPeriod = 1/context->audioSampleRate;
giuliomoro@181 55 return true;
giuliomoro@181 56 }
giuliomoro@181 57
giuliomoro@181 58 // render() is called regularly at the highest priority by the audio engine.
giuliomoro@181 59 // Input and output are given from the audio hardware and the other
giuliomoro@181 60 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
giuliomoro@181 61 // will be 0.
giuliomoro@181 62
giuliomoro@181 63
giuliomoro@181 64 enum {kVelocity, kNoteOn, kNoteNumber};
giuliomoro@181 65 void render(BeagleRTContext *context, void *userData)
giuliomoro@181 66 {
giuliomoro@224 67 // one way of getting the midi data is to parse them yourself
giuliomoro@224 68 // (you should set midi.enableParser(false) above):
giuliomoro@224 69 /*
giuliomoro@224 70 static midi_byte_t noteOnStatus = 0x90; //on channel 1
giuliomoro@181 71 static int noteNumber = 0;
giuliomoro@181 72 static int waitingFor = kNoteOn;
giuliomoro@184 73 static int playingNote = -1;
giuliomoro@197 74 int message;
giuliomoro@181 75 while ((message = midi.getInput()) >= 0){
giuliomoro@191 76 rt_printf("%d\n", message);
giuliomoro@181 77 switch(waitingFor){
giuliomoro@181 78 case kNoteOn:
giuliomoro@181 79 if(message == noteOnStatus){
giuliomoro@181 80 waitingFor = kNoteNumber;
giuliomoro@181 81 }
giuliomoro@181 82 break;
giuliomoro@181 83 case kNoteNumber:
giuliomoro@181 84 if((message & (1<<8)) == 0){
giuliomoro@181 85 noteNumber = message;
giuliomoro@181 86 waitingFor = kVelocity;
giuliomoro@181 87 }
giuliomoro@181 88 break;
giuliomoro@181 89 case kVelocity:
giuliomoro@181 90 if((message & (1<<8)) == 0){
giuliomoro@184 91 int _velocity = message;
giuliomoro@181 92 waitingFor = kNoteOn;
giuliomoro@184 93 // "monophonic" behaviour, with priority to the latest note on
giuliomoro@184 94 // i.e.: a note off from a previous note does not stop the current note
giuliomoro@184 95 // still you might end up having a key down and no note being played if you pressed and released another
giuliomoro@184 96 // key in the meantime
giuliomoro@184 97 if(_velocity == 0 && noteNumber == playingNote){
giuliomoro@181 98 noteOn = false;
giuliomoro@184 99 playingNote = -1;
giuliomoro@184 100 velocity = _velocity;
giuliomoro@184 101 } else if (_velocity > 0) {
giuliomoro@184 102 noteOn = true;
giuliomoro@184 103 velocity = _velocity;
giuliomoro@184 104 playingNote = noteNumber;
giuliomoro@184 105 f0 = powf(2, (playingNote-69)/12.0f) * 440;
giuliomoro@184 106 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
giuliomoro@184 107 }
giuliomoro@181 108 rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
giuliomoro@181 109 }
giuliomoro@181 110 break;
giuliomoro@181 111 }
giuliomoro@181 112 }
giuliomoro@199 113 */
giuliomoro@224 114 /*
giuliomoro@197 115 int num;
giuliomoro@197 116 //alternatively, you can use the built-in parser (only processes channel messages at the moment).
giuliomoro@197 117 while((num = midi.getParser()->numAvailableMessages()) > 0){
giuliomoro@197 118 static MidiChannelMessage message;
giuliomoro@197 119 message = midi.getParser()->getNextChannelMessage();
giuliomoro@197 120 message.prettyPrint();
giuliomoro@199 121 if(message.getType() == kmmNoteOn){
giuliomoro@199 122 f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
giuliomoro@199 123 velocity = message.getDataByte(1);
giuliomoro@199 124 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
giuliomoro@199 125 noteOn = velocity > 0;
giuliomoro@224 126 rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity);
giuliomoro@199 127 }
giuliomoro@197 128 }
giuliomoro@224 129 */
giuliomoro@224 130 // the following block toggles the LED on an Owl pedal
giuliomoro@224 131 // and asks the pedal to return the status of the LED
giuliomoro@224 132 // using MIDI control changes
giuliomoro@191 133 for(unsigned int n = 0; n < context->analogFrames; n++){
giuliomoro@191 134 static int count = 0;
giuliomoro@191 135 static bool state = 0;
giuliomoro@191 136 analogWriteFrameOnce(context, n, 1, state);
giuliomoro@191 137 if(count % 40000 == 0){
giuliomoro@191 138 state = !state;
giuliomoro@224 139 midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status
giuliomoro@191 140 midi.writeOutput(bytes, 6);
giuliomoro@191 141 }
giuliomoro@199 142 count++;
giuliomoro@199 143 }
giuliomoro@199 144 for(unsigned int n = 0; n < context->audioFrames; n++){
giuliomoro@224 145 if(gIsNoteOn == 1){
giuliomoro@181 146 static float phase = 0;
giuliomoro@224 147 phase += gPhaseIncrement;
giuliomoro@181 148 if(phase > 2 * M_PI)
giuliomoro@181 149 phase -= 2 * M_PI;
giuliomoro@224 150 float value = sinf(phase) * gVelocity/128.0f;
giuliomoro@181 151 audioWriteFrame(context, n, 0, value);
giuliomoro@181 152 audioWriteFrame(context, n, 1, value);
giuliomoro@181 153 } else {
giuliomoro@181 154 audioWriteFrame(context, n, 0, 0);
giuliomoro@181 155 audioWriteFrame(context, n, 1, 0);
giuliomoro@181 156 }
giuliomoro@181 157 }
giuliomoro@181 158 }
giuliomoro@181 159
giuliomoro@181 160 // cleanup() is called once at the end, after the audio has stopped.
giuliomoro@181 161 // Release any resources that were allocated in setup().
giuliomoro@181 162
giuliomoro@181 163 void cleanup(BeagleRTContext *context, void *userData)
giuliomoro@181 164 {
giuliomoro@181 165
giuliomoro@181 166 }