annotate CollidoscopeApp/src/MIDI.cpp @ 18:f1ff1a81be20 tip

Changed licenses names. Fixed one comment and usage text in CollidoscopeApp.cpp.
author Fiore Martin <f.martin@qmul.ac.uk>
date Thu, 25 Aug 2016 12:07:50 +0200
parents 75b744078d66
children
rev   line source
f@5 1 /*
f@5 2
f@5 3 Copyright (C) 2016 Queen Mary University of London
f@5 4 Author: Fiore Martin
f@5 5
f@5 6 This file is part of Collidoscope.
f@5 7
f@5 8 Collidoscope is free software: you can redistribute it and/or modify
f@5 9 it under the terms of the GNU General Public License as published by
f@5 10 the Free Software Foundation, either version 3 of the License, or
f@5 11 (at your option) any later version.
f@5 12
f@5 13 This program is distributed in the hope that it will be useful,
f@5 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@5 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@5 16 GNU General Public License for more details.
f@5 17
f@5 18 You should have received a copy of the GNU General Public License
f@5 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@5 20 */
f@5 21
f@0 22 #include "MIDI.h"
f@0 23 #include "Config.h"
f@0 24
f@0 25
f@0 26 collidoscope::MIDI::MIDI()
f@0 27 {
f@0 28 }
f@0 29
f@0 30
f@0 31 collidoscope::MIDI::~MIDI()
f@0 32 {
f@0 33 // FIXME check cause destructor of RTInput might throw
f@0 34 for ( auto & input : mInputs )
f@0 35 input->closePort();
f@0 36 }
f@0 37
f@0 38 void collidoscope::MIDI::RtMidiInCallback( double deltatime, std::vector<unsigned char> *message, void *userData )
f@0 39 {
f@0 40 collidoscope::MIDI* midi = ((collidoscope::MIDI*)userData);
f@0 41 std::lock_guard< std::mutex > lock( midi->mMutex );
f@0 42
f@0 43 MIDIMessage msg = midi->parseRtMidiMessage( message );
f@0 44
f@0 45 switch ( msg.getVoice() ){
f@0 46 case MIDIMessage::Voice::ePitchBend:
f@0 47 midi->mPitchBendMessages[msg.getChannel()] = msg;
f@0 48 break;
f@0 49
f@0 50 case MIDIMessage::Voice::eControlChange:
f@0 51 if ( msg.getChannel() == 7 ) // FIXME no harcoded
f@0 52 midi->mFilterMessages[msg.getChannel()] = msg;
f@0 53 else
f@0 54 midi->mMIDIMessages.push_back( msg );
f@0 55 break;
f@0 56
f@0 57 default:
f@0 58 midi->mMIDIMessages.push_back( msg );
f@0 59 break;
f@0 60 }
f@0 61 }
f@0 62
f@0 63 void collidoscope::MIDI::setup( const Config& config )
f@0 64 {
f@0 65 unsigned int numPorts = 0;
f@0 66
f@0 67 try {
f@0 68 RtMidiIn in;
f@0 69 numPorts = in.getPortCount();
f@0 70 }
f@0 71 catch ( RtMidiError &error ) {
f@0 72 throw MIDIException( error.getMessage() );
f@0 73 }
f@0 74
f@0 75 if ( numPorts == 0 ){
f@0 76 throw MIDIException(" no MIDI input found ");
f@0 77 }
f@0 78
f@0 79 for ( unsigned int portNum = 0; portNum < numPorts; portNum++ ) {
f@0 80 try {
f@0 81 std::unique_ptr< RtMidiIn > input ( new RtMidiIn() );
f@0 82 input->openPort( portNum, "Collidoscope Input" );
f@0 83 input->setCallback( &RtMidiInCallback, this );
f@0 84 mInputs.push_back( std::move(input) );
f@0 85
f@0 86 }
f@0 87 catch ( RtMidiError &error ) {
f@0 88 throw MIDIException( error.getMessage() );
f@0 89 }
f@0 90 }
f@0 91 }
f@0 92
f@0 93
f@0 94 void collidoscope::MIDI::checkMessages( std::vector<MIDIMessage> & midiMessages )
f@0 95 {
f@0 96 std::lock_guard<std::mutex> lock( mMutex );
f@0 97 midiMessages.swap( mMIDIMessages );
f@0 98
f@0 99 for ( int i = 0; i < NUM_WAVES; i++ ){
f@0 100 if ( mPitchBendMessages[i].mVoice != MIDIMessage::Voice::eIgnore ){
f@0 101 midiMessages.push_back( mPitchBendMessages[i] );
f@0 102 mPitchBendMessages[i].mVoice = MIDIMessage::Voice::eIgnore;
f@0 103 }
f@0 104
f@0 105 if ( mFilterMessages[i].mVoice != MIDIMessage::Voice::eIgnore ){
f@0 106 midiMessages.push_back( mFilterMessages[i] );
f@0 107 mFilterMessages[i].mVoice = MIDIMessage::Voice::eIgnore;
f@0 108 }
f@0 109 }
f@0 110 }
f@0 111
f@0 112 // only call this function when the size of mRtMidiMessage != 0
f@0 113 collidoscope::MIDIMessage collidoscope::MIDI::parseRtMidiMessage( std::vector<unsigned char> *rtMidiMessage )
f@0 114 {
f@0 115 collidoscope::MIDIMessage msg;
f@0 116
f@0 117 size_t numBytes = rtMidiMessage->size();
f@0 118
f@0 119 // voice is the 4 most significant bits
f@0 120 unsigned char voice = (*rtMidiMessage)[0] >> 4;
f@0 121
f@0 122 switch ( voice ){
f@0 123 case 0x9 :
f@0 124 msg.mVoice = MIDIMessage::Voice::eNoteOn;
f@0 125 break;
f@0 126
f@0 127 case 0x8:
f@0 128 msg.mVoice = MIDIMessage::Voice::eNoteOff;
f@0 129 break;
f@0 130
f@0 131 case 0xB:
f@0 132 msg.mVoice = MIDIMessage::Voice::eControlChange;
f@0 133 break;
f@0 134
f@0 135 case 0xE:
f@0 136 msg.mVoice = MIDIMessage::Voice::ePitchBend;
f@0 137 break;
f@0 138
f@0 139 default:
f@0 140 msg.mVoice = MIDIMessage::Voice::eIgnore;
f@0 141 return msg;
f@0 142 }
f@0 143
f@0 144 // channel is 4 less significant bits
f@0 145 unsigned char channel = (*rtMidiMessage)[0] & 0x0f;
f@0 146 msg.mChannel = channel;
f@0 147
f@0 148 //data byte 1
f@0 149 msg.mData1 = (*rtMidiMessage)[1];
f@0 150
f@0 151 // data byte 2 if it exists
f@0 152 msg.mData2 = (numBytes == 3 ? (*rtMidiMessage)[2] : 0);
f@0 153
f@0 154 return msg;
f@2 155 }