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 @ 5:75b744078d66

History | View | Annotate | Download (4.2 KB)

1 5:75b744078d66 f
/*
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 0:02467299402e f
#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 2:dd889fff8423 f
}