Browse Source

Update juce; Use nominalBlockLength

tags/2018-04-16
falkTX 8 years ago
parent
commit
5a0bf766a4
71 changed files with 1582 additions and 584 deletions
  1. +33
    -5
      libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.cpp
  2. +4
    -1
      libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.h
  3. +7
    -7
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp
  4. +3
    -3
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h
  5. +24
    -6
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  6. +18
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  7. +5
    -5
      libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp
  8. +1
    -1
      libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h
  9. +14
    -3
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  10. +14
    -8
      libs/juce/source/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp
  11. +56
    -0
      libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  12. +1
    -0
      libs/juce/source/modules/juce_audio_plugin_client/LV2/includes/buf-size.h
  13. +4
    -4
      libs/juce/source/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp
  14. +15
    -15
      libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  15. +16
    -16
      libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
  16. +314
    -43
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  17. +9
    -9
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.mm
  18. +11
    -6
      libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Common.h
  19. +3
    -0
      libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Headers.h
  20. +3
    -0
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  21. +220
    -0
      libs/juce/source/modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.cpp
  22. +135
    -0
      libs/juce/source/modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.h
  23. +35
    -32
      libs/juce/source/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp
  24. +1
    -1
      libs/juce/source/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h
  25. +1
    -0
      libs/juce/source/modules/juce_audio_utils/juce_audio_utils.cpp
  26. +1
    -0
      libs/juce/source/modules/juce_audio_utils/juce_audio_utils.h
  27. +17
    -0
      libs/juce/source/modules/juce_core/juce_core.cpp
  28. +20
    -0
      libs/juce/source/modules/juce_core/juce_core.h
  29. +29
    -32
      libs/juce/source/modules/juce_core/maths/juce_Expression.cpp
  30. +9
    -20
      libs/juce/source/modules/juce_core/maths/juce_Expression.h
  31. +5
    -1
      libs/juce/source/modules/juce_core/memory/juce_HeapBlock.h
  32. +2
    -2
      libs/juce/source/modules/juce_core/native/java/JuceAppActivity.java
  33. +2
    -2
      libs/juce/source/modules/juce_core/native/juce_mac_Files.mm
  34. +3
    -3
      libs/juce/source/modules/juce_core/native/juce_win32_Threads.cpp
  35. +36
    -5
      libs/juce/source/modules/juce_core/network/juce_Socket.cpp
  36. +14
    -0
      libs/juce/source/modules/juce_core/network/juce_Socket.h
  37. +6
    -1
      libs/juce/source/modules/juce_core/network/juce_URL.cpp
  38. +20
    -2
      libs/juce/source/modules/juce_core/network/juce_URL.h
  39. +18
    -0
      libs/juce/source/modules/juce_core/system/juce_CompilerSupport.h
  40. +1
    -1
      libs/juce/source/modules/juce_core/text/juce_CharPointer_ASCII.h
  41. +1
    -1
      libs/juce/source/modules/juce_core/text/juce_CharPointer_UTF8.h
  42. +2
    -2
      libs/juce/source/modules/juce_core/text/juce_StringArray.h
  43. +4
    -0
      libs/juce/source/modules/juce_core/unit_tests/juce_UnitTest.cpp
  44. +26
    -26
      libs/juce/source/modules/juce_data_structures/values/juce_ValueTree.cpp
  45. +15
    -15
      libs/juce/source/modules/juce_data_structures/values/juce_ValueTree.h
  46. +2
    -2
      libs/juce/source/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp
  47. +2
    -1
      libs/juce/source/modules/juce_events/interprocess/juce_ConnectedChildProcess.h
  48. +51
    -45
      libs/juce/source/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp
  49. +132
    -97
      libs/juce/source/modules/juce_graphics/image_formats/juce_PNGLoader.cpp
  50. +4
    -6
      libs/juce/source/modules/juce_graphics/images/juce_ImageFileFormat.cpp
  51. +20
    -15
      libs/juce/source/modules/juce_gui_basics/components/juce_Component.cpp
  52. +11
    -4
      libs/juce/source/modules/juce_gui_basics/components/juce_Component.h
  53. +6
    -0
      libs/juce/source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp
  54. +24
    -24
      libs/juce/source/modules/juce_gui_basics/layout/juce_ScrollBar.cpp
  55. +1
    -2
      libs/juce/source/modules/juce_gui_basics/layout/juce_ScrollBar.h
  56. +15
    -14
      libs/juce/source/modules/juce_gui_basics/menus/juce_PopupMenu.h
  57. +2
    -2
      libs/juce/source/modules/juce_gui_basics/mouse/juce_TooltipClient.h
  58. +10
    -5
      libs/juce/source/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm
  59. +0
    -6
      libs/juce/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  60. +19
    -40
      libs/juce/source/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp
  61. +3
    -2
      libs/juce/source/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp
  62. +5
    -4
      libs/juce/source/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp
  63. +1
    -1
      libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.cpp
  64. +2
    -2
      libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.h
  65. +6
    -0
      libs/juce/source/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp
  66. +3
    -0
      libs/juce/source/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.h
  67. +2
    -2
      libs/juce/source/modules/juce_gui_extra/documents/juce_FileBasedDocument.cpp
  68. +2
    -0
      libs/juce/source/modules/juce_gui_extra/embedding/juce_NSViewComponent.h
  69. +12
    -0
      libs/juce/source/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm
  70. +44
    -31
      libs/juce/source/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.cpp
  71. +25
    -0
      libs/juce/source/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.h

+ 33
- 5
libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.cpp View File

@@ -225,13 +225,43 @@ void FFT::perform (const Complex* const input, Complex* const output) const noex
config->perform (input, output);
}
const size_t maxFFTScratchSpaceToAlloca = 256 * 1024;
void FFT::performRealOnlyForwardTransform (float* d) const noexcept
{
const size_t scratchSize = 16 + sizeof (FFT::Complex) * (size_t) size;
if (scratchSize < maxFFTScratchSpaceToAlloca)
{
performRealOnlyForwardTransform (static_cast<Complex*> (alloca (scratchSize)), d);
}
else
{
HeapBlock<char> heapSpace (scratchSize);
performRealOnlyForwardTransform (reinterpret_cast<Complex*> (heapSpace.getData()), d);
}
}
void FFT::performRealOnlyInverseTransform (float* d) const noexcept
{
const size_t scratchSize = 16 + sizeof (FFT::Complex) * (size_t) size;
if (scratchSize < maxFFTScratchSpaceToAlloca)
{
performRealOnlyForwardTransform (static_cast<Complex*> (alloca (scratchSize)), d);
}
else
{
HeapBlock<char> heapSpace (scratchSize);
performRealOnlyInverseTransform (reinterpret_cast<Complex*> (heapSpace.getData()), d);
}
}
void FFT::performRealOnlyForwardTransform (Complex* scratch, float* d) const noexcept
{
// This can only be called on an FFT object that was created to do forward transforms.
jassert (! config->inverse);
Complex* const scratch = static_cast<Complex*> (alloca (16 + sizeof (Complex) * (size_t) size));
for (int i = 0; i < size; ++i)
{
scratch[i].r = d[i];
@@ -241,13 +271,11 @@ void FFT::performRealOnlyForwardTransform (float* d) const noexcept
perform (scratch, reinterpret_cast<Complex*> (d));
}
void FFT::performRealOnlyInverseTransform (float* d) const noexcept
void FFT::performRealOnlyInverseTransform (Complex* scratch, float* d) const noexcept
{
// This can only be called on an FFT object that was created to do inverse transforms.
jassert (config->inverse);
Complex* const scratch = static_cast<Complex*> (alloca (16 + sizeof (Complex) * (size_t) size));
perform (reinterpret_cast<const Complex*> (d), scratch);
const float scaleFactor = 1.0f / size;


+ 4
- 1
libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.h View File

@@ -84,9 +84,12 @@ public:
int getSize() const noexcept { return size; }
private:
struct FFTConfig;
JUCE_PUBLIC_IN_DLL_BUILD (struct FFTConfig)
ScopedPointer<FFTConfig> config;
const int size;
void performRealOnlyForwardTransform (Complex*, float*) const noexcept;
void performRealOnlyInverseTransform (Complex*, float*) const noexcept;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFT)
};

