|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2013 - Raw Material Software Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
- */
-
- MidiMessageCollector::MidiMessageCollector()
- : lastCallbackTime (0),
- sampleRate (44100.0001)
- {
- }
-
- MidiMessageCollector::~MidiMessageCollector()
- {
- }
-
- //==============================================================================
- void MidiMessageCollector::reset (const double sampleRate_)
- {
- jassert (sampleRate_ > 0);
-
- const ScopedLock sl (midiCallbackLock);
- sampleRate = sampleRate_;
- incomingMessages.clear();
- lastCallbackTime = Time::getMillisecondCounterHiRes();
- }
-
- void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
- {
- // you need to call reset() to set the correct sample rate before using this object
- jassert (sampleRate != 44100.0001);
-
- // the messages that come in here need to be time-stamped correctly - see MidiInput
- // for details of what the number should be.
- jassert (message.getTimeStamp() != 0);
-
- const ScopedLock sl (midiCallbackLock);
-
- const int sampleNumber
- = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate);
-
- incomingMessages.addEvent (message, sampleNumber);
-
- // if the messages don't get used for over a second, we'd better
- // get rid of any old ones to avoid the queue getting too big
- if (sampleNumber > sampleRate)
- incomingMessages.clear (0, sampleNumber - (int) sampleRate);
- }
-
- void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer,
- const int numSamples)
- {
- // you need to call reset() to set the correct sample rate before using this object
- jassert (sampleRate != 44100.0001);
- jassert (numSamples > 0);
-
- const double timeNow = Time::getMillisecondCounterHiRes();
- const double msElapsed = timeNow - lastCallbackTime;
-
- const ScopedLock sl (midiCallbackLock);
- lastCallbackTime = timeNow;
-
- if (! incomingMessages.isEmpty())
- {
- int numSourceSamples = jmax (1, roundToInt (msElapsed * 0.001 * sampleRate));
-
- int startSample = 0;
- int scale = 1 << 16;
-
- const uint8* midiData;
- int numBytes, samplePosition;
-
- MidiBuffer::Iterator iter (incomingMessages);
-
- if (numSourceSamples > numSamples)
- {
- // if our list of events is longer than the buffer we're being
- // asked for, scale them down to squeeze them all in..
- const int maxBlockLengthToUse = numSamples << 5;
-
- if (numSourceSamples > maxBlockLengthToUse)
- {
- startSample = numSourceSamples - maxBlockLengthToUse;
- numSourceSamples = maxBlockLengthToUse;
- iter.setNextSamplePosition (startSample);
- }
-
- scale = (numSamples << 10) / numSourceSamples;
-
- while (iter.getNextEvent (midiData, numBytes, samplePosition))
- {
- samplePosition = ((samplePosition - startSample) * scale) >> 10;
-
- destBuffer.addEvent (midiData, numBytes,
- jlimit (0, numSamples - 1, samplePosition));
- }
- }
- else
- {
- // if our event list is shorter than the number we need, put them
- // towards the end of the buffer
- startSample = numSamples - numSourceSamples;
-
- while (iter.getNextEvent (midiData, numBytes, samplePosition))
- {
- destBuffer.addEvent (midiData, numBytes,
- jlimit (0, numSamples - 1, samplePosition + startSample));
- }
- }
-
- incomingMessages.clear();
- }
- }
-
- //==============================================================================
- void MidiMessageCollector::handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity)
- {
- MidiMessage m (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity));
- m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
-
- addMessageToQueue (m);
- }
-
- void MidiMessageCollector::handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber)
- {
- MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber));
- m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
-
- addMessageToQueue (m);
- }
-
- void MidiMessageCollector::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
- {
- addMessageToQueue (message);
- }
|