From e6dd20444e18ba7ee8de4e83f2862d4dcc0f365c Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 13 May 2009 12:08:58 +0000 Subject: [PATCH] Fix for AU plugin midi event threading on some hosts; fix for timing of MidiOutput::sendBlockOfMessages; Fix for URL::addEscapeChars; added a MidiBuffer::swap method; restructured some AudioSampleBuffer methods to aid compiler inlining. --- .../wrapper/AU/juce_AU_Wrapper.mm | 17 ++++++++-- juce_amalgamated.cpp | 34 +++++++++---------- juce_amalgamated.h | 29 ++++++++++++++-- .../audio/devices/juce_MidiOutput.cpp | 4 +-- .../audio/dsp/juce_AudioSampleBuffer.cpp | 9 ----- .../audio/dsp/juce_AudioSampleBuffer.h | 20 +++++++++-- .../audio/midi/juce_MidiBuffer.cpp | 7 ++++ .../audio/midi/juce_MidiBuffer.h | 8 +++++ src/juce_core/io/network/juce_URL.cpp | 8 ++--- 9 files changed, 95 insertions(+), 41 deletions(-) diff --git a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm index 2d43b0ecf5..71d571b447 100644 --- a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm +++ b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm @@ -557,6 +557,7 @@ public: bufferSpace.setSize (2, 16); midiEvents.clear(); + incomingEvents.clear(); prepared = false; } @@ -591,6 +592,7 @@ public: GetMaxFramesPerSlice()); midiEvents.clear(); + incomingEvents.clear(); juce_free (channels); channels = (float**) juce_calloc (sizeof (float*) * jmax (juceFilter->getNumInputChannels(), @@ -699,6 +701,12 @@ public: break; } + { + const ScopedLock sl (incomingMidiLock); + midiEvents.clear(); + incomingEvents.swap (midiEvents); + } + { AudioSampleBuffer buffer (channels, jmax (numIn, numOut), numSamples); @@ -784,12 +792,13 @@ protected: #endif { #if JucePlugin_WantsMidiInput + const ScopedLock sl (incomingMidiLock); JUCE_NAMESPACE::uint8 data [4]; data[0] = nStatus | inChannel; data[1] = inData1; data[2] = inData2; - midiEvents.addEvent (data, 3, inStartFrame); + incomingEvents.addEvent (data, 3, inStartFrame); #endif return noErr; @@ -798,7 +807,8 @@ protected: OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) { #if JucePlugin_WantsMidiInput - midiEvents.addEvent (inData, inLength, 0); + const ScopedLock sl (incomingMidiLock); + incomingEvents.addEvent (inData, inLength, 0); #endif return noErr; } @@ -866,12 +876,13 @@ private: AudioProcessor* juceFilter; AudioSampleBuffer bufferSpace; float** channels; - MidiBuffer midiEvents; + MidiBuffer midiEvents, incomingEvents; bool prepared; SMPTETime lastSMPTETime; AUChannelInfo channelInfo [numChannelConfigs]; AudioUnitEvent auEvent; mutable MemoryBlock presetsArray; + CriticalSection incomingMidiLock; }; //============================================================================== diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 94d2e407e1..a02222cd40 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -3785,6 +3785,12 @@ const var var::call (const var::identifier& method, const var& arg1, const var& return invoke (method, args, 4); } +const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const +{ + var args[] = { arg1, arg2, arg3, arg4, arg5 }; + return invoke (method, args, 5); +} + var::identifier::identifier (const String& name_) throw() : name (name_), hashCode (name_.hashCode()) @@ -8265,12 +8271,8 @@ const String URL::addEscapeChars (const String& s, const bool isParameter) { const char c = *utf8++; - if (c == ' ') - { - result += T('+'); - } - else if (CharacterFunctions::isLetterOrDigit (c) - || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) + if (CharacterFunctions::isLetterOrDigit (c) + || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) { result << c; } @@ -23472,7 +23474,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, // this needs to be a value in the future - RTFM for this method! jassert (millisecondCounterToStartAt > 0); - samplesPerSecondForBuffer *= 0.001; + const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; MidiBuffer::Iterator i (buffer); @@ -23481,7 +23483,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, while (i.getNextEvent (data, len, time)) { - const double eventTime = millisecondCounterToStartAt + samplesPerSecondForBuffer * time; + const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; PendingMessage* const m = new PendingMessage (data, len, eventTime); @@ -24223,15 +24225,6 @@ AudioSampleBuffer::~AudioSampleBuffer() throw() juce_free (channels); } -float* AudioSampleBuffer::getSampleData (const int channelNumber, - const int sampleOffset) const throw() -{ - jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); - jassert (((unsigned int) sampleOffset) < (unsigned int) size); - - return channels [channelNumber] + sampleOffset; -} - void AudioSampleBuffer::setSize (const int newNumChannels, const int newNumSamples, const bool keepExistingContent, @@ -25053,6 +25046,13 @@ const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw() return *this; } +void MidiBuffer::swap (MidiBuffer& other) +{ + swapVariables (this->elements, other.elements); + swapVariables (this->numAllocated, other.numAllocated); + swapVariables (this->bytesUsed, other.bytesUsed); +} + MidiBuffer::~MidiBuffer() throw() { } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 5e12802f33..083bb91053 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -11454,6 +11454,8 @@ public: const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); /** If this variant is an object, this invokes one of its methods with 4 arguments. */ const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; + /** If this variant is an object, this invokes one of its methods with 5 arguments. */ + const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; /** If this variant is an object, this invokes one of its methods with a list of arguments. */ const var invoke (const identifier& method, const var* arguments, int numArguments) const; @@ -26057,6 +26059,13 @@ public: */ int getLastEventTime() const throw(); + /** Exchanges the contents of this buffer with another one. + + This is a quick operation, because no memory allocating or copying is done, it + just swaps the internal state of the two buffers. + */ + void swap (MidiBuffer& other); + /** Used to iterate through the events in a MidiBuffer. @@ -27110,13 +27119,29 @@ public: */ int getNumSamples() const throw() { return size; } + /** Returns a pointer one of the buffer's channels. + + For speed, this doesn't check whether the channel number is out of range, + so be careful when using it! + */ + float* getSampleData (const int channelNumber) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + return channels [channelNumber]; + } + /** Returns a pointer to a sample in one of the buffer's channels. For speed, this doesn't check whether the channel and sample number - are legal, so be careful when using it! + are out-of-range, so be careful when using it! */ float* getSampleData (const int channelNumber, - const int sampleOffset = 0) const throw(); + const int sampleOffset) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + jassert (((unsigned int) sampleOffset) < (unsigned int) size); + return channels [channelNumber] + sampleOffset; + } /** Returns an array of pointers to the channels in the buffer. diff --git a/src/juce_appframework/audio/devices/juce_MidiOutput.cpp b/src/juce_appframework/audio/devices/juce_MidiOutput.cpp index 63184778c7..da4b72a0ca 100644 --- a/src/juce_appframework/audio/devices/juce_MidiOutput.cpp +++ b/src/juce_appframework/audio/devices/juce_MidiOutput.cpp @@ -63,7 +63,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, // this needs to be a value in the future - RTFM for this method! jassert (millisecondCounterToStartAt > 0); - samplesPerSecondForBuffer *= 0.001; + const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; MidiBuffer::Iterator i (buffer); @@ -72,7 +72,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, while (i.getNextEvent (data, len, time)) { - const double eventTime = millisecondCounterToStartAt + samplesPerSecondForBuffer * time; + const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; PendingMessage* const m = new PendingMessage (data, len, eventTime); diff --git a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp index 0be8906c09..741c4211bc 100644 --- a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp +++ b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp @@ -169,15 +169,6 @@ AudioSampleBuffer::~AudioSampleBuffer() throw() juce_free (channels); } -float* AudioSampleBuffer::getSampleData (const int channelNumber, - const int sampleOffset) const throw() -{ - jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); - jassert (((unsigned int) sampleOffset) < (unsigned int) size); - - return channels [channelNumber] + sampleOffset; -} - void AudioSampleBuffer::setSize (const int newNumChannels, const int newNumSamples, const bool keepExistingContent, diff --git a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.h b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.h index 20d1c92333..d7f776f235 100644 --- a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.h +++ b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.h @@ -108,13 +108,29 @@ public: */ int getNumSamples() const throw() { return size; } + /** Returns a pointer one of the buffer's channels. + + For speed, this doesn't check whether the channel number is out of range, + so be careful when using it! + */ + float* getSampleData (const int channelNumber) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + return channels [channelNumber]; + } + /** Returns a pointer to a sample in one of the buffer's channels. For speed, this doesn't check whether the channel and sample number - are legal, so be careful when using it! + are out-of-range, so be careful when using it! */ float* getSampleData (const int channelNumber, - const int sampleOffset = 0) const throw(); + const int sampleOffset) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + jassert (((unsigned int) sampleOffset) < (unsigned int) size); + return channels [channelNumber] + sampleOffset; + } /** Returns an array of pointers to the channels in the buffer. diff --git a/src/juce_appframework/audio/midi/juce_MidiBuffer.cpp b/src/juce_appframework/audio/midi/juce_MidiBuffer.cpp index 3350174371..a922ad7d49 100644 --- a/src/juce_appframework/audio/midi/juce_MidiBuffer.cpp +++ b/src/juce_appframework/audio/midi/juce_MidiBuffer.cpp @@ -72,6 +72,13 @@ const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw() return *this; } +void MidiBuffer::swap (MidiBuffer& other) +{ + swapVariables (this->elements, other.elements); + swapVariables (this->numAllocated, other.numAllocated); + swapVariables (this->bytesUsed, other.bytesUsed); +} + MidiBuffer::~MidiBuffer() throw() { } diff --git a/src/juce_appframework/audio/midi/juce_MidiBuffer.h b/src/juce_appframework/audio/midi/juce_MidiBuffer.h index 8837d8eaa8..8f5c3d379f 100644 --- a/src/juce_appframework/audio/midi/juce_MidiBuffer.h +++ b/src/juce_appframework/audio/midi/juce_MidiBuffer.h @@ -155,6 +155,14 @@ public: */ int getLastEventTime() const throw(); + //============================================================================== + /** Exchanges the contents of this buffer with another one. + + This is a quick operation, because no memory allocating or copying is done, it + just swaps the internal state of the two buffers. + */ + void swap (MidiBuffer& other); + //============================================================================== /** Used to iterate through the events in a MidiBuffer. diff --git a/src/juce_core/io/network/juce_URL.cpp b/src/juce_core/io/network/juce_URL.cpp index 6b29b7a2b0..d123068994 100644 --- a/src/juce_core/io/network/juce_URL.cpp +++ b/src/juce_core/io/network/juce_URL.cpp @@ -525,12 +525,8 @@ const String URL::addEscapeChars (const String& s, const bool isParameter) { const char c = *utf8++; - if (c == ' ') - { - result += T('+'); - } - else if (CharacterFunctions::isLetterOrDigit (c) - || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) + if (CharacterFunctions::isLetterOrDigit (c) + || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) { result << c; }