view projects/basic_midi/render.cpp @ 181:391ad036557d

Basic Midi input implementation
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 15 Jan 2016 21:50:46 +0000
parents
children 9108a0a34cb8
line wrap: on
line source
/*
 * render.cpp
 *
 *  Created on: Oct 24, 2014
 *      Author: parallels
 */


#include <BeagleRT.h>
#include <Midi.h>
#include <stdlib.h>
#include <Utilities.h>
#include <rtdk.h>
#include <cmath>

// setup() is called once before the audio rendering starts.
// Use it to perform any initialisation and allocation which is dependent
// on the period size or sample rate.
//
// userData holds an opaque pointer to a data structure that was passed
// in from the call to initAudio().
//
// Return true on success; returning false halts the program.
Midi midi;
bool setup(BeagleRTContext *context, void *userData)
{
	midi.readFrom(0);
	if(context->analogFrames == 0) {
		rt_printf("Error: this example needs the matrix enabled\n");
		return false;
	}
	return true;
}

// render() is called regularly at the highest priority by the audio engine.
// Input and output are given from the audio hardware and the other
// ADCs and DACs (if available). If only audio is available, numMatrixFrames
// will be 0.

static midi_byte_t noteOnStatus =0x90; //on channel 1

enum {kVelocity, kNoteOn, kNoteNumber};
void render(BeagleRTContext *context, void *userData)
{
	static float f0;
	static float phaseIncrement = 0;
	int message;
	static bool noteOn = 0;
	static int velocity = 0;
	static int noteNumber = 0;
	static int waitingFor = kNoteOn;
	while ((message = midi.getInput()) >= 0){
		switch(waitingFor){
		case kNoteOn:
			if(message == noteOnStatus){
				noteOn = true;
				waitingFor = kNoteNumber;
			}
			break;
		case kNoteNumber:
			if((message & (1<<8)) == 0){
				noteNumber = message;
				waitingFor = kVelocity;
				f0 = powf(2, (noteNumber-69)/12.0f) * 440;
				phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
			}
			break;
		case kVelocity:
			if((message & (1<<8)) == 0){
				velocity = message;
				waitingFor = kNoteOn;
				if(velocity == 0)
					noteOn = false;
				rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
			}
			break;
		}
	}
	for(unsigned int n = 0; n < context->audioFrames; n++){
		if(noteOn == 1){
			static float phase = 0;
			phase += phaseIncrement;
			if(phase > 2 * M_PI)
				phase -= 2 * M_PI;
			float value = sinf(phase) * velocity/128.0f;
			audioWriteFrame(context, n, 0, value);
			audioWriteFrame(context, n, 1, value);
		} else {
			audioWriteFrame(context, n, 0, 0);
			audioWriteFrame(context, n, 1, 0);
		}
	}
}

// cleanup() is called once at the end, after the audio has stopped.
// Release any resources that were allocated in setup().

void cleanup(BeagleRTContext *context, void *userData)
{

}