Mercurial > hg > beaglert
changeset 181:391ad036557d
Basic Midi input implementation
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Fri, 15 Jan 2016 21:50:46 +0000 |
parents | 07cfd337ad18 |
children | 4c5acd649d46 |
files | .cproject core/Midi.cpp include/Midi.h projects/basic_midi/render.cpp |
diffstat | 4 files changed, 271 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Sat Jan 02 13:55:01 2016 +0100 +++ b/.cproject Fri Jan 15 21:50:46 2016 +0000 @@ -90,20 +90,10 @@ </tool> </toolChain> </folderInfo> - <folderInfo id="cdt.managedbuild.config.gnu.exe.debug.528876549.2008927038" name="/" resourcePath="projects/basic_passthru"> - <toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1736850748" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug" unusedChildren=""> - <tool id="cdt.managedbuild.tool.gnu.archiver.base.1097917114" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base.1542380883"/> - <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1032137455" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.2030825480"/> - <tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2021994070" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.917207395"/> - <tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1495645726" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug.214461086"/> - <tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.139128145" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1669966018"/> - <tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.757962791" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug.37270610"/> - </toolChain> - </folderInfo> <sourceEntries> <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/logAllAnalogs"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_midi"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -125,7 +115,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.1521194538" name="Release" parent="cdt.managedbuild.config.gnu.exe.release" postannouncebuildStep="Stopping process on BBB and copying new binary" postbuildStep="ssh root@192.168.7.2 "kill -s 2 \`pidof ${BuildArtifactFileName}\` 2>/dev/null"; scp ${BuildArtifactFilePrefix}${BuildArtifactFileName} root@192.168.7.2:~/beaglert/ ; echo 'done copying' | wall"> + <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.1521194538" name="Release" parent="cdt.managedbuild.config.gnu.exe.release" postannouncebuildStep="Stopping process on BBB and copying new binary" postbuildStep="ssh root@192.168.7.2 "kill -s 2 \`pidof ${BuildArtifactFileName}\` 2>/dev/null"; sleep 0.5; scp ${BuildArtifactFilePrefix}${BuildArtifactFileName} root@192.168.7.2:~/beaglert/ && echo 'done copying' | wall || echo 'error' | wall"> <folderInfo id="cdt.managedbuild.config.gnu.exe.release.1521194538." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1612059942" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release"> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.908983575" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/> @@ -191,20 +181,10 @@ </tool> </toolChain> </folderInfo> - <folderInfo id="cdt.managedbuild.config.gnu.exe.release.1521194538.842563663" name="/" resourcePath="projects/basic_passthru"> - <toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.586079455" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release" unusedChildren=""> - <tool id="cdt.managedbuild.tool.gnu.archiver.base.909396192" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base.810674388"/> - <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.426622727" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048"/> - <tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.967588030" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968"/> - <tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.240084743" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release.281634187"/> - <tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1381992272" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.929570421"/> - <tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.2090246626" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release.2052985276"/> - </toolChain> - </folderInfo> <sourceEntries> <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/logAllAnalogs"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_midi"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -234,12 +214,12 @@ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.528876549;cdt.managedbuild.config.gnu.exe.debug.528876549.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.917207395;cdt.managedbuild.tool.gnu.c.compiler.input.308014221"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> </scannerConfigBuildInfo> + <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968;cdt.managedbuild.tool.gnu.c.compiler.input.574072828"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> + </scannerConfigBuildInfo> <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048;cdt.managedbuild.tool.gnu.cpp.compiler.input.601059736"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/> </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968;cdt.managedbuild.tool.gnu.c.compiler.input.574072828"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> - </scannerConfigBuildInfo> <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.528876549;cdt.managedbuild.config.gnu.exe.debug.528876549.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.2030825480;cdt.managedbuild.tool.gnu.cpp.compiler.input.1166892316"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/> </scannerConfigBuildInfo>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/Midi.cpp Fri Jan 15 21:50:46 2016 +0000 @@ -0,0 +1,92 @@ +/* + * Midi.cpp + * + * Created on: 15 Jan 2016 + * Author: giulio + */ + +#include "Midi.h" +#include <fcntl.h> +#include <errno.h> + +bool Midi::staticConstructed; +AuxiliaryTask Midi::midiInputTask; +AuxiliaryTask Midi::midiOutputTask; +std::vector<Midi *> Midi::objAddrs(0); + +Midi::Midi(){ + outputPort = -1; + inputPort = -1; + size_t inputBytesInitialSize = 1000; + inputBytes.resize(inputBytesInitialSize); + inputBytesWritePointer = 0; + inputBytesReadPointer = inputBytes.size() - 1; + if(!staticConstructed){ + staticConstructor(); + } +} + +void Midi::staticConstructor(){ + staticConstructed = true; + midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput"); + midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiOutupt"); +} + +Midi::~Midi(){} + +void Midi::midiInputLoop(){ + printf("Midi input loop %d\n", objAddrs.size()); + for(unsigned int n = 0; n < objAddrs.size(); n++){ + printf("In the for\n"); + objAddrs[n] -> readInputLoop(); + } +} + +void Midi::readInputLoop(){ + 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); + } + usleep(1000); + 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); + inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY); + if(inputPort < 0){ + printf("Error occurred while opening midi port %d: %d", port, inputPort); + return -1; + } else { + printf("Reading from port %d\n", inputPort); + BeagleRT_scheduleAuxiliaryTask(midiInputTask); + return 1; + } +} + +int Midi::getInput(){ + if(inputPort < 0) + return -2; + if(inputBytesReadPointer == inputBytesWritePointer){ + return -1; // no bytes to read + } + midi_byte_t inputMessage = inputBytes[inputBytesReadPointer++]; + if(inputBytesReadPointer == inputBytes.size()){ // wrap pointer + inputBytesReadPointer = 0; + } + return inputMessage; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/Midi.h Fri Jan 15 21:50:46 2016 +0000 @@ -0,0 +1,72 @@ +/* + * Midi.h + * + * Created on: 15 Jan 2016 + * Author: giulio + */ + +#ifndef MIDI_H_ +#define MIDI_H_ + +#include <BeagleRT.h> +#include <vector> + +typedef unsigned char midi_byte_t; + +class Midi { +public: + Midi(); + /** + * Open the specified input Midi port and start reading from it. + * @param port Midi port to open + * @return 1 on success, -1 on failure + */ + int readFrom(int port); + /** + * Open the specified output Midi port and prepares to write to it. + * @param port Midi port to open + * @return 1 on success, -1 on failure + */ + int writeTo(int port); + + /** + * Get received midi byte, one at a time. + * @return -1 if no new byte is available, -2 on error, + * the oldest not yet retrieved midi byte otherwise + */ + int getInput(); + + /** + * Writes a Midi byte to the output port + * @param byte the Midi byte to write + * @return 1 on success, -1 on error + */ + int writeOutput(midi_byte_t byte); + + /** + * Writes Midi bytes to the output port + * @param bytes an array of bytes to be written + * @param length number of bytes to write + * @return 1 on success, -1 on error + */ + int writeMidiOut(short unsigned int* bytes, unsigned int length); + + virtual ~Midi(); + static void midiInputLoop(); + static bool staticConstructed; + static void staticConstructor(); +private: + void readInputLoop(); + 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; + static AuxiliaryTask midiInputTask; + static AuxiliaryTask midiOutputTask; +}; + + +#endif /* MIDI_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_midi/render.cpp Fri Jan 15 21:50:46 2016 +0000 @@ -0,0 +1,101 @@ +/* + * 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) +{ + +}