annotate projects/basic_midi/render.cpp @ 197:265a527f8be8

Added MidiParser for channel messages
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 05 Feb 2016 06:16:35 +0000
parents b3a306da03e0
children b128e3ea84ff
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@181 15 // setup() is called once before the audio rendering starts.
giuliomoro@181 16 // Use it to perform any initialisation and allocation which is dependent
giuliomoro@181 17 // on the period size or sample rate.
giuliomoro@181 18 //
giuliomoro@181 19 // userData holds an opaque pointer to a data structure that was passed
giuliomoro@181 20 // in from the call to initAudio().
giuliomoro@181 21 //
giuliomoro@181 22 // Return true on success; returning false halts the program.
giuliomoro@181 23 Midi midi;
giuliomoro@181 24 bool setup(BeagleRTContext *context, void *userData)
giuliomoro@181 25 {
giuliomoro@181 26 midi.readFrom(0);
giuliomoro@191 27 midi.writeTo(0);
giuliomoro@197 28 midi.enableParser(true);
giuliomoro@181 29 if(context->analogFrames == 0) {
giuliomoro@181 30 rt_printf("Error: this example needs the matrix enabled\n");
giuliomoro@181 31 return false;
giuliomoro@181 32 }
giuliomoro@181 33 return true;
giuliomoro@181 34 }
giuliomoro@181 35
giuliomoro@181 36 // render() is called regularly at the highest priority by the audio engine.
giuliomoro@181 37 // Input and output are given from the audio hardware and the other
giuliomoro@181 38 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
giuliomoro@181 39 // will be 0.
giuliomoro@181 40
giuliomoro@191 41 static midi_byte_t noteOnStatus = 0x90; //on channel 1
giuliomoro@181 42
giuliomoro@181 43 enum {kVelocity, kNoteOn, kNoteNumber};
giuliomoro@181 44 void render(BeagleRTContext *context, void *userData)
giuliomoro@181 45 {
giuliomoro@181 46 static float f0;
giuliomoro@181 47 static float phaseIncrement = 0;
giuliomoro@181 48 static bool noteOn = 0;
giuliomoro@181 49 static int velocity = 0;
giuliomoro@181 50 static int noteNumber = 0;
giuliomoro@181 51 static int waitingFor = kNoteOn;
giuliomoro@184 52 static int playingNote = -1;
giuliomoro@197 53 ///*
giuliomoro@197 54 int message;
giuliomoro@197 55 if(0) // one way of getting the midi data is to parse them yourself (you should set midi.enableParser(false) above):
giuliomoro@181 56 while ((message = midi.getInput()) >= 0){
giuliomoro@191 57 rt_printf("%d\n", message);
giuliomoro@181 58 switch(waitingFor){
giuliomoro@181 59 case kNoteOn:
giuliomoro@181 60 if(message == noteOnStatus){
giuliomoro@181 61 waitingFor = kNoteNumber;
giuliomoro@181 62 }
giuliomoro@181 63 break;
giuliomoro@181 64 case kNoteNumber:
giuliomoro@181 65 if((message & (1<<8)) == 0){
giuliomoro@181 66 noteNumber = message;
giuliomoro@181 67 waitingFor = kVelocity;
giuliomoro@181 68 }
giuliomoro@181 69 break;
giuliomoro@181 70 case kVelocity:
giuliomoro@181 71 if((message & (1<<8)) == 0){
giuliomoro@184 72 int _velocity = message;
giuliomoro@181 73 waitingFor = kNoteOn;
giuliomoro@184 74 // "monophonic" behaviour, with priority to the latest note on
giuliomoro@184 75 // i.e.: a note off from a previous note does not stop the current note
giuliomoro@184 76 // still you might end up having a key down and no note being played if you pressed and released another
giuliomoro@184 77 // key in the meantime
giuliomoro@184 78 if(_velocity == 0 && noteNumber == playingNote){
giuliomoro@181 79 noteOn = false;
giuliomoro@184 80 playingNote = -1;
giuliomoro@184 81 velocity = _velocity;
giuliomoro@184 82 } else if (_velocity > 0) {
giuliomoro@184 83 noteOn = true;
giuliomoro@184 84 velocity = _velocity;
giuliomoro@184 85 playingNote = noteNumber;
giuliomoro@184 86 f0 = powf(2, (playingNote-69)/12.0f) * 440;
giuliomoro@184 87 phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
giuliomoro@184 88 }
giuliomoro@181 89 rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
giuliomoro@181 90 }
giuliomoro@181 91 break;
giuliomoro@181 92 }
giuliomoro@181 93 }
giuliomoro@197 94 //*/
giuliomoro@197 95 int num;
giuliomoro@197 96 //alternatively, you can use the built-in parser (only processes channel messages at the moment).
giuliomoro@197 97 while((num = midi.getParser()->numAvailableMessages()) > 0){
giuliomoro@197 98 static MidiChannelMessage message;
giuliomoro@197 99 message = midi.getParser()->getNextChannelMessage();
giuliomoro@197 100 message.prettyPrint();
giuliomoro@197 101 }
giuliomoro@191 102
giuliomoro@191 103 for(unsigned int n = 0; n < context->analogFrames; n++){
giuliomoro@191 104 static int count = 0;
giuliomoro@191 105 static bool state = 0;
giuliomoro@191 106 analogWriteFrameOnce(context, n, 1, state);
giuliomoro@191 107 if(count % 40000 == 0){
giuliomoro@191 108 state = !state;
giuliomoro@191 109 midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status
giuliomoro@191 110 midi.writeOutput(bytes, 6);
giuliomoro@191 111 }
giuliomoro@191 112
giuliomoro@181 113 if(noteOn == 1){
giuliomoro@181 114 static float phase = 0;
giuliomoro@181 115 phase += phaseIncrement;
giuliomoro@181 116 if(phase > 2 * M_PI)
giuliomoro@181 117 phase -= 2 * M_PI;
giuliomoro@181 118 float value = sinf(phase) * velocity/128.0f;
giuliomoro@181 119 audioWriteFrame(context, n, 0, value);
giuliomoro@181 120 audioWriteFrame(context, n, 1, value);
giuliomoro@181 121 } else {
giuliomoro@181 122 audioWriteFrame(context, n, 0, 0);
giuliomoro@181 123 audioWriteFrame(context, n, 1, 0);
giuliomoro@181 124 }
giuliomoro@191 125 count++;
giuliomoro@181 126 }
giuliomoro@181 127 }
giuliomoro@181 128
giuliomoro@181 129 // cleanup() is called once at the end, after the audio has stopped.
giuliomoro@181 130 // Release any resources that were allocated in setup().
giuliomoro@181 131
giuliomoro@181 132 void cleanup(BeagleRTContext *context, void *userData)
giuliomoro@181 133 {
giuliomoro@181 134
giuliomoro@181 135 }