changeset 191:b3a306da03e0

Implemented Midi output
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 03 Feb 2016 01:18:30 +0000
parents 7144c5594d16
children 1402f22fc99a
files core/Midi.cpp include/Midi.h projects/basic_midi/render.cpp
diffstat 3 files changed, 97 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/core/Midi.cpp	Tue Jan 26 00:02:15 2016 +0000
+++ b/core/Midi.cpp	Wed Feb 03 01:18:30 2016 +0000
@@ -9,16 +9,20 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#define kMidiInput 0
+#define kMidiOutput 1
+
 bool Midi::staticConstructed;
 AuxiliaryTask Midi::midiInputTask;
 AuxiliaryTask Midi::midiOutputTask;
-std::vector<Midi *> Midi::objAddrs(0);
+std::vector<Midi *> Midi::objAddrs[2];
 
 Midi::Midi(){
 	outputPort = -1;
 	inputPort = -1;
 	size_t inputBytesInitialSize = 1000;
 	inputBytes.resize(inputBytesInitialSize);
+	outputBytes.resize(inputBytesInitialSize);
 	inputBytesWritePointer = 0;
 	inputBytesReadPointer = inputBytes.size() - 1;
 	if(!staticConstructed){
@@ -29,15 +33,21 @@
 void Midi::staticConstructor(){
 	staticConstructed = true;
 	midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput");
-	midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiOutupt");
+	midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiOutputLoop, 50, "MidiOutupt");
 }
 
 Midi::~Midi(){}
+void Midi::midiInputLoop(){
+	printf("Midi input loop %d\n", objAddrs[kMidiInput].size());
+	for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){
+		objAddrs[kMidiInput][n] -> readInputLoop();
+	}
+}
 
