| @@ -557,6 +557,7 @@ public: | |||||
| bufferSpace.setSize (2, 16); | bufferSpace.setSize (2, 16); | ||||
| midiEvents.clear(); | midiEvents.clear(); | ||||
| incomingEvents.clear(); | |||||
| prepared = false; | prepared = false; | ||||
| } | } | ||||
| @@ -591,6 +592,7 @@ public: | |||||
| GetMaxFramesPerSlice()); | GetMaxFramesPerSlice()); | ||||
| midiEvents.clear(); | midiEvents.clear(); | ||||
| incomingEvents.clear(); | |||||
| juce_free (channels); | juce_free (channels); | ||||
| channels = (float**) juce_calloc (sizeof (float*) * jmax (juceFilter->getNumInputChannels(), | channels = (float**) juce_calloc (sizeof (float*) * jmax (juceFilter->getNumInputChannels(), | ||||
| @@ -699,6 +701,12 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| { | |||||
| const ScopedLock sl (incomingMidiLock); | |||||
| midiEvents.clear(); | |||||
| incomingEvents.swap (midiEvents); | |||||
| } | |||||
| { | { | ||||
| AudioSampleBuffer buffer (channels, jmax (numIn, numOut), numSamples); | AudioSampleBuffer buffer (channels, jmax (numIn, numOut), numSamples); | ||||
| @@ -784,12 +792,13 @@ protected: | |||||
| #endif | #endif | ||||
| { | { | ||||
| #if JucePlugin_WantsMidiInput | #if JucePlugin_WantsMidiInput | ||||
| const ScopedLock sl (incomingMidiLock); | |||||
| JUCE_NAMESPACE::uint8 data [4]; | JUCE_NAMESPACE::uint8 data [4]; | ||||
| data[0] = nStatus | inChannel; | data[0] = nStatus | inChannel; | ||||
| data[1] = inData1; | data[1] = inData1; | ||||
| data[2] = inData2; | data[2] = inData2; | ||||
| midiEvents.addEvent (data, 3, inStartFrame); | |||||
| incomingEvents.addEvent (data, 3, inStartFrame); | |||||
| #endif | #endif | ||||
| return noErr; | return noErr; | ||||
| @@ -798,7 +807,8 @@ protected: | |||||
| OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) | OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) | ||||
| { | { | ||||
| #if JucePlugin_WantsMidiInput | #if JucePlugin_WantsMidiInput | ||||
| midiEvents.addEvent (inData, inLength, 0); | |||||
| const ScopedLock sl (incomingMidiLock); | |||||
| incomingEvents.addEvent (inData, inLength, 0); | |||||
| #endif | #endif | ||||
| return noErr; | return noErr; | ||||
| } | } | ||||
| @@ -866,12 +876,13 @@ private: | |||||
| AudioProcessor* juceFilter; | AudioProcessor* juceFilter; | ||||
| AudioSampleBuffer bufferSpace; | AudioSampleBuffer bufferSpace; | ||||
| float** channels; | float** channels; | ||||
| MidiBuffer midiEvents; | |||||
| MidiBuffer midiEvents, incomingEvents; | |||||
| bool prepared; | bool prepared; | ||||
| SMPTETime lastSMPTETime; | SMPTETime lastSMPTETime; | ||||
| AUChannelInfo channelInfo [numChannelConfigs]; | AUChannelInfo channelInfo [numChannelConfigs]; | ||||
| AudioUnitEvent auEvent; | AudioUnitEvent auEvent; | ||||
| mutable MemoryBlock presetsArray; | mutable MemoryBlock presetsArray; | ||||
| CriticalSection incomingMidiLock; | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -3785,6 +3785,12 @@ const var var::call (const var::identifier& method, const var& arg1, const var& | |||||
| return invoke (method, args, 4); | 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() | var::identifier::identifier (const String& name_) throw() | ||||
| : name (name_), | : name (name_), | ||||
| hashCode (name_.hashCode()) | hashCode (name_.hashCode()) | ||||
| @@ -8265,12 +8271,8 @@ const String URL::addEscapeChars (const String& s, const bool isParameter) | |||||
| { | { | ||||
| const char c = *utf8++; | 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; | 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! | // this needs to be a value in the future - RTFM for this method! | ||||
| jassert (millisecondCounterToStartAt > 0); | jassert (millisecondCounterToStartAt > 0); | ||||
| samplesPerSecondForBuffer *= 0.001; | |||||
| const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; | |||||
| MidiBuffer::Iterator i (buffer); | MidiBuffer::Iterator i (buffer); | ||||
| @@ -23481,7 +23483,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, | |||||
| while (i.getNextEvent (data, len, time)) | while (i.getNextEvent (data, len, time)) | ||||
| { | { | ||||
| const double eventTime = millisecondCounterToStartAt + samplesPerSecondForBuffer * time; | |||||
| const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; | |||||
| PendingMessage* const m | PendingMessage* const m | ||||
| = new PendingMessage (data, len, eventTime); | = new PendingMessage (data, len, eventTime); | ||||
| @@ -24223,15 +24225,6 @@ AudioSampleBuffer::~AudioSampleBuffer() throw() | |||||
| juce_free (channels); | 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, | void AudioSampleBuffer::setSize (const int newNumChannels, | ||||
| const int newNumSamples, | const int newNumSamples, | ||||
| const bool keepExistingContent, | const bool keepExistingContent, | ||||
| @@ -25053,6 +25046,13 @@ const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw() | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| void MidiBuffer::swap (MidiBuffer& other) | |||||
| { | |||||
| swapVariables <uint8*> (this->elements, other.elements); | |||||
| swapVariables <int> (this->numAllocated, other.numAllocated); | |||||
| swapVariables <int> (this->bytesUsed, other.bytesUsed); | |||||
| } | |||||
| MidiBuffer::~MidiBuffer() throw() | MidiBuffer::~MidiBuffer() throw() | ||||
| { | { | ||||
| } | } | ||||
| @@ -11454,6 +11454,8 @@ public: | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); | 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. */ | /** 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; | 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. */ | /** 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; | const var invoke (const identifier& method, const var* arguments, int numArguments) const; | ||||
| @@ -26057,6 +26059,13 @@ public: | |||||
| */ | */ | ||||
| int getLastEventTime() const throw(); | 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. | Used to iterate through the events in a MidiBuffer. | ||||
| @@ -27110,13 +27119,29 @@ public: | |||||
| */ | */ | ||||
| int getNumSamples() const throw() { return size; } | 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. | /** 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 | 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, | 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. | /** Returns an array of pointers to the channels in the buffer. | ||||
| @@ -63,7 +63,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, | |||||
| // this needs to be a value in the future - RTFM for this method! | // this needs to be a value in the future - RTFM for this method! | ||||
| jassert (millisecondCounterToStartAt > 0); | jassert (millisecondCounterToStartAt > 0); | ||||
| samplesPerSecondForBuffer *= 0.001; | |||||
| const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; | |||||
| MidiBuffer::Iterator i (buffer); | MidiBuffer::Iterator i (buffer); | ||||
| @@ -72,7 +72,7 @@ void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, | |||||
| while (i.getNextEvent (data, len, time)) | while (i.getNextEvent (data, len, time)) | ||||
| { | { | ||||
| const double eventTime = millisecondCounterToStartAt + samplesPerSecondForBuffer * time; | |||||
| const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; | |||||
| PendingMessage* const m | PendingMessage* const m | ||||
| = new PendingMessage (data, len, eventTime); | = new PendingMessage (data, len, eventTime); | ||||
| @@ -169,15 +169,6 @@ AudioSampleBuffer::~AudioSampleBuffer() throw() | |||||
| juce_free (channels); | 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, | void AudioSampleBuffer::setSize (const int newNumChannels, | ||||
| const int newNumSamples, | const int newNumSamples, | ||||
| const bool keepExistingContent, | const bool keepExistingContent, | ||||
| @@ -108,13 +108,29 @@ public: | |||||
| */ | */ | ||||
| int getNumSamples() const throw() { return size; } | 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. | /** 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 | 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, | 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. | /** Returns an array of pointers to the channels in the buffer. | ||||
| @@ -72,6 +72,13 @@ const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw() | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| void MidiBuffer::swap (MidiBuffer& other) | |||||
| { | |||||
| swapVariables <uint8*> (this->elements, other.elements); | |||||
| swapVariables <int> (this->numAllocated, other.numAllocated); | |||||
| swapVariables <int> (this->bytesUsed, other.bytesUsed); | |||||
| } | |||||
| MidiBuffer::~MidiBuffer() throw() | MidiBuffer::~MidiBuffer() throw() | ||||
| { | { | ||||
| } | } | ||||
| @@ -155,6 +155,14 @@ public: | |||||
| */ | */ | ||||
| int getLastEventTime() const throw(); | 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. | Used to iterate through the events in a MidiBuffer. | ||||
| @@ -525,12 +525,8 @@ const String URL::addEscapeChars (const String& s, const bool isParameter) | |||||
| { | { | ||||
| const char c = *utf8++; | 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; | result << c; | ||||
| } | } | ||||