comparison examples/basic_midi/render.cpp @ 300:dbeed520b014 prerelease

Renamed projects to examples
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 27 May 2016 13:58:20 +0100
parents projects/basic_midi/render.cpp@af1e662400fc
children e4392164b458
comparison
equal deleted inserted replaced
297:a3d83ebdf49b 300:dbeed520b014
1 /*
2 * render.cpp
3 *
4 * Created on: Oct 24, 2014
5 * Author: parallels
6 */
7
8 #include <BeagleRT.h>
9 #include <Midi.h>
10 #include <Utilities.h>
11 #include <stdlib.h>
12 #include <rtdk.h>
13 #include <cmath>
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 }
34 // setup() is called once before the audio rendering starts.
35 // Use it to perform any initialisation and allocation which is dependent
36 // on the period size or sample rate.
37 //
38 // userData holds an opaque pointer to a data structure that was passed
39 // in from the call to initAudio().
40 //
41 // Return true on success; returning false halts the program.
42 Midi midi;
43 int gMidiPort0 = 0;
44 bool setup(BeagleRTContext *context, void *userData)
45 {
46 midi.readFrom(gMidiPort0);
47 midi.writeTo(gMidiPort0);
48 midi.enableParser(true);
49 midi.setParserCallback(midiMessageCallback, &gMidiPort0);
50 if(context->analogFrames == 0) {
51 rt_printf("Error: this example needs the analog I/O to be enabled\n");
52 return false;
53 }
54 gSamplingPeriod = 1/context->audioSampleRate;
55 return true;
56 }
57
58 // render() is called regularly at the highest priority by the audio engine.
59 // Input and output are given from the audio hardware and the other
60 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
61 // will be 0.
62
63
64 enum {kVelocity, kNoteOn, kNoteNumber};
65 void render(BeagleRTContext *context, void *userData)
66 {
67 // one way of getting the midi data is to parse them yourself
68 // (you should set midi.enableParser(false) above):
69 /*
70 static midi_byte_t noteOnStatus = 0x90; //on channel 1
71 static int noteNumber = 0;
72 static int waitingFor = kNoteOn;
73 static int playingNote = -1;
74 int message;
75 while ((message = midi.getInput()) >= 0){
76 rt_printf("%d\n", message);
77 switch(waitingFor){
78 case kNoteOn:
79 if(message == noteOnStatus){
80 waitingFor = kNoteNumber;
81 }
82 break;
83 case kNoteNumber:
84 if((message & (1<<8)) == 0){
85 noteNumber = message;
86 waitingFor = kVelocity;
87 }
88 break;
89 case kVelocity:
90 if((message & (1<<8)) == 0){
91 int _velocity = message;
92 waitingFor = kNoteOn;
93 // "monophonic" behaviour, with priority to the latest note on
94 // i.e.: a note off from a previous note does not stop the current note
95 // still you might end up having a key down and no note being played if you pressed and released another
96 // key in the meantime
97 if(_velocity == 0 && noteNumber == playingNote){
98 noteOn = false;
99 playingNote = -1;
100 velocity = _velocity;
101 } else if (_velocity > 0) {
102 noteOn = true;
103 velocity = _velocity;
104 playingNote = noteNumber;
105 f0 = powf(2, (playingNote-69)/12.0f) * 440;
106 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
107 }
108 rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
109 }
110 break;
111 }
112 }
113 */
114 /*
115 int num;
116 //alternatively, you can use the built-in parser (only processes channel messages at the moment).
117 while((num = midi.getParser()->numAvailableMessages()) > 0){
118 static MidiChannelMessage message;
119 message = midi.getParser()->getNextChannelMessage();
120 message.prettyPrint();
121 if(message.getType() == kmmNoteOn){
122 f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
123 velocity = message.getDataByte(1);
124 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
125 noteOn = velocity > 0;
126 rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity);
127 }
128 }
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
133 for(unsigned int n = 0; n < context->analogFrames; n++){
134 static int count = 0;
135 static bool state = 0;
136 analogWriteFrameOnce(context, n, 1, state);
137 if(count % 40000 == 0){
138 state = !state;
139 midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status
140 midi.writeOutput(bytes, 6);
141 }
142 count++;
143 }
144 for(unsigned int n = 0; n < context->audioFrames; n++){
145 if(gIsNoteOn == 1){
146 static float phase = 0;
147 phase += gPhaseIncrement;
148 if(phase > 2 * M_PI)
149 phase -= 2 * M_PI;
150 float value = sinf(phase) * gVelocity/128.0f;
151 audioWriteFrame(context, n, 0, value);
152 audioWriteFrame(context, n, 1, value);
153 } else {
154 audioWriteFrame(context, n, 0, 0);
155 audioWriteFrame(context, n, 1, 0);
156 }
157 }
158 }
159
160 // cleanup() is called once at the end, after the audio has stopped.
161 // Release any resources that were allocated in setup().
162
163 void cleanup(BeagleRTContext *context, void *userData)
164 {
165
166 }