| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - MidiMessageCollector::MidiMessageCollector()
 - {
 - }
 - 
 - MidiMessageCollector::~MidiMessageCollector()
 - {
 - }
 - 
 - //==============================================================================
 - void MidiMessageCollector::reset (const double newSampleRate)
 - {
 -     const ScopedLock sl (midiCallbackLock);
 - 
 -     jassert (newSampleRate > 0);
 - 
 -    #if JUCE_DEBUG
 -     hasCalledReset = true;
 -    #endif
 -     sampleRate = newSampleRate;
 -     incomingMessages.clear();
 -     lastCallbackTime = Time::getMillisecondCounterHiRes();
 - }
 - 
 - void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
 - {
 -     const ScopedLock sl (midiCallbackLock);
 - 
 -    #if JUCE_DEBUG
 -     jassert (hasCalledReset); // you need to call reset() to set the correct sample rate before using this object
 -    #endif
 - 
 -     // 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);
 - 
 -     auto 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)
 - {
 -     const ScopedLock sl (midiCallbackLock);
 - 
 -    #if JUCE_DEBUG
 -     jassert (hasCalledReset); // you need to call reset() to set the correct sample rate before using this object
 -    #endif
 - 
 -     jassert (numSamples > 0);
 - 
 -     auto timeNow = Time::getMillisecondCounterHiRes();
 -     auto msElapsed = timeNow - lastCallbackTime;
 - 
 -     lastCallbackTime = timeNow;
 - 
 -     if (! incomingMessages.isEmpty())
 -     {
 -         int numSourceSamples = jmax (1, roundToInt (msElapsed * 0.001 * sampleRate));
 -         int startSample = 0;
 -         int scale = 1 << 16;
 - 
 -         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;
 - 
 -             auto iter = incomingMessages.cbegin();
 - 
 -             if (numSourceSamples > maxBlockLengthToUse)
 -             {
 -                 startSample = numSourceSamples - maxBlockLengthToUse;
 -                 numSourceSamples = maxBlockLengthToUse;
 -                 iter = incomingMessages.findNextSamplePosition (startSample);
 -             }
 - 
 -             scale = (numSamples << 10) / numSourceSamples;
 - 
 -             std::for_each (iter, incomingMessages.cend(), [&] (const MidiMessageMetadata& meta)
 -             {
 -                 const auto pos = ((meta.samplePosition - startSample) * scale) >> 10;
 -                 destBuffer.addEvent (meta.data, meta.numBytes, jlimit (0, numSamples - 1, pos));
 -             });
 -         }
 -         else
 -         {
 -             // if our event list is shorter than the number we need, put them
 -             // towards the end of the buffer
 -             startSample = numSamples - numSourceSamples;
 - 
 -             for (const auto metadata : incomingMessages)
 -                 destBuffer.addEvent (metadata.data, metadata.numBytes,
 -                                      jlimit (0, numSamples - 1, metadata.samplePosition + startSample));
 -         }
 - 
 -         incomingMessages.clear();
 -     }
 - }
 - 
 - void MidiMessageCollector::ensureStorageAllocated (size_t bytes)
 - {
 -     incomingMessages.ensureSize (bytes);
 - }
 - 
 - //==============================================================================
 - 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, float velocity)
 - {
 -     MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber, velocity));
 -     m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
 - 
 -     addMessageToQueue (m);
 - }
 - 
 - void MidiMessageCollector::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
 - {
 -     addMessageToQueue (message);
 - }
 - 
 - } // namespace juce
 
 
  |