|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-9 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online 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.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- #include "../../core/juce_StandardHeader.h"
-
- BEGIN_JUCE_NAMESPACE
-
- #include "juce_MidiBuffer.h"
-
-
- //==============================================================================
- MidiBuffer::MidiBuffer() throw()
- : bytesUsed (0)
- {
- }
-
- MidiBuffer::MidiBuffer (const MidiMessage& message) throw()
- : bytesUsed (0)
- {
- addEvent (message, 0);
- }
-
- MidiBuffer::MidiBuffer (const MidiBuffer& other) throw()
- : data (other.data),
- bytesUsed (other.bytesUsed)
- {
- }
-
- const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw()
- {
- bytesUsed = other.bytesUsed;
- data = other.data;
-
- return *this;
- }
-
- void MidiBuffer::swap (MidiBuffer& other)
- {
- data.swapWith (other.data);
- swapVariables <int> (bytesUsed, other.bytesUsed);
- }
-
- MidiBuffer::~MidiBuffer() throw()
- {
- }
-
- void MidiBuffer::clear() throw()
- {
- bytesUsed = 0;
- }
-
- void MidiBuffer::clear (const int startSample,
- const int numSamples) throw()
- {
- uint8* const start = findEventAfter (data, startSample - 1);
- uint8* const end = findEventAfter (start, startSample + numSamples - 1);
-
- if (end > start)
- {
- const size_t bytesToMove = (size_t) (bytesUsed - (end - (uint8*) data.getData()));
-
- if (bytesToMove > 0)
- memmove (start, end, bytesToMove);
-
- bytesUsed -= (int) (end - start);
- }
- }
-
- void MidiBuffer::addEvent (const MidiMessage& m,
- const int sampleNumber) throw()
- {
- addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
- }
-
- static int findActualEventLength (const uint8* const data,
- const int maxBytes) throw()
- {
- unsigned int byte = (unsigned int) *data;
-
- int size = 0;
-
- if (byte == 0xf0 || byte == 0xf7)
- {
- const uint8* d = data + 1;
-
- while (d < data + maxBytes)
- if (*d++ == 0xf7)
- break;
-
- size = (int) (d - data);
- }
- else if (byte == 0xff)
- {
- int n;
- const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n);
- size = jmin (maxBytes, n + 2 + bytesLeft);
- }
- else if (byte >= 0x80)
- {
- size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte));
- }
-
- return size;
- }
-
- void MidiBuffer::addEvent (const uint8* const newData,
- const int maxBytes,
- const int sampleNumber) throw()
- {
- const int numBytes = findActualEventLength (newData, maxBytes);
-
- if (numBytes > 0)
- {
- int spaceNeeded = bytesUsed + numBytes + 6;
- data.ensureSize ((spaceNeeded + spaceNeeded / 2 + 8) & ~7);
-
- uint8* d = findEventAfter ((uint8*) data.getData(), sampleNumber);
- const size_t bytesToMove = (size_t) (bytesUsed - (d - (uint8*) data.getData()));
-
- if (bytesToMove > 0)
- memmove (d + numBytes + 6,
- d,
- bytesToMove);
-
- *(int*) d = sampleNumber;
- d += 4;
- *(uint16*) d = (uint16) numBytes;
- d += 2;
-
- memcpy (d, newData, numBytes);
-
- bytesUsed += numBytes + 6;
- }
- }
-
- void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
- const int startSample,
- const int numSamples,
- const int sampleDeltaToAdd) throw()
- {
- Iterator i (otherBuffer);
- i.setNextSamplePosition (startSample);
-
- const uint8* eventData;
- int eventSize, position;
-
- while (i.getNextEvent (eventData, eventSize, position)
- && (position < startSample + numSamples || numSamples < 0))
- {
- addEvent (eventData, eventSize, position + sampleDeltaToAdd);
- }
- }
-
- bool MidiBuffer::isEmpty() const throw()
- {
- return bytesUsed == 0;
- }
-
- int MidiBuffer::getNumEvents() const throw()
- {
- int n = 0;
- const uint8* d = (uint8*) data.getData();
- const uint8* const end = d + bytesUsed;
-
- while (d < end)
- {
- d += 4;
- d += 2 + *(const uint16*) d;
- ++n;
- }
-
- return n;
- }
-
- int MidiBuffer::getFirstEventTime() const throw()
- {
- return (bytesUsed > 0) ? *(const int*) data.getData() : 0;
- }
-
- int MidiBuffer::getLastEventTime() const throw()
- {
- if (bytesUsed == 0)
- return 0;
-
- const uint8* d = (uint8*) data.getData();
- const uint8* const endData = d + bytesUsed;
-
- for (;;)
- {
- const uint8* nextOne = d + 6 + * (const uint16*) (d + 4);
-
- if (nextOne >= endData)
- return *(const int*) d;
-
- d = nextOne;
- }
- }
-
- uint8* MidiBuffer::findEventAfter (uint8* d, const int samplePosition) const throw()
- {
- const uint8* const endData = ((uint8*) data.getData()) + bytesUsed;
-
- while (d < endData && *(int*) d <= samplePosition)
- {
- d += 4;
- d += 2 + *(uint16*) d;
- }
-
- return d;
- }
-
- //==============================================================================
- MidiBuffer::Iterator::Iterator (const MidiBuffer& buffer_) throw()
- : buffer (buffer_),
- data ((uint8*) buffer_.data.getData())
- {
- }
-
- MidiBuffer::Iterator::~Iterator() throw()
- {
- }
-
- //==============================================================================
- void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) throw()
- {
- data = buffer.data;
- const uint8* dataEnd = ((uint8*) buffer.data.getData()) + buffer.bytesUsed;
-
- while (data < dataEnd && *(int*) data < samplePosition)
- {
- data += 4;
- data += 2 + *(uint16*) data;
- }
- }
-
- bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData,
- int& numBytes,
- int& samplePosition) throw()
- {
- if (data >= ((uint8*) buffer.data.getData()) + buffer.bytesUsed)
- return false;
-
- samplePosition = *(int*) data;
- data += 4;
- numBytes = *(uint16*) data;
- data += 2;
- midiData = data;
- data += numBytes;
-
- return true;
- }
-
- bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result,
- int& samplePosition) throw()
- {
- if (data >= ((uint8*) buffer.data.getData()) + buffer.bytesUsed)
- return false;
-
- samplePosition = *(int*) data;
- data += 4;
- const int numBytes = *(uint16*) data;
- data += 2;
- result = MidiMessage (data, numBytes, samplePosition);
- data += numBytes;
-
- return true;
- }
-
-
- END_JUCE_NAMESPACE
|