annotate projects/basic_midi/render.cpp @ 226:af1e662400fc mergingClockSync

Added argument to callback
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 13 Mar 2016 03:31:19 +0000
parents 97faaf985164
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 }