-void Midi::midiInputLoop(){
-	printf("Midi input loop %d\n", objAddrs.size());
-	for(unsigned int n = 0; n < objAddrs.size(); n++){
-		objAddrs[n] -> readInputLoop();
+void Midi::midiOutputLoop(){
+	printf("Midi output loop %d\n", objAddrs[kMidiOutput].size());
+	for(unsigned int n = 0; n < objAddrs[kMidiOutput].size(); n++){
+		objAddrs[kMidiOutput][n] -> writeOutputLoop();
 	}
 }
 
@@ -45,8 +55,6 @@
 	while(!gShouldStop){
 		int maxBytesToRead = inputBytes.size() - inputBytesWritePointer;
 		int ret = read(inputPort, &inputBytes[inputBytesWritePointer], sizeof(midi_byte_t)*maxBytesToRead);
-		static int count = 0;
-		count++;
 		if(ret < 0){
 			if(errno != EAGAIN){ // read() would return EAGAIN when no data are available to read just now
 				rt_printf("Error while reading midi %d\n", errno);
@@ -64,20 +72,63 @@
 	}
 }
 
+void Midi::writeOutputLoop(){
+	while(!gShouldStop){
+		usleep(1000);
+		int length = outputBytesWritePointer - outputBytesReadPointer;
+		if(length < 0){
+			length = outputBytes.size() - outputBytesReadPointer;
+		}
+		if(length == 0){ //nothing to be written
+			continue;
+		}
+		int ret;
+		ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length);
+		if(ret < 0){ //error occurred
+//			if(errno != EAGAIN){ // () would return EAGAIN when no data are available to read just now
+//				rt_printf("Error while writing midi %d\n", errno);
+//			}
+			rt_printf("error occurred while writing: %d\n", errno);
+			usleep(10000); //wait before retrying
+			continue;
+		}
+
+//		inputBytesWritePointer += ret;
+//		if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around
+//			inputBytesWritePointer = 0;
+//		}
+//		if(ret < maxBytesToRead){ //no more data to retrieve at the moment
+//			usleep(1000);
+//		} // otherwise there might be more data ready to be read, so don't sleep
+	}
+}
 int Midi::readFrom(int port){
-	objAddrs.push_back(this);
+	objAddrs[kMidiInput].push_back(this);
 	inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY);
 	if(inputPort < 0){
-		printf("Error occurred while opening midi port %d: %d", port, inputPort);
+		printf("Error occurred while opening midi input port %d: %d", port, inputPort);
 		return -1;
 	} else {
-		printf("Reading from port %d\n", inputPort);
+		printf("Reading from port %d\n", port);
 		BeagleRT_scheduleAuxiliaryTask(midiInputTask);
 		return 1;
 	}
 }
 
-int  Midi::getInput(){
+int Midi::writeTo(int port){
+	objAddrs[kMidiOutput].push_back(this);
+	outputPort = open("/dev/midi1", O_WRONLY, 0);
+	if(outputPort < 0){
+		printf("Error occurred while opening midi output port %d: %d", port, outputPort);
+		return -1;
+	} else {
+		printf("Writing to Midi port %d\n", port);
+		BeagleRT_scheduleAuxiliaryTask(midiOutputTask);
+		return 1;
+	}
+}
+
+int Midi::getInput(){
 	if(inputPort < 0)
 		return -2;
 	if(inputBytesReadPointer == inputBytesWritePointer){
@@ -89,3 +140,15 @@
 	}
 	return inputMessage;
 }
+
+int Midi::writeOutput(midi_byte_t byte){
+	return writeOutput(&byte, 1);
+}
+
+int Midi::writeOutput(midi_byte_t* bytes, unsigned int length){
+	int ret = write(outputPort, bytes, length);
+	if(ret < 0)
+		return -1;
+	else
+		return 1;
+}
--- a/include/Midi.h	Tue Jan 26 00:02:15 2016 +0000
+++ b/include/Midi.h	Wed Feb 03 01:18:30 2016 +0000
@@ -30,7 +30,7 @@
 	int writeTo(int port);
 
 	/**
-	 * Get received midi byte, one at a time.
+	 * Get received midi bytes, one at a time.
 	 * @return  -1 if no new byte is available, -2 on error,
 	 * the oldest not yet retrieved midi byte otherwise
 	*/
@@ -49,21 +49,25 @@
 	 * @param length number of bytes to write
 	 * @return 1 on success, -1 on error
 	 */
-	int writeMidiOut(short unsigned int* bytes, unsigned int length);
+	int writeOutput(midi_byte_t* bytes, unsigned int length);
 
 	virtual ~Midi();
 	static void midiInputLoop();
+	static void midiOutputLoop();
     static bool staticConstructed;
 	static void staticConstructor();
 private:
 	void readInputLoop();
+	void writeOutputLoop();
 	int outputPort;
 	int inputPort;
 	std::vector<midi_byte_t> inputBytes;
 	unsigned int inputBytesWritePointer;
 	unsigned int inputBytesReadPointer;
 	std::vector<midi_byte_t> outputBytes;
-	static std::vector<Midi*> objAddrs;
+	unsigned int outputBytesWritePointer;
+	unsigned int outputBytesReadPointer;
+	static std::vector<Midi*> objAddrs[2];
 	static AuxiliaryTask midiInputTask;
 	static AuxiliaryTask midiOutputTask;
 };
--- a/projects/basic_midi/render.cpp	Tue Jan 26 00:02:15 2016 +0000
+++ b/projects/basic_midi/render.cpp	Wed Feb 03 01:18:30 2016 +0000
@@ -24,6 +24,7 @@
 bool setup(BeagleRTContext *context, void *userData)
 {
 	midi.readFrom(0);
+	midi.writeTo(0);
 	if(context->analogFrames == 0) {
 		rt_printf("Error: this example needs the matrix enabled\n");
 		return false;
@@ -36,7 +37,7 @@
 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
 // will be 0.
 
-static midi_byte_t noteOnStatus =0x90; //on channel 1
+static midi_byte_t noteOnStatus = 0x90; //on channel 1
 
 enum {kVelocity, kNoteOn, kNoteNumber};
 void render(BeagleRTContext *context, void *userData)
@@ -50,6 +51,7 @@
 	static int waitingFor = kNoteOn;
 	static int playingNote = -1;
 	while ((message = midi.getInput()) >= 0){
+		rt_printf("%d\n", message);
 		switch(waitingFor){
 		case kNoteOn:
 			if(message == noteOnStatus){
@@ -86,7 +88,17 @@
 			break;
 		}
 	}
-	for(unsigned int n = 0; n < context->audioFrames; n++){
+
+	for(unsigned int n = 0; n < context->analogFrames; n++){
+		static int count = 0;
+		static bool state = 0;
+		analogWriteFrameOnce(context, n, 1, state);
+		if(count % 40000 == 0){
+			state = !state;
+			midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status
+			midi.writeOutput(bytes, 6);
+		}
+
 		if(noteOn == 1){
 			static float phase = 0;
 			phase += phaseIncrement;
@@ -99,6 +111,7 @@
 			audioWriteFrame(context, n, 0, 0);
 			audioWriteFrame(context, n, 1, 0);
 		}
+		count++;
 	}
 }