+ 7
- 7
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp View File

@@ -81,7 +81,7 @@ void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNo
}
}
void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber)
void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber, const float velocity)
{
const ScopedLock sl (lock);
@@ -91,18 +91,18 @@ void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber
eventsToAdd.addEvent (MidiMessage::noteOff (midiChannel, midiNoteNumber), timeNow);
eventsToAdd.clear (0, timeNow - 500);
noteOffInternal (midiChannel, midiNoteNumber);
noteOffInternal (midiChannel, midiNoteNumber, velocity);
}
}
void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiNoteNumber)
void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiNoteNumber, const float velocity)
{
if (isNoteOn (midiChannel, midiNoteNumber))
{
noteStates [midiNoteNumber] &= ~(1 << (midiChannel - 1));
for (int i = listeners.size(); --i >= 0;)
listeners.getUnchecked(i)->handleNoteOff (this, midiChannel, midiNoteNumber);
listeners.getUnchecked(i)->handleNoteOff (this, midiChannel, midiNoteNumber, velocity);
}
}
@@ -118,7 +118,7 @@ void MidiKeyboardState::allNotesOff (const int midiChannel)
else
{
for (int i = 0; i < 128; ++i)
noteOff (midiChannel, i);
noteOff (midiChannel, i, 0.0f);
}
}
@@ -130,12 +130,12 @@ void MidiKeyboardState::processNextMidiEvent (const MidiMessage& message)
}
else if (message.isNoteOff())
{
noteOffInternal (message.getChannel(), message.getNoteNumber());
noteOffInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity());
}
else if (message.isAllNotesOff())
{
for (int i = 0; i < 128; ++i)
noteOffInternal (message.getChannel(), i);
noteOffInternal (message.getChannel(), i, 0.0f);
}
}


+ 3
- 3
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h View File

@@ -64,7 +64,7 @@ public:
careful not to block, and avoid any UI activity in the callback.
*/
virtual void handleNoteOff (MidiKeyboardState* source,
int midiChannel, int midiNoteNumber) = 0;
int midiChannel, int midiNoteNumber, float velocity) = 0;
};
@@ -135,7 +135,7 @@ public:
But if the note isn't acutally down for the given channel, this method will in fact do nothing.
*/
void noteOff (int midiChannel, int midiNoteNumber);
void noteOff (int midiChannel, int midiNoteNumber, float velocity);
/** This will turn off any currently-down notes for the given midi channel.
@@ -196,7 +196,7 @@ private:
Array <MidiKeyboardStateListener*> listeners;
void noteOnInternal (int midiChannel, int midiNoteNumber, float velocity);
void noteOffInternal (int midiChannel, int midiNoteNumber);
void noteOffInternal (int midiChannel, int midiNoteNumber, float velocity);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiKeyboardState)
};


+ 24
- 6
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

@@ -33,6 +33,11 @@ namespace MidiHelpers
{
return (uint8) jlimit (0, 127, v);
}
inline uint8 floatVelocityToByte (const float v) noexcept
{
return validVelocity (roundToInt (v * 127.0f));
}
}
//==============================================================================
@@ -386,7 +391,7 @@ float MidiMessage::getFloatVelocity() const noexcept
void MidiMessage::setVelocity (const float newVelocity) noexcept
{
if (isNoteOnOrOff())
getData()[2] = MidiHelpers::validVelocity (roundToInt (newVelocity * 127.0f));
getData()[2] = MidiHelpers::floatVelocityToByte (newVelocity);
}
void MidiMessage::multiplyVelocity (const float scaleFactor) noexcept
@@ -522,11 +527,6 @@ MidiMessage MidiMessage::controllerEvent (const int channel, const int controlle
controllerType & 127, value & 127);
}
MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept
{
return noteOn (channel, noteNumber, (uint8) (velocity * 127.0f + 0.5f));
}
MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept
{
jassert (channel > 0 && channel <= 16);
@@ -536,6 +536,11 @@ MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const
noteNumber & 127, MidiHelpers::validVelocity (velocity));
}
MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept
{
return noteOn (channel, noteNumber, MidiHelpers::floatVelocityToByte (velocity));
}
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept
{
jassert (channel > 0 && channel <= 16);
@@ -545,6 +550,19 @@ MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8
noteNumber & 127, MidiHelpers::validVelocity (velocity));
}
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, float velocity) noexcept
{
return noteOff (channel, noteNumber, MidiHelpers::floatVelocityToByte (velocity));
}
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept
{
jassert (channel > 0 && channel <= 16);
jassert (isPositiveAndBelow (noteNumber, (int) 128));
return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0);
}
MidiMessage MidiMessage::allNotesOff (const int channel) noexcept
{
return controllerEvent (channel, 123, 0);


+ 18
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -234,6 +234,15 @@ public:
*/
bool isNoteOff (bool returnTrueForNoteOnVelocity0 = true) const noexcept;
/** Creates a key-up message.
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@param velocity in the range 0 to 1.0
@see isNoteOff
*/
static MidiMessage noteOff (int channel, int noteNumber, float velocity) noexcept;
/** Creates a key-up message.
@param channel the midi channel, in the range 1 to 16
@@ -241,7 +250,15 @@ public:
@param velocity in the range 0 to 127
@see isNoteOff
*/
static MidiMessage noteOff (int channel, int noteNumber, uint8 velocity = 0) noexcept;
static MidiMessage noteOff (int channel, int noteNumber, uint8 velocity) noexcept;
/** Creates a key-up message.
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@see isNoteOff
*/
static MidiMessage noteOff (int channel, int noteNumber) noexcept;
/** Returns true if this message is a 'key-down' or 'key-up' event.


+ 5
- 5
libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp View File

@@ -33,12 +33,12 @@ MidiMessageCollector::~MidiMessageCollector()
}
//==============================================================================
void MidiMessageCollector::reset (const double sampleRate_)
void MidiMessageCollector::reset (const double newSampleRate)
{
jassert (sampleRate_ > 0);
jassert (newSampleRate > 0);
const ScopedLock sl (midiCallbackLock);
sampleRate = sampleRate_;
sampleRate = newSampleRate;
incomingMessages.clear();
lastCallbackTime = Time::getMillisecondCounterHiRes();
}
@@ -139,9 +139,9 @@ void MidiMessageCollector::handleNoteOn (MidiKeyboardState*, int midiChannel, in
addMessageToQueue (m);
}
void MidiMessageCollector::handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber)
void MidiMessageCollector::handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity)
{
MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber));
MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber, velocity));
m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
addMessageToQueue (m);


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h View File

@@ -86,7 +86,7 @@ public:
/** @internal */
void handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override;
/** @internal */
void handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber) override;
void handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override;
/** @internal */
void handleIncomingMidiMessage (MidiInput*, const MidiMessage&) override;


+ 14
- 3
libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp View File

