giuliomoro@181: /* giuliomoro@181: * render.cpp giuliomoro@181: * giuliomoro@181: * Created on: Oct 24, 2014 giuliomoro@181: * Author: parallels giuliomoro@181: */ giuliomoro@181: giuliomoro@181: #include giuliomoro@181: #include giuliomoro@187: #include giuliomoro@181: #include giuliomoro@181: #include giuliomoro@181: #include giuliomoro@181: giuliomoro@181: // setup() is called once before the audio rendering starts. giuliomoro@181: // Use it to perform any initialisation and allocation which is dependent giuliomoro@181: // on the period size or sample rate. giuliomoro@181: // giuliomoro@181: // userData holds an opaque pointer to a data structure that was passed giuliomoro@181: // in from the call to initAudio(). giuliomoro@181: // giuliomoro@181: // Return true on success; returning false halts the program. giuliomoro@181: Midi midi; giuliomoro@181: bool setup(BeagleRTContext *context, void *userData) giuliomoro@181: { giuliomoro@181: midi.readFrom(0); giuliomoro@191: midi.writeTo(0); giuliomoro@197: midi.enableParser(true); giuliomoro@181: if(context->analogFrames == 0) { giuliomoro@181: rt_printf("Error: this example needs the matrix enabled\n"); giuliomoro@181: return false; giuliomoro@181: } giuliomoro@181: return true; giuliomoro@181: } giuliomoro@181: giuliomoro@181: // render() is called regularly at the highest priority by the audio engine. giuliomoro@181: // Input and output are given from the audio hardware and the other giuliomoro@181: // ADCs and DACs (if available). If only audio is available, numMatrixFrames giuliomoro@181: // will be 0. giuliomoro@181: giuliomoro@191: static midi_byte_t noteOnStatus = 0x90; //on channel 1 giuliomoro@181: giuliomoro@181: enum {kVelocity, kNoteOn, kNoteNumber}; giuliomoro@181: void render(BeagleRTContext *context, void *userData) giuliomoro@181: { giuliomoro@181: static float f0; giuliomoro@181: static float phaseIncrement = 0; giuliomoro@181: static bool noteOn = 0; giuliomoro@181: static int velocity = 0; giuliomoro@181: static int noteNumber = 0; giuliomoro@181: static int waitingFor = kNoteOn; giuliomoro@184: static int playingNote = -1; giuliomoro@197: ///* giuliomoro@197: int message; giuliomoro@197: if(0) // one way of getting the midi data is to parse them yourself (you should set midi.enableParser(false) above): giuliomoro@181: while ((message = midi.getInput()) >= 0){ giuliomoro@191: rt_printf("%d\n", message); giuliomoro@181: switch(waitingFor){ giuliomoro@181: case kNoteOn: giuliomoro@181: if(message == noteOnStatus){ giuliomoro@181: waitingFor = kNoteNumber; giuliomoro@181: } giuliomoro@181: break; giuliomoro@181: case kNoteNumber: giuliomoro@181: if((message & (1<<8)) == 0){ giuliomoro@181: noteNumber = message; giuliomoro@181: waitingFor = kVelocity; giuliomoro@181: } giuliomoro@181: break; giuliomoro@181: case kVelocity: giuliomoro@181: if((message & (1<<8)) == 0){ giuliomoro@184: int _velocity = message; giuliomoro@181: waitingFor = kNoteOn; giuliomoro@184: // "monophonic" behaviour, with priority to the latest note on giuliomoro@184: // i.e.: a note off from a previous note does not stop the current note giuliomoro@184: // still you might end up having a key down and no note being played if you pressed and released another giuliomoro@184: // key in the meantime giuliomoro@184: if(_velocity == 0 && noteNumber == playingNote){ giuliomoro@181: noteOn = false; giuliomoro@184: playingNote = -1; giuliomoro@184: velocity = _velocity; giuliomoro@184: } else if (_velocity > 0) { giuliomoro@184: noteOn = true; giuliomoro@184: velocity = _velocity; giuliomoro@184: playingNote = noteNumber; giuliomoro@184: f0 = powf(2, (playingNote-69)/12.0f) * 440; giuliomoro@184: phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate; giuliomoro@184: } giuliomoro@181: rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity); giuliomoro@181: } giuliomoro@181: break; giuliomoro@181: } giuliomoro@181: } giuliomoro@197: //*/ giuliomoro@197: int num; giuliomoro@197: //alternatively, you can use the built-in parser (only processes channel messages at the moment). giuliomoro@197: while((num = midi.getParser()->numAvailableMessages()) > 0){ giuliomoro@197: static MidiChannelMessage message; giuliomoro@197: message = midi.getParser()->getNextChannelMessage(); giuliomoro@197: message.prettyPrint(); giuliomoro@197: } giuliomoro@191: giuliomoro@191: for(unsigned int n = 0; n < context->analogFrames; n++){ giuliomoro@191: static int count = 0; giuliomoro@191: static bool state = 0; giuliomoro@191: analogWriteFrameOnce(context, n, 1, state); giuliomoro@191: if(count % 40000 == 0){ giuliomoro@191: state = !state; giuliomoro@191: midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status giuliomoro@191: midi.writeOutput(bytes, 6); giuliomoro@191: } giuliomoro@191: giuliomoro@181: if(noteOn == 1){ giuliomoro@181: static float phase = 0; giuliomoro@181: phase += phaseIncrement; giuliomoro@181: if(phase > 2 * M_PI) giuliomoro@181: phase -= 2 * M_PI; giuliomoro@181: float value = sinf(phase) * velocity/128.0f; giuliomoro@181: audioWriteFrame(context, n, 0, value); giuliomoro@181: audioWriteFrame(context, n, 1, value); giuliomoro@181: } else { giuliomoro@181: audioWriteFrame(context, n, 0, 0); giuliomoro@181: audioWriteFrame(context, n, 1, 0); giuliomoro@181: } giuliomoro@191: count++; giuliomoro@181: } giuliomoro@181: } giuliomoro@181: giuliomoro@181: // cleanup() is called once at the end, after the audio has stopped. giuliomoro@181: // Release any resources that were allocated in setup(). giuliomoro@181: giuliomoro@181: void cleanup(BeagleRTContext *context, void *userData) giuliomoro@181: { giuliomoro@181: giuliomoro@181: }