To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / CollidoscopeApp / src / MIDI.cpp @ 9:20bb004a36de

History | View | Annotate | Download (4.2 KB)

1
/*
2

3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

    
22
#include "MIDI.h"
23
#include "Config.h"
24

    
25

    
26
collidoscope::MIDI::MIDI()
27
{
28
}
29

    
30

    
31
collidoscope::MIDI::~MIDI()
32
{
33
    // FIXME check cause destructor of RTInput might throw 
34
    for ( auto & input : mInputs )
35
        input->closePort();
36
}
37

    
38
void collidoscope::MIDI::RtMidiInCallback( double deltatime, std::vector<unsigned char> *message, void *userData )
39
{
40
    collidoscope::MIDI* midi = ((collidoscope::MIDI*)userData);
41
    std::lock_guard< std::mutex > lock( midi->mMutex );
42

    
43
    MIDIMessage msg = midi->parseRtMidiMessage( message );
44

    
45
    switch ( msg.getVoice() ){
46
    case MIDIMessage::Voice::ePitchBend:
47
        midi->mPitchBendMessages[msg.getChannel()] = msg;
48
        break;
49

    
50
    case MIDIMessage::Voice::eControlChange:
51
        if ( msg.getChannel() == 7 ) // FIXME no harcoded 
52
            midi->mFilterMessages[msg.getChannel()] = msg;
53
        else
54
            midi->mMIDIMessages.push_back( msg );
55
        break;
56

    
57
    default:
58
        midi->mMIDIMessages.push_back( msg );
59
        break;
60
    }
61
}
62

    
63
void collidoscope::MIDI::setup( const Config& config )
64
{
65
    unsigned int numPorts = 0; 
66

    
67
    try {
68
        RtMidiIn in;
69
        numPorts = in.getPortCount();
70
    }
71
    catch ( RtMidiError &error ) {
72
        throw MIDIException( error.getMessage() );
73
    }
74

    
75
    if ( numPorts == 0 ){
76
        throw MIDIException(" no MIDI input found ");
77
    }
78

    
79
    for ( unsigned int portNum = 0; portNum < numPorts; portNum++ ) {
80
        try {
81
            std::unique_ptr< RtMidiIn > input ( new RtMidiIn() );
82
            input->openPort( portNum, "Collidoscope Input" );
83
            input->setCallback( &RtMidiInCallback, this );
84
            mInputs.push_back( std::move(input) );
85

    
86
        }
87
        catch ( RtMidiError &error ) {
88
            throw MIDIException( error.getMessage() );
89
        }
90
    }
91
}
92

    
93

    
94
void collidoscope::MIDI::checkMessages( std::vector<MIDIMessage> & midiMessages )
95
{
96
    std::lock_guard<std::mutex> lock( mMutex );
97
    midiMessages.swap( mMIDIMessages );
98
    
99
    for ( int i = 0; i < NUM_WAVES; i++ ){
100
        if ( mPitchBendMessages[i].mVoice != MIDIMessage::Voice::eIgnore ){
101
            midiMessages.push_back( mPitchBendMessages[i] );
102
            mPitchBendMessages[i].mVoice = MIDIMessage::Voice::eIgnore;
103
        }
104

    
105
        if ( mFilterMessages[i].mVoice != MIDIMessage::Voice::eIgnore ){
106
            midiMessages.push_back( mFilterMessages[i] );
107
            mFilterMessages[i].mVoice = MIDIMessage::Voice::eIgnore;
108
        }
109
    }
110
}
111

    
112
// only call this function when the size of mRtMidiMessage != 0
113
collidoscope::MIDIMessage collidoscope::MIDI::parseRtMidiMessage( std::vector<unsigned char> *rtMidiMessage )
114
{
115
    collidoscope::MIDIMessage msg;
116

    
117
    size_t numBytes = rtMidiMessage->size();
118
    
119
    // voice is the 4 most significant bits
120
    unsigned char voice = (*rtMidiMessage)[0] >> 4;
121

    
122
    switch ( voice ){
123
    case 0x9 :
124
        msg.mVoice = MIDIMessage::Voice::eNoteOn;
125
        break;
126

    
127
    case 0x8:
128
        msg.mVoice = MIDIMessage::Voice::eNoteOff;
129
        break;
130

    
131
    case 0xB:
132
        msg.mVoice = MIDIMessage::Voice::eControlChange;
133
        break;
134

    
135
    case 0xE:
136
        msg.mVoice = MIDIMessage::Voice::ePitchBend;
137
        break;
138

    
139
    default:
140
        msg.mVoice = MIDIMessage::Voice::eIgnore;
141
        return msg;
142
    }
143

    
144
    // channel is 4 less significant bits
145
    unsigned char channel = (*rtMidiMessage)[0] & 0x0f;
146
    msg.mChannel = channel;
147
    
148
    //data byte 1
149
    msg.mData1 = (*rtMidiMessage)[1];
150

    
151
    // data byte 2 if it exists 
152
    msg.mData2 = (numBytes == 3 ? (*rtMidiMessage)[2] : 0);
153

    
154
    return msg;
155
}