@@ -429,7 +429,7 @@ struct AAXClasses
public AudioProcessorListener
{
public:
JuceAAX_Processor() : sampleRate (0), lastBufferSize (1024)
JuceAAX_Processor() : sampleRate (0), lastBufferSize (1024), maxBufferSize (1024)
{
pluginInstance = createPluginFilterOfType (AudioProcessor::wrapperType_AAX);
pluginInstance->setPlayHead (this);
@@ -858,7 +858,17 @@ struct AAXClasses
pluginInstance->setPlayConfigDetails (pluginInstance->getNumInputChannels(),
pluginInstance->getNumOutputChannels(),
sampleRate, bufferSize);
pluginInstance->prepareToPlay (sampleRate, bufferSize);
if (bufferSize > maxBufferSize)
{
// we only call prepareToPlay here if the new buffer size is larger than
// the one used last time prepareToPlay was called.
// currently, this should never actually happen, because as of Pro Tools 12,
// the maximum possible value is 1024, and we call prepareToPlay with that
// value during initialisation.
pluginInstance->prepareToPlay (sampleRate, bufferSize);
maxBufferSize = bufferSize;
}
}
const ScopedLock sl (pluginInstance->getCallbackLock());
@@ -962,6 +972,7 @@ struct AAXClasses
audioProcessor.setPlayConfigDetails (numberOfInputChannels, numberOfOutputChannels, sampleRate, lastBufferSize);
audioProcessor.prepareToPlay (sampleRate, lastBufferSize);
maxBufferSize = lastBufferSize;
check (Controller()->SetSignalLatency (audioProcessor.getLatencySamples()));
}
@@ -973,7 +984,7 @@ struct AAXClasses
Array<float*> channelList;
int32_t juceChunkIndex;
AAX_CSampleRate sampleRate;
int lastBufferSize;
int lastBufferSize, maxBufferSize;
struct ChunkMemoryBlock : public ReferenceCountedObject
{


+ 14
- 8
libs/juce/source/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp View File

@@ -55,8 +55,14 @@
#include "CAVectorUnit.h"
#include "CAXException.h"
// NB: This line added for JUCE, for backwards-compatibility with pre-10.8 frameworks
#define kAudioUnitProperty_NickName ((AudioUnitPropertyID) 54)
// This is for JUCE, added as a workaround for problems in older hosts following an API change.
struct OldHostCallbackInfo
{
void* hostUserData;
HostCallback_GetBeatAndTempo beatAndTempoProc;
HostCallback_GetMusicalTimeLocation musicalTimeLocationProc;
HostCallback_GetTransportState transportStateProc;
};
#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64)
@@ -509,7 +515,7 @@ OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID,
#if !CA_NO_AU_HOST_CALLBACKS
case kAudioUnitProperty_HostCallbacks:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
outDataSize = sizeof(mHostCallbackInfo);
outDataSize = sizeof(OldHostCallbackInfo);
outWritable = true;
break;
#endif
@@ -540,7 +546,7 @@ OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID,
outWritable = false;
break;
case kAudioUnitProperty_NickName:
case /*kAudioUnitProperty_NickName*/ 54:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
outDataSize = sizeof(CFStringRef);
outWritable = true;
@@ -743,7 +749,7 @@ OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID,
#if !CA_NO_AU_HOST_CALLBACKS
case kAudioUnitProperty_HostCallbacks:
memcpy(outData, &mHostCallbackInfo, sizeof(mHostCallbackInfo));
memcpy(outData, &mHostCallbackInfo, sizeof(OldHostCallbackInfo));
break;
#endif
#if !CA_NO_AU_UI_FEATURES
@@ -791,7 +797,7 @@ OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID,
*(Float64*)outData = mCurrentRenderTime.mSampleTime;
break;
case kAudioUnitProperty_NickName:
case /*kAudioUnitProperty_NickName*/ 54:
// Ownership follows Core Foundation's 'Copy Rule'
if (mNickName) CFRetain(mNickName);
*(CFStringRef*)outData = mNickName;
@@ -1006,7 +1012,7 @@ OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID,
#endif // !CA_NO_AU_UI_FEATURES
case kAudioUnitProperty_NickName:
case /*kAudioUnitProperty_NickName*/ 54:
{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
@@ -1093,7 +1099,7 @@ OSStatus AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID inID,
#endif // !CA_NO_AU_UI_FEATURES
case kAudioUnitProperty_NickName:
case /*kAudioUnitProperty_NickName*/ 54:
{
if(inScope == kAudioUnitScope_Global) {
if (mNickName) CFRelease(mNickName);


+ 56
- 0
libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm View File

@@ -504,6 +504,47 @@ public:
return numChannelConfigs;
}
UInt32 GetAudioChannelLayout (AudioUnitScope scope,
AudioUnitElement element,
AudioChannelLayout *outLayoutPtr,
Boolean &outWritable)
{
// fallback to old code if this plug-in does not have multi channel IO
if (! hasMultiChannelConfiguration())
return 0;
if (element == 0 && (scope == kAudioUnitScope_Output || scope == kAudioUnitScope_Input))
{
outWritable = false;
const int numChannels = (scope == kAudioUnitScope_Output) ? findNumOutputChannels()
: findNumInputChannels();
const size_t sizeInBytes = (sizeof (AudioChannelLayout) - sizeof (AudioChannelDescription)) +
(numChannels * sizeof (AudioChannelDescription));
if (outLayoutPtr != nullptr)
{
zeromem (outLayoutPtr, sizeInBytes);
outLayoutPtr->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
outLayoutPtr->mNumberChannelDescriptions = numChannels;
for (int i = 0; i < numChannels; ++i)
{
AudioChannelDescription& layoutDescr = outLayoutPtr->mChannelDescriptions [i];
layoutDescr.mChannelLabel = kAudioChannelLabel_Unused;
layoutDescr.mChannelFlags = kAudioChannelFlags_AllOff;
}
}
return static_cast<UInt32> (sizeInBytes);
}
return JuceAUBaseClass::GetAudioChannelLayout(scope, element, outLayoutPtr, outWritable);
}
//==============================================================================
ComponentResult GetParameterInfo (AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
@@ -1367,6 +1408,21 @@ private:
SetAFactoryPresetAsCurrent (currentPreset);
}
//==============================================================================
bool hasMultiChannelConfiguration () noexcept
{
for (int i = 0; i < numChannelConfigs; ++i)
{
#if !JucePlugin_IsSynth
if (channelConfigs[i][0] > 2)
return true;
#endif
if (channelConfigs[i][1] > 2)
return true;
}
return false;
}
JUCE_DECLARE_NON_COPYABLE (JuceAU)
};


+ 1
- 0
libs/juce/source/modules/juce_audio_plugin_client/LV2/includes/buf-size.h View File

@@ -33,6 +33,7 @@
#define LV2_BUF_SIZE__fixedBlockLength LV2_BUF_SIZE_PREFIX "fixedBlockLength"
#define LV2_BUF_SIZE__maxBlockLength LV2_BUF_SIZE_PREFIX "maxBlockLength"
#define LV2_BUF_SIZE__minBlockLength LV2_BUF_SIZE_PREFIX "minBlockLength"
#define LV2_BUF_SIZE__nominalBlockLength LV2_BUF_SIZE_PREFIX "nominalBlockLength"
#define LV2_BUF_SIZE__powerOf2BlockLength LV2_BUF_SIZE_PREFIX "powerOf2BlockLength"
#define LV2_BUF_SIZE__sequenceSize LV2_BUF_SIZE_PREFIX "sequenceSize"



+ 4
- 4
libs/juce/source/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp View File

@@ -1174,12 +1174,12 @@ public:

for (int j=0; options[j].key != 0; ++j)
{
if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[j].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
bufferSize = *(int*)options[j].value;
else
std::cerr << "Host provides maxBlockLength but has wrong value type" << std::endl;
std::cerr << "Host provides nominalBlockLength but has wrong value type" << std::endl;

break;
}
@@ -1651,12 +1651,12 @@ public:
{
for (int j=0; options[j].key != 0; ++j)
{
if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[j].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
bufferSize = *(int*)options[j].value;
else
std::cerr << "Host changed maxBlockLength but with wrong value type" << std::endl;
std::cerr << "Host changed nominalBlockLength but with wrong value type" << std::endl;
}
else if (options[j].key == uridMap->map(uridMap->handle, LV2_CORE__sampleRate))
{


+ 15
- 15
libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp View File

@@ -122,14 +122,14 @@ static juce::uint32 lastMasterIdleCall = 0;
namespace juce
{
#if JUCE_MAC
extern void initialiseMac();
extern void* attachComponentToWindowRef (Component*, void* parent, bool isNSView);
extern void detachComponentFromWindowRef (Component*, void* window, bool isNSView);
extern void setNativeHostWindowSize (void* window, Component*, int newWidth, int newHeight, bool isNSView);
extern void checkWindowVisibility (void* window, Component*, bool isNSView);
extern bool forwardCurrentKeyEventToHost (Component*, bool isNSView);
extern void initialiseMacVST();
extern void* attachComponentToWindowRefVST (Component*, void* parent, bool isNSView);
extern void detachComponentFromWindowRefVST (Component*, void* window, bool isNSView);
extern void setNativeHostWindowSizeVST (void* window, Component*, int newWidth, int newHeight, bool isNSView);
extern void checkWindowVisibilityVST (void* window, Component*, bool isNSView);
extern bool forwardCurrentKeyEventToHostVST (Component*, bool isNSView);
#if ! JUCE_64BIT
extern void updateEditorCompBounds (Component*);
extern void updateEditorCompBoundsVST (Component*);
#endif
#endif
@@ -1049,7 +1049,7 @@ public:
#if JUCE_MAC
if (hostWindow != 0)
checkWindowVisibility (hostWindow, editorComp, useNSView);
checkWindowVisibilityVST (hostWindow, editorComp, useNSView);
#endif
tryMasterIdle();
@@ -1143,7 +1143,7 @@ public:
#if JUCE_MAC
if (hostWindow != 0)
{
detachComponentFromWindowRef (editorComp, hostWindow, useNSView);
detachComponentFromWindowRefVST (editorComp, hostWindow, useNSView);
hostWindow = 0;
}
#endif
@@ -1200,7 +1200,7 @@ public:
Window editorWnd = (Window) editorComp->getWindowHandle();
XReparentWindow (display, editorWnd, hostWindow, 0, 0);
#else
hostWindow = attachComponentToWindowRef (editorComp, ptr, useNSView);
hostWindow = attachComponentToWindowRefVST (editorComp, ptr, useNSView);
#endif
editorComp->setVisible (true);
@@ -1255,7 +1255,7 @@ public:
{
// some hosts don't support the sizeWindow call, so do it manually..
#if JUCE_MAC
setNativeHostWindowSize (hostWindow, editorComp, newWidth, newHeight, useNSView);
setNativeHostWindowSizeVST (hostWindow, editorComp, newWidth, newHeight, useNSView);
#elif JUCE_LINUX
// (Currently, all linux hosts support sizeWindow, so this should never need to happen)
@@ -1359,7 +1359,7 @@ public:
{
// If we have an unused keypress, move the key-focus to a host window
// and re-inject the event..
return forwardCurrentKeyEventToHost (this, wrapper.useNSView);
return forwardCurrentKeyEventToHostVST (this, wrapper.useNSView);
}
#endif
@@ -1375,7 +1375,7 @@ public:
#if JUCE_MAC && ! JUCE_64BIT
if (! wrapper.useNSView)
updateEditorCompBounds (this);
updateEditorCompBoundsVST (this);
#endif
}
@@ -1568,14 +1568,14 @@ namespace
JUCE_EXPORTED_FUNCTION AEffect* VSTPluginMain (audioMasterCallback audioMaster);
JUCE_EXPORTED_FUNCTION AEffect* VSTPluginMain (audioMasterCallback audioMaster)
{
initialiseMac();
initialiseMacVST();
return pluginEntryPoint (audioMaster);
}
JUCE_EXPORTED_FUNCTION AEffect* main_macho (audioMasterCallback audioMaster);
JUCE_EXPORTED_FUNCTION AEffect* main_macho (audioMasterCallback audioMaster)
{
initialiseMac();
initialiseMacVST();
return pluginEntryPoint (audioMaster);
}


+ 16
- 16
libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm View File

@@ -42,8 +42,8 @@ namespace juce
{
#if ! JUCE_64BIT
void updateEditorCompBounds (Component*);
void updateEditorCompBounds (Component* comp)
void updateEditorCompBoundsVST (Component*);
void updateEditorCompBoundsVST (Component* comp)
{
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
@@ -63,22 +63,22 @@ void updateEditorCompBounds (Component* comp)
static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
{
updateEditorCompBounds ((Component*) user);
updateEditorCompBoundsVST ((Component*) user);
return noErr;
}
#endif
//==============================================================================
void initialiseMac();
void initialiseMac()
void initialiseMacVST();
void initialiseMacVST()
{
#if ! JUCE_64BIT
NSApplicationLoad();
#endif
}
void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView);
void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView)
void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView);
void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView)
{
JUCE_AUTORELEASEPOOL
{
@@ -133,7 +133,7 @@ void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, boo
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateEditorCompBounds (comp);
updateEditorCompBoundsVST (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
@@ -181,8 +181,8 @@ void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, boo
}
}
void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView);
void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView);
void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView)
{
JUCE_AUTORELEASEPOOL
{
@@ -239,8 +239,8 @@ void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
}
}
void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
{
JUCE_AUTORELEASEPOOL
{
@@ -277,8 +277,8 @@ void setNativeHostWindowSize (void* window, Component* component, int newWidth,
}
}
void checkWindowVisibility (void* window, Component* comp, bool isNSView);
void checkWindowVisibility (void* window, Component* comp, bool isNSView)
void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView);
void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)
{
(void) window; (void) comp; (void) isNSView;
@@ -288,8 +288,8 @@ void checkWindowVisibility (void* window, Component* comp, bool isNSView)
#endif
}
bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView);
bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView)
bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView);
bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)
{
#if ! JUCE_64BIT
if (! isNSView)


+ 314
- 43
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -62,10 +62,10 @@ using namespace Steinberg;
//==============================================================================
#if JUCE_MAC
extern void initialiseMac();
extern void* attachComponentToWindowRef (Component*, void* parent, bool isNSView);
extern void detachComponentFromWindowRef (Component*, void* window, bool isNSView);
extern void setNativeHostWindowSize (void* window, Component*, int newWidth, int newHeight, bool isNSView);
extern void initialiseMacVST3();
extern void* attachComponentToWindowRefVST3 (Component*, void* parent, bool isNSView);
extern void detachComponentFromWindowRefVST3 (Component*, void* window, bool isNSView);
extern void setNativeHostWindowSizeVST3 (void* window, Component*, int newWidth, int newHeight, bool isNSView);
#endif
//==============================================================================
@@ -73,7 +73,7 @@ class JuceAudioProcessor : public FUnknown
{
public:
JuceAudioProcessor (AudioProcessor* source) noexcept
: refCount (0), audioProcessor (source) {}
: isBypassed (false), refCount (0), audioProcessor (source) {}
virtual ~JuceAudioProcessor() {}
@@ -84,6 +84,8 @@ public:
static const FUID iid;
bool isBypassed;
private:
Atomic<int> refCount;
ScopedPointer<AudioProcessor> audioProcessor;
@@ -230,14 +232,104 @@ public:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Param)
};
//==============================================================================
struct BypassParam : public Vst::Parameter
{
BypassParam (AudioProcessor& p, int index) : owner (p), paramIndex (index)
{
info.id = (Vst::ParamID) index;
toString128 (info.title, "Bypass");
toString128 (info.shortTitle, "Bypass");
toString128 (info.units, "");
info.stepCount = 2;
info.defaultNormalizedValue = 0.0f;
info.unitId = Vst::kRootUnitId;
info.flags = Vst::ParameterInfo::kIsBypass;
}
virtual ~BypassParam() {}
bool setNormalized (Vst::ParamValue v) override
{
bool bypass = (v != 0.0f);
v = (bypass ? 1.0f : 0.0f);
if (valueNormalized != v)
{
valueNormalized = v;
changed();
return true;
}
return false;
}
void toString (Vst::ParamValue value, Vst::String128 result) const override
{
bool bypass = (value != 0.0f);
toString128 (result, bypass ? "On" : "Off");
}
bool fromString (const Vst::TChar* text, Vst::ParamValue& outValueNormalized) const override
{
const String paramValueString (getStringFromVstTChars (text));
if (paramValueString.equalsIgnoreCase ("on")
|| paramValueString.equalsIgnoreCase ("yes")
|| paramValueString.equalsIgnoreCase ("true"))
{
outValueNormalized = 1.0f;
return true;
}
if (paramValueString.equalsIgnoreCase ("off")
|| paramValueString.equalsIgnoreCase ("no")
|| paramValueString.equalsIgnoreCase ("false"))
{
outValueNormalized = 0.0f;
return true;
}
var varValue = JSON::fromString (paramValueString);
if (varValue.isDouble() || varValue.isInt()
|| varValue.isInt64() || varValue.isBool())
{
double value = varValue;
outValueNormalized = (value != 0.0) ? 1.0f : 0.0f;
return true;
}
return false;
}
static String getStringFromVstTChars (const Vst::TChar* text)
{
return juce::String (juce::CharPointer_UTF16 (reinterpret_cast<const juce::CharPointer_UTF16::CharType*> (text)));
}
Vst::ParamValue toPlain (Vst::ParamValue v) const override { return v; }
Vst::ParamValue toNormalized (Vst::ParamValue v) const override { return v; }
private:
AudioProcessor& owner;
int paramIndex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BypassParam)
};
//==============================================================================
tresult PLUGIN_API setComponentState (IBStream* stream) override
{
// Cubase and Nuendo need to inform the host of the current parameter values
if (AudioProcessor* const pluginInstance = getPluginInstance())
{
for (int i = 0; i < pluginInstance->getNumParameters(); ++i)
const int numParameters = pluginInstance->getNumParameters();
for (int i = 0; i < numParameters; ++i)
setParamNormalized ((Vst::ParamID) i, (double) pluginInstance->getParameter (i));
setParamNormalized ((Vst::ParamID) numParameters, audioProcessor->isBypassed ? 1.0f : 0.0f);
}
return Vst::EditController::setComponentState (stream);
@@ -271,13 +363,32 @@ public:
}
//==============================================================================
tresult PLUGIN_API getMidiControllerAssignment (Steinberg::int32, Steinberg::int16,
Vst::CtrlNumber,
Vst::ParamID& id) override
tresult PLUGIN_API getMidiControllerAssignment (Steinberg::int32 /*busIndex*/, Steinberg::int16 channel,
Vst::CtrlNumber midiControllerNumber, Vst::ParamID& resultID) override
{
//TODO
id = 0;
return kNotImplemented;
resultID = (Vst::ParamID) midiControllerToParameter[channel][midiControllerNumber];
return kResultTrue; // Returning false makes some hosts stop asking for further MIDI Controller Assignments
}
// Converts an incoming parameter index to a MIDI controller:
bool getMidiControllerForParameter (int index, int& channel, int& ctrlNumber)
{
const int mappedIndex = index - parameterToMidiControllerOffset;
if (isPositiveAndBelow (mappedIndex, numElementsInArray (parameterToMidiController)))
{
const MidiController& mc = parameterToMidiController[mappedIndex];
if (mc.channel != -1 && mc.ctrlNumber != -1)
{
channel = jlimit (1, 16, mc.channel + 1);
ctrlNumber = mc.ctrlNumber;
return true;
}
}
return false;
}
//==============================================================================
@@ -327,6 +438,18 @@ private:
ComSmartPtr<JuceAudioProcessor> audioProcessor;
ScopedJuceInitialiser_GUI libraryInitialiser;
struct MidiController
{
MidiController() noexcept : channel (-1), ctrlNumber (-1) {}
int channel, ctrlNumber;
};
enum { numMIDIChannels = 16 };
int parameterToMidiControllerOffset;
MidiController parameterToMidiController[numMIDIChannels * Vst::kCountCtrlNumber];
int midiControllerToParameter[numMIDIChannels][Vst::kCountCtrlNumber];
//==============================================================================
void setupParameters()
{
@@ -335,13 +458,41 @@ private:
pluginInstance->addListener (this);
if (parameters.getParameterCount() <= 0)
for (int i = 0; i < pluginInstance->getNumParameters(); ++i)
{
const int numParameters = pluginInstance->getNumParameters();
for (int i = 0; i < numParameters; ++i)
parameters.addParameter (new Param (*pluginInstance, i));
parameters.addParameter (new BypassParam (*pluginInstance, numParameters));
}
// We need to account for the bypass parameter in the numParameters passed to
// the next function
initialiseMidiControllerMappings (pluginInstance->getNumParameters() + 1);
audioProcessorChanged (pluginInstance);
}
}
void initialiseMidiControllerMappings (const int numVstParameters)
{
parameterToMidiControllerOffset = numVstParameters;
for (int c = 0, p = 0; c < numMIDIChannels; ++c)
{
for (int i = 0; i < Vst::kCountCtrlNumber; ++i, ++p)
{
midiControllerToParameter[c][i] = p + parameterToMidiControllerOffset;
parameterToMidiController[p].channel = c;
parameterToMidiController[p].ctrlNumber = i;
parameters.addParameter (new Vst::Parameter (toString ("MIDI CC " + String (c) + "|" + String (i)),
(Vst::ParamID) (p + parameterToMidiControllerOffset), 0, 0, 0,
Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
}
}
}
void sendIntMessage (const char* idTag, const Steinberg::int64 value)
{
jassert (hostContext != nullptr);
@@ -401,7 +552,7 @@ private:
component->setVisible (true);
#else
isNSView = (strcmp (type, kPlatformTypeNSView) == 0);
macHostWindow = juce::attachComponentToWindowRef (component, parent, isNSView);
macHostWindow = juce::attachComponentToWindowRefVST3 (component, parent, isNSView);
#endif
component->resizeHostWindow();
@@ -420,7 +571,7 @@ private:
#else
if (macHostWindow != nullptr)
{
juce::detachComponentFromWindowRef (component, macHostWindow, isNSView);
juce::detachComponentFromWindowRefVST3 (component, macHostWindow, isNSView);
macHostWindow = nullptr;
}
#endif
@@ -532,7 +683,7 @@ private:
setSize (w, h);
#else
if (owner.macHostWindow != nullptr && ! getHostType().isWavelab())
juce::setNativeHostWindowSize (owner.macHostWindow, this, w, h, owner.isNSView);
juce::setNativeHostWindowSizeVST3 (owner.macHostWindow, this, w, h, owner.isNSView);
#endif
if (owner.plugFrame != nullptr)
@@ -604,6 +755,8 @@ public:
processSetup.sampleRate = 44100.0;
processSetup.symbolicSampleSize = Vst::kSample32;
vstBypassParameterId = pluginInstance->getNumParameters();
pluginInstance->setPlayHead (this);
}
@@ -801,12 +954,92 @@ public:
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
bool isBypassed() { return comPluginInstance->isBypassed; }
void setBypassed (bool bypassed) { comPluginInstance->isBypassed = bypassed; }
//==============================================================================
void writeJucePrivateStateInformation (MemoryOutputStream& out)
{
ValueTree privateData (kJucePrivateDataIdentifier);
// for now we only store the bypass value
privateData.setProperty ("Bypass", var (isBypassed()), nullptr);
privateData.writeToStream (out);
}
void setJucePrivateStateInformation (const void* data, int sizeInBytes)
{
ValueTree privateData = ValueTree::readFromData (data, static_cast<size_t> (sizeInBytes));
setBypassed (static_cast<bool> (privateData.getProperty ("Bypass", var (false))));
}
void getStateInformation (MemoryBlock& destData)
{
pluginInstance->getStateInformation (destData);
// With bypass support, JUCE now needs to store private state data.
// Put this at the end of the plug-in state and add a few null characters
// so that plug-ins built with older versions of JUCE will hopefully ignore
// this data. Additionally, we need to add some sort of magic identifier
// at the very end of the private data so that JUCE has some sort of
// way to figure out if the data was stored with a newer JUCE version.
MemoryOutputStream extraData;
extraData.writeInt64 (0);
writeJucePrivateStateInformation (extraData);
const int64 privateDataSize = (int64) (extraData.getDataSize() - sizeof (int64));
extraData.writeInt64 (privateDataSize);
extraData << kJucePrivateDataIdentifier;
// write magic string
destData.append (extraData.getData(), extraData.getDataSize());
}
void setStateInformation (const void* data, int sizeAsInt)
{
size_t size = static_cast<size_t> (sizeAsInt);
// Check if this data was written with a newer JUCE version
// and if it has the JUCE private data magic code at the end
const size_t jucePrivDataIdentifierSize = std::strlen (kJucePrivateDataIdentifier);
if (size >= (jucePrivDataIdentifierSize + sizeof (int64)))
{
const char* buffer = static_cast<const char*> (data);
String magic (CharPointer_UTF8 (buffer + size - jucePrivDataIdentifierSize),
CharPointer_UTF8 (buffer + size));
if (magic == kJucePrivateDataIdentifier)
{
// found a JUCE private data section
uint64 privateDataSize;
std::memcpy (&privateDataSize,
buffer + (size - jucePrivDataIdentifierSize - sizeof (uint64)),
sizeof (uint64));
privateDataSize = ByteOrder::swapIfBigEndian (privateDataSize);
size -= privateDataSize + jucePrivDataIdentifierSize + sizeof (uint64);
if (privateDataSize > 0)
setJucePrivateStateInformation (buffer + size, static_cast<int> (privateDataSize));
size -= sizeof (uint64);
}
}
pluginInstance->setStateInformation (data, static_cast<int> (size));
}
//==============================================================================
#if JUCE_VST3_CAN_REPLACE_VST2
void loadVST2VstWBlock (const char* data, int size)
{
const int headerLen = htonl (*(juce::int32*) (data + 4));
const int headerLen = static_cast<int> (htonl (*(juce::int32*) (data + 4)));
const struct fxBank* bank = (const struct fxBank*) (data + (8 + headerLen));
const int version = htonl (bank->version); (void) version;
const int version = static_cast<int> (htonl (bank->version)); (void) version;
jassert ('VstW' == htonl (*(juce::int32*) data));
jassert (1 == htonl (*(juce::int32*) (data + 8))); // version should be 1 according to Steinberg's docs
@@ -815,9 +1048,9 @@ public:
jassert (version == 1 || version == 2);
jassert (JucePlugin_VSTUniqueID == htonl (bank->fxID));
pluginInstance->setStateInformation (bank->content.data.chunk,
jmin ((int) (size - (bank->content.data.chunk - data)),
(int) htonl (bank->content.data.size)));
setStateInformation (bank->content.data.chunk,
jmin ((int) (size - (bank->content.data.chunk - data)),
(int) htonl (bank->content.data.size)));
}
bool loadVST3PresetFile (const char* data, int size)
@@ -845,7 +1078,7 @@ public:
juce::uint64 chunkOffset = ByteOrder::littleEndianInt64 (data + entryOffset + 4);
juce::uint64 chunkSize = ByteOrder::littleEndianInt64 (data + entryOffset + 12);
if (chunkOffset + chunkSize > size)
if (chunkOffset + chunkSize > static_cast<juce::uint64> (size))
{
jassertfalse;
return false;
@@ -887,7 +1120,7 @@ public:
#if JUCE_VST3_CAN_REPLACE_VST2
return loadVST2CompatibleState ((const char*) data, size);
#else
pluginInstance->setStateInformation (data, size);
setStateInformation (data, size);
return true;
#endif
}
@@ -928,7 +1161,7 @@ public:
if (bytesRead <= 0 || (status != kResultTrue && ! getHostType().isWavelab()))
break;
allData.write (buffer, bytesRead);
allData.write (buffer, static_cast<size_t> (bytesRead));
}
}
@@ -959,13 +1192,13 @@ public:
return state->write (&t, 4);
}
static tresult writeVST2Header (IBStream* state)
static tresult writeVST2Header (IBStream* state, bool bypassed)
{
tresult status = writeVST2Int (state, 'VstW');
if (status == kResultOk) status = writeVST2Int (state, 8); // header size
if (status == kResultOk) status = writeVST2Int (state, 1); // version
if (status == kResultOk) status = writeVST2Int (state, 0); // bypass
if (status == kResultOk) status = writeVST2Int (state, bypassed ? 1 : 0); // bypass
return status;
}
@@ -977,10 +1210,10 @@ public:
return kInvalidArgument;
juce::MemoryBlock mem;
pluginInstance->getStateInformation (mem);
getStateInformation (mem);
#if JUCE_VST3_CAN_REPLACE_VST2
tresult status = writeVST2Header (state);
tresult status = writeVST2Header (state, isBypassed());
if (status != kResultOk)
return status;
@@ -989,13 +1222,13 @@ public:
struct fxBank bank;
zerostruct (bank);
bank.chunkMagic = htonl (cMagic);
bank.byteSize = htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
bank.fxMagic = htonl (chunkBankMagic);
bank.version = htonl (2);
bank.fxID = htonl (JucePlugin_VSTUniqueID);
bank.fxVersion = htonl (JucePlugin_VersionCode);
bank.content.data.size = htonl ((unsigned int) mem.getSize());
bank.chunkMagic = (VstInt32) htonl (cMagic);
bank.byteSize = (VstInt32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
bank.fxMagic = (VstInt32) htonl (chunkBankMagic);
bank.version = (VstInt32) htonl (2);
bank.fxID = (VstInt32) htonl (JucePlugin_VSTUniqueID);
bank.fxVersion = (VstInt32) htonl (JucePlugin_VersionCode);
bank.content.data.size = (VstInt32) htonl ((unsigned int) mem.getSize());
status = state->write (&bank, bankBlockSize);
@@ -1087,7 +1320,7 @@ public:
bool getCurrentPosition (CurrentPositionInfo& info) override
{
info.timeInSamples = jmax ((juce::int64) 0, processContext.projectTimeSamples);
info.timeInSeconds = processContext.projectTimeMusic;
info.timeInSeconds = processContext.systemTime / 1000000000.0;
info.bpm = jmax (1.0, processContext.tempo);
info.timeSigNumerator = jmax (1, (int) processContext.timeSigNumerator);
info.timeSigDenominator = jmax (1, (int) processContext.timeSigDenominator);
@@ -1250,13 +1483,38 @@ public:
if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue)
{
const int id = (int) paramQueue->getParameterId();
jassert (isPositiveAndBelow (id, pluginInstance->getNumParameters()));
pluginInstance->setParameter (id, (float) value);
if (isPositiveAndBelow (id, pluginInstance->getNumParameters()))
pluginInstance->setParameter (id, (float) value);
else if (id == vstBypassParameterId)
setBypassed (static_cast<float> (value) != 0.0f);
else
addParameterChangeToMidiBuffer (offsetSamples, id, value);
}
}
}
}
void addParameterChangeToMidiBuffer (const Steinberg::int32 offsetSamples, const int id, const double value)
{
// If the parameter is mapped to a MIDI CC message then insert it into the midiBuffer.
int channel, ctrlNumber;
if (juceVST3EditController->getMidiControllerForParameter (id, channel, ctrlNumber))
{
if (ctrlNumber == Vst::kAfterTouch)
midiBuffer.addEvent (MidiMessage::channelPressureChange (channel,
jlimit (0, 127, (int) (value * 128.0))), offsetSamples);
else if (ctrlNumber == Vst::kPitchBend)
midiBuffer.addEvent (MidiMessage::pitchWheel (channel,
jlimit (0, 0x3fff, (int) (value * 0x4000))), offsetSamples);
else
midiBuffer.addEvent (MidiMessage::controllerEvent (channel,
jlimit (0, 127, ctrlNumber),
jlimit (0, 127, (int) (value * 128.0))), offsetSamples);
}
}
tresult PLUGIN_API process (Vst::ProcessData& data) override
{
if (pluginInstance == nullptr)
@@ -1312,9 +1570,16 @@ public:
processParameterChanges (*data.inputParameterChanges);
if (pluginInstance->isSuspended())
{
buffer.clear();
}
else
pluginInstance->processBlock (buffer, midiBuffer);
{
if (isBypassed())
pluginInstance->processBlockBypassed (buffer, midiBuffer);
else
pluginInstance->processBlock (buffer, midiBuffer);
}
}
for (int i = 0; i < numOutputChans; ++i)
@@ -1372,6 +1637,10 @@ private:
ScopedJuceInitialiser_GUI libraryInitialiser;
int vstBypassParameterId;
static const char* kJucePrivateDataIdentifier;
//==============================================================================
void addBusTo (Vst::BusList& busList, Vst::Bus* newBus)
{
@@ -1385,7 +1654,7 @@ private:
void addEventBusTo (Vst::BusList& busList, const juce::String& name)
{
addBusTo (busList, new Vst::EventBus (toString (name), 16, Vst::kMain, Vst::BusInfo::kDefaultActive));
addBusTo (busList, new Vst::EventBus (toString (name), Vst::kMain, Vst::BusInfo::kDefaultActive, 16));
}
Vst::BusList* getBusListFor (Vst::MediaType type, Vst::BusDirection dir)
@@ -1431,13 +1700,15 @@ private:
Steinberg::FUID getJuceVST3ComponentIID() { return JuceVST3Component::iid; }
#endif
const char* JuceVST3Component::kJucePrivateDataIdentifier = "JUCEPrivateData";
//==============================================================================
#if JUCE_MSVC
#pragma warning (push, 0)
#pragma warning (disable: 4310)
#elif JUCE_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-w"
#pragma clang diagnostic ignored "-Wall"
#endif
DECLARE_CLASS_IID (JuceAudioProcessor, 0x0101ABAB, 0xABCDEF01, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
@@ -1463,7 +1734,7 @@ DEF_CLASS_IID (JuceAudioProcessor)
for (size_t i = 0; i <= 8; ++i)
{
juce::uint8 c = i < len ? JucePlugin_Name[i] : 0;
juce::uint8 c = i < len ? static_cast<juce::uint8> (JucePlugin_Name[i]) : 0;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
@@ -1498,7 +1769,7 @@ DEF_CLASS_IID (JuceAudioProcessor)
bool initModule()
{
#if JUCE_MAC
initialiseMac();
initialiseMacVST3();
#endif
return true;


+ 9
- 9
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.mm View File

@@ -42,7 +42,7 @@
//==============================================================================
namespace juce
{
static void initialiseMac()
void initialiseMacVST3()
{
#if ! JUCE_64BIT
NSApplicationLoad();
@@ -50,7 +50,7 @@ namespace juce
}
#if ! JUCE_64BIT
static void updateComponentPos (Component* const comp)
static void updateComponentPosVST3 (Component* const comp)
{
DBG ("updateComponentPos()");
@@ -70,14 +70,14 @@ namespace juce
(int) (windowPos.top + r.origin.y));
}
static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
static pascal OSStatus viewBoundsChangedEventVST3 (EventHandlerCallRef, EventRef, void* user)
{
updateComponentPos ((Component*) user);
updateComponentPosVST3 ((Component*) user);
return noErr;
}
#endif
static void* attachComponentToWindowRef (Component* comp, void* windowRef, bool isHIView)
void* attachComponentToWindowRefVST3 (Component* comp, void* windowRef, bool isHIView)
{
DBG ("attachComponentToWindowRef()");
@@ -163,10 +163,10 @@ namespace juce
EventHandlerRef ref;
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEventVST3), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateComponentPos (comp);
updateComponentPosVST3 (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
@@ -194,7 +194,7 @@ namespace juce
}
}
static void detachComponentFromWindowRef (Component* comp, void* nsWindow, bool isHIView)
void detachComponentFromWindowRefVST3 (Component* comp, void* nsWindow, bool isHIView)
{
JUCE_AUTORELEASEPOOL
{
@@ -242,7 +242,7 @@ namespace juce
}
}
static void setNativeHostWindowSize (void* nsWindow, Component* component, int newWidth, int newHeight, bool isHIView)
void setNativeHostWindowSizeVST3 (void* nsWindow, Component* component, int newWidth, int newHeight, bool isHIView)
{
JUCE_AUTORELEASEPOOL
{


+ 11
- 6
libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Common.h View File

@@ -60,12 +60,17 @@ static bool doUIDsMatch (const Steinberg::TUID a, const Steinberg::TUID b) noexc
}
//==============================================================================
static juce::String toString (const Steinberg::char8* string) noexcept { return juce::String (string); }
static juce::String toString (const Steinberg::char16* string) noexcept { return juce::String (juce::CharPointer_UTF16 ((juce::CharPointer_UTF16::CharType*) string)); }
inline juce::String toString (const Steinberg::char8* string) noexcept { return juce::String (string); }
inline juce::String toString (const Steinberg::char16* string) noexcept { return juce::String (juce::CharPointer_UTF16 ((juce::CharPointer_UTF16::CharType*) string)); }
// NB: The casts are handled by a Steinberg::UString operator
static juce::String toString (const Steinberg::UString128& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
static juce::String toString (const Steinberg::UString256& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
inline juce::String toString (const Steinberg::UString128& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
inline juce::String toString (const Steinberg::UString256& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
static void toString128 (Steinberg::Vst::String128 result, const char* source)
{
Steinberg::UString (result, 128).fromAscii (source);
}
static void toString128 (Steinberg::Vst::String128 result, const juce::String& source)
{
@@ -391,7 +396,7 @@ namespace VST3BufferExchange
channelIndexOffset += numChansForBus;
}
static void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result, BusMap& busMapToUse,
inline void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result, BusMap& busMapToUse,
const Array<Steinberg::Vst::SpeakerArrangement>& arrangements,
AudioSampleBuffer& source)
{
@@ -402,7 +407,7 @@ namespace VST3BufferExchange
arrangements.getUnchecked (i), source);
}
static void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result,
inline void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result,
Steinberg::Vst::IAudioProcessor& processor,
BusMap& busMapToUse, bool isInput, int numBusses,
AudioSampleBuffer& source)


+ 3
- 0
libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Headers.h View File

@@ -44,6 +44,7 @@
#pragma clang diagnostic ignored "-Woverloaded-virtual"
#pragma clang diagnostic ignored "-Wshadow"
#pragma clang diagnostic ignored "-Wdeprecated-register"
#pragma clang diagnostic ignored "-Wunused-function"
#endif
/* These files come with the Steinberg VST3 SDK - to get them, you'll need to
@@ -75,6 +76,7 @@
#include <pluginterfaces/vst/ivstprocesscontext.h>
#include <pluginterfaces/vst/vsttypes.h>
#include <pluginterfaces/vst/ivstunits.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <public.sdk/source/common/memorystream.h>
#else
#include <base/source/baseiids.cpp>
@@ -92,6 +94,7 @@
#include <pluginterfaces/base/ipluginbase.h>
#include <pluginterfaces/base/ustring.cpp>
#include <pluginterfaces/gui/iplugview.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <public.sdk/source/common/memorystream.cpp>
#include <public.sdk/source/common/pluginview.cpp>
#include <public.sdk/source/vst/vsteditcontroller.cpp>


+ 3
- 0
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessor.h View File

@@ -106,6 +106,9 @@ public:
Your code must be able to cope with variable-sized blocks, or you're going to get
clicks and crashes!
Also note that some hosts will occasionally decide to pass a buffer containing
zero samples, so make sure that your algorithm can deal with that!
If the filter is receiving a midi input, then the midiMessages array will be filled
with the midi messages for this block. Each message's timestamp will indicate the
message's time, as a number of samples from the start of the block.


+ 220
- 0
libs/juce/source/modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.cpp View File

@@ -0,0 +1,220 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2015 - ROLI 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.
==============================================================================
*/
struct AudioVisualiserComponent::ChannelInfo
{
ChannelInfo (AudioVisualiserComponent& o, int bufferSize)
: owner (o), nextSample (0), subSample (0)
{
setBufferSize (bufferSize);
clear();
}
void clear() noexcept
{
for (int i = 0; i < levels.size(); ++i)
levels.getReference(i) = Range<float>();
value = Range<float>();
subSample = 0;
}
void pushSamples (const float* inputSamples, const int num) noexcept
{
for (int i = 0; i < num; ++i)
pushSample (inputSamples[i]);
}
void pushSample (const float newSample) noexcept
{
if (--subSample <= 0)
{
nextSample %= levels.size();
levels.getReference (nextSample++) = value;
subSample = owner.getSamplesPerBlock();
value = Range<float> (newSample, newSample);
}
else
{
value = value.getUnionWith (newSample);
}
}
void setBufferSize (int newSize)
{
levels.removeRange (newSize, levels.size());
levels.insertMultiple (-1, Range<float>(), newSize - levels.size());
if (nextSample >= newSize)
nextSample = 0;
}
AudioVisualiserComponent& owner;
Array<Range<float> > levels;
Range<float> value;
int nextSample, subSample;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChannelInfo)
};
//==============================================================================
AudioVisualiserComponent::AudioVisualiserComponent (const int initialNumChannels)
: numSamples (1024),
inputSamplesPerBlock (256),
backgroundColour (Colours::black),
waveformColour (Colours::white)
{
setOpaque (true);
setNumChannels (initialNumChannels);
setRepaintRate (60);
}
AudioVisualiserComponent::~AudioVisualiserComponent()
{
}
void AudioVisualiserComponent::setNumChannels (const int numChannels)
{
channels.clear();
for (int i = 0; i < numChannels; ++i)
channels.add (new ChannelInfo (*this, numSamples));
}
void AudioVisualiserComponent::setBufferSize (int newNumSamples)
{
numSamples = newNumSamples;
for (int i = 0; i < channels.size(); ++i)
channels.getUnchecked(i)->setBufferSize (newNumSamples);
}
void AudioVisualiserComponent::clear()
{
for (int i = 0; i < channels.size(); ++i)
channels.getUnchecked(i)->clear();
}
void AudioVisualiserComponent::pushBuffer (const float** d, int numChannels, int num)
{
numChannels = jmin (numChannels, channels.size());
for (int i = 0; i < numChannels; ++i)
channels.getUnchecked(i)->pushSamples (d[i], num);
}
void AudioVisualiserComponent::pushBuffer (const AudioSampleBuffer& buffer)
{
pushBuffer (buffer.getArrayOfReadPointers(),
buffer.getNumChannels(),
buffer.getNumSamples());
}
void AudioVisualiserComponent::pushBuffer (const AudioSourceChannelInfo& buffer)
{
const int numChannels = jmin (buffer.buffer->getNumChannels(), channels.size());
for (int i = 0; i < numChannels; ++i)
channels.getUnchecked(i)->pushSamples (buffer.buffer->getReadPointer (i, buffer.startSample),
buffer.numSamples);
}
void AudioVisualiserComponent::pushSample (const float* d, int numChannels)
{
numChannels = jmin (numChannels, channels.size());
for (int i = 0; i < numChannels; ++i)
channels.getUnchecked(i)->pushSample (d[i]);
}
void AudioVisualiserComponent::setSamplesPerBlock (int newSamplesPerPixel) noexcept
{
inputSamplesPerBlock = newSamplesPerPixel;
}
void AudioVisualiserComponent::setRepaintRate (int frequencyInHz)
{
startTimerHz (frequencyInHz);
}
void AudioVisualiserComponent::timerCallback()
{
repaint();
}
void AudioVisualiserComponent::setColours (Colour bk, Colour fg) noexcept
{
backgroundColour = bk;
waveformColour = fg;
repaint();
}
void AudioVisualiserComponent::paint (Graphics& g)
{
g.fillAll (backgroundColour);
Rectangle<float> r (getLocalBounds().toFloat());
const float channelHeight = r.getHeight() / channels.size();
g.setColour (waveformColour);
for (int i = 0; i < channels.size(); ++i)
{
const ChannelInfo& c = *channels.getUnchecked(i);
paintChannel (g, r.removeFromTop (channelHeight),
c.levels.begin(), c.levels.size(), c.nextSample);
}
}
void AudioVisualiserComponent::getChannelAsPath (Path& path, const Range<float>* levels, int numLevels, int nextSample)
{
path.preallocateSpace (4 * numLevels + 8);
for (int i = 0; i < numLevels; ++i)
{
const float level = -(levels[(nextSample + i) % numLevels].getEnd());
if (i == 0)
path.startNewSubPath (0.0f, level);
else
path.lineTo ((float) i, level);
}
for (int i = numLevels; --i >= 0;)
path.lineTo ((float) i, -(levels[(nextSample + i) % numLevels].getStart()));
path.closeSubPath();
}
void AudioVisualiserComponent::paintChannel (Graphics& g, Rectangle<float> area,
const Range<float>* levels, int numLevels, int nextSample)
{
Path p;
getChannelAsPath (p, levels, numLevels, nextSample);
g.fillPath (p, AffineTransform::fromTargetPoints (0.0f, -1.0f, area.getX(), area.getY(),
0.0f, 1.0f, area.getX(), area.getBottom(),
(float) numLevels, -1.0f, area.getRight(), area.getY()));
}

+ 135
- 0
libs/juce/source/modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.h View File

@@ -0,0 +1,135 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2015 - ROLI 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.
==============================================================================
*/
#ifndef JUCE_AUDIOVISUALISER_H_INCLUDED
#define JUCE_AUDIOVISUALISER_H_INCLUDED
//==============================================================================
/**
A simple component that can be used to show a scrolling waveform of audio data.
This is a handy way to get a quick visualisation of some audio data. Just create
one of these, set its size and oversampling rate, and then feed it with incoming
data by calling one of its pushBuffer() or pushSample() methods.
You can override its paint method for more customised views, but it's only designed
as a quick-and-dirty class for simple tasks, so please don't send us feature requests
for fancy additional features that you'd like it to support! If you're building a
real-world app that requires more powerful waveform display, you'll probably want to
create your own component instead.
*/
class AudioVisualiserComponent : public Component,
private Timer
{
public:
/** Creates a visualiser with the given number of channels. */
AudioVisualiserComponent (int initialNumChannels);
/** Destructor. */
~AudioVisualiserComponent();
/** Changes the number of channels that the visualiser stores. */
void setNumChannels (int numChannels);
/** Changes the number of samples that the visualiser keeps in its history.
Note that this value refers to the number of averaged sample blocks, and each
block is calculated as the peak of a number of incoming audio samples. To set
the number of incoming samples per block, use setSamplesPerBlock().
*/
void setBufferSize (int bufferSize);
/** */
void setSamplesPerBlock (int newNumInputSamplesPerBlock) noexcept;
/** */
int getSamplesPerBlock() const noexcept { return inputSamplesPerBlock; }
/** Clears the contents of the buffers. */
void clear();
/** Pushes a buffer of channels data.
The number of channels provided here is expected to match the number of channels
that this AudioVisualiserComponent has been told to use.
*/
void pushBuffer (const AudioSampleBuffer& bufferToPush);
/** Pushes a buffer of channels data.
The number of channels provided here is expected to match the number of channels
that this AudioVisualiserComponent has been told to use.
*/
void pushBuffer (const AudioSourceChannelInfo& bufferToPush);
/** Pushes a buffer of channels data.
The number of channels provided here is expected to match the number of channels
that this AudioVisualiserComponent has been told to use.
*/
void pushBuffer (const float** channelData, int numChannels, int numSamples);
/** Pushes a single sample (per channel).
The number of channels provided here is expected to match the number of channels
that this AudioVisualiserComponent has been told to use.
*/
void pushSample (const float* samplesForEachChannel, int numChannels);
/** Sets the colours used to paint the */
void setColours (Colour backgroundColour, Colour waveformColour) noexcept;
/** Sets the frequency at which the component repaints itself. */
void setRepaintRate (int frequencyInHz);
/** Draws a channel of audio data in the given bounds.
The default implementation just calls getChannelAsPath() and fits this into the given
area. You may want to override this to draw things differently.
*/
virtual void paintChannel (Graphics&, Rectangle<float> bounds,
const Range<float>* levels, int numLevels, int nextSample);
/** Creates a path which contains the waveform shape of a given set of range data.
The path is normalised so that -1 and +1 are its upper and lower bounds, and it
goes from 0 to numLevels on the X axis.
*/
void getChannelAsPath (Path& result, const Range<float>* levels, int numLevels, int nextSample);
//==========================================================================
/** @internal */
void paint (Graphics&) override;
private:
struct ChannelInfo;
friend struct ChannelInfo;
friend struct ContainerDeletePolicy<ChannelInfo>;
OwnedArray<ChannelInfo> channels;
int numSamples, inputSamplesPerBlock;
float interpolation;
Colour backgroundColour, waveformColour;
void timerCallback() override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioVisualiserComponent)
};
#endif // JUCE_AUDIOVISUALISER_H_INCLUDED

+ 35
- 32
libs/juce/source/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp View File

@@ -401,14 +401,17 @@ void MidiKeyboardComponent::paint (Graphics& g)
}
}
g.setColour (lineColour);
switch (orientation)
if (! lineColour.isTransparent())
{
case horizontalKeyboard: g.fillRect (0, height - 1, x, 1); break;
case verticalKeyboardFacingLeft: g.fillRect (0, 0, 1, x); break;
case verticalKeyboardFacingRight: g.fillRect (width - 1, 0, 1, x); break;
default: break;
g.setColour (lineColour);
switch (orientation)
{
case horizontalKeyboard: g.fillRect (0, height - 1, x, 1); break;
case verticalKeyboardFacingLeft: g.fillRect (0, 0, 1, x); break;
case verticalKeyboardFacingRight: g.fillRect (width - 1, 0, 1, x); break;
default: break;
}
}
const Colour blackNoteColour (findColour (blackNoteColourId));