comparison projects/basic_midi/render.cpp @ 235:3d41a6fa1830

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