comparison projects/basic_midi/render.cpp @ 224:97faaf985164 mergingClockSync

Added callback for Midi channel messages
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 08 Mar 2016 15:49:42 +0000
parents b128e3ea84ff
children af1e662400fc
comparison
equal deleted inserted replaced
223:ec9425f728bc 224:97faaf985164
10 #include <Utilities.h> 10 #include <Utilities.h>
11 #include <stdlib.h> 11 #include <stdlib.h>
12 #include <rtdk.h> 12 #include <rtdk.h>
13 #include <cmath> 13 #include <cmath>
14 14
15 float gFreq;
16 float gPhaseIncrement = 0;
17 bool gIsNoteOn = 0;
18 int gVelocity = 0;
19 float gSamplingPeriod = 0;
20
21 void midiMessageCallback(MidiChannelMessage message){
22 message.prettyPrint();
23 if(message.getType() == kmmNoteOn){
24 gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
25 gVelocity = message.getDataByte(1);
26 gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod;
27 gIsNoteOn = gVelocity > 0;
28 rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity);
29 }
30 }
15 // setup() is called once before the audio rendering starts. 31 // setup() is called once before the audio rendering starts.
16 // Use it to perform any initialisation and allocation which is dependent 32 // Use it to perform any initialisation and allocation which is dependent
17 // on the period size or sample rate. 33 // on the period size or sample rate.
18 // 34 //
19 // userData holds an opaque pointer to a data structure that was passed 35 // userData holds an opaque pointer to a data structure that was passed
23 Midi midi; 39 Midi midi;
24 bool setup(BeagleRTContext *context, void *userData) 40 bool setup(BeagleRTContext *context, void *userData)
25 { 41 {
26 midi.readFrom(0); 42 midi.readFrom(0);
27 midi.writeTo(0); 43 midi.writeTo(0);
28 // midi.enableParser(true); 44 midi.enableParser(true);
45 midi.setParserCallback(midiMessageCallback);
29 if(context->analogFrames == 0) { 46 if(context->analogFrames == 0) {
30 rt_printf("Error: this example needs the matrix enabled\n"); 47 rt_printf("Error: this example needs the matrix enabled\n");
31 return false; 48 return false;
32 } 49 }
50 gSamplingPeriod = 1/context->audioSampleRate;
33 return true; 51 return true;
34 } 52 }
35 53
36 // render() is called regularly at the highest priority by the audio engine. 54 // render() is called regularly at the highest priority by the audio engine.
37 // Input and output are given from the audio hardware and the other 55 // Input and output are given from the audio hardware and the other
38 // ADCs and DACs (if available). If only audio is available, numMatrixFrames 56 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
39 // will be 0. 57 // will be 0.
40 58
41 static midi_byte_t noteOnStatus = 0x90; //on channel 1
42 59
43 enum {kVelocity, kNoteOn, kNoteNumber}; 60 enum {kVelocity, kNoteOn, kNoteNumber};
44 void render(BeagleRTContext *context, void *userData) 61 void render(BeagleRTContext *context, void *userData)
45 { 62 {
46 static float f0; 63 // one way of getting the midi data is to parse them yourself
47 static float phaseIncrement = 0; 64 // (you should set midi.enableParser(false) above):
48 static bool noteOn = 0; 65 /*
49 static int velocity = 0; 66 static midi_byte_t noteOnStatus = 0x90; //on channel 1
50 static int noteNumber = 0; 67 static int noteNumber = 0;
51 static int waitingFor = kNoteOn; 68 static int waitingFor = kNoteOn;
52 static int playingNote = -1; 69 static int playingNote = -1;
53 /*
54 int message; 70 int message;
55 // one way of getting the midi data is to parse them yourself (you should set midi.enableParser(false) above):
56 while ((message = midi.getInput()) >= 0){ 71 while ((message = midi.getInput()) >= 0){
57 rt_printf("%d\n", message); 72 rt_printf("%d\n", message);
58 switch(waitingFor){ 73 switch(waitingFor){
59 case kNoteOn: 74 case kNoteOn:
60 if(message == noteOnStatus){ 75 if(message == noteOnStatus){
90 } 105 }
91 break; 106 break;
92 } 107 }
93 } 108 }
94 */ 109 */
110 /*
95 int num; 111 int num;
96 //alternatively, you can use the built-in parser (only processes channel messages at the moment). 112 //alternatively, you can use the built-in parser (only processes channel messages at the moment).
97 while((num = midi.getParser()->numAvailableMessages()) > 0){ 113 while((num = midi.getParser()->numAvailableMessages()) > 0){
98 static MidiChannelMessage message; 114 static MidiChannelMessage message;
99 message = midi.getParser()->getNextChannelMessage(); 115 message = midi.getParser()->getNextChannelMessage();
101 if(message.getType() == kmmNoteOn){ 117 if(message.getType() == kmmNoteOn){
102 f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440; 118 f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
103 velocity = message.getDataByte(1); 119 velocity = message.getDataByte(1);
104 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate; 120 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
105 noteOn = velocity > 0; 121 noteOn = velocity > 0;
106 rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, velocity); 122 rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity);
107 } 123 }
108 } 124 }
109 125 */
126 // the following block toggles the LED on an Owl pedal
127 // and asks the pedal to return the status of the LED
128 // using MIDI control changes
110 for(unsigned int n = 0; n < context->analogFrames; n++){ 129 for(unsigned int n = 0; n < context->analogFrames; n++){
111 static int count = 0; 130 static int count = 0;
112 static bool state = 0; 131 static bool state = 0;
113 analogWriteFrameOnce(context, n, 1, state); 132 analogWriteFrameOnce(context, n, 1, state);
114 if(count % 40000 == 0){ 133 if(count % 40000 == 0){
115 state = !state; 134 state = !state;
116 midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status 135 midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status
117 midi.writeOutput(bytes, 6); 136 midi.writeOutput(bytes, 6);
118 } 137 }
119 count++; 138 count++;
120 } 139 }
121 for(unsigned int n = 0; n < context->audioFrames; n++){ 140 for(unsigned int n = 0; n < context->audioFrames; n++){
122 if(noteOn == 1){ 141 if(gIsNoteOn == 1){
123 static float phase = 0; 142 static float phase = 0;
124 phase += phaseIncrement; 143 phase += gPhaseIncrement;
125 if(phase > 2 * M_PI) 144 if(phase > 2 * M_PI)
126 phase -= 2 * M_PI; 145 phase -= 2 * M_PI;
127 float value = sinf(phase) * velocity/128.0f; 146 float value = sinf(phase) * gVelocity/128.0f;
128 audioWriteFrame(context, n, 0, value); 147 audioWriteFrame(context, n, 0, value);
129 audioWriteFrame(context, n, 1, value); 148 audioWriteFrame(context, n, 1, value);
130 } else { 149 } else {
131 audioWriteFrame(context, n, 0, 0); 150 audioWriteFrame(context, n, 0, 0);
132 audioWriteFrame(context, n, 1, 0); 151 audioWriteFrame(context, n, 1, 0);