Browse Source

Update juce

tags/2018-04-16
falkTX 8 years ago
parent
commit
cdc0511f74
100 changed files with 6804 additions and 3066 deletions
  1. +2
    -1
      libs/drowaudio/build-drowaudio/premake.lua
  2. +7
    -11
      libs/juce-plugin/JucePluginMain.cpp
  3. +3
    -2
      libs/juce/build-juce/AppConfig.h
  4. +1
    -0
      libs/juce/build-juce/premake.lua
  5. +16
    -16
      libs/juce/source/README.txt
  6. +1
    -0
      libs/juce/source/doxygen/Doxyfile
  7. +336
    -0
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp
  8. +361
    -0
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioChannelSet.h
  9. +2
    -2
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
  10. +11
    -6
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  11. +0
    -1
      libs/juce/source/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp
  12. +0
    -1
      libs/juce/source/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.h
  13. +117
    -16
      libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.cpp
  14. +39
    -0
      libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.h
  15. +0
    -1
      libs/juce/source/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h
  16. +2
    -2
      libs/juce/source/modules/juce_audio_basics/effects/juce_LinearSmoothedValue.h
  17. +10
    -0
      libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp
  18. +28
    -2
      libs/juce/source/modules/juce_audio_basics/juce_audio_basics.h
  19. +1
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.cpp
  20. +74
    -67
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  21. +21
    -13
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  22. +1
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp
  23. +13
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h
  24. +1
    -2
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiRPN.cpp
  25. +182
    -172
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp
  26. +1
    -30
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.h
  27. +0
    -1
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEMessages.cpp
  28. +8
    -3
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp
  29. +8
    -1
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.h
  30. +14
    -6
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZone.h
  31. +50
    -5
      libs/juce/source/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp
  32. +21
    -11
      libs/juce/source/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h
  33. +17
    -5
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  34. +8
    -1
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  35. +72
    -226
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  36. +31
    -67
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  37. +7
    -32
      libs/juce/source/modules/juce_audio_devices/juce_audio_devices.cpp
  38. +30
    -20
      libs/juce/source/modules/juce_audio_devices/juce_audio_devices.h
  39. +10
    -3
      libs/juce/source/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h
  40. +1
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_android_Midi.cpp
  41. +2
    -2
      libs/juce/source/modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  42. +48
    -5
      libs/juce/source/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  43. +3
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
  44. +93
    -77
      libs/juce/source/modules/juce_audio_devices/native/juce_linux_Midi.cpp
  45. +43
    -18
      libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  46. +8
    -0
      libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp
  47. +4
    -3
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  48. +7
    -0
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  49. +1
    -1
      libs/juce/source/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
  50. +8
    -5
      libs/juce/source/modules/juce_audio_formats/codecs/flac/alloc.h
  51. +4
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/assert.h
  52. +4
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/callback.h
  53. +0
    -33
      libs/juce/source/modules/juce_audio_formats/codecs/flac/compat.h
  54. +3
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/endswap.h
  55. +0
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/metadata.h
  56. +0
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_decoder.h
  57. +0
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_encoder.h
  58. +0
    -5
      libs/juce/source/modules/juce_audio_formats/codecs/flac/win_utf8_io.h
  59. +6
    -8
      libs/juce/source/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
  60. +67
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
  61. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp
  62. +7
    -21
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  63. +2
    -0
      libs/juce/source/modules/juce_audio_formats/juce_audio_formats.cpp
  64. +27
    -1
      libs/juce/source/modules/juce_audio_formats/juce_audio_formats.h
  65. +41
    -0
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Modifier_Injector.h
  66. +555
    -335
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  67. +5
    -5
      libs/juce/source/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUCarbonViewControl.cpp
  68. +500
    -764
      libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  69. +1426
    -0
      libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
  70. +140
    -0
      libs/juce/source/modules/juce_audio_plugin_client/AUResources.r
  71. +14
    -0
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode1.cpp
  72. +13
    -0
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode2.cpp
  73. +13
    -3
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode3.cpp
  74. +2
    -1
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode_Header.h
  75. +35
    -12
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
  76. +110
    -0
      libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp
  77. +68
    -14
      libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  78. +1061
    -846
      libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  79. +12
    -8
      libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
  80. +399
    -155
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  81. +38
    -3
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client.h
  82. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp
  83. +26
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm
  84. +69
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r
  85. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm
  86. +66
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm
  87. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm
  88. +6
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS.r
  89. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_1.cpp
  90. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_2.cpp
  91. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_3.cpp
  92. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_4.cpp
  93. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_utils.cpp
  94. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_utils.mm
  95. +33
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp
  96. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp
  97. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp
  98. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST_utils.mm
  99. +25
    -0
      libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_utils.cpp
  100. +2
    -1
      libs/juce/source/modules/juce_audio_plugin_client/utility/juce_CheckSettingMacros.h

+ 2
- 1
libs/drowaudio/build-drowaudio/premake.lua View File

@@ -5,7 +5,8 @@ package = make_library_project("drowaudio")
package.includepaths = {
".",
"../../juce/source"
"../../juce/source",
"../../juce/source/modules"
}
package.files = {


+ 7
- 11
libs/juce-plugin/JucePluginMain.cpp View File

@@ -16,13 +16,13 @@
#include "modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp"
#elif JucePlugin_Build_VST
// we need to include 'juce_VSTMidiEventList' before 'juce_VST_Wrapper'
#ifndef _MSC_VER
#define __cdecl
#endif
#include "pluginterfaces/vst2.x/aeffectx.h"
namespace juce {
#include "modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h"
}
// #ifndef _MSC_VER
// #define __cdecl
// #endif
// #include "pluginterfaces/vst2.x/aeffectx.h"
// namespace juce {
// #include "modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h"
// }
#ifdef JUCE_MAC
#include "modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm"
#else
@@ -37,7 +37,3 @@
#if ! JucePlugin_Build_Standalone
#include "modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp"
#endif

namespace juce {
#include "modules/juce_audio_processors/processors/juce_AudioProcessor_export.cpp"
}

+ 3
- 2
libs/juce/build-juce/AppConfig.h View File

@@ -28,6 +28,7 @@
//=============================================================================
#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1
#define JUCE_STANDALONE_APPLICATION 0
//=============================================================================
@@ -96,14 +97,14 @@
If your app doesn't need to read FLAC files, you might want to disable this to
reduce the size of your codebase and build time.
*/
#define JUCE_USE_FLAC 0
#define JUCE_USE_FLAC 1
/** Config: JUCE_USE_OGGVORBIS
Enables the Ogg-Vorbis audio codec classes (available on all platforms).
If your app doesn't need to read Ogg-Vorbis files, you might want to disable this to
reduce the size of your codebase and build time.
*/
#define JUCE_USE_OGGVORBIS 0
#define JUCE_USE_OGGVORBIS 1
/** Config: JUCE_USE_MP3AUDIOFORMAT
Enables the software-based MP3AudioFormat class.


+ 1
- 0
libs/juce/build-juce/premake.lua View File

@@ -6,6 +6,7 @@ package = make_library_project("juce")
package.includepaths = {
".",
"../source",
"../source/modules",
"../../../sdks/vstsdk2.4/"
}


+ 16
- 16
libs/juce/source/README.txt View File

@@ -1,17 +1,17 @@
# The JUCE Library
JUCE (Jules' Utility Class Extensions) is an all-encompassing
C++ framework for developing cross-platform software.
It contains pretty much everything you're likely to need to create
most applications, and is particularly well-suited for building
highly-customised GUIs, and for handling graphics and sound.
Most JUCE modules are shared under the GNU Public Licence
(GPLv2, v3, and the AGPLv3). This means that the code can
be freely copied and distributed, and costs nothing to use
in other GPL applications. One module (the juce_core module)
is permissively licensed under the ISC.
For more information, visit the website:
# The JUCE Library
JUCE (Jules' Utility Class Extensions) is an all-encompassing
C++ framework for developing cross-platform software.
It contains pretty much everything you're likely to need to create
most applications, and is particularly well-suited for building
highly-customised GUIs, and for handling graphics and sound.
Most JUCE modules are shared under the GNU Public Licence
(GPLv2, v3, and the AGPLv3). This means that the code can
be freely copied and distributed, and costs nothing to use
in other GPL applications. One module (the juce_core module)
is permissively licensed under the ISC.
For more information, visit the website:
http://www.juce.com

+ 1
- 0
libs/juce/source/doxygen/Doxyfile View File

@@ -2060,6 +2060,7 @@ PREDEFINED = WIN32=1 \
JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS=1 \
JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES=1 \
JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL=1 \
JUCE_COMPILER_SUPPORTS_LAMBDAS=1 \
JUCE_MODAL_LOOPS_PERMITTED=1

# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this


+ 336
- 0
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp View File

@@ -0,0 +1,336 @@
/*
==============================================================================
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.
==============================================================================
*/
AudioChannelSet::AudioChannelSet (uint32 c) : channels (c) {}
bool AudioChannelSet::operator== (const AudioChannelSet& other) const noexcept { return channels == other.channels; }
bool AudioChannelSet::operator!= (const AudioChannelSet& other) const noexcept { return channels != other.channels; }
bool AudioChannelSet::operator< (const AudioChannelSet& other) const noexcept { return channels < other.channels; }
String AudioChannelSet::getChannelTypeName (AudioChannelSet::ChannelType type)
{
if (type >= discreteChannel0)
return String ("Discrete ") + String (type - discreteChannel0 + 1);
switch (type)
{
case left: return NEEDS_TRANS("Left");
case right: return NEEDS_TRANS("Right");
case centre: return NEEDS_TRANS("Centre");
case LFE: return NEEDS_TRANS("LFE");
case leftSurround: return NEEDS_TRANS("Left Surround");
case rightSurround: return NEEDS_TRANS("Right Surround");
case leftCentre: return NEEDS_TRANS("Left Centre");
case rightCentre: return NEEDS_TRANS("Right Centre");
case centreSurround: return NEEDS_TRANS("Centre Surround");
case leftSurroundRear: return NEEDS_TRANS("Left Surround Rear");
case rightSurroundRear: return NEEDS_TRANS("Right Surround Rear");
case topMiddle: return NEEDS_TRANS("Top Middle");
case topFrontLeft: return NEEDS_TRANS("Top Front Left");
case topFrontCentre: return NEEDS_TRANS("Top Front Centre");
case topFrontRight: return NEEDS_TRANS("Top Front Right");
case topRearLeft: return NEEDS_TRANS("Top Rear Left");
case topRearCentre: return NEEDS_TRANS("Top Rear Centre");
case topRearRight: return NEEDS_TRANS("Top Rear Right");
case wideLeft: return NEEDS_TRANS("Wide Left");
case wideRight: return NEEDS_TRANS("Wide Right");
case LFE2: return NEEDS_TRANS("LFE 2");
case leftSurroundSide: return NEEDS_TRANS ("Left Surround Side");
case rightSurroundSide: return NEEDS_TRANS ("Right Surround Side");
case ambisonicW: return NEEDS_TRANS("Ambisonic W");
case ambisonicX: return NEEDS_TRANS("Ambisonic X");
case ambisonicY: return NEEDS_TRANS("Ambisonic Y");
case ambisonicZ: return NEEDS_TRANS("Ambisonic Z");
default: break;
}
return "Unknown";
}
String AudioChannelSet::getAbbreviatedChannelTypeName (AudioChannelSet::ChannelType type)
{
if (type >= discreteChannel0)
return String (type - discreteChannel0 + 1);
switch (type)
{
case left: return "L";
case right: return "R";
case centre: return "C";
case LFE: return "Lfe";
case leftSurround: return "Ls";
case rightSurround: return "Rs";
case leftCentre: return "Lc";
case rightCentre: return "Rc";
case centreSurround: return "Cs";
case leftSurroundRear: return "Lrs";
case rightSurroundRear: return "Rrs";
case topMiddle: return "Tm";
case topFrontLeft: return "Tfl";
case topFrontCentre: return "Tfc";
case topFrontRight: return "Tfr";
case topRearLeft: return "Trl";
case topRearCentre: return "Trc";
case topRearRight: return "Trr";
case wideLeft: return "Wl";
case wideRight: return "Wr";
case LFE2: return "Lfe2";
case leftSurroundSide: return "Lss";
case rightSurroundSide: return "Rss";
case ambisonicW: return "W";
case ambisonicX: return "X";
case ambisonicY: return "Y";
case ambisonicZ: return "Z";
default: break;
}
return "";
}
String AudioChannelSet::getSpeakerArrangementAsString() const
{
StringArray speakerTypes;
Array<AudioChannelSet::ChannelType> speakers = getChannelTypes();
for (int i = 0; i < speakers.size(); ++i)
{
String name = getAbbreviatedChannelTypeName (speakers.getReference (i));
if (name.isNotEmpty())
speakerTypes.add (name);
}
return speakerTypes.joinIntoString (" ");
}
String AudioChannelSet::getDescription() const
{
if (isDiscreteLayout()) return String ("Discrete #") + String (size());
if (*this == disabled()) return "Disabled";
if (*this == mono()) return "Mono";
if (*this == stereo()) return "Stereo";
if (*this == createLCR()) return "LCR";
if (*this == createLRS()) return "LRS";
if (*this == createLCRS()) return "LCRS";
if (*this == create5point0()) return "5.1 Surround";
if (*this == create5point1()) return "5.1 Surround (+Lfe)";
if (*this == create6point0()) return "6.1 Surround";
if (*this == create6point1()) return "6.1 Surround (+Lfe)";
if (*this == create6point0Music()) return "6.1 (Music) Surround";
if (*this == create6point1Music()) return "6.1 (Music) Surround (+Lfe)";
if (*this == create7point0()) return "7.1 Surround";
if (*this == create7point1()) return "7.1 Surround (Lfe)";
if (*this == create7point0SDDS()) return "7.1 Surround SDDS";
if (*this == create7point1SDDS()) return "7.1 Surround SDDS (+Lfe)";
if (*this == quadraphonic()) return "Quadraphonic";
if (*this == pentagonal()) return "Pentagonal";
if (*this == hexagonal()) return "Hexagonal";
if (*this == octagonal()) return "Octagonal";
if (*this == ambisonic()) return "Ambisonic";
return "Unknown";
}
bool AudioChannelSet::isDiscreteLayout() const noexcept
{
Array<AudioChannelSet::ChannelType> speakers = getChannelTypes();
for (int i = 0; i < speakers.size(); ++i)
if (speakers.getReference (i) > ambisonicZ)
return true;
return false;
}
int AudioChannelSet::size() const noexcept
{
return channels.countNumberOfSetBits();
}
AudioChannelSet::ChannelType AudioChannelSet::getTypeOfChannel (int index) const noexcept
{
int bit = channels.findNextSetBit(0);
for (int i = 0; i < index && bit >= 0; ++i)
bit = channels.findNextSetBit (bit + 1);
return static_cast<ChannelType> (bit);
}
int AudioChannelSet::getChannelIndexForType (AudioChannelSet::ChannelType type) const noexcept
{
int idx = 0;
for (int bit = channels.findNextSetBit (0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
{
if (static_cast<ChannelType> (bit) == type)
return idx;
idx++;
}
return -1;
}
Array<AudioChannelSet::ChannelType> AudioChannelSet::getChannelTypes() const
{
Array<ChannelType> result;
for (int bit = channels.findNextSetBit(0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
result.add (static_cast<ChannelType> (bit));
return result;
}
void AudioChannelSet::addChannel (ChannelType newChannel)
{
const int bit = static_cast<int> (newChannel);
jassert (bit >= 0 && bit < 1024);
channels.setBit (bit);
}
void AudioChannelSet::removeChannel (ChannelType newChannel)
{
const int bit = static_cast<int> (newChannel);
jassert (bit >= 0 && bit < 1024);
channels.clearBit (bit);
}
AudioChannelSet AudioChannelSet::disabled() { return AudioChannelSet(); }
AudioChannelSet AudioChannelSet::mono() { return AudioChannelSet (1u << centre); }
AudioChannelSet AudioChannelSet::stereo() { return AudioChannelSet ((1u << left) | (1u << right)); }
AudioChannelSet AudioChannelSet::createLCR() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre)); }
AudioChannelSet AudioChannelSet::createLRS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << surround)); }
AudioChannelSet AudioChannelSet::createLCRS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << surround)); }
AudioChannelSet AudioChannelSet::create5point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround)); }
AudioChannelSet AudioChannelSet::create5point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << LFE)); }
AudioChannelSet AudioChannelSet::create6point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround)); }
AudioChannelSet AudioChannelSet::create6point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround) | (1u << LFE)); }
AudioChannelSet AudioChannelSet::create6point0Music() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftSurroundSide) | (1u << rightSurroundSide)); }
AudioChannelSet AudioChannelSet::create6point1Music() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << LFE)); }
AudioChannelSet AudioChannelSet::create7point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
AudioChannelSet AudioChannelSet::create7point0SDDS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftCentre) | (1u << rightCentre)); }
AudioChannelSet AudioChannelSet::create7point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << LFE)); }
AudioChannelSet AudioChannelSet::create7point1SDDS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftCentre) | (1u << rightCentre) | (1u << LFE)); }
AudioChannelSet AudioChannelSet::ambisonic() { return AudioChannelSet ((1u << ambisonicW) | (1u << ambisonicX) | (1u << ambisonicY) | (1u << ambisonicZ)); }
AudioChannelSet AudioChannelSet::quadraphonic() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround)); }
AudioChannelSet AudioChannelSet::pentagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
AudioChannelSet AudioChannelSet::hexagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << centre) | (1u << centreSurround)); }
AudioChannelSet AudioChannelSet::octagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround) | (1u << centre) | (1u << centreSurround) | (1u << wideLeft) | (1u << wideRight)); }
AudioChannelSet AudioChannelSet::discreteChannels (int numChannels)
{
AudioChannelSet s;
s.channels.setRange (discreteChannel0, numChannels, true);
return s;
}
AudioChannelSet AudioChannelSet::canonicalChannelSet (int numChannels)
{
if (numChannels == 1) return AudioChannelSet::mono();
if (numChannels == 2) return AudioChannelSet::stereo();
if (numChannels == 3) return AudioChannelSet::createLCR();
if (numChannels == 4) return AudioChannelSet::quadraphonic();
if (numChannels == 5) return AudioChannelSet::create5point0();
if (numChannels == 6) return AudioChannelSet::create5point1();
if (numChannels == 7) return AudioChannelSet::create7point0();
if (numChannels == 8) return AudioChannelSet::create7point1();
return discreteChannels (numChannels);
}
AudioChannelSet AudioChannelSet::namedChannelSet (int numChannels)
{
if (numChannels == 1) return AudioChannelSet::mono();
if (numChannels == 2) return AudioChannelSet::stereo();
if (numChannels == 3) return AudioChannelSet::createLCR();
if (numChannels == 4) return AudioChannelSet::quadraphonic();
if (numChannels == 5) return AudioChannelSet::create5point0();
if (numChannels == 6) return AudioChannelSet::create5point1();
if (numChannels == 7) return AudioChannelSet::create7point0();
if (numChannels == 8) return AudioChannelSet::create7point1();
return AudioChannelSet();
}
Array<AudioChannelSet> AudioChannelSet::channelSetsWithNumberOfChannels (int numChannels)
{
Array<AudioChannelSet> retval;
if (numChannels != 0)
{
retval.add (AudioChannelSet::discreteChannels (numChannels));
if (numChannels == 1)
{
retval.add (AudioChannelSet::mono());
}
else if (numChannels == 2)
{
retval.add (AudioChannelSet::stereo());
}
else if (numChannels == 3)
{
retval.add (AudioChannelSet::createLCR());
retval.add (AudioChannelSet::createLRS());
}
else if (numChannels == 4)
{
retval.add (AudioChannelSet::quadraphonic());
retval.add (AudioChannelSet::createLCRS());
retval.add (AudioChannelSet::ambisonic());
}
else if (numChannels == 5)
{
retval.add (AudioChannelSet::create5point0());
retval.add (AudioChannelSet::pentagonal());
}
else if (numChannels == 6)
{
retval.add (AudioChannelSet::create5point1());
retval.add (AudioChannelSet::create6point0());
retval.add (AudioChannelSet::create6point0Music());
retval.add (AudioChannelSet::hexagonal());
}
else if (numChannels == 7)
{
retval.add (AudioChannelSet::create7point0());
retval.add (AudioChannelSet::create7point0SDDS());
retval.add (AudioChannelSet::create6point1());
retval.add (AudioChannelSet::create6point1Music());
}
else if (numChannels == 8)
{
retval.add (AudioChannelSet::create7point1());
retval.add (AudioChannelSet::create7point1SDDS());
retval.add (AudioChannelSet::octagonal());
}
}
return retval;
}

+ 361
- 0
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioChannelSet.h View File

@@ -0,0 +1,361 @@
/*
==============================================================================
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_AUDIOCHANNELSET_H_INCLUDED
#define JUCE_AUDIOCHANNELSET_H_INCLUDED
//==============================================================================
/**
Represents a set of audio channel types.
For example, you might have a set of left + right channels, which is a stereo
channel set. It is a collection of values from the AudioChannelSet::ChannelType
enum, where each type may only occur once within the set.
The documentation below lists which AudioChannelSet corresponds to which native
layouts used by AAX, VST2/VST3 and CoreAudio/AU. The layout tags in CoreAudio
are particularly confusing. For example, the layout which is labeled as "7.1 SDDS"
in Logic Pro, corresponds to CoreAudio/AU's kAudioChannelLayoutTag_DTS_7_0 tag, whereas
AAX's DTS 7.1 Layout corresponds to CoreAudio/AU's
kAudioChannelLayoutTag_MPEG_7_1_A format, etc. Please do not use the CoreAudio tag
as an indication to the actual layout of the speakers.
@see Bus
*/
class JUCE_API AudioChannelSet
{
public:
/** Creates an empty channel set.
You can call addChannel to add channels to the set.
*/
AudioChannelSet() noexcept {}
/** Creates a zero-channel set which can be used to indicate that a
bus is disabled. */
static AudioChannelSet disabled();
//==============================================================================
/** Creates a one-channel mono set (centre).
Is equivalent to: kMonoAAX (VST), AAX_eStemFormat_Mono (AAX), kAudioChannelLayoutTag_Mono (CoreAudio)
*/
static AudioChannelSet mono();
/** Creates a set containing a stereo set (left, right).
Is equivalent to: kStereo (VST), AAX_eStemFormat_Stereo (AAX), kAudioChannelLayoutTag_Stereo (CoreAudio)
*/
static AudioChannelSet stereo();
//==============================================================================
/** Creates a set containing an LCR set (left, right, centre).
Is equivalent to: k30Cine (VST), AAX_eStemFormat_LCR (AAX), kAudioChannelLayoutTag_MPEG_3_0_A (CoreAudio)
This format is referred to as "LRC" in Cubase.
This format is referred to as "LCR" in Pro Tools.
*/
static AudioChannelSet createLCR();
/** Creates a set containing an LRS set (left, right, surround).
Is equivalent to: k30Music (VST), n/a (AAX), kAudioChannelLayoutTag_ITU_2_1 (CoreAudio)
This format is referred to as "LRS" in Cubase.
*/
static AudioChannelSet createLRS();
/** Creates a set containing an LCRS set (left, right, centre, surround).
Is equivalent to: k40Cine (VST), AAX_eStemFormat_LCRS (AAX), kAudioChannelLayoutTag_MPEG_4_0_A (CoreAudio)
This format is referred to as "LCRS (Pro Logic)" in Logic Pro.
This format is referred to as "LRCS" in Cubase.
This format is referred to as "LCRS" in Pro Tools.
*/
static AudioChannelSet createLCRS();
//==============================================================================
/** Creates a set for a 5.0 surround setup (left, right, centre, leftSurround, rightSurround).
Is equivalent to: k50 (VST), AAX_eStemFormat_5_0 (AAX), kAudioChannelLayoutTag_MPEG_5_0_A (CoreAudio)
This format is referred to as "5.0" in Cubase.
This format is referred to as "5.0" in Pro Tools.
*/
static AudioChannelSet create5point0();
/** Creates a set for a 5.1 surround setup (left, right, centre, leftSurround, rightSurround, LFE).
Is equivalent to: k51 (VST), AAX_eStemFormat_5_1 (AAX), kAudioChannelLayoutTag_MPEG_5_1_A (CoreAudio)
This format is referred to as "5.1 (ITU 775)" in Logic Pro.
This format is referred to as "5.1" in Cubase.
This format is referred to as "5.1" in Pro Tools.
*/
static AudioChannelSet create5point1();
/** Creates a set for a 6.0 Cine surround setup (left, right, centre, leftSurround, rightSurround, centreSurround).
Is equivalent to: k60Cine (VST), AAX_eStemFormat_6_0 (AAX), kAudioChannelLayoutTag_AudioUnit_6_0 (CoreAudio)
Logic Pro incorrectly uses this for the surround format labeled "6.1 (ES/EX)".
This format is referred to as "6.0 Cine" in Cubase.
This format is referred to as "6.0" in Pro Tools.
*/
static AudioChannelSet create6point0();
/** Creates a set for a 6.1 Cine surround setup (left, right, centre, leftSurround, rightSurround, centreSurround, LFE).
Is equivalent to: k61Cine (VST), AAX_eStemFormat_6_1 (AAX), kAudioChannelLayoutTag_MPEG_6_1_A (CoreAudio)
This format is referred to as "6.1" in Pro Tools.
*/
static AudioChannelSet create6point1();
/** Creates a set for a 6.0 Music surround setup (left, right, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide).
Is equivalent to: k60Music (VST), n/a (AAX), kAudioChannelLayoutTag_DTS_6_0_A (CoreAudio)
This format is referred to as "6.0 Music" in Cubase.
*/
static AudioChannelSet create6point0Music();
/** Creates a set for a 6.0 Music surround setup (left, right, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide, LFE).
Is equivalent to: k61Music (VST), n/a (AAX), kAudioChannelLayoutTag_DTS_6_1_A (CoreAudio)
*/
static AudioChannelSet create6point1Music();
/** Creates a set for a DTS 7.0 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear).
Is equivalent to: k70Music (VST), AAX_eStemFormat_7_0_DTS (AAX), kAudioChannelLayoutTag_AudioUnit_7_0 (CoreAudio)
This format is referred to as "7.0" in Pro Tools.
*/
static AudioChannelSet create7point0();
/** Creates a set for a SDDS 7.0 surround setup (left, right, centre, leftSurround, rightSurround, leftCentre, rightCentre).
Is equivalent to: k70Cine (VST), AAX_eStemFormat_7_0_SDDS (AAX), kAudioChannelLayoutTag_AudioUnit_7_0_Front (CoreAudio)
This format is referred to as "7.0 SDDS" in Pro Tools.
*/
static AudioChannelSet create7point0SDDS();
/** Creates a set for a DTS 7.1 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, LFE).
Is equivalent to: k71CineSideFill (VST), AAX_eStemFormat_7_1_DTS (AAX), kAudioChannelLayoutTag_MPEG_7_1_C/kAudioChannelLayoutTag_ITU_3_4_1 (CoreAudio)
This format is referred to as "7.1 (3/4.1)" in Logic Pro.
This format is referred to as "7.1" in Pro Tools.
*/
static AudioChannelSet create7point1();
/** Creates a set for a 7.1 surround setup (left, right, centre, leftSurround, rightSurround, leftCentre, rightCentre, LFE).
Is equivalent to: k71Cine (VST), AAX_eStemFormat_7_1_SDDS (AAX), kAudioChannelLayoutTag_MPEG_7_1_A (CoreAudio)
This format is referred to as "7.1 (SDDS)" in Logic Pro.
This format is referred to as "7.1 SDDS" in Pro Tools.
*/
static AudioChannelSet create7point1SDDS();
//==============================================================================
/** Creates a set for ambisonic surround setups (ambisonicW, ambisonicX, ambisonicY, ambisonicZ).
Is equivalent to: kBFormat (VST), n/a (AAX), kAudioChannelLayoutTag_Ambisonic_B_Format (CoreAudio)
*/
static AudioChannelSet ambisonic();
/** Creates a set for quadraphonic surround setup (left, right, leftSurround, rightSurround)
Is equivalent to: k40Music (VST), AAX_eStemFormat_Quad (AAX), kAudioChannelLayoutTag_Quadraphonic (CoreAudio)
This format is referred to as "Quadraphonic" in Logic Pro.
This format is referred to as "Quadro" in Cubase.
This format is referred to as "Quad" in Pro Tools.
*/
static AudioChannelSet quadraphonic();
/** Creates a set for pentagonal surround setup (left, right, centre, leftSurroundRear, rightSurroundRear).
Is equivalent to: n/a (VST), n/a (AAX), kAudioChannelLayoutTag_Pentagonal (CoreAudio)
*/
static AudioChannelSet pentagonal();
/** Creates a set for hexagonal surround setup (left, right, leftSurroundRear, rightSurroundRear, centre, surroundCentre).
Is equivalent to: n/a (VST), n/a (AAX), kAudioChannelLayoutTag_Hexagonal (CoreAudio)
*/
static AudioChannelSet hexagonal();
/** Creates a set for octagonal surround setup (left, right, leftSurround, rightSurround, centre, centreSurround, wideLeft, wideRight).
Is equivalent to: n/a (VST), n/a (AAX), kAudioChannelLayoutTag_Octagonal (CoreAudio)
*/
static AudioChannelSet octagonal();
//==============================================================================
/** Creates a set of untyped discrete channels. */
static AudioChannelSet discreteChannels (int numChannels);
/** Create a canonical channel set for a given number of channels.
For example, numChannels = 1 will return mono, numChannels = 2 will return stereo, etc. */
static AudioChannelSet canonicalChannelSet (int numChannels);
/** Create a channel set for a given number of channels which is non-discrete.
If numChannels is larger than the number of channels of the surround format
with the maximum amount of channels (currently 7.1 Surround), then this
function returns an empty set.*/
static AudioChannelSet namedChannelSet (int numChannels);
/** Return an array of channel sets which have a given number of channels */
static Array<AudioChannelSet> channelSetsWithNumberOfChannels (int numChannels);
//==============================================================================
/** Represents different audio channel types. */
enum ChannelType
{
unknown = 0,
left = 1, // L
right = 2, // R
centre = 3, // C (sometimes M for mono)
LFE = 4,
leftSurround = 5, // Ls
rightSurround = 6, // Rs
leftCentre = 7, // Lc (AAX/VST), Lc used as Lss in AU for most layouts
rightCentre = 8, // Rc (AAX/VST), Rc used as Rss in AU for most layouts
centreSurround = 9, // Cs/S
surround = centreSurround, // Cs/S
leftSurroundSide = 10, // Lss (AXX), Side Left "Sl" (VST), Left Centre "LC" (AU)
rightSurroundSide = 11, // Rss (AXX), Side right "Sr" (VST), Right Centre "Rc" (AU)
topMiddle = 12,
topFrontLeft = 13,
topFrontCentre = 14,
topFrontRight = 15,
topRearLeft = 16,
topRearCentre = 17,
topRearRight = 18,
LFE2 = 19,
leftSurroundRear = 20, // Lsr (AAX), Lcs (VST), Rls (AU)
rightSurroundRear = 21, // Rsr (AAX), Rcs (VST), Rrs (AU)
wideLeft = 22,
wideRight = 23,
ambisonicW = 24,
ambisonicX = 25,
ambisonicY = 26,
ambisonicZ = 27,
discreteChannel0 = 64 /**< Non-typed individual channels are indexed upwards from this value. */
};
/** Returns the name of a given channel type. For example, this method may return "Surround Left". */
static String getChannelTypeName (ChannelType);
/** Returns the abbreviated name of a channel type. For example, this method may return "Ls". */
static String getAbbreviatedChannelTypeName (ChannelType);
//==============================================================================
enum
{
maxChannelsOfNamedLayout = 8
};
/** Adds a channel to the set. */
void addChannel (ChannelType newChannelType);
/** Removes a channel from the set. */
void removeChannel (ChannelType newChannelType);
/** Returns the number of channels in the set. */
int size() const noexcept;
/** Returns true if there are no channels in the set. */
bool isDisabled() const noexcept { return size() == 0; }
/** Returns an array of all the types in this channel set. */
Array<ChannelType> getChannelTypes() const;
/** Returns the type of one of the channels in the set, by index. */
ChannelType getTypeOfChannel (int channelIndex) const noexcept;
/** Returns the index for a particular channel-type.
Will return -1 if the this set does not contain a channel of this type. */
int getChannelIndexForType (ChannelType type) const noexcept;
/** Returns a string containing a whitespace-separated list of speaker types
corresponding to each channel. For example in a 5.1 arrangement,
the string may be "L R C Lfe Ls Rs". If the speaker arrangement is unknown,
the returned string will be empty.*/
String getSpeakerArrangementAsString() const;
/** Returns the description of the current layout. For example, this method may return
"Quadraphonic". Note that the returned string may not be unique. */
String getDescription() const;
/** Returns if this is a channel layout made-up of discrete channels. */
bool isDiscreteLayout() const noexcept;
/** Intersect two channel layouts. */
void intersect (const AudioChannelSet& other) { channels &= other.channels; }
//==============================================================================
bool operator== (const AudioChannelSet&) const noexcept;
bool operator!= (const AudioChannelSet&) const noexcept;
bool operator< (const AudioChannelSet&) const noexcept;
private:
BigInteger channels;
explicit AudioChannelSet (uint32);
};
#endif // JUCE_AUDIOCHANNELSET_H_INCLUDED

+ 2
- 2
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h View File

@@ -397,9 +397,9 @@ public:
convert between 32 and 64 bit float buffer types.
*/
template <typename OtherType>
void makeCopyOf (const AudioBuffer<OtherType>& other)
void makeCopyOf (const AudioBuffer<OtherType>& other, bool avoidReallocating = false)
{
setSize (other.getNumChannels(), other.getNumSamples());
setSize (other.getNumChannels(), other.getNumSamples(), false, false, avoidReallocating);
if (other.hasBeenCleared())
{


+ 11
- 6
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp View File

@@ -204,10 +204,11 @@ namespace FloatVectorHelpers
typedef float Type;
typedef float32x4_t ParallelType;
typedef uint32x4_t IntegerType;
union signMaskUnion { ParallelType f; IntegerType i; };
enum { numParallel = 4 };
static forcedinline IntegerType toint (ParallelType v) noexcept { union { ParallelType f; IntegerType i; } u; u.f = v; return u.i; }
static forcedinline ParallelType toflt (IntegerType v) noexcept { union { ParallelType f; IntegerType i; } u; u.i = v; return u.f; }
static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
static forcedinline ParallelType load1 (Type v) noexcept { return vld1q_dup_f32 (&v); }
static forcedinline ParallelType loadA (const Type* v) noexcept { return vld1q_f32 (v); }
@@ -235,10 +236,11 @@ namespace FloatVectorHelpers
typedef double Type;
typedef double ParallelType;
typedef uint64 IntegerType;
union signMaskUnion { ParallelType f; IntegerType i; };
enum { numParallel = 1 };
static forcedinline IntegerType toint (ParallelType v) noexcept { union { ParallelType f; IntegerType i; } u; u.f = v; return u.i; }
static forcedinline ParallelType toflt (IntegerType v) noexcept { union { ParallelType f; IntegerType i; } u; u.i = v; return u.f; }
static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
static forcedinline ParallelType load1 (Type v) noexcept { return v; }
static forcedinline ParallelType loadA (const Type* v) noexcept { return *v; }
@@ -346,6 +348,9 @@ namespace FloatVectorHelpers
#define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), s1 = src1Load (src1), s2 = src2Load (src2);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
union signMask32 { float f; uint32 i; };
union signMask64 { double d; uint64 i; };
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
template<int typeSize> struct ModeType { typedef BasicOps32 Mode; };
template<> struct ModeType<8> { typedef BasicOps64 Mode; };
@@ -806,7 +811,7 @@ void FloatVectorOperations::abs (float* dest, const float* src, int num) noexcep
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num);
#else
union { float f; uint32 i; } signMask;
FloatVectorHelpers::signMask32 signMask;
signMask.i = 0x7fffffffUL;
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabsf (src[i]), Mode::bit_and (s, mask),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
@@ -821,7 +826,7 @@ void FloatVectorOperations::abs (double* dest, const double* src, int num) noexc
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num);
#else
union {double d; uint64 i;} signMask;
FloatVectorHelpers::signMask64 signMask;
signMask.i = 0x7fffffffffffffffULL;
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabs (src[i]), Mode::bit_and (s, mask),


+ 0
- 1
libs/juce/source/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp View File

@@ -22,7 +22,6 @@
==============================================================================
*/
struct CatmullRomAlgorithm
{
static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept


+ 0
- 1
libs/juce/source/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.h View File

@@ -22,7 +22,6 @@
==============================================================================
*/
/**
Interpolator for resampling a stream of floats using Catmull-Rom interpolation.


+ 117
- 16
libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.cpp View File

@@ -62,33 +62,131 @@ IIRCoefficients::IIRCoefficients (double c1, double c2, double c3,
IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate,
const double frequency) noexcept
{
jassert (sampleRate > 0);
return makeLowPass (sampleRate, frequency, 1.0 / std::sqrt (2.0));
}
IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate,
const double frequency,
const double Q) noexcept
{
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
const double c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
return IIRCoefficients (c1,
c1 * 2.0,
c1,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
c1 * (1.0 - 1.0 / Q * n + nSquared));
}
IIRCoefficients IIRCoefficients::makeHighPass (const double sampleRate,
const double frequency) noexcept
{
return makeHighPass (sampleRate, frequency, 1.0 / std::sqrt(2.0));
}
IIRCoefficients IIRCoefficients::makeHighPass (const double sampleRate,
const double frequency,
const double Q) noexcept
{
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double n = std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
const double c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
return IIRCoefficients (c1,
c1 * -2.0,
c1,
1.0,
c1 * 2.0 * (nSquared - 1.0),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
c1 * (1.0 - 1.0 / Q * n + nSquared));
}
IIRCoefficients IIRCoefficients::makeBandPass (const double sampleRate,
const double frequency) noexcept
{
return makeBandPass (sampleRate, frequency, 1.0 / std::sqrt (2.0));
}
IIRCoefficients IIRCoefficients::makeBandPass (const double sampleRate,
const double frequency,
const double Q) noexcept
{
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
return IIRCoefficients (c1 * n / Q,
0.0,
-c1 * n / Q,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - 1.0 / Q * n + nSquared));
}
IIRCoefficients IIRCoefficients::makeNotchFilter (const double sampleRate,
const double frequency) noexcept
{
return makeNotchFilter (sampleRate, frequency, 1.0 / std::sqrt (2.0));
}
IIRCoefficients IIRCoefficients::makeNotchFilter (const double sampleRate,
const double frequency,
const double Q) noexcept
{
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + n / Q + nSquared);
return IIRCoefficients (c1 * (1.0 + nSquared),
2.0 * c1 * (1.0 - nSquared),
c1 * (1.0 + nSquared),
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - n / Q + nSquared));
}
IIRCoefficients IIRCoefficients::makeAllPass (const double sampleRate,
const double frequency) noexcept
{
return makeAllPass (sampleRate, frequency, 1.0 / std::sqrt (2.0));
}
IIRCoefficients IIRCoefficients::makeAllPass (const double sampleRate,
const double frequency,
const double Q) noexcept
{
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
return IIRCoefficients (c1 * (1.0 - n / Q + nSquared),
c1 * 2.0 * (1.0 - nSquared),
1.0,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - n / Q + nSquared));
}
IIRCoefficients IIRCoefficients::makeLowShelf (const double sampleRate,
@@ -96,8 +194,9 @@ IIRCoefficients IIRCoefficients::makeLowShelf (const double sampleRate,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
jassert (sampleRate > 0.0);
jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double A = jmax (0.0f, std::sqrt (gainFactor));
const double aminus1 = A - 1.0;
@@ -120,8 +219,9 @@ IIRCoefficients IIRCoefficients::makeHighShelf (const double sampleRate,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
jassert (sampleRate > 0.0);
jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double A = jmax (0.0f, std::sqrt (gainFactor));
const double aminus1 = A - 1.0;
@@ -140,15 +240,16 @@ IIRCoefficients IIRCoefficients::makeHighShelf (const double sampleRate,
}
IIRCoefficients IIRCoefficients::makePeakFilter (const double sampleRate,
const double centreFrequency,
const double frequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
jassert (sampleRate > 0.0);
jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
jassert (Q > 0.0);
const double A = jmax (0.0f, std::sqrt (gainFactor));
const double omega = (double_Pi * 2.0 * jmax (centreFrequency, 2.0)) / sampleRate;
const double omega = (double_Pi * 2.0 * jmax (frequency, 2.0)) / sampleRate;
const double alpha = 0.5 * std::sin (omega) / Q;
const double c2 = -2.0 * std::cos (omega);
const double alphaTimesA = alpha * A;
@@ -164,12 +265,12 @@ IIRCoefficients IIRCoefficients::makePeakFilter (const double sampleRate,
//==============================================================================
IIRFilter::IIRFilter() noexcept
: v1 (0), v2 (0), active (false)
: v1 (0.0), v2 (0.0), active (false)
{
}
IIRFilter::IIRFilter (const IIRFilter& other) noexcept
: v1 (0), v2 (0), active (other.active)
: v1 (0.0), v2 (0.0), active (other.active)
{
const SpinLock::ScopedLockType sl (other.processLock);
coefficients = other.coefficients;
@@ -198,7 +299,7 @@ void IIRFilter::setCoefficients (const IIRCoefficients& newCoefficients) noexcep
void IIRFilter::reset() noexcept
{
const SpinLock::ScopedLockType sl (processLock);
v1 = v2 = 0;
v1 = v2 = 0.0;
}
float IIRFilter::processSingleSampleRaw (const float in) noexcept


+ 39
- 0
libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.h View File

@@ -55,14 +55,53 @@ public:
/** Destructor. */
~IIRCoefficients() noexcept;
//==============================================================================
/** Returns the coefficients for a low-pass filter. */
static IIRCoefficients makeLowPass (double sampleRate,
double frequency) noexcept;
/** Returns the coefficients for a low-pass filter with variable Q. */
static IIRCoefficients makeLowPass (double sampleRate,
double frequency,
double Q) noexcept;
//==============================================================================
/** Returns the coefficients for a high-pass filter. */
static IIRCoefficients makeHighPass (double sampleRate,
double frequency) noexcept;
/** Returns the coefficients for a high-pass filter with variable Q. */
static IIRCoefficients makeHighPass (double sampleRate,
double frequency,
double Q) noexcept;
//==============================================================================
/** Returns the coefficients for a band-pass filter. */
static IIRCoefficients makeBandPass (double sampleRate, double frequency) noexcept;
/** Returns the coefficients for a band-pass filter with variable Q. */
static IIRCoefficients makeBandPass (double sampleRate,
double frequency,
double Q) noexcept;
//==============================================================================
/** Returns the coefficients for a notch filter. */
static IIRCoefficients makeNotchFilter (double sampleRate, double frequency) noexcept;
/** Returns the coefficients for a notch filter with variable Q. */
static IIRCoefficients makeNotchFilter (double sampleRate,
double frequency,
double Q) noexcept;
//==============================================================================
/** Returns the coefficients for an all-pass filter. */
static IIRCoefficients makeAllPass (double sampleRate, double frequency) noexcept;
/** Returns the coefficients for an all-pass filter with variable Q. */
static IIRCoefficients makeAllPass (double sampleRate,
double frequency,
double Q) noexcept;
//==============================================================================
/** Returns the coefficients for a low-pass shelf filter with variable Q and gain.


+ 0
- 1
libs/juce/source/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h View File

@@ -22,7 +22,6 @@
==============================================================================
*/
/**
Interpolator for resampling a stream of floats using 4-point lagrange interpolation.


+ 2
- 2
libs/juce/source/modules/juce_audio_basics/effects/juce_LinearSmoothedValue.h View File

@@ -33,8 +33,8 @@
*/
//==============================================================================
template<typename FloatType>
class JUCE_API LinearSmoothedValue
template <typename FloatType>
class LinearSmoothedValue
{
public:
/** Constructor. */


+ 10
- 0
libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp View File

@@ -31,6 +31,8 @@
#error "Incorrect use of JUCE cpp file"
#endif
#include "AppConfig.h"
#include "juce_audio_basics.h"
#if JUCE_MINGW && ! defined (__SSE2__)
@@ -67,6 +69,13 @@
#define JUCE_USE_ARM_NEON 1
#endif
#if TARGET_IPHONE_SIMULATOR
#ifdef JUCE_USE_ARM_NEON
#undef JUCE_USE_ARM_NEON
#endif
#define JUCE_USE_ARM_NEON 0
#endif
#if JUCE_USE_ARM_NEON
#include <arm_neon.h>
#endif
@@ -76,6 +85,7 @@ namespace juce
#include "buffers/juce_AudioDataConverters.cpp"
#include "buffers/juce_FloatVectorOperations.cpp"
#include "buffers/juce_AudioChannelSet.cpp"
#include "effects/juce_IIRFilter.cpp"
#include "effects/juce_IIRFilterOld.cpp"
#include "effects/juce_LagrangeInterpolator.cpp"


+ 28
- 2
libs/juce/source/modules/juce_audio_basics/juce_audio_basics.h View File

@@ -22,12 +22,37 @@
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.txt file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_audio_basics
vendor: juce
version: 4.3.0
name: JUCE audio and MIDI data classes
description: Classes for audio buffer manipulation, midi message handling, synthesis, etc.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_core
OSXFrameworks: Accelerate
iOSFrameworks: Accelerate
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
#ifndef JUCE_AUDIO_BASICS_H_INCLUDED
#define JUCE_AUDIO_BASICS_H_INCLUDED
#include "../juce_core/juce_core.h"
#include "juce_core/juce_core.h"
//==============================================================================
namespace juce
{
@@ -37,6 +62,7 @@ namespace juce
#include "buffers/juce_AudioDataConverters.h"
#include "buffers/juce_FloatVectorOperations.h"
#include "buffers/juce_AudioSampleBuffer.h"
#include "buffers/juce_AudioChannelSet.h"
#include "effects/juce_Decibels.h"
#include "effects/juce_IIRFilter.h"
#include "effects/juce_IIRFilterOld.h"


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.cpp View File

@@ -248,7 +248,7 @@ bool MidiFile::readFrom (InputStream& sourceStream)
clear();
MemoryBlock data;
const int maxSensibleMidiFileSize = 2 * 1024 * 1024;
const int maxSensibleMidiFileSize = 200 * 1024 * 1024;
// (put a sanity-check on the file size, as midi files are generally small)
if (sourceStream.readIntoMemoryBlock (data, maxSensibleMidiFileSize))


+ 74
- 67
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

@@ -33,11 +33,23 @@ namespace MidiHelpers
{
return (uint8) jlimit (0, 127, v);
}
}
inline uint8 floatVelocityToByte (const float v) noexcept
{
return validVelocity (roundToInt (v * 127.0f));
}
//==============================================================================
uint8 MidiMessage::floatValueToMidiByte (const float v) noexcept
{
return MidiHelpers::validVelocity (roundToInt (v * 127.0f));
}
uint16 MidiMessage::pitchbendToPitchwheelPos (const float pitchbend,
const float pitchbendRange) noexcept
{
// can't translate a pitchbend value that is outside of the given range!
jassert (std::abs (pitchbend) <= pitchbendRange);
return static_cast<uint16> (pitchbend > 0.0f
? jmap (pitchbend, 0.0f, pitchbendRange, 8192.0f, 16383.0f)
: jmap (pitchbend, -pitchbendRange, 0.0f, 0.0f, 8192.0f));
}
//==============================================================================
@@ -84,25 +96,24 @@ int MidiMessage::getMessageLengthFromFirstByte (const uint8 firstByte) noexcept
MidiMessage::MidiMessage() noexcept
: timeStamp (0), size (2)
{
preallocatedData.asBytes[0] = 0xf0;
preallocatedData.asBytes[1] = 0xf7;
packedData.asBytes[0] = 0xf0;
packedData.asBytes[1] = 0xf7;
}
MidiMessage::MidiMessage (const void* const d, const int dataSize, const double t)
: timeStamp (t),
size (dataSize)
: timeStamp (t), size (dataSize)
{
jassert (dataSize > 0);
memcpy (allocateSpace (dataSize), d, (size_t) dataSize);
// this checks that the length matches the data..
jassert (dataSize > 3 || *(uint8*)d >= 0xf0 || getMessageLengthFromFirstByte (*(uint8*)d) == size);
// check that the length matches the data..
jassert (size > 3 || *(uint8*)d >= 0xf0 || getMessageLengthFromFirstByte (*(uint8*)d) == size);
memcpy (allocateSpace (dataSize), d, (size_t) dataSize);
}
MidiMessage::MidiMessage (const int byte1, const double t) noexcept
: timeStamp (t), size (1)
{
preallocatedData.asBytes[0] = (uint8) byte1;
packedData.asBytes[0] = (uint8) byte1;
// check that the length matches the data..
jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1);
@@ -111,8 +122,8 @@ MidiMessage::MidiMessage (const int byte1, const double t) noexcept
MidiMessage::MidiMessage (const int byte1, const int byte2, const double t) noexcept
: timeStamp (t), size (2)
{
preallocatedData.asBytes[0] = (uint8) byte1;
preallocatedData.asBytes[1] = (uint8) byte2;
packedData.asBytes[0] = (uint8) byte1;
packedData.asBytes[1] = (uint8) byte2;
// check that the length matches the data..
jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2);
@@ -121,9 +132,9 @@ MidiMessage::MidiMessage (const int byte1, const int byte2, const double t) noex
MidiMessage::MidiMessage (const int byte1, const int byte2, const int byte3, const double t) noexcept
: timeStamp (t), size (3)
{
preallocatedData.asBytes[0] = (uint8) byte1;
preallocatedData.asBytes[1] = (uint8) byte2;
preallocatedData.asBytes[2] = (uint8) byte3;
packedData.asBytes[0] = (uint8) byte1;
packedData.asBytes[1] = (uint8) byte2;
packedData.asBytes[2] = (uint8) byte3;
// check that the length matches the data..
jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3);
@@ -132,29 +143,19 @@ MidiMessage::MidiMessage (const int byte1, const int byte2, const int byte3, con
MidiMessage::MidiMessage (const MidiMessage& other)
: timeStamp (other.timeStamp), size (other.size)
{
if (other.allocatedData != nullptr)
{
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
}
if (isHeapAllocated())
memcpy (allocateSpace (size), other.getData(), (size_t) size);
else
{
preallocatedData.asInt32 = other.preallocatedData.asInt32;
}
packedData.allocatedData = other.packedData.allocatedData;
}
MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
: timeStamp (newTimeStamp), size (other.size)
{
if (other.allocatedData != nullptr)
{
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
}
if (isHeapAllocated())
memcpy (allocateSpace (size), other.getData(), (size_t) size);
else
{
preallocatedData.asInt32 = other.preallocatedData.asInt32;
}
packedData.allocatedData = other.packedData.allocatedData;
}
MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte,
@@ -229,16 +230,15 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const
}
else
{
preallocatedData.asInt32 = 0;
size = getMessageLengthFromFirstByte ((uint8) byte);
preallocatedData.asBytes[0] = (uint8) byte;
packedData.asBytes[0] = (uint8) byte;
if (size > 1)
{
preallocatedData.asBytes[1] = src[0];
packedData.asBytes[1] = src[0];
if (size > 2)
preallocatedData.asBytes[2] = src[1];
packedData.asBytes[2] = src[1];
}
}
@@ -246,7 +246,7 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const
}
else
{
preallocatedData.asInt32 = 0;
packedData.allocatedData = nullptr;
size = 0;
}
}
@@ -255,19 +255,25 @@ MidiMessage& MidiMessage::operator= (const MidiMessage& other)
{
if (this != &other)
{
timeStamp = other.timeStamp;
size = other.size;
if (other.allocatedData != nullptr)
if (other.isHeapAllocated())
{
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
if (isHeapAllocated())
packedData.allocatedData = static_cast<uint8*> (std::realloc (packedData.allocatedData, (size_t) other.size));
else
packedData.allocatedData = static_cast<uint8*> (std::malloc ((size_t) other.size));
memcpy (packedData.allocatedData, other.packedData.allocatedData, (size_t) other.size);
}
else
{
allocatedData.free();
preallocatedData.asInt32 = other.preallocatedData.asInt32;
if (isHeapAllocated())
std::free (packedData.allocatedData);
packedData.allocatedData = other.packedData.allocatedData;
}
timeStamp = other.timeStamp;
size = other.size;
}
return *this;
@@ -277,36 +283,36 @@ MidiMessage& MidiMessage::operator= (const MidiMessage& other)
MidiMessage::MidiMessage (MidiMessage&& other) noexcept
: timeStamp (other.timeStamp), size (other.size)
{
if (other.allocatedData != nullptr)
allocatedData.swapWith (other.allocatedData);
else
preallocatedData.asInt32 = other.preallocatedData.asInt32;
packedData.allocatedData = other.packedData.allocatedData;
other.size = 0;
}
MidiMessage& MidiMessage::operator= (MidiMessage&& other) noexcept
{
jassert (this != &other); // shouldn't be possible
packedData.allocatedData = other.packedData.allocatedData;
timeStamp = other.timeStamp;
size = other.size;
allocatedData.swapWith (other.allocatedData);
preallocatedData.asInt32 = other.preallocatedData.asInt32;
other.size = 0;
return *this;
}
#endif
MidiMessage::~MidiMessage() {}
MidiMessage::~MidiMessage() noexcept
{
if (isHeapAllocated())
std::free (packedData.allocatedData);
}
uint8* MidiMessage::allocateSpace (int bytes)
{
if (bytes > 4)
if (bytes > (int) sizeof (packedData))
{
allocatedData.malloc ((size_t) bytes);
return allocatedData;
uint8* d = static_cast<uint8*> (std::malloc ((size_t) bytes));
packedData.allocatedData = d;
return d;
}
return preallocatedData.asBytes;
return packedData.asBytes;
}
String MidiMessage::getDescription() const
@@ -416,7 +422,7 @@ float MidiMessage::getFloatVelocity() const noexcept
void MidiMessage::setVelocity (const float newVelocity) noexcept
{
if (isNoteOnOrOff())
getData()[2] = MidiHelpers::floatVelocityToByte (newVelocity);
getData()[2] = floatValueToMidiByte (newVelocity);
}
void MidiMessage::multiplyVelocity (const float scaleFactor) noexcept
@@ -563,7 +569,7 @@ MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const
MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept
{
return noteOn (channel, noteNumber, MidiHelpers::floatVelocityToByte (velocity));
return noteOn (channel, noteNumber, floatValueToMidiByte (velocity));
}
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept
@@ -577,7 +583,7 @@ MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, float velocity) noexcept
{
return noteOff (channel, noteNumber, MidiHelpers::floatVelocityToByte (velocity));
return noteOff (channel, noteNumber, floatValueToMidiByte (velocity));
}
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept
@@ -722,9 +728,10 @@ MidiMessage MidiMessage::textMetaEvent (int type, StringRef text)
header[--n] = 0xff;
const size_t headerLen = sizeof (header) - n;
const int totalSize = (int) (headerLen + textSize);
uint8* const dest = result.allocateSpace ((int) (headerLen + textSize));
result.size = (int) (headerLen + textSize);
uint8* const dest = result.allocateSpace (totalSize);
result.size = totalSize;
memcpy (dest, header + n, headerLen);
memcpy (dest + headerLen, text.text.getAddress(), textSize);
@@ -841,7 +848,7 @@ bool MidiMessage::isKeySignatureMetaEvent() const noexcept
int MidiMessage::getKeySignatureNumberOfSharpsOrFlats() const noexcept
{
return (int) getMetaEventData()[0];
return (int) (int8) getMetaEventData()[0];
}
bool MidiMessage::isKeySignatureMajorKey() const noexcept
@@ -1010,7 +1017,7 @@ String MidiMessage::getMidiNoteName (int note, bool useSharps, bool includeOctav
return String();
}
double MidiMessage::getMidiNoteInHertz (int noteNumber, const double frequencyOfA) noexcept
double MidiMessage::getMidiNoteInHertz (const int noteNumber, const double frequencyOfA) noexcept
{
return frequencyOfA * pow (2.0, (noteNumber - 69) / 12.0);
}


+ 21
- 13
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -104,7 +104,7 @@ public:
MidiMessage (const MidiMessage&, double newTimeStamp);
/** Destructor. */
~MidiMessage();
~MidiMessage() noexcept;
/** Copies this message from another one. */
MidiMessage& operator= (const MidiMessage& other);
@@ -118,7 +118,7 @@ public:
/** Returns a pointer to the raw midi data.
@see getRawDataSize
*/
const uint8* getRawData() const noexcept { return allocatedData != nullptr ? allocatedData.getData() : preallocatedData.asBytes; }
const uint8* getRawData() const noexcept { return getData(); }
/** Returns the number of bytes of data in the message.
@see getRawData
@@ -851,7 +851,7 @@ public:
The value passed in must be 0x80 or higher.
*/
static int getMessageLengthFromFirstByte (const uint8 firstByte) noexcept;
static int getMessageLengthFromFirstByte (uint8 firstByte) noexcept;
//==============================================================================
/** Returns the name of a midi note number.
@@ -878,7 +878,7 @@ public:
The frequencyOfA parameter is an optional frequency for 'A', normally 440-444Hz for concert pitch.
@see getMidiNoteName
*/
static double getMidiNoteInHertz (int noteNumber, const double frequencyOfA = 440.0) noexcept;
static double getMidiNoteInHertz (int noteNumber, double frequencyOfA = 440.0) noexcept;
/** Returns true if the given midi note number is a black key. */
static bool isMidiNoteBlack (int noteNumber) noexcept;
@@ -905,21 +905,29 @@ public:
*/
static const char* getControllerName (int controllerNumber);
/** Converts a floating-point value between 0 and 1 to a MIDI 7-bit value between 0 and 127. */
static uint8 floatValueToMidiByte (float valueBetween0and1) noexcept;
/** Converts a pitchbend value in semitones to a MIDI 14-bit pitchwheel position value. */
static uint16 pitchbendToPitchwheelPos (float pitchbendInSemitones,
float pitchbendRangeInSemitones) noexcept;
private:
//==============================================================================
double timeStamp;
HeapBlock<uint8> allocatedData;
int size;
#ifndef DOXYGEN
union
union PackedData
{
uint8 asBytes[4];
uint32 asInt32;
} preallocatedData;
uint8* allocatedData;
uint8 asBytes[sizeof (uint8*)];
};
PackedData packedData;
double timeStamp;
int size;
#endif
inline uint8* getData() noexcept { return allocatedData != nullptr ? allocatedData.getData() : preallocatedData.asBytes; }
inline bool isHeapAllocated() const noexcept { return size > (int) sizeof (packedData); }
inline uint8* getData() const noexcept { return isHeapAllocated() ? packedData.allocatedData : (uint8*) packedData.asBytes; }
uint8* allocateSpace (int);
};


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp View File

@@ -80,7 +80,7 @@ int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const noexcep
return -1;
}
int MidiMessageSequence::getIndexOf (MidiEventHolder* const event) const noexcept
int MidiMessageSequence::getIndexOf (const MidiEventHolder* const event) const noexcept
{
return list.indexOf (event);
}


+ 13
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h View File

@@ -48,6 +48,18 @@ public:
/** Replaces this sequence with another one. */
MidiMessageSequence& operator= (const MidiMessageSequence&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
MidiMessageSequence (MidiMessageSequence&& other) noexcept
: list (static_cast<OwnedArray<MidiEventHolder>&&> (other.list))
{}
MidiMessageSequence& operator= (MidiMessageSequence&& other) noexcept
{
list = static_cast<OwnedArray<MidiEventHolder>&&> (other.list);
return *this;
}
#endif
/** Destructor. */
~MidiMessageSequence();
@@ -109,7 +121,7 @@ public:
int getIndexOfMatchingKeyUp (int index) const noexcept;
/** Returns the index of an event. */
int getIndexOf (MidiEventHolder* event) const noexcept;
int getIndexOf (const MidiEventHolder* event) const noexcept;
/** Returns the index of the first event on or after the given timestamp.
If the time is beyond the end of the sequence, this will return the


+ 1
- 2
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiRPN.cpp View File

@@ -22,7 +22,6 @@
==============================================================================
*/
MidiRPNDetector::MidiRPNDetector() noexcept
{
}
@@ -55,7 +54,7 @@ void MidiRPNDetector::reset() noexcept
}
//==============================================================================
MidiRPNDetector::ChannelState::ChannelState () noexcept
MidiRPNDetector::ChannelState::ChannelState() noexcept
: parameterMSB (0xff), parameterLSB (0xff), valueMSB (0xff), valueLSB (0xff), isNRPN (false)
{
}


+ 182
- 172
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp View File

@@ -39,6 +39,9 @@ MPEInstrument::MPEInstrument() noexcept
pressureDimension.value = &MPENote::pressure;
timbreDimension.value = &MPENote::timbre;
// the default value for pressure is 0, for all other dimension it is centre (= default MPEValue)
std::fill_n (pressureDimension.lastValueReceivedOnChannel, 16, MPEValue::minValue());
legacyMode.isEnabled = false;
legacyMode.pitchbendRange = 2;
legacyMode.channelRange = Range<int> (1, 17);
@@ -271,22 +274,6 @@ void MPEInstrument::handleTimbreLSB (int midiChannel, int value) noexcept
lastTimbreLowerBitReceivedOnChannel[midiChannel - 1] = uint8 (value);
}
//==============================================================================
MPEValue MPEInstrument::getInitialPitchbendForNoteOn (int midiChannel, int /*midiNoteNumber*/, MPEValue /*midiNoteOnVelocity*/) const
{
return pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1];
}
MPEValue MPEInstrument::getInitialPressureForNoteOn (int /*midiChannel*/, int /*midiNoteNumber*/, MPEValue midiNoteOnVelocity) const
{
return midiNoteOnVelocity;
}
MPEValue MPEInstrument::getInitialTimbreForNoteOn (int midiChannel, int /*midiNoteNumber*/, MPEValue /*midiNoteOnVelocity*/) const
{
return timbreDimension.lastValueReceivedOnChannel[midiChannel - 1];
}
//==============================================================================
void MPEInstrument::noteOn (int midiChannel,
int midiNoteNumber,
@@ -298,9 +285,9 @@ void MPEInstrument::noteOn (int midiChannel,
MPENote newNote (midiChannel,
midiNoteNumber,
midiNoteOnVelocity,
getInitialPitchbendForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity),
getInitialPressureForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity),
getInitialTimbreForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity),
getInitialValueForNewNote (midiChannel, pitchbendDimension),
getInitialValueForNewNote (midiChannel, pressureDimension),
getInitialValueForNewNote (midiChannel, timbreDimension),
isNoteChannelSustained[midiChannel - 1] ? MPENote::keyDownAndSustained : MPENote::keyDown);
const ScopedLock sl (lock);
@@ -334,10 +321,11 @@ void MPEInstrument::noteOff (int midiChannel,
note->keyState = (note->keyState == MPENote::keyDownAndSustained) ? MPENote::sustained : MPENote::off;
note->noteOffVelocity = midiNoteOffVelocity;
// last pitchbend and timbre values received for this note should not be re-used for
// last dimension values received for this note should not be re-used for
// any new notes, so reset them:
pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue();
timbreDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue();
pressureDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::minValue();
pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::centreValue();
timbreDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::centreValue();
if (note->keyState == MPENote::off)
{
@@ -370,6 +358,14 @@ void MPEInstrument::timbre (int midiChannel, MPEValue value)
updateDimension (midiChannel, timbreDimension, value);
}
MPEValue MPEInstrument::getInitialValueForNewNote (int midiChannel, MPEDimension& dimension) const
{
if (getLastNotePlayedPtr (midiChannel) != nullptr)
return &dimension == &pressureDimension ? MPEValue::minValue() : MPEValue::centreValue();
return dimension.lastValueReceivedOnChannel[midiChannel - 1];
}
//==============================================================================
void MPEInstrument::updateDimension (int midiChannel, MPEDimension& dimension, MPEValue value)
{
@@ -758,7 +754,7 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 1);
expectEquals (test.noteAddedCallCounter, 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
// note-off
test.noteOff (3, 60, MPEValue::from7BitInt (33));
@@ -774,13 +770,13 @@ public:
// note off with non-matching note number shouldn't do anything
test.noteOff (3, 61, MPEValue::from7BitInt (33));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteReleasedCallCounter, 0);
// note off with non-matching midi channel shouldn't do anything
test.noteOff (2, 60, MPEValue::from7BitInt (33));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteReleasedCallCounter, 0);
}
{
@@ -791,9 +787,9 @@ public:
test.noteOn (3, 1, MPEValue::from7BitInt (100));
test.noteOn (3, 2, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 3);
expectNote (test.getNote (3, 0), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 1), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 2), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 0), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 1), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 2), 100, 0, 8192, 64, MPENote::keyDown);
}
{
// pathological case: second note-on for same note should retrigger it.
@@ -802,7 +798,7 @@ public:
test.noteOn (3, 0, MPEValue::from7BitInt (100));
test.noteOn (3, 0, MPEValue::from7BitInt (60));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 0), 60, 60, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 0), 60, 0, 8192, 64, MPENote::keyDown);
}
}
@@ -844,42 +840,42 @@ public:
// sustain pedal on per-note channel shouldn't do anything.
test.sustainPedal (3, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 0);
// sustain pedal on non-zone channel shouldn't do anything either.
test.sustainPedal (1, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 0);
// sustain pedal on master channel should sustain notes on *that* zone.
test.sustainPedal (2, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 1);
// release
test.sustainPedal (2, false);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 2);
// should also sustain new notes added after the press
test.sustainPedal (2, true);
expectEquals (test.noteKeyStateChangedCallCounter, 3);
test.noteOn (4, 51, MPEValue::from7BitInt (100));
expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
expectEquals (test.noteKeyStateChangedCallCounter, 3);
// ...but only if that sustain came on the master channel of that zone!
test.sustainPedal (11, true);
test.noteOn (11, 52, MPEValue::from7BitInt (100));
expectNote (test.getNote (11, 52), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (11, 52), 100, 0, 8192, 64, MPENote::keyDown);
test.noteOff (11, 52, MPEValue::from7BitInt (100));
expectEquals (test.noteReleasedCallCounter, 1);
@@ -890,8 +886,8 @@ public:
expectEquals (test.getNumPlayingNotes(), 2);
expectEquals (test.noteReleasedCallCounter, 2);
expectEquals (test.noteKeyStateChangedCallCounter, 5);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::sustained);
// notes should be turned off when pedal is released
test.sustainPedal (2, false);
@@ -908,26 +904,26 @@ public:
// sostenuto pedal on per-note channel shouldn't do anything.
test.sostenutoPedal (3, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 0);
// sostenuto pedal on non-zone channel shouldn't do anything either.
test.sostenutoPedal (1, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 0);
// sostenuto pedal on master channel should sustain notes on *that* zone.
test.sostenutoPedal (2, true);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 1);
// release
test.sostenutoPedal (2, false);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 2);
// should only sustain notes turned on *before* the press (difference to sustain pedal)
@@ -935,9 +931,9 @@ public:
expectEquals (test.noteKeyStateChangedCallCounter, 3);
test.noteOn (4, 51, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 3);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteKeyStateChangedCallCounter, 3);
// note-off should not turn off sustained notes inside the same zone,
@@ -946,7 +942,7 @@ public:
test.noteOff (4, 51, MPEValue::from7BitInt (100));
test.noteOff (10, 60, MPEValue::from7BitInt (100)); // not affected!
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
expectEquals (test.noteReleasedCallCounter, 2);
expectEquals (test.noteKeyStateChangedCallCounter, 4);
@@ -1047,22 +1043,22 @@ public:
// applying pressure on a per-note channel should modulate one note
test.pressure (3, MPEValue::from7BitInt (33));
expectNote (test.getNote (3, 60), 100, 33, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
// applying pressure on a master channel should modulate all notes in this zone
test.pressure (2, MPEValue::from7BitInt (44));
expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 3);
// applying pressure on an unrelated channel should be ignored
test.pressure (1, MPEValue::from7BitInt (55));
expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 3);
}
{
@@ -1073,7 +1069,7 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (66));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 66, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
}
@@ -1091,6 +1087,49 @@ public:
expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
}
{
UnitTestInstrument test;
test.setZoneLayout (testLayout);
// if no pressure is sent before note-on, default = 0 should be used
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
test.setZoneLayout (testLayout);
// if pressure is sent before note-on, use that
test.pressure (3, MPEValue::from7BitInt (77));
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
test.setZoneLayout (testLayout);
// if pressure is sent before note-on, but it belonged to another note
// on the same channel that has since been turned off, use default = 0
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (77));
test.noteOff (3, 61, MPEValue::from7BitInt (100));
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
test.setZoneLayout (testLayout);
// edge case: two notes on the same channel simultaneously. the second one should use
// pressure = 0 initially but then react to additional pressure messages
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (77));
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
test.pressure (3, MPEValue::from7BitInt (78));
expectNote (test.getNote (3, 60), 100, 78, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 77, 8192, 64, MPENote::keyDown);
}
}
beginTest ("pitchbend");
@@ -1105,9 +1144,9 @@ public:
// applying pitchbend on a per-note channel should modulate one note
test.pitchbend (3, MPEValue::from14BitInt (1111));
expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
// applying pitchbend on a master channel should be ignored for the
@@ -1115,16 +1154,16 @@ public:
// Note: noteChanged will be called anyway for notes in that zone
// because the total pitchbend for those notes has changed
test.pitchbend (2, MPEValue::from14BitInt (2222));
expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 3);
// applying pitchbend on an unrelated channel should do nothing.
test.pitchbend (1, MPEValue::from14BitInt (3333));
expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 3);
}
{
@@ -1135,8 +1174,8 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (4444));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 4444, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 4444, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1150,7 +1189,7 @@ public:
test.noteOff (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (5555));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 5555, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1169,14 +1208,14 @@ public:
test.sustainPedal (2, true);
test.noteOff (3, 60, MPEValue::from7BitInt (64));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
expectEquals (test.noteKeyStateChangedCallCounter, 2);
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (6666));
expectEquals (test.getNumPlayingNotes(), 2);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (3, 61), 100, 100, 6666, 64, MPENote::keyDownAndSustained);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained);
expectNote (test.getNote (3, 61), 100, 0, 6666, 64, MPENote::keyDownAndSustained);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1193,11 +1232,11 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (5555));
expectNote (test.getNote (3, 60), 100, 100, 5555, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown);
test.noteOff (3, 60, MPEValue::from7BitInt (100));
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
}
{
// applying per-note pitchbend should set the note's totalPitchbendInSemitones
@@ -1289,23 +1328,23 @@ public:
// modulating timbre on a per-note channel should modulate one note
test.timbre (3, MPEValue::from7BitInt (33));
expectNote (test.getNote (3, 60), 100, 100, 8192, 33, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 33, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
// modulating timbre on a master channel should modulate all notes in this zone
test.timbre (2, MPEValue::from7BitInt (44));
expectNote (test.getNote (3, 60), 100, 100, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 3);
// modulating timbre on an unrelated channel should be ignored
test.timbre (1, MPEValue::from7BitInt (55));
expectNote (test.getNote (3, 60), 100, 100, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown);
expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 3);
}
{
@@ -1316,8 +1355,8 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (66));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 66, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 66, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
}
{
@@ -1331,7 +1370,7 @@ public:
test.noteOff (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (77));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (3, 60), 100, 100, 8192, 77, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 77, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
}
{
@@ -1341,11 +1380,11 @@ public:
// Zsolt's edge case for timbre
test.noteOn (3, 60, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (42));
expectNote (test.getNote (3, 60), 100, 100, 8192, 42, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 42, MPENote::keyDown);
test.noteOff (3, 60, MPEValue::from7BitInt (100));
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
}
}
@@ -1361,8 +1400,8 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 99, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
}
@@ -1377,8 +1416,8 @@ public:
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 99, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
}
{
@@ -1391,9 +1430,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pressure (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 99, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePressureChangedCallCounter, 1);
}
{
@@ -1425,9 +1464,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (9999));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1440,9 +1479,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (9999));
expectNote (test.getNote (3, 60), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1455,9 +1494,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (9999));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 1);
}
{
@@ -1470,9 +1509,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.pitchbend (3, MPEValue::from14BitInt (9999));
expectNote (test.getNote (3, 60), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown);
expectEquals (test.notePitchbendChangedCallCounter, 3);
}
}
@@ -1489,9 +1528,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
}
{
@@ -1504,9 +1543,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
}
{
@@ -1519,9 +1558,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 1);
}
{
@@ -1534,9 +1573,9 @@ public:
test.noteOn (3, 62, MPEValue::from7BitInt (100));
test.noteOn (3, 61, MPEValue::from7BitInt (100));
test.timbre (3, MPEValue::from7BitInt (99));
expectNote (test.getNote (3, 60), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 100, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown);
expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown);
expectEquals (test.noteTimbreChangedCallCounter, 3);
}
}
@@ -1724,7 +1763,7 @@ public:
expectEquals (test.getNumPlayingNotes(), 0);
}
beginTest ("default getInitial...ForNoteOn");
beginTest ("default initial values for pitchbend and timbre");
{
MPEInstrument test;
test.setZoneLayout (testLayout);
@@ -1739,16 +1778,7 @@ public:
test.noteOn (3, 60, MPEValue::from7BitInt (100));
expectNote (test.getMostRecentNote (3), 100, 100, 3333, 66, MPENote::keyDown);
}
beginTest ("overriding getInitial...ForNoteOn");
{
CustomInitialValuesTest<33, 4444, 55> test;
test.setZoneLayout (testLayout);
test.noteOn (3, 61, MPEValue::from7BitInt (100));
expectNote (test.getMostRecentNote (3), 100, 33, 4444, 55, MPENote::keyDown);
expectNote (test.getMostRecentNote (3), 100, 0, 3333, 66, MPENote::keyDown);
}
beginTest ("Legacy mode");
@@ -1806,10 +1836,10 @@ public:
test.pressure (2, MPEValue::from7BitInt (88));
test.timbre (15, MPEValue::from7BitInt (77));
expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (2, 60), 100, 88, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (15, 60), 100, 100, 8192, 77, MPENote::keyDown);
expectNote (test.getNote (16, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (15, 60), 100, 0, 8192, 77, MPENote::keyDown);
expectNote (test.getNote (16, 60), 100, 0, 8192, 64, MPENote::keyDown);
// note off should work in legacy mode
@@ -1835,10 +1865,10 @@ public:
test.noteOn (16, 60, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 4);
expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (6, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (7, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (6, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (7, 60), 100, 0, 8192, 64, MPENote::keyDown);
}
{
// tracking mode in legacy mode
@@ -1851,9 +1881,9 @@ public:
test.noteOn (1, 62, MPEValue::from7BitInt (100));
test.noteOn (1, 61, MPEValue::from7BitInt (100));
test.pitchbend (1, MPEValue::from14BitInt (9999));
expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
@@ -1864,9 +1894,9 @@ public:
test.noteOn (1, 62, MPEValue::from7BitInt (100));
test.noteOn (1, 61, MPEValue::from7BitInt (100));
test.pitchbend (1, MPEValue::from14BitInt (9999));
expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
@@ -1877,9 +1907,9 @@ public:
test.noteOn (1, 62, MPEValue::from7BitInt (100));
test.noteOn (1, 61, MPEValue::from7BitInt (100));
test.pitchbend (1, MPEValue::from14BitInt (9999));
expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 100, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown);
}
{
UnitTestInstrument test;
@@ -1890,9 +1920,9 @@ public:
test.noteOn (1, 62, MPEValue::from7BitInt (100));
test.noteOn (1, 61, MPEValue::from7BitInt (100));
test.pitchbend (1, MPEValue::from14BitInt (9999));
expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 100, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown);
expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown);
}
}
{
@@ -1916,7 +1946,7 @@ public:
test.noteOff (1, 60, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained);
test.sustainPedal (1, false);
expectEquals (test.getNumPlayingNotes(), 0);
@@ -1939,7 +1969,7 @@ public:
test.noteOff (2, 61, MPEValue::from7BitInt (100));
expectEquals (test.getNumPlayingNotes(), 1);
expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::sustained);
expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained);
test.sostenutoPedal (1, false);
expectEquals (test.getNumPlayingNotes(), 0);
@@ -2081,26 +2111,6 @@ private:
}
};
//==============================================================================
template <int initial7BitPressure, int initial14BitPitchbend, int initial7BitTimbre>
class CustomInitialValuesTest : public MPEInstrument
{
MPEValue getInitialPitchbendForNoteOn (int, int, MPEValue) const override
{
return MPEValue::from14BitInt (initial14BitPitchbend);
}
MPEValue getInitialPressureForNoteOn (int, int, MPEValue) const override
{
return MPEValue::from7BitInt (initial7BitPressure);
}
MPEValue getInitialTimbreForNoteOn (int, int, MPEValue) const override
{
return MPEValue::from7BitInt (initial7BitTimbre);
}
};
//==============================================================================
void expectNote (MPENote noteToTest,
int noteOnVelocity7Bit,


+ 1
- 30
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.h View File

@@ -320,36 +320,6 @@ public:
/** Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. */
void setLegacyModePitchbendRange (int pitchbendRange);
protected:
//==============================================================================
/** This method defines what initial pitchbend value should be used for newly
triggered notes. The default is to use the last pitchbend value
that has been received on the same MIDI channel (or no pitchbend
if no pitchbend messages have been received so far).
Override this method if you need different behaviour.
*/
virtual MPEValue getInitialPitchbendForNoteOn (int midiChannel,
int midiNoteNumber,
MPEValue midiNoteOnVelocity) const;
/** This method defines what initial pressure value should be used for newly
triggered notes. The default is to re-use the note-on velocity value.
Override this method if you need different behaviour.
*/
virtual MPEValue getInitialPressureForNoteOn (int midiChannel,
int midiNoteNumber,
MPEValue midiNoteOnVelocity) const;
/** This method defines what initial timbre value should be used for newly
triggered notes. The default is to use the last timbre value that has
that has been received on the same MIDI channel (or a neutral centred value
if no pitchbend messages have been received so far).
Override this method if you need different behaviour.
*/
virtual MPEValue getInitialTimbreForNoteOn (int midiChannel,
int midiNoteNumber,
MPEValue midiNoteOnVelocity) const;
private:
//==============================================================================
CriticalSection lock;
@@ -384,6 +354,7 @@ private:
void updateDimensionMaster (MPEZone&, MPEDimension&, MPEValue);
void updateDimensionForNote (MPENote&, MPEDimension&, MPEValue);
void callListenersDimensionChanged (MPENote&, MPEDimension&);
MPEValue getInitialValueForNewNote (int midiChannel, MPEDimension&) const;
void processMidiNoteOnMessage (const MidiMessage&);
void processMidiNoteOffMessage (const MidiMessage&);


+ 0
- 1
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEMessages.cpp View File

@@ -22,7 +22,6 @@
==============================================================================
*/
MidiBuffer MPEMessages::addZone (MPEZone zone)
{
MidiBuffer buffer (MidiRPNGenerator::generate (zone.getFirstNoteChannel(),


+ 8
- 3
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp View File

@@ -25,7 +25,8 @@
MPESynthesiserBase::MPESynthesiserBase()
: instrument (new MPEInstrument),
sampleRate (0),
minimumSubBlockSize (32)
minimumSubBlockSize (32),
subBlockSubdivisionIsStrict (false)
{
instrument->addListener (this);
}
@@ -100,6 +101,7 @@ void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
MidiBuffer::Iterator midiIterator (inputMidi);
midiIterator.setNextSamplePosition (startSample);
bool firstEvent = true;
int midiEventPos;
MidiMessage m;
@@ -122,12 +124,14 @@ void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
break;
}
if (samplesToNextMidiMessage < minimumSubBlockSize)
if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
{
handleMidiEvent (m);
continue;
}
firstEvent = false;
renderNextSubBlock (outputAudio, startSample, samplesToNextMidiMessage);
handleMidiEvent (m);
startSample += samplesToNextMidiMessage;
@@ -154,8 +158,9 @@ void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
}
//==============================================================================
void MPESynthesiserBase::setMinimumRenderingSubdivisionSize (int numSamples) noexcept
void MPESynthesiserBase::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
{
jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
minimumSubBlockSize = numSamples;
subBlockSubdivisionIsStrict = shouldBeStrict;
}

+ 8
- 1
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.h View File

@@ -127,8 +127,14 @@ public:
The default setting is 32, which means that midi messages are accurate to about < 1ms
accuracy, which is probably fine for most purposes, but you may want to increase or
decrease this value for your synth.
If shouldBeStrict is true, the audio sub-blocks will strictly never be smaller than numSamples.
If shouldBeStrict is false (default), the first audio sub-block in the buffer is allowed
to be smaller, to make sure that the first MIDI event in a buffer will always be sample-accurate
(this can sometimes help to avoid quantisation or phasing issues).
*/
void setMinimumRenderingSubdivisionSize (int numSamples) noexcept;
void setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict = false) noexcept;
//==============================================================================
/** Puts the synthesiser into legacy mode.
@@ -185,6 +191,7 @@ private:
CriticalSection noteStateLock;
double sampleRate;
int minimumSubBlockSize;
bool subBlockSubdivisionIsStrict;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiserBase)
};


+ 14
- 6
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZone.h View File

@@ -69,27 +69,35 @@ struct JUCE_API MPEZone
int perNotePitchbendRange = 48,
int masterPitchbendRange = 2) noexcept;
/* Returns the MIDI master channel of this zone. */
/* Returns the MIDI master channel number (in the range 1-16) of this zone. */
int getMasterChannel() const noexcept;
/** Returns the number of note channels occupied by this zone. */
int getNumNoteChannels() const noexcept;
/* Returns the MIDI channel number of the lowest-numbered note channel of this zone. */
/* Returns the MIDI channel number (in the range 1-16) of the
lowest-numbered note channel of this zone.
*/
int getFirstNoteChannel() const noexcept;
/* Returns the MIDI channel number of the highest-numbered note channel of this zone. */
/* Returns the MIDI channel number (in the range 1-16) of the
highest-numbered note channel of this zone.
*/
int getLastNoteChannel() const noexcept;
/** Returns the MIDI channel numbers of the note channels of this zone as a Range. */
/** Returns the MIDI channel numbers (in the range 1-16) of the
note channels of this zone as a Range.
*/
Range<int> getNoteChannelRange() const noexcept;
/** Returns true if the MIDI channel (in the range 1-16) is used by this zone
either as a note channel or as the master channel; false otherwise. */
either as a note channel or as the master channel; false otherwise.
*/
bool isUsingChannel (int channel) const noexcept;
/** Returns true if the MIDI channel (in the range 1-16) is used by this zone
as a note channel; false otherwise. */
as a note channel; false otherwise.
*/
bool isUsingChannelAsNoteChannel (int channel) const noexcept;
/** Returns the per-note pitchbend range in semitones set for this zone. */


+ 50
- 5
libs/juce/source/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp View File

@@ -26,7 +26,8 @@ BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* s,
TimeSliceThread& thread,
const bool deleteSourceWhenDeleted,
const int bufferSizeSamples,
const int numChannels)
const int numChannels,
bool prefillBufferOnPrepareToPlay)
: source (s, deleteSourceWhenDeleted),
backgroundThread (thread),
numberOfSamplesToBuffer (jmax (1024, bufferSizeSamples)),
@@ -36,7 +37,8 @@ BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* s,
nextPlayPos (0),
sampleRate (0),
wasSourceLooping (false),
isPrepared (false)
isPrepared (false),
prefillBuffer (prefillBufferOnPrepareToPlay)
{
jassert (source != nullptr);
@@ -73,12 +75,13 @@ void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double ne
backgroundThread.addTimeSliceClient (this);
while (bufferValidEnd - bufferValidStart < jmin (((int) newSampleRate) / 4,
buffer.getNumSamples() / 2))
do
{
backgroundThread.moveToFrontOfQueue (this);
Thread::sleep (5);
}
while (prefillBuffer
&& (bufferValidEnd - bufferValidStart < jmin (((int) newSampleRate) / 4, buffer.getNumSamples() / 2)));
}
}
@@ -88,7 +91,12 @@ void BufferingAudioSource::releaseResources()
backgroundThread.removeTimeSliceClient (this);
buffer.setSize (numberOfChannels, 0);
source->releaseResources();
// MSVC2015 seems to need this if statement to not generate a warning during linking.
// As source is set in the constructor, there is no way that source could
// ever equal this, but it seems to make MSVC2015 happy.
if (source != this)
source->releaseResources();
}
void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
@@ -148,6 +156,41 @@ void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info
}
}
bool BufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const uint32 timeout)
{
if (!source || source->getTotalLength() <= 0)
return false;
if (nextPlayPos + info.numSamples < 0)
return true;
if (! isLooping() && nextPlayPos > getTotalLength())
return true;
const uint32 endTime = Time::getMillisecondCounter() + timeout;
uint32 now = Time::getMillisecondCounter();
while (now < endTime)
{
{
const ScopedLock sl (bufferStartPosLock);
const int validStart = static_cast<int> (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos);
const int validEnd = static_cast<int> (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos);
if (validStart <= 0 && validStart < validEnd && validEnd >= info.numSamples)
return true;
}
if (! bufferReadyEvent.wait (static_cast<int> (endTime - now)))
return false;
now = Time::getMillisecondCounter();
}
return false;
}
int64 BufferingAudioSource::getNextReadPosition() const
{
jassert (source->getTotalLength() > 0);
@@ -241,6 +284,8 @@ bool BufferingAudioSource::readNextBufferChunk()
bufferValidEnd = newBVE;
}
bufferReadyEvent.signal();
return true;
}


+ 21
- 11
libs/juce/source/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h View File

@@ -43,21 +43,24 @@ public:
//==============================================================================
/** Creates a BufferingAudioSource.
@param source the input source to read from
@param backgroundThread a background thread that will be used for the
background read-ahead. This object must not be deleted
until after any BufferingAudioSources that are using it
have been deleted!
@param deleteSourceWhenDeleted if true, then the input source object will
be deleted when this object is deleted
@param numberOfSamplesToBuffer the size of buffer to use for reading ahead
@param numberOfChannels the number of channels that will be played
@param source the input source to read from
@param backgroundThread a background thread that will be used for the
background read-ahead. This object must not be deleted
until after any BufferingAudioSources that are using it
have been deleted!
@param deleteSourceWhenDeleted if true, then the input source object will
be deleted when this object is deleted
@param numberOfSamplesToBuffer the size of buffer to use for reading ahead
@param numberOfChannels the number of channels that will be played
@param prefillBufferOnPrepareToPlay if true, then calling prepareToPlay on this object will
block until the buffer has been filled
*/
BufferingAudioSource (PositionableAudioSource* source,
TimeSliceThread& backgroundThread,
bool deleteSourceWhenDeleted,
int numberOfSamplesToBuffer,
int numberOfChannels = 2);
int numberOfChannels = 2,
bool prefillBufferOnPrepareToPlay = true);
/** Destructor.
@@ -89,6 +92,12 @@ public:
/** Implements the PositionableAudioSource method. */
bool isLooping() const override { return source->isLooping(); }
/** A useful function to block until the next the buffer info can be filled.
This is useful for offline rendering.
*/
bool waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const uint32 timeout);
private:
//==============================================================================
OptionalScopedPointer<PositionableAudioSource> source;
@@ -96,9 +105,10 @@ private:
int numberOfSamplesToBuffer, numberOfChannels;
AudioSampleBuffer buffer;
CriticalSection bufferStartPosLock;
WaitableEvent bufferReadyEvent;
int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos;
double volatile sampleRate;
bool wasSourceLooping, isPrepared;
bool wasSourceLooping, isPrepared, prefillBuffer;
bool readNextBufferChunk();
void readBufferSection (int64 start, int length, int bufferOffset);


+ 17
- 5
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -88,6 +88,7 @@ Synthesiser::Synthesiser()
: sampleRate (0),
lastNoteOnCounter (0),
minimumSubBlockSize (32),
subBlockSubdivisionIsStrict (false),
shouldStealNotes (true)
{
for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i)
@@ -147,10 +148,11 @@ void Synthesiser::setNoteStealingEnabled (const bool shouldSteal)
shouldStealNotes = shouldSteal;
}
void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples) noexcept
void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
{
jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
minimumSubBlockSize = numSamples;
subBlockSubdivisionIsStrict = shouldBeStrict;
}
//==============================================================================
@@ -177,10 +179,12 @@ void Synthesiser::processNextBlock (AudioBuffer<floatType>& outputAudio,
{
// must set the sample rate before using this!
jassert (sampleRate != 0);
const int targetChannels = outputAudio.getNumChannels();
MidiBuffer::Iterator midiIterator (midiData);
midiIterator.setNextSamplePosition (startSample);
bool firstEvent = true;
int midiEventPos;
MidiMessage m;
@@ -190,7 +194,9 @@ void Synthesiser::processNextBlock (AudioBuffer<floatType>& outputAudio,
{
if (! midiIterator.getNextEvent (m, midiEventPos))
{
renderVoices (outputAudio, startSample, numSamples);
if (targetChannels > 0)
renderVoices (outputAudio, startSample, numSamples);
return;
}
@@ -198,18 +204,24 @@ void Synthesiser::processNextBlock (AudioBuffer<floatType>& outputAudio,
if (samplesToNextMidiMessage >= numSamples)
{
renderVoices (outputAudio, startSample, numSamples);
if (targetChannels > 0)
renderVoices (outputAudio, startSample, numSamples);
handleMidiEvent (m);
break;
}
if (samplesToNextMidiMessage < minimumSubBlockSize)
if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
{
handleMidiEvent (m);
continue;
}
renderVoices (outputAudio, startSample, samplesToNextMidiMessage);
firstEvent = false;
if (targetChannels > 0)
renderVoices (outputAudio, startSample, samplesToNextMidiMessage);
handleMidiEvent (m);
startSample += samplesToNextMidiMessage;
numSamples -= samplesToNextMidiMessage;


+ 8
- 1
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h View File

@@ -539,8 +539,14 @@ public:
The default setting is 32, which means that midi messages are accurate to about < 1ms
accuracy, which is probably fine for most purposes, but you may want to increase or
decrease this value for your synth.
If shouldBeStrict is true, the audio sub-blocks will strictly never be smaller than numSamples.
If shouldBeStrict is false (default), the first audio sub-block in the buffer is allowed
to be smaller, to make sure that the first MIDI event in a buffer will always be sample-accurate
(this can sometimes help to avoid quantisation or phasing issues).
*/
void setMinimumRenderingSubdivisionSize (int numSamples) noexcept;
void setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict = false) noexcept;
protected:
//==============================================================================
@@ -615,6 +621,7 @@ private:
double sampleRate;
uint32 lastNoteOnCounter;
int minimumSubBlockSize;
bool subBlockSubdivisionIsStrict;
bool shouldStealNotes;
BigInteger sustainPedalsDown;


+ 72
- 226
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -86,72 +86,12 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
};
//==============================================================================
// This is an AudioTransportSource which will own it's assigned source
struct AudioSourceOwningTransportSource : public AudioTransportSource
{
AudioSourceOwningTransportSource (PositionableAudioSource* s) : source (s)
{
AudioTransportSource::setSource (s);
}
~AudioSourceOwningTransportSource()
{
setSource (nullptr);
}
private:
ScopedPointer<PositionableAudioSource> source;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSourceOwningTransportSource)
};
//==============================================================================
// An AudioSourcePlayer which will remove itself from the AudioDeviceManager's
// callback list once it finishes playing its source
struct AutoRemovingSourcePlayer : public AudioSourcePlayer,
private Timer
{
AutoRemovingSourcePlayer (AudioDeviceManager& dm, AudioTransportSource* ts, bool ownSource)
: manager (dm), transportSource (ts, ownSource)
{
jassert (ts != nullptr);
manager.addAudioCallback (this);
AudioSourcePlayer::setSource (transportSource);
startTimerHz (10);
}
~AutoRemovingSourcePlayer()
{
setSource (nullptr);
manager.removeAudioCallback (this);
}
void timerCallback() override
{
if (getCurrentSource() == nullptr || ! transportSource->isPlaying())
delete this;
}
void audioDeviceStopped() override
{
AudioSourcePlayer::audioDeviceStopped();
setSource (nullptr);
}
private:
AudioDeviceManager& manager;
OptionalScopedPointer<AudioTransportSource> transportSource;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AutoRemovingSourcePlayer)
};
//==============================================================================
AudioDeviceManager::AudioDeviceManager()
: numInputChansNeeded (0),
numOutputChansNeeded (2),
listNeedsScanning (true),
inputLevel (0),
testSoundPosition (0),
cpuUsageMs (0),
timeToCpuScale (0)
{
@@ -162,10 +102,6 @@ AudioDeviceManager::~AudioDeviceManager()
{
currentAudioDevice = nullptr;
defaultMidiOutput = nullptr;
for (int i = 0; i < callbacks.size(); ++i)
if (AutoRemovingSourcePlayer* p = dynamic_cast<AutoRemovingSourcePlayer*> (callbacks.getUnchecked(i)))
delete p;
}
//==============================================================================
@@ -346,8 +282,8 @@ String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
}
setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize");
setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate");
setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize", setup.bufferSize);
setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate", setup.sampleRate);
setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
@@ -650,6 +586,8 @@ void AudioDeviceManager::stopDevice()
{
if (currentAudioDevice != nullptr)
currentAudioDevice->stop();
testSound = nullptr;
}
void AudioDeviceManager::closeAudioDevice()
@@ -761,31 +699,8 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
{
const ScopedLock sl (audioCallbackLock);
if (inputLevelMeasurementEnabledCount.get() > 0 && numInputChannels > 0)
{
for (int j = 0; j < numSamples; ++j)
{
float s = 0;
for (int i = 0; i < numInputChannels; ++i)
s += std::abs (inputChannelData[i][j]);
s /= numInputChannels;
const double decayFactor = 0.99992;
if (s > inputLevel)
inputLevel = s;
else if (inputLevel > 0.001f)
inputLevel *= decayFactor;
else
inputLevel = 0;
}
}
else
{
inputLevel = 0;
}
inputLevelMeter.updateLevel (inputChannelData, numInputChannels, numSamples);
outputLevelMeter.updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
if (callbacks.size() > 0)
{
@@ -821,6 +736,20 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
for (int i = 0; i < numOutputChannels; ++i)
zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
}
if (testSound != nullptr)
{
const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
const float* const src = testSound->getReadPointer (0, testSoundPosition);
for (int i = 0; i < numOutputChannels; ++i)
for (int j = 0; j < numSamps; ++j)
outputChannelData [i][j] += src[j];
testSoundPosition += numSamps;
if (testSoundPosition >= testSound->getNumSamples())
testSound = nullptr;
}
}
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
@@ -989,170 +918,87 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
}
//==============================================================================
// An AudioSource which simply outputs a buffer
class AudioSampleBufferSource : public PositionableAudioSource
{
public:
AudioSampleBufferSource (AudioSampleBuffer* audioBuffer, bool ownBuffer, bool playOnAllChannels)
: buffer (audioBuffer, ownBuffer),
position (0), looping (false), playAcrossAllChannels (playOnAllChannels)
{}
AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
//==============================================================================
void setNextReadPosition (int64 newPosition) override
{
jassert (newPosition >= 0);
if (looping)
newPosition = newPosition % static_cast<int64> (buffer->getNumSamples());
position = jmin (buffer->getNumSamples(), static_cast<int> (newPosition));
}
int64 getNextReadPosition() const override { return static_cast<int64> (position); }
int64 getTotalLength() const override { return static_cast<int64> (buffer->getNumSamples()); }
bool isLooping() const override { return looping; }
void setLooping (bool shouldLoop) override { looping = shouldLoop; }
//==============================================================================
void prepareToPlay (int, double) override {}
void releaseResources() override {}
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
{
if (enabled.get() != 0 && numChannels > 0)
{
bufferToFill.clearActiveBufferRegion();
const int bufferSize = buffer->getNumSamples();
const int samplesNeeded = bufferToFill.numSamples;
const int samplesToCopy = jmin (bufferSize - position, samplesNeeded);
if (samplesToCopy > 0)
for (int j = 0; j < numSamples; ++j)
{
int maxInChannels = buffer->getNumChannels();
int maxOutChannels = bufferToFill.buffer->getNumChannels();
if (! playAcrossAllChannels)
maxOutChannels = jmin (maxOutChannels, maxInChannels);
for (int i = 0; i < maxOutChannels; ++i)
bufferToFill.buffer->copyFrom (i, bufferToFill.startSample, *buffer,
i % maxInChannels, position, samplesToCopy);
}
position += samplesNeeded;
float s = 0;
if (looping)
position %= bufferSize;
}
for (int i = 0; i < numChannels; ++i)
s += std::abs (channelData[i][j]);
private:
//==============================================================================
OptionalScopedPointer<AudioSampleBuffer> buffer;
int position;
bool looping, playAcrossAllChannels;
s /= numChannels;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSampleBufferSource)
};
void AudioDeviceManager::playSound (const File& file)
{
if (file.existsAsFile())
{
AudioFormatManager formatManager;
const double decayFactor = 0.99992;
formatManager.registerBasicFormats();
playSound (formatManager.createReaderFor (file), true);
if (s > level)
level = s;
else if (level > 0.001f)
level *= decayFactor;
else
level = 0;
}
}
}
void AudioDeviceManager::playSound (const void* resourceData, size_t resourceSize)
{
if (resourceData != nullptr && resourceSize > 0)
else
{
AudioFormatManager formatManager;
formatManager.registerBasicFormats();
MemoryInputStream* mem = new MemoryInputStream (resourceData, resourceSize, false);
playSound (formatManager.createReaderFor (mem), true);
level = 0;
}
}
void AudioDeviceManager::playSound (AudioFormatReader* reader, bool deleteWhenFinished)
void AudioDeviceManager::LevelMeter::setEnabled (bool shouldBeEnabled) noexcept
{
if (reader != nullptr)
playSound (new AudioFormatReaderSource (reader, deleteWhenFinished), true);
enabled.set (shouldBeEnabled ? 1 : 0);
level = 0;
}
void AudioDeviceManager::playSound (AudioSampleBuffer* buffer, bool deleteWhenFinished, bool playOnAllOutputChannels)
double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
{
if (buffer != nullptr)
playSound (new AudioSampleBufferSource (buffer, deleteWhenFinished, playOnAllOutputChannels), true);
jassert (enabled.get() != 0); // you need to call setEnabled (true) before using this!
return level;
}
void AudioDeviceManager::playSound (PositionableAudioSource* audioSource, bool deleteWhenFinished)
void AudioDeviceManager::playTestSound()
{
if (audioSource != nullptr && currentAudioDevice != nullptr)
{
AudioTransportSource* transport = dynamic_cast<AudioTransportSource*> (audioSource);
{ // cunningly nested to swap, unlock and delete in that order.
ScopedPointer<AudioSampleBuffer> oldSound;
if (transport == nullptr)
{
if (deleteWhenFinished)
{
transport = new AudioSourceOwningTransportSource (audioSource);
}
else
{
transport = new AudioTransportSource();
transport->setSource (audioSource);
deleteWhenFinished = true;
}
const ScopedLock sl (audioCallbackLock);
oldSound = testSound;
}
transport->start();
new AutoRemovingSourcePlayer (*this, transport, deleteWhenFinished);
}
else
{
if (deleteWhenFinished)
delete audioSource;
}
}
void AudioDeviceManager::playTestSound()
{
const double sampleRate = currentAudioDevice->getCurrentSampleRate();
const int soundLength = (int) sampleRate;
testSoundPosition = 0;
const double frequency = 440.0;
const float amplitude = 0.5f;
const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
if (currentAudioDevice != nullptr)
{
const double sampleRate = currentAudioDevice->getCurrentSampleRate();
const int soundLength = (int) sampleRate;
AudioSampleBuffer* newSound = new AudioSampleBuffer (1, soundLength);
const double frequency = 440.0;
const float amplitude = 0.5f;
for (int i = 0; i < soundLength; ++i)
newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength);
playSound (newSound, true, true);
}
for (int i = 0; i < soundLength; ++i)
newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
//==============================================================================
void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement)
{
if (enableMeasurement)
++inputLevelMeasurementEnabledCount;
else
--inputLevelMeasurementEnabledCount;
newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
inputLevel = 0;
const ScopedLock sl (audioCallbackLock);
testSound = newSound;
}
}
double AudioDeviceManager::getCurrentInputLevel() const
{
jassert (inputLevelMeasurementEnabledCount.get() > 0); // you need to call enableInputLevelMeasurement() before using this!
return inputLevel;
}
double AudioDeviceManager::getCurrentInputLevel() const noexcept { return inputLevelMeter.getCurrentLevel(); }
double AudioDeviceManager::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); }
void AudioDeviceManager::enableInputLevelMeasurement (bool enable) noexcept { inputLevelMeter.setEnabled (enable); }
void AudioDeviceManager::enableOutputLevelMeasurement (bool enable) noexcept { outputLevelMeter.setEnabled (enable); }

+ 31
- 67
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -404,78 +404,28 @@ public:
*/
void playTestSound();
/** Plays a sound from a file. */
void playSound (const File& file);
/** Convenient method to play sound from a JUCE resource. */
void playSound (const void* resourceData, size_t resourceSize);
/** Plays the sound from an audio format reader.
If deleteWhenFinished is true then the format reader will be
automatically deleted once the sound has finished playing.
*/
void playSound (AudioFormatReader* buffer, bool deleteWhenFinished = false);
/** Plays the sound from a positionable audio source.
This will output the sound coming from a positionable audio source.
This gives you slightly more control over the sound playback compared
to the other playSound methods. For example, if you would like to
stop the sound prematurely you can call this method with a
TransportAudioSource and then call audioSource->stop. Note that,
you must call audioSource->start to start the playback, if your
audioSource is a TransportAudioSource.
The audio device manager will not hold any references to this audio
source once the audio source has stopped playing for any reason,
for example when the sound has finished playing or when you have
called audioSource->stop. Therefore, calling audioSource->start() on
a finished audioSource will not restart the sound again. If this is
desired simply call playSound with the same audioSource again.
@param audioSource the audio source to play
@param deleteWhenFinished If this is true then the audio source will
be deleted once the device manager has finished playing.
*/
void playSound (PositionableAudioSource* audioSource, bool deleteWhenFinished = false);
/** Plays the sound from an audio sample buffer.
This will output the sound contained in an audio sample buffer. If
deleteWhenFinished is true then the audio sample buffer will be
automatically deleted once the sound has finished playing.
If playOnAllOutputChannels is true, then if there are more output channels
than buffer channels, then the ones that are available will be re-used on
multiple outputs so that something is sent to all output channels. If it
is false, then the buffer will just be played on the first output channels.
*/
void playSound (AudioSampleBuffer* buffer,
bool deleteWhenFinished = false,
bool playOnAllOutputChannels = false);
//==============================================================================
/** Turns on level-measuring.
When enabled, the device manager will measure the peak input level
across all channels, and you can get this level by calling getCurrentInputLevel().
This is mainly intended for audio setup UI panels to use to create a mic
level display, so that the user can check that they've selected the right
device.
/** Turns on level-measuring for input channels.
@see getCurrentInputLevel()
*/
void enableInputLevelMeasurement (bool enableMeasurement) noexcept;
A simple filter is used to make the level decay smoothly, but this is
only intended for giving rough feedback, and not for any kind of accurate
measurement.
/** Turns on level-measuring for output channels.
@see getCurrentOutputLevel()
*/
void enableInputLevelMeasurement (bool enableMeasurement);
void enableOutputLevelMeasurement (bool enableMeasurement) noexcept;
/** Returns the current input level.
To use this, you must first enable it by calling enableInputLevelMeasurement().
See enableInputLevelMeasurement() for more info.
@see enableInputLevelMeasurement()
*/
double getCurrentInputLevel() const;
double getCurrentInputLevel() const noexcept;
/** Returns the current output level.
To use this, you must first enable it by calling enableOutputLevelMeasurement().
@see enableOutputLevelMeasurement()
*/
double getCurrentOutputLevel() const noexcept;
/** Returns the a lock that can be used to synchronise access to the audio callback.
Obviously while this is locked, you're blocking the audio thread from running, so
@@ -502,8 +452,6 @@ private:
BigInteger inputChannels, outputChannels;
ScopedPointer<XmlElement> lastExplicitSettings;
mutable bool listNeedsScanning;
Atomic<int> inputLevelMeasurementEnabledCount;
double inputLevel;
AudioSampleBuffer tempBuffer;
struct MidiCallbackInfo
@@ -520,8 +468,24 @@ private:
ScopedPointer<MidiOutput> defaultMidiOutput;
CriticalSection audioCallbackLock, midiCallbackLock;
ScopedPointer<AudioSampleBuffer> testSound;
int testSoundPosition;
double cpuUsageMs, timeToCpuScale;
struct LevelMeter
{
LevelMeter() noexcept;
void updateLevel (const float* const*, int numChannels, int numSamples) noexcept;
void setEnabled (bool) noexcept;
double getCurrentLevel() const noexcept;
Atomic<int> enabled;
double level;
};
LevelMeter inputLevelMeter, outputLevelMeter;
//==============================================================================
class CallbackHandler;
friend class CallbackHandler;


+ 7
- 32
libs/juce/source/modules/juce_audio_devices/juce_audio_devices.cpp View File

@@ -31,6 +31,8 @@
#error "Incorrect use of JUCE cpp file"
#endif
#include "AppConfig.h"
#define JUCE_CORE_INCLUDE_OBJC_HELPERS 1
#define JUCE_CORE_INCLUDE_COM_SMART_PTR 1
#define JUCE_CORE_INCLUDE_JNI_HELPERS 1
@@ -45,7 +47,6 @@
#define Component CarbonDummyCompName
#import <CoreAudio/AudioHardware.h>
#import <CoreMIDI/MIDIServices.h>
#import <DiscRecording/DiscRecording.h>
#import <AudioToolbox/AudioServices.h>
#undef Point
#undef Component
@@ -55,10 +56,14 @@
#import <AVFoundation/AVFoundation.h>
#import <CoreMIDI/MIDIServices.h>
#if TARGET_OS_SIMULATOR
#import <CoreMIDI/MIDINetworkSession.h>
#endif
//==============================================================================
#elif JUCE_WINDOWS
#if JUCE_WASAPI
#include <MMReg.h>
#include <mmreg.h>
#endif
#if JUCE_ASIO
@@ -84,15 +89,6 @@
#include <iasiodrv.h>
#endif
#if JUCE_USE_CDBURNER
/* You'll need the Platform SDK for these headers - if you don't have it and don't
need to use CD-burning, then you might just want to set the JUCE_USE_CDBURNER flag
to 0, to avoid these includes.
*/
#include <imapi.h>
#include <imapierror.h>
#endif
//==============================================================================
#elif JUCE_LINUX
#if JUCE_ALSA
@@ -139,7 +135,6 @@ namespace juce
#include "audio_io/juce_AudioIODeviceType.cpp"
#include "midi_io/juce_MidiMessageCollector.cpp"
#include "midi_io/juce_MidiOutput.cpp"
#include "audio_cd/juce_AudioCDReader.cpp"
#include "sources/juce_AudioSourcePlayer.cpp"
#include "sources/juce_AudioTransportSource.cpp"
#include "native/juce_MidiDataConcatenator.h"
@@ -149,14 +144,6 @@ namespace juce
#include "native/juce_mac_CoreAudio.cpp"
#include "native/juce_mac_CoreMidi.cpp"
#if JUCE_USE_CDREADER
#include "native/juce_mac_AudioCDReader.mm"
#endif
#if JUCE_USE_CDBURNER
#include "native/juce_mac_AudioCDBurner.mm"
#endif
//==============================================================================
#elif JUCE_IOS
#include "native/juce_ios_Audio.cpp"
@@ -179,14 +166,6 @@ namespace juce
#include "native/juce_win32_ASIO.cpp"
#endif
#if JUCE_USE_CDREADER
#include "native/juce_win32_AudioCDReader.cpp"
#endif
#if JUCE_USE_CDBURNER
#include "native/juce_win32_AudioCDBurner.cpp"
#endif
//==============================================================================
#elif JUCE_LINUX
#if JUCE_ALSA
@@ -199,10 +178,6 @@ namespace juce
#include "native/juce_linux_JackAudio.cpp"
#endif
#if JUCE_USE_CDREADER
#include "native/juce_linux_AudioCDReader.cpp"
#endif
//==============================================================================
#elif JUCE_ANDROID
#include "native/juce_android_Audio.cpp"


+ 30
- 20
libs/juce/source/modules/juce_audio_devices/juce_audio_devices.h View File

@@ -22,12 +22,39 @@
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.txt file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_audio_devices
vendor: juce
version: 4.3.0
name: JUCE audio and MIDI I/O device classes
description: Classes to play and record from audio and MIDI I/O devices
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_audio_basics, juce_events
OSXFrameworks: CoreAudio CoreMIDI AudioToolbox
iOSFrameworks: CoreAudio CoreMIDI AudioToolbox AVFoundation
linuxPackages: alsa
mingwLibs: winmm
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
#ifndef JUCE_AUDIO_DEVICES_H_INCLUDED
#define JUCE_AUDIO_DEVICES_H_INCLUDED
#include "../juce_events/juce_events.h"
#include "../juce_audio_basics/juce_audio_basics.h"
#include "../juce_audio_formats/juce_audio_formats.h"
#include <juce_events/juce_events.h>
#include <juce_audio_basics/juce_audio_basics.h>
//==============================================================================
/** Config: JUCE_ASIO
@@ -90,21 +117,6 @@
#endif
#endif
//==============================================================================
/** Config: JUCE_USE_CDREADER
Enables the AudioCDReader class (on supported platforms).
*/
#ifndef JUCE_USE_CDREADER
#define JUCE_USE_CDREADER 0
#endif
/** Config: JUCE_USE_CDBURNER
Enables the AudioCDBurner class (on supported platforms).
*/
#ifndef JUCE_USE_CDBURNER
#define JUCE_USE_CDBURNER 0
#endif
//==============================================================================
namespace juce
{
@@ -117,8 +129,6 @@ namespace juce
#include "midi_io/juce_MidiOutput.h"
#include "sources/juce_AudioSourcePlayer.h"
#include "sources/juce_AudioTransportSource.h"
#include "audio_cd/juce_AudioCDBurner.h"
#include "audio_cd/juce_AudioCDReader.h"
#include "audio_io/juce_AudioDeviceManager.h"
}


+ 10
- 3
libs/juce/source/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h View File

@@ -71,8 +71,7 @@ public:
// the normal message, handle it now..
if (*d >= 0xf8 && *d <= 0xfe)
{
const MidiMessage m (*d++, time);
callback.handleIncomingMidiMessage (input, m);
callback.handleIncomingMidiMessage (input, MidiMessage (*d++, time));
--numBytes;
}
else
@@ -83,7 +82,15 @@ public:
data[len++] = *d++;
--numBytes;
if (len >= MidiMessage::getMessageLengthFromFirstByte (data[0]))
const uint8 firstByte = data[0];
if (firstByte < 0x80 || firstByte == 0xf7)
{
len = 0;
break; // ignore this malformed MIDI message..
}
if (len >= MidiMessage::getMessageLengthFromFirstByte (firstByte))
break;
}
}


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/native/juce_android_Midi.cpp View File

@@ -153,7 +153,7 @@ JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024JuceM
class AndroidMidiDeviceManager
{
public:
AndroidMidiDeviceManager ()
AndroidMidiDeviceManager()
: deviceManager (android.activity.callObjectMethod (JuceAppActivity.getAndroidMidiDeviceManager))
{
}


+ 2
- 2
libs/juce/source/modules/juce_audio_devices/native/juce_android_OpenSL.cpp View File

@@ -332,7 +332,7 @@ private:
void run() override
{
setThreadToAudioPriority ();
setThreadToAudioPriority();
if (recorder != nullptr) recorder->start();
if (player != nullptr) player->start();
@@ -341,7 +341,7 @@ private:
processBuffers();
}
void setThreadToAudioPriority ()
void setThreadToAudioPriority()
{
// see android.os.Process.THREAD_PRIORITY_AUDIO
const int THREAD_PRIORITY_AUDIO = -16;


+ 48
- 5
libs/juce/source/modules/juce_audio_devices/native/juce_ios_Audio.cpp View File

@@ -287,7 +287,14 @@ public:
return r;
}
int getDefaultBufferSize() override { return 256; }
int getDefaultBufferSize() override
{
#if TARGET_IPHONE_SIMULATOR
return 512;
#else
return 256;
#endif
}
String open (const BigInteger& inputChannelsWanted,
const BigInteger& outputChannelsWanted,
@@ -431,6 +438,8 @@ public:
void handleStatusChange (bool enabled, const char* reason)
{
const ScopedLock myScopedLock (callbackLock);
JUCE_IOS_AUDIO_LOG ("handleStatusChange: enabled: " << (int) enabled << ", reason: " << reason);
isRunning = enabled;
@@ -447,6 +456,8 @@ public:
void handleRouteChange (const char* reason)
{
const ScopedLock myScopedLock (callbackLock);
JUCE_IOS_AUDIO_LOG ("handleRouteChange: reason: " << reason);
fixAudioRouteIfSetToReceiver();
@@ -518,9 +529,9 @@ private:
if (audioInputIsAvailable && numInputChannels > 0)
err = AudioUnitRender (audioUnit, flags, time, 1, numFrames, data);
const ScopedLock sl (callbackLock);
const ScopedTryLock stl (callbackLock);
if (callback != nullptr)
if (stl.isLocked() && callback != nullptr)
{
if ((int) numFrames > floatData.getNumSamples())
prepareFloatBuffers ((int) numFrames);
@@ -679,7 +690,23 @@ private:
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format));
UInt32 framesPerSlice;
UInt32 dataSize = sizeof (framesPerSlice);
AudioUnitInitialize (audioUnit);
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0, &actualBufferSize, sizeof (actualBufferSize));
if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0, &framesPerSlice, &dataSize) == noErr
&& dataSize == sizeof (framesPerSlice) && static_cast<int> (framesPerSlice) != actualBufferSize)
{
actualBufferSize = static_cast<int> (framesPerSlice);
prepareFloatBuffers (actualBufferSize);
}
return true;
}
@@ -755,8 +782,24 @@ void AudioSessionHolder::handleStatusChange (bool enabled, const char* reason) c
void AudioSessionHolder::handleRouteChange (const char* reason) const
{
for (auto device: activeDevices)
device->handleRouteChange (reason);
struct RouteChangeMessage : public CallbackMessage
{
RouteChangeMessage (Array<iOSAudioIODevice*> devs, const char* r)
: devices (devs), changeReason (r)
{
}
void messageCallback() override
{
for (auto device: devices)
device->handleRouteChange (changeReason);
}
Array<iOSAudioIODevice*> devices;
const char* changeReason;
};
(new RouteChangeMessage (activeDevices, reason))->post();
}
#undef JUCE_NSERROR_CHECK

+ 3
- 1
libs/juce/source/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp View File

@@ -183,7 +183,7 @@ public:
// open output ports
const StringArray outputChannels (getOutputChannelNames());
for (int i = 0; i < outputChannels.size (); ++i)
for (int i = 0; i < outputChannels.size(); ++i)
{
String outputName;
outputName << "out_" << ++totalNumberOfOutputChannels;
@@ -290,6 +290,8 @@ public:
}
}
updateActivePorts();
return lastError;
}


+ 93
- 77
libs/juce/source/modules/juce_audio_devices/native/juce_linux_Midi.cpp View File

@@ -45,37 +45,17 @@ class AlsaClient : public ReferenceCountedObject
public:
typedef ReferenceCountedObjectPtr<AlsaClient> Ptr;
AlsaClient (bool forInput)
: input (forInput), handle (nullptr)
static Ptr getInstance (bool forInput)
{
snd_seq_open (&handle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0);
}
~AlsaClient()
{
if (handle != nullptr)
{
snd_seq_close (handle);
handle = nullptr;
}
jassert (activeCallbacks.size() == 0);
AlsaClient*& instance = (forInput ? inInstance : outInstance);
if (instance == nullptr)
instance = new AlsaClient (forInput);
if (inputThread)
{
inputThread->stopThread (3000);
inputThread = nullptr;
}
return instance;
}
bool isInput() const noexcept { return input; }
void setName (const String& name)
{
snd_seq_set_client_name (handle, name.toUTF8());
}
void registerCallback (AlsaPortAndCallback* cb)
{
if (cb != nullptr)
@@ -103,7 +83,8 @@ public:
inputThread->signalThreadShouldExit();
}
void handleIncomingMidiMessage (const MidiMessage& message, int port);
void handleIncomingMidiMessage (snd_seq_event*, const MidiMessage&);
void handlePartialSysexMessage (snd_seq_event*, const uint8*, int, double);
snd_seq_t* get() const noexcept { return handle; }
@@ -114,12 +95,56 @@ private:
Array<AlsaPortAndCallback*> activeCallbacks;
CriticalSection callbackLock;
static AlsaClient* inInstance;
static AlsaClient* outInstance;
//==============================================================================
friend class ReferenceCountedObjectPtr<AlsaClient>;
friend struct ContainerDeletePolicy<AlsaClient>;
AlsaClient (bool forInput)
: input (forInput), handle (nullptr)
{
AlsaClient*& instance = (input ? inInstance : outInstance);
jassert (instance == nullptr);
instance = this;
snd_seq_open (&handle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0);
snd_seq_set_client_name (handle, forInput ? JUCE_ALSA_MIDI_INPUT_NAME
: JUCE_ALSA_MIDI_OUTPUT_NAME);
}
~AlsaClient()
{
AlsaClient*& instance = (input ? inInstance : outInstance);
jassert (instance != nullptr);
instance = nullptr;
if (handle != nullptr)
{
snd_seq_close (handle);
handle = nullptr;
}
jassert (activeCallbacks.size() == 0);
if (inputThread)
{
inputThread->stopThread (3000);
inputThread = nullptr;
}
}
//==============================================================================
class MidiInputThread : public Thread
{
public:
MidiInputThread (AlsaClient& c)
: Thread ("Juce MIDI Input"), client (c)
: Thread ("Juce MIDI Input"), client (c), concatenator (2048)
{
jassert (client.input && client.get() != nullptr);
}
@@ -159,13 +184,9 @@ private:
snd_midi_event_reset_decode (midiParser);
if (numBytes > 0)
{
const MidiMessage message ((const uint8*) buffer, (int) numBytes,
Time::getMillisecondCounter() * 0.001);
client.handleIncomingMidiMessage (message, inputEvent->dest.port);
}
concatenator.pushMidiData (buffer, (int) numBytes,
Time::getMillisecondCounter() * 0.001,
inputEvent, client);
snd_seq_free_event (inputEvent);
}
@@ -180,29 +201,14 @@ private:
private:
AlsaClient& client;
MidiDataConcatenator concatenator;
};
ScopedPointer<MidiInputThread> inputThread;
};
static AlsaClient::Ptr globalAlsaSequencerIn()
{
static AlsaClient::Ptr global (new AlsaClient (true));
return global;
}
static AlsaClient::Ptr globalAlsaSequencerOut()
{
static AlsaClient::Ptr global (new AlsaClient (false));
return global;
}
static AlsaClient::Ptr globalAlsaSequencer (bool input)
{
return input ? globalAlsaSequencerIn()
: globalAlsaSequencerOut();
}
AlsaClient* AlsaClient::inInstance = nullptr;
AlsaClient* AlsaClient::outInstance = nullptr;
//==============================================================================
// represents an input or output port of the supplied AlsaClient
@@ -282,6 +288,11 @@ public:
callback->handleIncomingMidiMessage (midiInput, message);
}
void handlePartialSysexMessage (const uint8* messageData, int numBytesSoFar, double timeStamp)
{
callback->handlePartialSysexMessage (midiInput, messageData, numBytesSoFar, timeStamp);
}
private:
AlsaPort port;
MidiInput* midiInput;
@@ -291,14 +302,22 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AlsaPortAndCallback)
};
void AlsaClient::handleIncomingMidiMessage (const MidiMessage& message, int port)
void AlsaClient::handleIncomingMidiMessage (snd_seq_event_t* event, const MidiMessage& message)
{
const ScopedLock sl (callbackLock);
if (AlsaPortAndCallback* const cb = activeCallbacks[port])
if (AlsaPortAndCallback* const cb = activeCallbacks[event->dest.port])
cb->handleIncomingMidiMessage (message);
}
void AlsaClient::handlePartialSysexMessage (snd_seq_event* event, const uint8* messageData, int numBytesSoFar, double timeStamp)
{
const ScopedLock sl (callbackLock);
if (AlsaPortAndCallback* const cb = activeCallbacks[event->dest.port])
cb->handlePartialSysexMessage (messageData, numBytesSoFar, timeStamp);
}
//==============================================================================
static AlsaPort iterateMidiClient (const AlsaClient::Ptr& seq,
snd_seq_client_info_t* clientInfo,
@@ -325,19 +344,23 @@ static AlsaPort iterateMidiClient (const AlsaClient::Ptr& seq,
&& (snd_seq_port_info_get_capability (portInfo) & (forInput ? SND_SEQ_PORT_CAP_READ
: SND_SEQ_PORT_CAP_WRITE)) != 0)
{
deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));
const String clientName = snd_seq_client_info_get_name (clientInfo);
const String portName = snd_seq_port_info_get_name(portInfo);
if (clientName == portName)
deviceNamesFound.add (clientName);
else
deviceNamesFound.add (clientName + ": " + portName);
if (deviceNamesFound.size() == deviceIndexToOpen + 1)
{
const int sourcePort = snd_seq_port_info_get_port (portInfo);
const int sourceClient = snd_seq_client_info_get_client (clientInfo);
if (sourcePort != -1)
{
const String name (forInput ? JUCE_ALSA_MIDI_INPUT_NAME
: JUCE_ALSA_MIDI_OUTPUT_NAME);
seq->setName (name);
port.createPort (seq, name, forInput);
const int sourceClient = snd_seq_client_info_get_client (clientInfo);
port.createPort (seq, portName, forInput);
port.connectWith (sourceClient, sourcePort);
}
}
@@ -355,7 +378,7 @@ static AlsaPort iterateMidiDevices (const bool forInput,
const int deviceIndexToOpen)
{
AlsaPort port;
const AlsaClient::Ptr client (globalAlsaSequencer (forInput));
const AlsaClient::Ptr client (AlsaClient::getInstance (forInput));
if (snd_seq_t* const seqHandle = client->get())
{
@@ -387,19 +410,6 @@ static AlsaPort iterateMidiDevices (const bool forInput,
return port;
}
AlsaPort createMidiDevice (const bool forInput, const String& deviceNameToOpen)
{
AlsaPort port;
AlsaClient::Ptr client (new AlsaClient (forInput));
if (client->get())
{
client->setName (deviceNameToOpen + (forInput ? " Input" : " Output"));
port.createPort (client, forInput ? "in" : "out", forInput);
}
return port;
}
//==============================================================================
class MidiOutputDevice
@@ -450,7 +460,7 @@ public:
numBytes -= numSent;
data += numSent;
snd_seq_ev_set_source (&event, 0);
snd_seq_ev_set_source (&event, port.portId);
snd_seq_ev_set_subs (&event);
snd_seq_ev_set_direct (&event);
@@ -507,8 +517,11 @@ MidiOutput* MidiOutput::openDevice (int deviceIndex)
MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{
MidiOutput* newDevice = nullptr;
AlsaPort port;
const AlsaClient::Ptr client (AlsaClient::getInstance (false));
AlsaPort port (createMidiDevice (false, deviceName));
port.createPort (client, deviceName, false);
if (port.isValid())
{
@@ -584,8 +597,11 @@ MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback)
MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
{
MidiInput* newDevice = nullptr;
AlsaPort port;
const AlsaClient::Ptr client (AlsaClient::getInstance (true));
AlsaPort port (createMidiDevice (true, deviceName));
port.createPort (client, deviceName, true);
if (port.isValid())
{


+ 43
- 18
libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp View File

@@ -149,6 +149,7 @@ bool JUCE_CALLTYPE SystemAudioVolume::setMuted (bool mute) { return SystemVol
struct CoreAudioClasses
{
class CoreAudioIODeviceType;
class CoreAudioIODevice;
//==============================================================================
@@ -691,7 +692,7 @@ public:
{ const ScopedLock sl (callbackLock); }
// wait until it's definately stopped calling back..
// wait until it's definitely stopped calling back..
for (int i = 40; --i >= 0;)
{
Thread::sleep (50);
@@ -847,6 +848,11 @@ private:
intern->deviceDetailsChanged();
break;
case kAudioObjectPropertyOwnedObjects:
intern->stop (false);
intern->owner.deviceType.triggerAsyncAudioDeviceListChange();
break;
case kAudioDevicePropertyBufferSizeRange:
case kAudioDevicePropertyVolumeScalar:
case kAudioDevicePropertyMute:
@@ -902,10 +908,12 @@ private:
class CoreAudioIODevice : public AudioIODevice
{
public:
CoreAudioIODevice (const String& deviceName,
CoreAudioIODevice (CoreAudioIODeviceType& dt,
const String& deviceName,
AudioDeviceID inputDeviceId, const int inputIndex_,
AudioDeviceID outputDeviceId, const int outputIndex_)
: AudioIODevice (deviceName, "CoreAudio"),
deviceType (dt),
inputIndex (inputIndex_),
outputIndex (outputIndex_),
isOpen_ (false),
@@ -1060,6 +1068,12 @@ public:
return lastError;
}
void audioDeviceListChanged()
{
deviceType.audioDeviceListChanged();
}
CoreAudioIODeviceType& deviceType;
int inputIndex, outputIndex;
private:
@@ -1745,7 +1759,8 @@ private:
//==============================================================================
class CoreAudioIODeviceType : public AudioIODeviceType
class CoreAudioIODeviceType : public AudioIODeviceType,
private AsyncUpdater
{
public:
CoreAudioIODeviceType()
@@ -1771,7 +1786,7 @@ public:
}
//==============================================================================
void scanForDevices()
void scanForDevices() override
{
hasScanned = true;
@@ -1827,7 +1842,7 @@ public:
outputDeviceNames.appendNumbersToDuplicates (false, true);
}
StringArray getDeviceNames (bool wantInputNames) const
StringArray getDeviceNames (bool wantInputNames) const override
{
jassert (hasScanned); // need to call scanForDevices() before doing this
@@ -1835,7 +1850,7 @@ public:
: outputDeviceNames;
}
int getDefaultDeviceIndex (bool forInput) const
int getDefaultDeviceIndex (bool forInput) const override
{
jassert (hasScanned); // need to call scanForDevices() before doing this
@@ -1870,7 +1885,7 @@ public:
return 0;
}
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
int getIndexOfDevice (AudioIODevice* device, bool asInput) const override
{
jassert (hasScanned); // need to call scanForDevices() before doing this
@@ -1894,10 +1909,10 @@ public:
return -1;
}
bool hasSeparateInputsAndOutputs() const { return true; }
bool hasSeparateInputsAndOutputs() const override { return true; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
const String& inputDeviceName) override
{
jassert (hasScanned); // need to call scanForDevices() before doing this
@@ -1913,15 +1928,15 @@ public:
String combinedName (outputDeviceName.isEmpty() ? inputDeviceName : outputDeviceName);
if (inputDeviceID == outputDeviceID)
return new CoreAudioIODevice (combinedName, inputDeviceID, inputIndex, outputDeviceID, outputIndex);
return new CoreAudioIODevice (*this, combinedName, inputDeviceID, inputIndex, outputDeviceID, outputIndex);
ScopedPointer<CoreAudioIODevice> in, out;
if (inputDeviceID != 0)
in = new CoreAudioIODevice (inputDeviceName, inputDeviceID, inputIndex, 0, -1);
in = new CoreAudioIODevice (*this, inputDeviceName, inputDeviceID, inputIndex, 0, -1);
if (outputDeviceID != 0)
out = new CoreAudioIODevice (outputDeviceName, 0, -1, outputDeviceID, outputIndex);
out = new CoreAudioIODevice (*this, outputDeviceName, 0, -1, outputDeviceID, outputIndex);
if (in == nullptr) return out.release();
if (out == nullptr) return in.release();
@@ -1932,6 +1947,17 @@ public:
return combo.release();
}
void audioDeviceListChanged()
{
scanForDevices();
callDeviceChangeListeners();
}
void triggerAsyncAudioDeviceListChange()
{
triggerAsyncUpdate();
}
//==============================================================================
private:
StringArray inputDeviceNames, outputDeviceNames;
@@ -1969,18 +1995,17 @@ private:
return total;
}
void audioDeviceListChanged()
{
scanForDevices();
callDeviceChangeListeners();
}
static OSStatus hardwareListenerProc (AudioDeviceID, UInt32, const AudioObjectPropertyAddress*, void* clientData)
{
static_cast<CoreAudioIODeviceType*> (clientData)->audioDeviceListChanged();
return noErr;
}
void handleAsyncUpdate() override
{
audioDeviceListChanged();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioIODeviceType)
};


+ 8
- 0
libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp View File

@@ -220,6 +220,14 @@ namespace CoreMidiHelpers
// correctly when called from the message thread!
jassert (MessageManager::getInstance()->isThisTheMessageThread());
#if TARGET_OS_SIMULATOR
// Enable MIDI for iOS simulator
MIDINetworkSession* session = [MIDINetworkSession defaultSession];
session.enabled = YES;
session.connectionPolicy = MIDINetworkConnectionPolicy_Anyone;
#endif
CoreMidiHelpers::ScopedCFString name;
name.cfString = getGlobalMidiClientName().toCFString();
CHECK_ERROR (MIDIClientCreate (name.cfString, &globalSystemChangeCallback, nullptr, &globalMidiClient));


+ 4
- 3
libs/juce/source/modules/juce_audio_devices/native/juce_win32_ASIO.cpp View File

@@ -365,17 +365,18 @@ public:
void updateSampleRates()
{
// find a list of sample rates..
const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 };
Array<double> newRates;
if (asioObject != nullptr)
{
const int possibleSampleRates[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 };
for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index)
if (asioObject->canSampleRate ((double) possibleSampleRates[index]) == 0)
newRates.add ((double) possibleSampleRates[index]);
}
if (newRates.size() == 0)
if (newRates.isEmpty())
{
double cr = getSampleRate();
JUCE_ASIO_LOG ("No sample rates supported - current rate: " + String ((int) cr));
@@ -1571,7 +1572,7 @@ private:
DWORD dsize = sizeof (pathName);
if (RegQueryValueEx (pathKey, 0, 0, &dtype, (LPBYTE) pathName, &dsize) == ERROR_SUCCESS)
// In older code, this used to check for the existance of the file, but there are situations
// In older code, this used to check for the existence of the file, but there are situations
// where our process doesn't have access to it, but where the driver still loads ok..
ok = (pathName[0] != 0);


+ 7
- 0
libs/juce/source/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp View File

@@ -96,11 +96,18 @@ bool check (HRESULT hr)
}
#if JUCE_MINGW
#define JUCE_COMCLASS(name, guid) \
struct name; \
template<> struct UUIDGetter<name> { static CLSID get() { return uuidFromString (guid); } }; \
struct name
#ifdef __uuidof
#undef __uuidof
#endif
#define __uuidof(cls) UUIDGetter<cls>::get()
struct PROPERTYKEY
{
GUID fmtid;


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/sources/juce_AudioTransportSource.h View File

@@ -60,7 +60,7 @@ public:
The source passed in will not be deleted by this object, so must be managed by
the caller.
@param newSource the new input source to use. This may be zero
@param newSource the new input source to use. This may be a nullptr
@param readAheadBufferSize a size of buffer to use for reading ahead. If this
is zero, no reading ahead will be done; if it's
greater than zero, a BufferingAudioSource will be used


+ 8
- 5
libs/juce/source/modules/juce_audio_formats/codecs/flac/alloc.h View File

@@ -41,11 +41,14 @@
* before #including this file, otherwise SIZE_MAX might not be defined
*/
#include <limits.h> /* for SIZE_MAX */
#if HAVE_STDINT_H
#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */
#endif
#include <stdlib.h> /* for size_t, malloc(), etc */
// JUCE: removed as JUCE already includes standard headers and including
// these in FlacNamespace will cause problems
//#include <limits.h> /* for SIZE_MAX */
//#if HAVE_STDINT_H
//#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */
//#endif
//#include <stdlib.h> /* for size_t, malloc(), etc */
#include "compat.h"
#ifndef SIZE_MAX


+ 4
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/assert.h View File

@@ -35,7 +35,10 @@
/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */
#ifdef DEBUG
#include <assert.h>
// JUCE: removed as JUCE already includes standard headers and including
// these in FlacNamespace will cause problems
//#include <assert.h>
#define FLAC__ASSERT(x) assert(x)
#define FLAC__ASSERT_DECLARATION(x) x
#else


+ 4
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/callback.h View File

@@ -34,7 +34,10 @@
#define FLAC__CALLBACK_H
#include "ordinals.h"
#include <stdlib.h> /* for size_t */
// JUCE: removed as JUCE already includes this and including stdlib
// in FlacNamespace will cause problems
//#include <stdlib.h>
/** \file include/FLAC/callback.h
*


+ 0
- 33
libs/juce/source/modules/juce_audio_formats/codecs/flac/compat.h View File

@@ -39,15 +39,7 @@
#ifndef FLAC__SHARE__COMPAT_H
#define FLAC__SHARE__COMPAT_H
#if defined _WIN32 && !defined __CYGWIN__
/* where MSVC puts unlink() */
# include <io.h>
#else
# include <unistd.h>
#endif
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#include <sys/types.h> /* for off_t */
#define FLAC__off_t __int64 /* use this instead of off_t to fix the 2 GB limit */
#if !defined __MINGW32__
#define fseeko _fseeki64
@@ -62,11 +54,6 @@
#define FLAC__off_t off_t
#endif
#if HAVE_INTTYPES_H
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#if defined(_MSC_VER)
#define strtoll _strtoi64
#define strtoull _strtoui64
@@ -95,33 +82,13 @@
#define FLAC__STRNCASECMP strncasecmp
#endif
#if defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ || defined __EMX__
#include <io.h> /* for _setmode(), chmod() */
#include <fcntl.h> /* for _O_BINARY */
#else
#include <unistd.h> /* for chown(), unlink() */
#endif
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#if defined __BORLANDC__
#include <utime.h> /* for utime() */
#else
#include <sys/utime.h> /* for utime() */
#endif
#else
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
#include <utime.h> /* for utime() */
#endif
#if defined _MSC_VER
# if _MSC_VER >= 1600
/* Visual Studio 2010 has decent C99 support */
# include <stdint.h>
# define PRIu64 "llu"
# define PRId64 "lld"
# define PRIx64 "llx"
# else
# include <limits.h>
# ifndef UINT32_MAX
# define UINT32_MAX _UI32_MAX
# endif


+ 3
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/endswap.h View File

@@ -51,7 +51,9 @@ static inline unsigned short __builtin_bswap16(unsigned short a)
#elif defined HAVE_BYTESWAP_H /* Linux */
#include <byteswap.h>
// JUCE: removed as JUCE already includes standard headers and including
// these in FlacNamespace will cause problems
//#include <byteswap.h>
#define ENDSWAP_16(x) (bswap_16 (x))
#define ENDSWAP_32(x) (bswap_32 (x))


+ 0
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/metadata.h View File

@@ -33,7 +33,6 @@
#ifndef FLAC__METADATA_H
#define FLAC__METADATA_H
#include <sys/types.h> /* for off_t */
#include "export.h"
#include "callback.h"
#include "format.h"


+ 0
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_decoder.h View File

@@ -33,7 +33,6 @@
#ifndef FLAC__STREAM_DECODER_H
#define FLAC__STREAM_DECODER_H
#include <stdio.h> /* for FILE */
#include "export.h"
#include "format.h"


+ 0
- 1
libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_encoder.h View File

@@ -33,7 +33,6 @@
#ifndef FLAC__STREAM_ENCODER_H
#define FLAC__STREAM_ENCODER_H
#include <stdio.h> /* for FILE */
#include "export.h"
#include "format.h"
#include "stream_decoder.h"


+ 0
- 5
libs/juce/source/modules/juce_audio_formats/codecs/flac/win_utf8_io.h View File

@@ -38,11 +38,6 @@
extern "C" {
#endif
#include <stdio.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <windows.h>
int get_utf8_argv(int *argc, char ***argv);
int printf_utf8(const char *format, ...);


+ 6
- 8
libs/juce/source/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp View File

@@ -668,13 +668,14 @@ public:
//==============================================================================
bool write (const int** data, int numSamples) override
{
jassert (numSamples >= 0);
jassert (data != nullptr && *data != nullptr); // the input must contain at least one channel!
if (writeFailed)
return false;
const size_t bytes = (size_t) numSamples * numChannels * bitsPerSample / 8;
tempBlock.ensureSize ((size_t) bytes, false);
const size_t bytes = numChannels * (size_t) numSamples * bitsPerSample / 8;
tempBlock.ensureSize (bytes, false);
switch (bitsPerSample)
{
@@ -695,13 +696,10 @@ public:
writeFailed = true;
return false;
}
else
{
bytesWritten += bytes;
lengthInSamples += (uint64) numSamples;
return true;
}
bytesWritten += bytes;
lengthInSamples += (uint64) numSamples;
return true;
}
private:


+ 67
- 2
libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp View File

@@ -24,6 +24,66 @@
#if JUCE_USE_FLAC
}
#if defined _WIN32 && !defined __CYGWIN__
#include <io.h>
#else
#include <unistd.h>
#endif
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#include <sys/types.h> /* for off_t */
#endif
#if HAVE_INTTYPES_H
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#if defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ || defined __EMX__
#include <io.h> /* for _setmode(), chmod() */
#include <fcntl.h> /* for _O_BINARY */
#else
#include <unistd.h> /* for chown(), unlink() */
#endif
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
#if defined __BORLANDC__
#include <utime.h> /* for utime() */
#else
#include <sys/utime.h> /* for utime() */
#endif
#else
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
#include <utime.h> /* for utime() */
#endif
#if defined _MSC_VER
#if _MSC_VER >= 1600
#include <stdint.h>
#else
#include <limits.h>
#endif
#endif
#ifdef _WIN32
#include <stdio.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <windows.h>
#endif
#ifdef DEBUG
#include <assert.h>
#endif
#include <stdlib.h>
#include <stdio.h>
namespace juce
{
namespace FlacNamespace
{
#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
@@ -35,6 +95,8 @@ namespace FlacNamespace
#if JUCE_MSVC
#pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312 4505 4365 4005 4334 181 111)
#else
#define HAVE_LROUND 1
#endif
#if JUCE_MAC
@@ -66,6 +128,7 @@ namespace FlacNamespace
#define __STDC_LIMIT_MACROS 1
#define flac_max jmax
#define flac_min jmin
#undef DEBUG // (some flac code dumps debug trace if the app defines this macro)
#include "flac/all.h"
#include "flac/libFLAC/bitmath.c"
#include "flac/libFLAC/bitreader.c"
@@ -324,7 +387,8 @@ class FlacWriter : public AudioFormatWriter
{
public:
FlacWriter (OutputStream* const out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
: AudioFormatWriter (out, flacFormatName, rate, numChans, bits)
: AudioFormatWriter (out, flacFormatName, rate, numChans, bits),
streamStartPos (output != nullptr ? jmax (output->getPosition(), 0ll) : 0ll)
{
using namespace FlacNamespace;
encoder = FLAC__stream_encoder_new();
@@ -432,7 +496,7 @@ public:
packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);
memcpy (buffer + 18, info.md5sum, 16);
const bool seekOk = output->setPosition (4);
const bool seekOk = output->setPosition (streamStartPos + 4);
ignoreUnused (seekOk);
// if this fails, you've given it an output stream that can't seek! It needs
@@ -482,6 +546,7 @@ public:
private:
FlacNamespace::FLAC__StreamEncoder* encoder;
int64 streamStartPos;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacWriter)
};


+ 1
- 1
libs/juce/source/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp View File

@@ -222,7 +222,7 @@ public:
DisposeMovie (movie);
#if JUCE_MAC
ExitMoviesOnThread ();
ExitMoviesOnThread();
#endif
}
}


+ 7
- 21
libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp View File

@@ -646,24 +646,6 @@ namespace WavFileHelpers
return true;
}
static String getStringFromWindows1252Codepage (const uint8* data, size_t num)
{
HeapBlock<juce_wchar> unicode (num + 1);
for (size_t i = 0; i < num; ++i)
unicode[i] = CharacterFunctions::getUnicodeCharFromWindows1252Codepage (data[i]);
unicode[num] = 0;
return CharPointer_UTF32 (unicode);
}
static String getStringFromData (const MemoryBlock& mb)
{
return CharPointer_UTF8::isValidString ((const char*) mb.getData(), (int) mb.getSize())
? mb.toString()
: getStringFromWindows1252Codepage ((const uint8*) mb.getData(), mb.getSize());
}
static void addToMetadata (StringPairArray& values, InputStream& input, int64 chunkEnd)
{
while (input.getPosition() < chunkEnd)
@@ -674,7 +656,10 @@ namespace WavFileHelpers
if (infoLength > 0)
{
infoLength = jlimit ((int64) 0, infoLength, (int64) input.readInt());
infoLength = jmin (infoLength, (int64) input.readInt());
if (infoLength <= 0)
return;
for (int i = 0; i < numElementsInArray (types); ++i)
{
@@ -682,7 +667,8 @@ namespace WavFileHelpers
{
MemoryBlock mb;
input.readIntoMemoryBlock (mb, (ssize_t) infoLength);
values.set (types[i], getStringFromData (mb));
values.set (types[i], String::createStringFromData ((const char*) mb.getData(),
(int) mb.getSize()));
break;
}
}
@@ -1276,7 +1262,7 @@ public:
if (writeFailed)
return false;
const size_t bytes = numChannels * (unsigned int) numSamples * bitsPerSample / 8;
const size_t bytes = numChannels * (size_t) numSamples * bitsPerSample / 8;
tempBlock.ensureSize (bytes, false);
switch (bitsPerSample)


+ 2
- 0
libs/juce/source/modules/juce_audio_formats/juce_audio_formats.cpp View File

@@ -31,6 +31,8 @@
#error "Incorrect use of JUCE cpp file"
#endif
#include "AppConfig.h"
#define JUCE_CORE_INCLUDE_COM_SMART_PTR 1
#define JUCE_CORE_INCLUDE_JNI_HELPERS 1
#define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1


+ 27
- 1
libs/juce/source/modules/juce_audio_formats/juce_audio_formats.h View File

@@ -22,10 +22,36 @@
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.txt file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_audio_formats
vendor: juce
version: 4.3.0
name: JUCE audio file format codecs
description: Classes for reading and writing various audio file formats.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_audio_basics
OSXFrameworks: CoreAudio CoreMIDI QuartzCore AudioToolbox
iOSFrameworks: AudioToolbox QuartzCore
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
#ifndef JUCE_AUDIO_FORMATS_H_INCLUDED
#define JUCE_AUDIO_FORMATS_H_INCLUDED
#include "../juce_audio_basics/juce_audio_basics.h"
#include <juce_audio_basics/juce_audio_basics.h>
//==============================================================================
/** Config: JUCE_USE_FLAC


+ 41
- 0
libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Modifier_Injector.h View File

@@ -0,0 +1,41 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2016 - 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_AAX_MODIFIER_INJECTOR_H_INCLUDED
#define JUCE_AAX_MODIFIER_INJECTOR_H_INCLUDED
struct ModifierKeyProvider
{
virtual ~ModifierKeyProvider() {}
virtual int getWin32Modifiers() const = 0;
};
struct ModifierKeyReceiver
{
virtual ~ModifierKeyReceiver() {}
virtual void setModifierKeyProvider (ModifierKeyProvider*) = 0;
virtual void removeModifierKeyProvider() = 0;
};
#endif

+ 555
- 335
libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
File diff suppressed because it is too large
View File


+ 5
- 5
libs/juce/source/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUCarbonViewControl.cpp View File

@@ -82,19 +82,19 @@ void AUCarbonViewControl::Bind()
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) {
EventTypeSpec events[] = {
EventTypeSpec controlEvents[] = {
{ kEventClassControl, kEventControlHit },
{ kEventClassControl, kEventControlClick },
{ kEventClassControl, kEventControlTrack }
};
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(controlEvents), controlEvents);
}
if (mType == kTypeText) {
EventTypeSpec events[] = {
EventTypeSpec controlFocusEvents[] = {
{ kEventClassControl, kEventControlSetFocusPart }
};
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(controlFocusEvents), controlFocusEvents);
ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback;
// this will fail for a static text field
SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc);
@@ -591,7 +591,7 @@ AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
#endif
#ifndef __LP64__
if (result != noErr) { // if the PresentPreset property is not implemented, fall back to the CurrentPreset property
OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
kAudioUnitProperty_CurrentPreset,
kAudioUnitScope_Global,
0,


+ 500
- 764
libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
File diff suppressed because it is too large
View File


+ 1426
- 0
libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
File diff suppressed because it is too large
View File


+ 140
- 0
libs/juce/source/modules/juce_audio_plugin_client/AUResources.r View File

@@ -0,0 +1,140 @@
/*
File: AUResources.r
Abstract: AUResources.r
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUResources.r
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* sample macro definitions -- all of these symbols must be defined
#define RES_ID kHALOutputResID
#define COMP_TYPE kAudioUnitComponentType
#define COMP_SUBTYPE kAudioUnitOutputSubType
#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
#define VERSION 0x00010000
#define NAME "AudioHALOutput"
#define DESCRIPTION "Audio hardware output AudioUnit"
#define ENTRY_POINT "AUHALEntry"
*/
#define UseExtendedThingResource 1

#include <CoreServices/CoreServices.r>

// this is a define used to indicate that a component has no static data that would mean
// that no more than one instance could be open at a time - never been true for AUs
#ifndef cmpThreadSafeOnMac
#define cmpThreadSafeOnMac 0x10000000
#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'STR ' (RES_ID, purgeable) {
NAME
};

resource 'STR ' (RES_ID + 1, purgeable) {
DESCRIPTION
};

resource 'dlle' (RES_ID) {
ENTRY_POINT
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'thng' (RES_ID, NAME) {
COMP_TYPE,
COMP_SUBTYPE,
COMP_MANUF,
0, 0, 0, 0, // no 68K
'STR ', RES_ID,
'STR ', RES_ID + 1,
0, 0, /* icon */
VERSION,
componentHasMultiplePlatforms | componentDoAutoVersion,
0,
{
#if defined(ppc_YES)
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPCNativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(ppc64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPC64NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(i386_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformIA32NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(x86_64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, 8
#define NeedLeadingComma 1
#endif
}
};

#undef RES_ID
#undef COMP_TYPE
#undef COMP_SUBTYPE
#undef COMP_MANUF
#undef VERSION
#undef NAME
#undef DESCRIPTION
#undef ENTRY_POINT
#undef NeedLeadingComma

+ 14
- 0
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode1.cpp View File

@@ -49,6 +49,16 @@
#undef UNICODE
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wcomment"
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wextra-tokens"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wdeprecated"
#endif
#include <CEffectGroup.cpp>
#include <CEffectGroupMIDI.cpp>
#include <CEffectMIDIUtils.cpp>
@@ -58,4 +68,8 @@
#include <CEffectTypeRTAS.cpp>
#include <ChunkDataParser.cpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif

+ 13
- 0
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode2.cpp View File

@@ -29,6 +29,15 @@
#include "juce_RTAS_DigiCode_Header.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcomment"
#pragma clang diagnostic ignored "-Wextra-tokens"
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wdeprecated"
#endif
/*
This file is used to include and build the required digidesign CPP files without your project
needing to reference the files directly. Because these files will be found via your include path,
@@ -47,4 +56,8 @@
#include <CEffectProcessMIDI.cpp>
#include <PlugInUtils.cpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif

+ 13
- 3
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode3.cpp View File

@@ -27,8 +27,16 @@
#if JucePlugin_Build_RTAS
#include "../utility/juce_IncludeSystemHeaders.h"
#include "juce_RTAS_DigiCode_Header.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wextra-tokens"
#pragma clang diagnostic ignored "-Wreorder"
#endif
/*
This file is used to include and build the required digidesign CPP files without your project
needing to reference the files directly. Because these files will be found via your include path,
@@ -47,18 +55,20 @@
#if WINDOWS_VERSION
#undef _UNICODE
#undef UNICODE
#define DllMain DllMainRTAS
#include <DLLMain.cpp>
#undef DllMain
#include <DefaultSwap.cpp>
#else
#include <PlugInInitialize.cpp>
#include <Dispatcher.cpp>
#endif
#else
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#else
#if _MSC_VER
short __stdcall NewPlugIn (void*) { return 0; }


+ 2
- 1
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode_Header.h View File

@@ -43,10 +43,11 @@
#define WINDOWS_VERSION 1
#define PLUGIN_SDK_BUILD 1
#define PLUGIN_SDK_DIRECTMIDI 1
#define _STDINT_H 1
// the Digidesign projects all use a struct alignment of 2..
#pragma pack (2)
#pragma warning (disable: 4267 4996 4311 4312 4103 4121 4100 4127 4189 4245 4389 4512 4701)
#pragma warning (disable: 4267 4996 4311 4312 4103 4121 4100 4127 4189 4245 4389 4512 4701 4703)
#include <ForcedInclude.h>


+ 35
- 12
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp View File

@@ -39,6 +39,13 @@
#include <Mac2Win.H>
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Widiomatic-parentheses"
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wcomment"
#endif
/* Note about include paths
------------------------
@@ -86,10 +93,14 @@
#include <FicProcessTokens.h>
#include <ExternalVersionDefines.h>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
//==============================================================================
#ifdef _MSC_VER
#pragma pack (push, 8)
#pragma warning (disable: 4263 4264)
#pragma warning (disable: 4263 4264 4250)
#endif
#include "../utility/juce_IncludeModuleHeaders.h"
@@ -269,7 +280,7 @@ public:
}
}
void DrawContents (Rect*)
void DrawContents (Rect*) override
{
#if JUCE_WINDOWS
if (wrapper != nullptr)
@@ -280,7 +291,7 @@ public:
#endif
}
void DrawBackground (Rect*) {}
void DrawBackground (Rect*) override {}
//==============================================================================
private:
@@ -466,8 +477,19 @@ public:
AddControl (new CPluginControl_OnOff ('bypa', "Master Bypass\nMastrByp\nMByp\nByp", false, true));
DefineMasterBypassControlIndex (bypassControlIndex);
for (int i = 0; i < juceFilter->getNumParameters(); ++i)
AddControl (new JucePluginControl (*juceFilter, i));
const int numParameters = juceFilter->getNumParameters();
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
const bool usingManagedParameters = false;
#else
const bool usingManagedParameters = (juceFilter->getParameters().size() == numParameters);
#endif
for (int i = 0; i < numParameters; ++i)
{
OSType rtasParamID = static_cast<OSType> (usingManagedParameters ? juceFilter->getParameterID (i).hashCode() : i);
AddControl (new JucePluginControl (*juceFilter, i, rtasParamID));
}
// we need to do this midi log-in to get timecode, regardless of whether
// the plugin actually uses midi...
@@ -476,14 +498,14 @@ public:
#if JucePlugin_WantsMidiInput
if (CEffectType* const type = dynamic_cast<CEffectType*> (this->GetProcessType()))
{
char nodeName [64];
char nodeName[80] = { 0 };
type->GetProcessTypeName (63, nodeName);
p2cstrcpy (nodeName, reinterpret_cast<unsigned char*> (nodeName));
nodeName[nodeName[0] + 1] = 0;
midiBufferNode = new CEffectMIDIOtherBufferedNode (&mMIDIWorld,
8192,
eLocalNode,
nodeName,
nodeName + 1,
midiBuffer);
midiBufferNode->Initialize (0xffff, true);
@@ -803,14 +825,14 @@ private:
{
public:
//==============================================================================
JucePluginControl (AudioProcessor& p, const int i)
: processor (p), index (i)
JucePluginControl (AudioProcessor& p, const int i, OSType rtasParamID)
: processor (p), index (i), paramID (rtasParamID)
{
CPluginControl::SetValue (GetDefaultValue());
}
//==============================================================================
OSType GetID() const { return index + 1; }
OSType GetID() const { return paramID; }
long GetDefaultValue() const { return floatToLong (processor.getParameterDefaultValue (index)); }
void SetDefaultValue (long) {}
long GetNumSteps() const { return processor.getParameterNumSteps (index); }
@@ -855,6 +877,7 @@ private:
//==============================================================================
AudioProcessor& processor;
const int index;
const OSType paramID;
JUCE_DECLARE_NON_COPYABLE (JucePluginControl)
};
@@ -933,7 +956,7 @@ private:
#if JUCE_WINDOWS
Process::setCurrentModuleInstanceHandle (gThisModule);
#endif
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_RTAS;
initialiseJuce_GUI();
return new JucePlugInProcess();


+ 110
- 0
libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp View File

@@ -0,0 +1,110 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "../../juce_core/system/juce_TargetPlatform.h"
#include "../utility/juce_CheckSettingMacros.h"
#include "../utility/juce_IncludeSystemHeaders.h"
#include "../utility/juce_IncludeModuleHeaders.h"
#include "../utility/juce_FakeMouseMoveGenerator.h"
#include "../utility/juce_WindowsHooks.h"
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_gui_extra/juce_gui_extra.h>
#include <juce_audio_utils/juce_audio_utils.h>
// You can set this flag in your build if you need to specify a different
// standalone JUCEApplication class for your app to use. If you don't
// set it then by default we'll just create a simple one as below.
#if ! JUCE_USE_CUSTOM_AU3_STANDALONE_APP
extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
namespace juce
{
#include "juce_StandaloneFilterWindow.h"
}
//==============================================================================
class StandaloneFilterApp : public JUCEApplication
{
public:
StandaloneFilterApp()
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Standalone;
PropertiesFile::Options options;
options.applicationName = getApplicationName();
options.filenameSuffix = ".settings";
options.osxLibrarySubFolder = "Application Support";
#if JUCE_LINUX
options.folderName = "~/.config";
#else
options.folderName = "";
#endif
appProperties.setStorageParameters (options);
}
const String getApplicationName() override { return JucePlugin_Name; }
const String getApplicationVersion() override { return JucePlugin_VersionString; }
bool moreThanOneInstanceAllowed() override { return true; }
void anotherInstanceStarted (const String&) override {}
virtual StandaloneFilterWindow* createWindow()
{
return new StandaloneFilterWindow (getApplicationName(), Colours::white, appProperties.getUserSettings(), false);
}
//==============================================================================
void initialise (const String&) override
{
mainWindow = createWindow();
#if JUCE_IOS || JUCE_ANDROID
Desktop::getInstance().setKioskModeComponent (mainWindow, false);
#endif
mainWindow->setVisible (true);
}
void shutdown() override
{
mainWindow = nullptr;
appProperties.saveIfNeeded();
}
//==============================================================================
void systemRequestedQuit() override
{
quit();
}
protected:
ApplicationProperties appProperties;
ScopedPointer<StandaloneFilterWindow> mainWindow;
};
#endif

+ 68
- 14
libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h View File

@@ -25,8 +25,6 @@
#ifndef JUCE_STANDALONEFILTERWINDOW_H_INCLUDED
#define JUCE_STANDALONEFILTERWINDOW_H_INCLUDED
extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
//==============================================================================
/**
An object that creates and plays a standalone instance of an AudioProcessor.
@@ -36,6 +34,9 @@ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
computer's audio/MIDI devices using AudioDeviceManager and AudioProcessorPlayer.
*/
class StandalonePluginHolder
#if JUCE_IOS || JUCE_ANDROID
: private Timer
#endif
{
public:
/** Creates an instance of the default plugin.
@@ -63,10 +64,18 @@ public:
setupAudioDevices (preferredDefaultDeviceName, preferredSetupOptions);
reloadPluginState();
startPlaying();
#if JUCE_IOS || JUCE_ANDROID
startTimer (500);
#endif
}
virtual ~StandalonePluginHolder()
{
#if JUCE_IOS || JUCE_ANDROID
stopTimer();
#endif
deletePlugin();
shutDownAudioDevices();
}
@@ -74,21 +83,17 @@ public:
//==============================================================================
virtual void createPlugin()
{
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
processor = ::createPluginFilterOfType (AudioProcessor::wrapperType_Standalone);
#else
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Standalone);
processor = createPluginFilter();
jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object!
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);
#endif
jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object!
// try to disable sidechain and aux buses
const int numInBuses = processor->busArrangement.inputBuses.size();
const int numOutBuses = processor->busArrangement.inputBuses.size();
for (int busIdx = 1; busIdx < numInBuses; ++busIdx)
processor->setPreferredBusArrangement (true, busIdx, AudioChannelSet::disabled());
for (int busIdx = 1; busIdx < numOutBuses; ++busIdx)
processor->setPreferredBusArrangement (false, busIdx, AudioChannelSet::disabled());
processor->disableNonMainBuses();
processor->setRateAndBufferSizeDetails(44100, 512);
}
@@ -115,7 +120,7 @@ public:
if (settings != nullptr)
f = File (settings->getValue ("lastStateFile"));
if (f == File::nonexistent)
if (f == File())
f = File::getSpecialLocation (File::userDocumentsDirectory);
return f;
@@ -130,6 +135,7 @@ public:
/** Pops up a dialog letting the user save the processor's state to a file. */
void askUserToSaveState (const String& fileSuffix = String())
{
#if JUCE_MODAL_LOOPS_PERMITTED
FileChooser fc (TRANS("Save current state"), getLastFile(), getFilePatterns (fileSuffix));
if (fc.browseForFileToSave (true))
@@ -144,11 +150,15 @@ public:
TRANS("Error whilst saving"),
TRANS("Couldn't write to the specified file!"));
}
#else
ignoreUnused (fileSuffix);
#endif
}
/** Pops up a dialog letting the user re-load the processor's state from a file. */
void askUserToLoadState (const String& fileSuffix = String())
{
#if JUCE_MODAL_LOOPS_PERMITTED
FileChooser fc (TRANS("Load a saved state"), getLastFile(), getFilePatterns (fileSuffix));
if (fc.browseForFileToOpen())
@@ -164,6 +174,9 @@ public:
TRANS("Error whilst loading"),
TRANS("Couldn't read from the specified file!"));
}
#else
ignoreUnused (fileSuffix);
#endif
}
//==============================================================================
@@ -254,6 +267,10 @@ public:
AudioDeviceManager deviceManager;
AudioProcessorPlayer player;
#if JUCE_IOS || JUCE_ANDROID
StringArray lastMidiDevices;
#endif
private:
void setupAudioDevices (const String& preferredDefaultDeviceName,
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions)
@@ -272,6 +289,43 @@ private:
deviceManager.removeAudioCallback (&player);
}
#if JUCE_IOS || JUCE_ANDROID
void timerCallback() override
{
StringArray midiInputDevices = MidiInput::getDevices();
if (midiInputDevices != lastMidiDevices)
{
{
const int n = lastMidiDevices.size();
for (int i = 0; i < n; ++i)
{
const String& oldDevice = lastMidiDevices[i];
if (! midiInputDevices.contains (oldDevice))
{
deviceManager.setMidiInputEnabled (oldDevice, false);
deviceManager.removeMidiInputCallback (oldDevice, &player);
}
}
}
{
const int n = midiInputDevices.size();
for (int i = 0; i < n; ++i)
{
const String& newDevice = midiInputDevices[i];
if (! lastMidiDevices.contains (newDevice))
{
deviceManager.addMidiInputCallback (newDevice, &player);
deviceManager.setMidiInputEnabled (newDevice, true);
}
}
}
}
}
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandalonePluginHolder)
};


+ 1061
- 846
libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
File diff suppressed because it is too large
View File


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

@@ -23,6 +23,9 @@
*/
#include "../../juce_core/system/juce_TargetPlatform.h"
#if JUCE_MAC
#include "../utility/juce_CheckSettingMacros.h"
#if JucePlugin_Build_VST || JucePlugin_Build_VST3
@@ -39,7 +42,7 @@ namespace juce
{
#if ! JUCE_64BIT
void updateEditorCompBoundsVST (Component*);
JUCE_API void updateEditorCompBoundsVST (Component*);
void updateEditorCompBoundsVST (Component* comp)
{
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
@@ -66,12 +69,12 @@ static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, vo
static bool shouldManuallyCloseHostWindow()
{
return getHostType().isCubase7orLater() || getHostType().isRenoise();
return getHostType().isCubase7orLater() || getHostType().isRenoise() || ((SystemStats::getOperatingSystemType() & 0xff) >= 12);
}
#endif
//==============================================================================
void initialiseMacVST();
JUCE_API void initialiseMacVST();
void initialiseMacVST()
{
#if ! JUCE_64BIT
@@ -79,7 +82,7 @@ void initialiseMacVST()
#endif
}
void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView);
JUCE_API void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView);
void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView)
{
JUCE_AUTORELEASEPOOL
@@ -184,7 +187,7 @@ void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView,
}
}
void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView);
JUCE_API void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView);
void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView)
{
JUCE_AUTORELEASEPOOL
@@ -242,7 +245,7 @@ void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSVi
}
}
void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
JUCE_API 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
@@ -280,7 +283,7 @@ void setNativeHostWindowSizeVST (void* window, Component* component, int newWidt
}
}
void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView);
JUCE_API void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView);
void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)
{
ignoreUnused (window, comp, isNSView);
@@ -291,7 +294,7 @@ void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)
#endif
}
bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView);
JUCE_API bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView);
bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)
{
#if ! JUCE_64BIT
@@ -311,3 +314,4 @@ bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)
} // (juce namespace)
#endif
#endif

+ 399
- 155
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -27,11 +27,19 @@
//==============================================================================
#if JucePlugin_Build_VST3 && (__APPLE_CPP__ || __APPLE_CC__ || _WIN32 || _WIN64)
#if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)
#undef JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
#define JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY 1
#endif
#include "../../juce_audio_processors/format_types/juce_VST3Headers.h"
#undef JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
#include "../utility/juce_CheckSettingMacros.h"
#include "../utility/juce_IncludeModuleHeaders.h"
#include "../utility/juce_WindowsHooks.h"
#include "../utility/juce_PluginBusUtilities.h"
#include "../utility/juce_FakeMouseMoveGenerator.h"
#include "../../juce_audio_processors/format_types/juce_VST3Common.h"
#ifndef JUCE_VST3_CAN_REPLACE_VST2
@@ -68,9 +76,9 @@ using namespace Steinberg;
extern void updateEditorCompBoundsVST (Component*);
#endif
extern void* attachComponentToWindowRefVST (Component*, void* parentWindowOrView, bool isNSView);
extern void detachComponentFromWindowRefVST (Component*, void* nsWindow, bool isNSView);
extern void setNativeHostWindowSizeVST (void* window, Component*, int newWidth, int newHeight, bool isNSView);
extern JUCE_API void* attachComponentToWindowRefVST (Component*, void* parentWindowOrView, bool isNSView);
extern JUCE_API void detachComponentFromWindowRefVST (Component*, void* nsWindow, bool isNSView);
extern JUCE_API void setNativeHostWindowSizeVST (void* window, Component*, int newWidth, int newHeight, bool isNSView);
#endif
//==============================================================================
@@ -100,6 +108,8 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceAudioProcessor)
};
class JuceVST3Component;
//==============================================================================
class JuceVST3EditController : public Vst::EditController,
public Vst::IMidiMapping,
@@ -107,6 +117,9 @@ class JuceVST3EditController : public Vst::EditController,
{
public:
JuceVST3EditController (Vst::IHostApplication* host)
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
: usingManagedParameter (false)
#endif
{
if (host != nullptr)
host->queryInterface (FUnknown::iid, (void**) &hostContext);
@@ -178,11 +191,18 @@ public:
}
//==============================================================================
enum InternalParameters
{
paramPreset = 0x70727374, // 'prst'
paramBypass = 0x62797073, // 'byps'
paramMidiControllerOffset = 0x6d636d00 // 'mdm*'
};
struct Param : public Vst::Parameter
{
Param (AudioProcessor& p, int index) : owner (p), paramIndex (index)
Param (AudioProcessor& p, int index, Vst::ParamID paramID) : owner (p), paramIndex (index)
{
info.id = (Vst::ParamID) index;
info.id = paramID;
toString128 (info.title, p.getParameterName (index));
toString128 (info.shortTitle, p.getParameterName (index, 8));
toString128 (info.units, p.getParameterLabel (index));
@@ -204,6 +224,8 @@ public:
if (v != valueNormalized)
{
valueNormalized = v;
owner.setParameter (paramIndex, static_cast<float> (v));
changed();
return true;
}
@@ -249,9 +271,9 @@ public:
//==============================================================================
struct BypassParam : public Vst::Parameter
{
BypassParam (AudioProcessor& p, int index) : owner (p), paramIndex (index)
BypassParam (AudioProcessor& p, Vst::ParamID vstParamID) : owner (p)
{
info.id = (Vst::ParamID) index;
info.id = vstParamID;
toString128 (info.title, "Bypass");
toString128 (info.shortTitle, "Bypass");
toString128 (info.units, "");
@@ -327,11 +349,83 @@ public:
private:
AudioProcessor& owner;
int paramIndex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BypassParam)
};
//==============================================================================
struct ProgramChangeParameter : public Vst::Parameter
{
ProgramChangeParameter (AudioProcessor& p) : owner (p)
{
jassert (owner.getNumPrograms() > 1);
info.id = paramPreset;
toString128 (info.title, "Program");
toString128 (info.shortTitle, "Program");
toString128 (info.units, "");
info.stepCount = owner.getNumPrograms() - 1;
info.defaultNormalizedValue = static_cast<Vst::ParamValue> (owner.getCurrentProgram()) / static_cast<Vst::ParamValue> (info.stepCount);
info.unitId = Vst::kRootUnitId;
info.flags = Vst::ParameterInfo::kIsProgramChange | Vst::ParameterInfo::kCanAutomate;
}
virtual ~ProgramChangeParameter() {}
bool setNormalized (Vst::ParamValue v) override
{
Vst::ParamValue program = v * info.stepCount;
if (! isPositiveAndBelow ((int) program, owner.getNumPrograms()))
return false;
if (valueNormalized != v)
{
valueNormalized = v;
changed();
return true;
}
return false;
}
void toString (Vst::ParamValue value, Vst::String128 result) const override
{
Vst::ParamValue program = value * info.stepCount;
toString128 (result, owner.getProgramName ((int) program));
}
bool fromString (const Vst::TChar* text, Vst::ParamValue& outValueNormalized) const override
{
const String paramValueString (getStringFromVstTChars (text));
const int n = owner.getNumPrograms();
for (int i = 0; i < n; ++i)
{
if (paramValueString == owner.getProgramName (i))
{
outValueNormalized = static_cast<Vst::ParamValue> (i) / info.stepCount;
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 * info.stepCount; }
Vst::ParamValue toNormalized (Vst::ParamValue v) const override { return v / info.stepCount; }
private:
AudioProcessor& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgramChangeParameter)
};
//==============================================================================
tresult PLUGIN_API setComponentState (IBStream* stream) override
{
@@ -341,11 +435,18 @@ public:
const int numParameters = pluginInstance->getNumParameters();
for (int i = 0; i < numParameters; ++i)
setParamNormalized ((Vst::ParamID) i, (double) pluginInstance->getParameter (i));
setParamNormalized (getVSTParamIDForIndex (i), (double) pluginInstance->getParameter (i));
setParamNormalized ((Vst::ParamID) numParameters, audioProcessor->isBypassed ? 1.0f : 0.0f);
setParamNormalized (bypassParamID, audioProcessor->isBypassed ? 1.0f : 0.0f);
const int numPrograms = pluginInstance->getNumPrograms();
if (numPrograms > 1)
setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram()) / static_cast<Vst::ParamValue> (numPrograms - 1));
}
if (Vst::IComponentHandler* handler = getComponentHandler())
handler->restartComponent (Vst::kParamValuesChanged);
return Vst::EditController::setComponentState (stream);
}
@@ -380,15 +481,15 @@ public:
tresult PLUGIN_API getMidiControllerAssignment (Steinberg::int32 /*busIndex*/, Steinberg::int16 channel,
Vst::CtrlNumber midiControllerNumber, Vst::ParamID& resultID) override
{
resultID = (Vst::ParamID) midiControllerToParameter[channel][midiControllerNumber];
resultID = 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)
bool getMidiControllerForParameter (Vst::ParamID index, int& channel, int& ctrlNumber)
{
const int mappedIndex = index - parameterToMidiControllerOffset;
const int mappedIndex = static_cast<int> (index - parameterToMidiControllerOffset);
if (isPositiveAndBelow (mappedIndex, numElementsInArray (parameterToMidiController)))
{
@@ -405,6 +506,13 @@ public:
return false;
}
inline bool isMidiControllerParamID (Vst::ParamID paramID) const noexcept
{
return (paramID >= parameterToMidiControllerOffset
&& isPositiveAndBelow (paramID - parameterToMidiControllerOffset,
static_cast<Vst::ParamID> (numElementsInArray (parameterToMidiController))));
}
//==============================================================================
IPlugView* PLUGIN_API createView (const char* name) override
{
@@ -421,19 +529,26 @@ public:
}
//==============================================================================
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override { beginEdit ((Vst::ParamID) index); }
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override { beginEdit (getVSTParamIDForIndex (index)); }
void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) override
{
// NB: Cubase has problems if performEdit is called without setParamNormalized
EditController::setParamNormalized ((Vst::ParamID) index, (double) newValue);
performEdit ((Vst::ParamID) index, (double) newValue);
EditController::setParamNormalized (getVSTParamIDForIndex (index), (double) newValue);
performEdit (getVSTParamIDForIndex (index), (double) newValue);
}
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override { endEdit ((Vst::ParamID) index); }
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override { endEdit (getVSTParamIDForIndex (index)); }
void audioProcessorChanged (AudioProcessor*) override
{
if (AudioProcessor* pluginInstance = getPluginInstance())
{
if (pluginInstance->getNumPrograms() > 1)
EditController::setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (pluginInstance->getNumPrograms() - 1));
}
if (componentHandler != nullptr)
componentHandler->restartComponent (Vst::kLatencyChanged | Vst::kParamValuesChanged);
}
@@ -448,6 +563,9 @@ public:
}
private:
friend class JuceVST3Component;
//==============================================================================
ComSmartPtr<JuceAudioProcessor> audioProcessor;
ScopedJuceInitialiser_GUI libraryInitialiser;
@@ -460,9 +578,17 @@ private:
};
enum { numMIDIChannels = 16 };
int parameterToMidiControllerOffset;
Vst::ParamID parameterToMidiControllerOffset;
MidiController parameterToMidiController[numMIDIChannels * Vst::kCountCtrlNumber];
int midiControllerToParameter[numMIDIChannels][Vst::kCountCtrlNumber];
Vst::ParamID midiControllerToParameter[numMIDIChannels][Vst::kCountCtrlNumber];
//==============================================================================
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
bool usingManagedParameter;
Array<Vst::ParamID> vstParamIDs;
#endif
Vst::ParamID bypassParamID;
//==============================================================================
void setupParameters()
@@ -471,40 +597,61 @@ private:
{
pluginInstance->addListener (this);
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
const bool usingManagedParameter = false;
#endif
if (parameters.getParameterCount() <= 0)
{
const int numParameters = pluginInstance->getNumParameters();
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
usingManagedParameter = (pluginInstance->getParameters().size() == numParameters);
#endif
for (int i = 0; i < numParameters; ++i)
parameters.addParameter (new Param (*pluginInstance, i));
{
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
const Vst::ParamID vstParamID = static_cast<Vst::ParamID> (i);
#else
const Vst::ParamID vstParamID = generateVSTParamIDForIndex (pluginInstance, i);
vstParamIDs.add (vstParamID);
#endif
parameters.addParameter (new Param (*pluginInstance, i, vstParamID));
}
bypassParamID = static_cast<Vst::ParamID> (usingManagedParameter ? paramBypass : numParameters);
parameters.addParameter (new BypassParam (*pluginInstance, bypassParamID));
parameters.addParameter (new BypassParam (*pluginInstance, numParameters));
if (pluginInstance->getNumPrograms() > 1)
parameters.addParameter (new ProgramChangeParameter (*pluginInstance));
}
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
// (NB: the +1 is to account for the bypass parameter)
initialiseMidiControllerMappings (pluginInstance->getNumParameters() + 1);
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (usingManagedParameter ? paramMidiControllerOffset
: parameters.getParameterCount());
initialiseMidiControllerMappings();
#endif
audioProcessorChanged (pluginInstance);
}
}
void initialiseMidiControllerMappings (const int numVstParameters)
void initialiseMidiControllerMappings()
{
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;
midiControllerToParameter[c][i] = static_cast<Vst::ParamID> (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));
static_cast<Vst::ParamID> (p) + parameterToMidiControllerOffset, 0, 0, 0,
Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
}
}
}
@@ -522,6 +669,34 @@ private:
}
}
//==============================================================================
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept { return static_cast<Vst::ParamID> (paramIndex); }
#else
static Vst::ParamID generateVSTParamIDForIndex (AudioProcessor* const pluginFilter, int paramIndex)
{
jassert (pluginFilter != nullptr);
const int n = pluginFilter->getNumParameters();
const bool managedParameter = (pluginFilter->getParameters().size() == n);
if (isPositiveAndBelow (paramIndex, n))
{
const String& juceParamID = pluginFilter->getParameterID (paramIndex);
return managedParameter ? static_cast<Vst::ParamID> (juceParamID.hashCode())
: static_cast<Vst::ParamID> (juceParamID.getIntValue());
}
return static_cast<Vst::ParamID> (-1);
}
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
{
return usingManagedParameter ? vstParamIDs.getReference (paramIndex)
: static_cast<Vst::ParamID> (paramIndex);
}
#endif
//==============================================================================
class JuceVST3Editor : public Vst::EditorView
{
@@ -625,14 +800,30 @@ private:
return kResultFalse;
}
tresult PLUGIN_API canResize() override { return kResultTrue; }
tresult PLUGIN_API canResize() override
{
if (component != nullptr)
if (AudioProcessorEditor* editor = component->pluginEditor)
return editor->isResizable() ? kResultTrue : kResultFalse;
return kResultFalse;
}
tresult PLUGIN_API checkSizeConstraint (ViewRect* rectToCheck) override
{
if (rectToCheck != nullptr && component != nullptr)
{
rectToCheck->right = rectToCheck->left + component->getWidth();
rectToCheck->bottom = rectToCheck->top + component->getHeight();
// checkSizeConstraint
Rectangle<int> juceRect = Rectangle<int>::leftTopRightBottom (rectToCheck->left, rectToCheck->top,
rectToCheck->right, rectToCheck->bottom);
if (AudioProcessorEditor* editor = component->pluginEditor)
if (ComponentBoundsConstrainer* constrainer = editor->getConstrainer())
juceRect.setSize (jlimit (constrainer->getMinimumWidth(), constrainer->getMaximumWidth(), juceRect.getWidth()),
jlimit (constrainer->getMinimumHeight(), constrainer->getMaximumHeight(), juceRect.getHeight()));
rectToCheck->right = rectToCheck->left + juceRect.getWidth();
rectToCheck->bottom = rectToCheck->top + juceRect.getHeight();
return kResultTrue;
}
@@ -646,8 +837,8 @@ private:
{
public:
ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin)
: owner (editor),
pluginEditor (plugin.createEditorIfNeeded())
: pluginEditor (plugin.createEditorIfNeeded()),
owner (editor)
{
setOpaque (true);
setBroughtToFrontOnMouseClick (true);
@@ -661,6 +852,8 @@ private:
setBounds (pluginEditor->getLocalBounds());
resizeHostWindow();
}
ignoreUnused (fakeMouseGenerator);
}
~ContentWrapperComponent()
@@ -718,9 +911,11 @@ private:
}
}
ScopedPointer<AudioProcessorEditor> pluginEditor;
private:
JuceVST3Editor& owner;
ScopedPointer<AudioProcessorEditor> pluginEditor;
FakeMouseMoveGenerator fakeMouseGenerator;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
};
@@ -771,8 +966,7 @@ public:
pluginInstance (createPluginFilterOfType (AudioProcessor::wrapperType_VST3)),
host (h),
isMidiInputBusEnabled (false),
isMidiOutputBusEnabled (false),
busUtils (*pluginInstance, false)
isMidiOutputBusEnabled (false)
{
#if JucePlugin_WantsMidiInput
isMidiInputBusEnabled = true;
@@ -782,10 +976,19 @@ public:
isMidiOutputBusEnabled = true;
#endif
busUtils.findAllCompatibleLayouts();
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
const int numConfigs = sizeof (configs) / sizeof (short[2]);
jassert (numConfigs > 0 && (configs[0][0] > 0 || configs[0][1] > 0));
pluginInstance->setPlayConfigDetails (configs[0][0], configs[0][1], 44100.0, 1024);
#endif
copyEnabledBuses (lastEnabledBusStates.inputBuses, pluginInstance->busArrangement.inputBuses, Vst::kInput);
copyEnabledBuses (lastEnabledBusStates.outputBuses, pluginInstance->busArrangement.outputBuses, Vst::kOutput);
// VST-3 requires your default layout to be non-discrete!
// For example, your default layout must be mono, stereo, quadrophonic
// and not AudioChannelSet::discreteChannels (2) etc.
jassert (checkBusFormatsAreNotDiscrete());
comPluginInstance = new JuceAudioProcessor (pluginInstance);
@@ -796,7 +999,11 @@ public:
processSetup.sampleRate = 44100.0;
processSetup.symbolicSampleSize = Vst::kSample32;
vstBypassParameterId = pluginInstance->getNumParameters();
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
vstBypassParameterId = static_cast<Vst::ParamID> (pluginInstance->getNumParameters());
#else
cacheParameterIDs();
#endif
pluginInstance->setPlayHead (this);
}
@@ -1249,7 +1456,7 @@ public:
{
if (listIndex == 0)
{
info.id = paramPreset;
info.id = JuceVST3EditController::paramPreset;
info.programCount = (Steinberg::int32) getPluginInstance().getNumPrograms();
toString128 (info.name, TRANS("Factory Presets"));
@@ -1264,7 +1471,7 @@ public:
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override
{
if (listId == paramPreset
if (listId == JuceVST3EditController::paramPreset
&& isPositiveAndBelow ((int) programIndex, getPluginInstance().getNumPrograms()))
{
toString128 (name, getPluginInstance().getProgramName ((int) programIndex));
@@ -1335,8 +1542,7 @@ public:
Steinberg::int32 PLUGIN_API getBusCount (Vst::MediaType type, Vst::BusDirection dir) override
{
if (type == Vst::kAudio)
return (dir == Vst::kInput ? pluginInstance->busArrangement.inputBuses
: pluginInstance->busArrangement.outputBuses).size();
return pluginInstance->getBusCount (dir == Vst::kInput);
if (type == Vst::kEvent)
{
@@ -1350,33 +1556,25 @@ public:
return 0;
}
static const AudioProcessor::AudioProcessorBus* getAudioBus (AudioProcessor::AudioBusArrangement& busArrangement,
Vst::BusDirection dir, Steinberg::int32 index) noexcept
{
const Array<AudioProcessor::AudioProcessorBus>& buses = dir == Vst::kInput ? busArrangement.inputBuses
: busArrangement.outputBuses;
return isPositiveAndBelow (index, static_cast<Steinberg::int32> (buses.size())) ? &buses.getReference (index) : nullptr;
}
const AudioProcessor::AudioProcessorBus* getAudioBus (Vst::BusDirection dir, Steinberg::int32 index) const noexcept
{
return getAudioBus (pluginInstance->busArrangement, dir, index);
}
tresult PLUGIN_API getBusInfo (Vst::MediaType type, Vst::BusDirection dir,
Steinberg::int32 index, Vst::BusInfo& info) override
{
if (type == Vst::kAudio)
{
if (const AudioProcessor::AudioProcessorBus* bus = getAudioBus (lastEnabledBusStates, dir, index))
if (const AudioProcessor::Bus* bus = pluginInstance->getBus (dir == Vst::kInput, index))
{
info.mediaType = Vst::kAudio;
info.direction = dir;
info.channelCount = bus->channels.size();
toString128 (info.name, bus->name);
info.busType = index == 0 ? Vst::kMain : Vst::kAux;
info.flags = busUtils.getSupportedBusLayouts (dir == Vst::kInput, index).isEnabledByDefault ? Vst::BusInfo::kDefaultActive : 0;
info.channelCount = bus->getLastEnabledLayout().size();
toString128 (info.name, bus->getName());
#if JucePlugin_IsSynth
info.busType = (dir == Vst::kInput && index > 0 ? Vst::kAux : Vst::kMain);
#else
info.busType = (index == 0 ? Vst::kMain : Vst::kAux);
#endif
info.flags = (bus->isEnabledByDefault()) ? Vst::BusInfo::kDefaultActive : 0;
return kResultTrue;
}
}
@@ -1386,11 +1584,11 @@ public:
info.flags = Vst::BusInfo::kDefaultActive;
#if JucePlugin_WantsMidiInput
if (dir == Vst::kInput)
if (dir == Vst::kInput && index == 0)
{
info.mediaType = Vst::kEvent;
info.direction = dir;
info.channelCount = 0;
info.channelCount = 16;
toString128 (info.name, TRANS("MIDI Input"));
info.busType = Vst::kMain;
return kResultTrue;
@@ -1398,11 +1596,11 @@ public:
#endif
#if JucePlugin_ProducesMidiOutput
if (dir == Vst::kOutput)
if (dir == Vst::kOutput && index == 0)
{
info.mediaType = Vst::kEvent;
info.direction = dir;
info.channelCount = 0;
info.channelCount = 16;
toString128 (info.name, TRANS("MIDI Output"));
info.busType = Vst::kMain;
return kResultTrue;
@@ -1430,73 +1628,59 @@ public:
}
if (type == Vst::kAudio)
{
if (const AudioProcessor::AudioProcessorBus* bus = getAudioBus (dir, index))
{
if (state == (bus->channels.size() > 0))
return kResultTrue;
AudioChannelSet newChannels;
if (state)
if (const AudioProcessor::AudioProcessorBus* lastBusState = getAudioBus (lastEnabledBusStates, dir, index))
newChannels = lastBusState->channels;
if (pluginInstance->setPreferredBusArrangement (dir == Vst::kInput, index, newChannels))
return kResultTrue;
}
}
if (AudioProcessor::Bus* bus = pluginInstance->getBus (dir == Vst::kInput, index))
return (bus->enable (state != 0) ? kResultTrue : kResultFalse);
return kResultFalse;
}
void copyEnabledBuses (Array<AudioProcessor::AudioProcessorBus>& copies,
const Array<AudioProcessor::AudioProcessorBus>& source,
Vst::BusDirection dir)
bool checkBusFormatsAreNotDiscrete()
{
for (int i = 0; i < source.size(); ++i)
{
AudioProcessor::AudioProcessorBus bus = source.getReference (i);
const int numInputBuses = pluginInstance->getBusCount (true);
const int numOutputBuses = pluginInstance->getBusCount (false);
if (bus.channels.size() == 0 && i < copies.size())
bus = AudioProcessor::AudioProcessorBus (bus.name, copies.getReference (i).channels);
for (int i = 0; i < numInputBuses; ++i)
if (pluginInstance->getChannelLayoutOfBus (true, i).isDiscreteLayout())
return false;
if (bus.channels.size() == 0)
bus = AudioProcessor::AudioProcessorBus (bus.name, busUtils.getDefaultLayoutForBus (dir == Vst::kInput, i));
for (int i = 0; i < numOutputBuses; ++i)
if (pluginInstance->getChannelLayoutOfBus (false, i).isDiscreteLayout())
return false;
copies.set (i, bus);
}
return true;
}
tresult PLUGIN_API setBusArrangements (Vst::SpeakerArrangement* inputs, Steinberg::int32 numIns,
Vst::SpeakerArrangement* outputs, Steinberg::int32 numOuts) override
{
PluginBusUtilities::ScopedBusRestorer restorer (busUtils);
const int numInputBuses = pluginInstance->getBusCount (true);
const int numOutputBuses = pluginInstance->getBusCount (false);
for (int i = 0; i < numIns; ++i)
if (! pluginInstance->setPreferredBusArrangement (true, i, getChannelSetForSpeakerArrangement (inputs[i])))
return kInvalidArgument;
if (numIns > numInputBuses || numOuts > numOutputBuses)
return false;
for (int i = 0; i < numOuts; ++i)
if (! pluginInstance->setPreferredBusArrangement (false, i, getChannelSetForSpeakerArrangement (outputs[i])))
return kInvalidArgument;
AudioProcessor::BusesLayout requested = pluginInstance->getBusesLayout();
restorer.release();
for (int i = 0; i < numIns; ++i)
requested.getChannelSet (true, i) = getChannelSetForSpeakerArrangement (inputs[i]);
preparePlugin (getPluginInstance().getSampleRate(),
getPluginInstance().getBlockSize());
for (int i = 0; i < numOuts; ++i)
requested.getChannelSet (false, i) = getChannelSetForSpeakerArrangement (outputs[i]);
copyEnabledBuses (lastEnabledBusStates.inputBuses, pluginInstance->busArrangement.inputBuses, Vst::kInput);
copyEnabledBuses (lastEnabledBusStates.outputBuses, pluginInstance->busArrangement.outputBuses, Vst::kOutput);
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
if (! AudioProcessor::containsLayout (requested, configs))
return kResultFalse;
#endif
return kResultTrue;
return (pluginInstance->setBusesLayoutWithoutEnabling (requested) ? kResultTrue : kResultFalse);
}
tresult PLUGIN_API getBusArrangement (Vst::BusDirection dir, Steinberg::int32 index, Vst::SpeakerArrangement& arr) override
{
if (const AudioProcessor::AudioProcessorBus* bus = getAudioBus (lastEnabledBusStates, dir, index))
if (AudioProcessor::Bus* bus = pluginInstance->getBus (dir == Vst::kInput, index))
{
arr = getSpeakerArrangement (bus->channels);
arr = getVst3SpeakerArrangement (bus->getLastEnabledLayout());
return kResultTrue;
}
@@ -1569,22 +1753,35 @@ public:
if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue)
{
const int id = (int) paramQueue->getParameterId();
const Vst::ParamID vstParamID = paramQueue->getParameterId();
if (isPositiveAndBelow (id, pluginInstance->getNumParameters()))
pluginInstance->setParameter (id, static_cast<float> (value));
else if (id == vstBypassParameterId)
if (vstParamID == vstBypassParameterId)
setBypassed (static_cast<float> (value) != 0.0f);
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
else
addParameterChangeToMidiBuffer (offsetSamples, id, value);
else if (juceVST3EditController->isMidiControllerParamID (vstParamID))
addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);
#endif
else if (vstParamID == JuceVST3EditController::paramPreset)
{
const int numPrograms = pluginInstance->getNumPrograms();
const int programValue = roundToInt (value * numPrograms);
if (numPrograms > 1 && isPositiveAndBelow (programValue, numPrograms)
&& programValue != pluginInstance->getCurrentProgram())
pluginInstance->setCurrentProgram (programValue);
}
else
{
const int index = getJuceIndexForVSTParamID (vstParamID);
if (isPositiveAndBelow (index, pluginInstance->getNumParameters()))
pluginInstance->setParameter (index, static_cast<float> (value));
}
}
}
}
}
void addParameterChangeToMidiBuffer (const Steinberg::int32 offsetSamples, const int id, const double value)
void addParameterChangeToMidiBuffer (const Steinberg::int32 offsetSamples, const Vst::ParamID id, const double value)
{
// If the parameter is mapped to a MIDI CC message then insert it into the midiBuffer.
int channel, ctrlNumber;
@@ -1625,10 +1822,6 @@ public:
MidiEventList::toMidiBuffer (midiBuffer, *data.inputEvents);
#endif
#if JUCE_DEBUG && ! JucePlugin_ProducesMidiOutput
const int numMidiEventsComingIn = midiBuffer.getNumEvents();
#endif
if (getHostType().isWavelab())
{
const int numInputChans = (data.inputs != nullptr && data.inputs[0].channelBuffers32 != nullptr) ? (int) data.inputs[0].numChannels : 0;
@@ -1646,22 +1839,6 @@ public:
#if JucePlugin_ProducesMidiOutput
if (data.outputEvents != nullptr)
MidiEventList::toEventList (*data.outputEvents, midiBuffer);
#elif JUCE_DEBUG
/* This assertion is caused when you've added some events to the
midiMessages array in your processBlock() method, which usually means
that you're trying to send them somewhere. But in this case they're
getting thrown away.
If your plugin does want to send MIDI messages, you'll need to set
the JucePlugin_ProducesMidiOutput macro to 1 in your
JucePluginCharacteristics.h file.
If you don't want to produce any MIDI output, then you should clear the
midiMessages array at the end of your processBlock() method, to
indicate that you don't want any of the events to be passed through
to the output.
*/
jassert (midiBuffer.getNumEvents() <= numMidiEventsComingIn);
#endif
return kResultTrue;
@@ -1687,13 +1864,16 @@ private:
Array<float*> channelListFloat;
Array<double*> channelListDouble;
AudioProcessor::AudioBusArrangement lastEnabledBusStates;
bool isMidiInputBusEnabled, isMidiOutputBusEnabled;
PluginBusUtilities busUtils;
ScopedJuceInitialiser_GUI libraryInitialiser;
int vstBypassParameterId;
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
bool usingManagedParameter;
Array<Vst::ParamID> vstParamIDs;
HashMap<int32, int> paramMap;
#endif
Vst::ParamID vstBypassParameterId;
static const char* kJucePrivateDataIdentifier;
@@ -1715,7 +1895,8 @@ private:
const int numChans = jmin ((int) data.inputs[bus].numChannels, plugInInputChannels - totalInputChans);
for (int i = 0; i < numChans; ++i)
channelList.set (totalInputChans++, busChannels[i]);
if (busChannels[i] != nullptr)
channelList.set (totalInputChans++, busChannels[i]);
}
}
}
@@ -1732,10 +1913,16 @@ private:
for (int i = 0; i < numChans; ++i)
{
if (totalOutputChans >= totalInputChans)
channelList.set (totalOutputChans, busChannels[i]);
++totalOutputChans;
if (busChannels[i] != nullptr)
{
if (totalOutputChans >= totalInputChans)
{
FloatVectorOperations::clear (busChannels[i], data.numSamples);
channelList.set (totalOutputChans, busChannels[i]);
}
++totalOutputChans;
}
}
}
}
@@ -1754,6 +1941,10 @@ private:
if (data.inputParameterChanges != nullptr)
processParameterChanges (*data.inputParameterChanges);
#if JUCE_DEBUG && ! JucePlugin_ProducesMidiOutput
const int numMidiEventsComingIn = midiBuffer.getNumEvents();
#endif
if (pluginInstance->isSuspended())
{
buffer.clear();
@@ -1769,6 +1960,24 @@ private:
pluginInstance->processBlock (buffer, midiBuffer);
}
}
#if JUCE_DEBUG && (! JucePlugin_ProducesMidiOutput)
/* This assertion is caused when you've added some events to the
midiMessages array in your processBlock() method, which usually means
that you're trying to send them somewhere. But in this case they're
getting thrown away.
If your plugin does want to send MIDI messages, you'll need to set
the JucePlugin_ProducesMidiOutput macro to 1 in your
JucePluginCharacteristics.h file.
If you don't want to produce any MIDI output, then you should clear the
midiMessages array at the end of your processBlock() method, to
indicate that you don't want any of the events to be passed through
to the output.
*/
jassert (midiBuffer.getNumEvents() <= numMidiEventsComingIn);
#endif
}
if (data.outputs != nullptr)
@@ -1783,9 +1992,9 @@ private:
for (int i = 0; i < numChans; ++i)
{
if (outChanIndex < totalInputChans)
if (outChanIndex < totalInputChans && busChannels[i] != nullptr)
FloatVectorOperations::copy (busChannels[i], buffer.getReadPointer (outChanIndex), (int) data.numSamples);
else if (outChanIndex >= totalOutputChans)
else if (outChanIndex >= totalOutputChans && busChannels[i] != nullptr)
FloatVectorOperations::clear (busChannels[i], (int) data.numSamples);
++outChanIndex;
@@ -1809,12 +2018,6 @@ private:
return AudioBusPointerHelper<FloatType>::impl (data);
}
//==============================================================================
enum InternalParameters
{
paramPreset = 'prst'
};
void preparePlugin (double sampleRate, int bufferSize)
{
AudioProcessor& p = getPluginInstance();
@@ -1823,6 +2026,45 @@ private:
p.prepareToPlay (sampleRate, bufferSize);
}
//==============================================================================
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept { return static_cast<Vst::ParamID> (paramIndex); }
inline int getJuceIndexForVSTParamID (Vst::ParamID paramID) const noexcept { return static_cast<int> (paramID); }
#else
void cacheParameterIDs()
{
const int numParameters = pluginInstance->getNumParameters();
usingManagedParameter = (pluginInstance->getParameters().size() == numParameters);
vstBypassParameterId = static_cast<Vst::ParamID> (usingManagedParameter ? JuceVST3EditController::paramBypass : numParameters);
for (int i = 0; i < numParameters; ++i)
{
const Vst::ParamID paramID = JuceVST3EditController::generateVSTParamIDForIndex (pluginInstance, i);
// Consider yourself very unlucky if you hit this assertion. The hash code of your
// parameter ids are not unique.
jassert (! vstParamIDs.contains (static_cast<Vst::ParamID> (paramID)));
vstParamIDs.add (paramID);
paramMap.set (static_cast<int32> (paramID), i);
}
}
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
{
return usingManagedParameter ? vstParamIDs.getReference (paramIndex)
: static_cast<Vst::ParamID> (paramIndex);
}
inline int getJuceIndexForVSTParamID (Vst::ParamID paramID) const noexcept
{
return usingManagedParameter ? paramMap[static_cast<int32> (paramID)]
: static_cast<int> (paramID);
}
#endif
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component)
};
@@ -2211,6 +2453,8 @@ private:
// The VST3 plugin entry point.
JUCE_EXPORTED_FUNCTION IPluginFactory* PLUGIN_API GetPluginFactory()
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST3;
#if JUCE_WINDOWS
// Cunning trick to force this function to be exported. Life's too short to
// faff around creating .def files for this kind of thing.


+ 38
- 3
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client.h View File

@@ -22,12 +22,47 @@
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.txt file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_audio_plugin_client
vendor: juce
version: 4.3.0
name: JUCE audio plugin wrapper classes
description: Classes for building VST, VST3, AudioUnit, AAX and RTAS plugins.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_gui_basics, juce_audio_basics, juce_audio_processors
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
#ifndef JUCE_AUDIO_PLUGIN_CLIENT_H_INCLUDED
#define JUCE_AUDIO_PLUGIN_CLIENT_H_INCLUDED
#include "../juce_gui_basics/juce_gui_basics.h"
#include "../juce_audio_basics/juce_audio_basics.h"
#include "../juce_audio_processors/juce_audio_processors.h"
#include <juce_gui_basics/juce_gui_basics.h>
#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_audio_processors/juce_audio_processors.h>
/** Config: JUCE_FORCE_USE_LEGACY_PARAM_IDS
Enable this if you want to force JUCE to use a continuous parameter
index to identify a parameter in a DAW (this was the default in old
versions of JUCE). This is index is usually used by the DAW to save
automation data and enabling this may mess up user's DAW projects.
*/
#ifndef JUCE_FORCE_USE_LEGACY_PARAM_IDS
#define JUCE_FORCE_USE_LEGACY_PARAM_IDS 0
#endif
namespace juce
{


+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "AAX/juce_AAX_Wrapper.cpp"

+ 26
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm View File

@@ -0,0 +1,26 @@
/*
==============================================================================
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.
==============================================================================
*/
#define JUCE_INCLUDED_AAX_IN_MM 1
#include "AAX/juce_AAX_Wrapper.cpp"

+ 69
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r View File

@@ -0,0 +1,69 @@
/*
==============================================================================

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.

==============================================================================
*/

#define UseExtendedThingResource 1
#include <AudioUnit/AudioUnit.r>

//==============================================================================
/* The AppConfig.h file should be a file in your project, containing info to describe the
plugin's name, type, etc. The introjucer will generate this file automatically for you.

You may need to adjust the include path of your project to make sure it can be
found by this include statement. (Don't hack this file to change the include path)
*/
#include "AppConfig.h"


//==============================================================================
// component resources for Audio Unit
#define RES_ID 1000
#define COMP_TYPE JucePlugin_AUMainType
#define COMP_SUBTYPE JucePlugin_AUSubType
#define COMP_MANUF JucePlugin_AUManufacturerCode
#define VERSION JucePlugin_VersionCode
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name
#define DESCRIPTION JucePlugin_Desc
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "Entry"

#include "AUResources.r"

//==============================================================================
// component resources for Audio Unit Carbon View

#ifndef BUILD_AU_CARBON_UI
#define BUILD_AU_CARBON_UI 1
#endif

#if BUILD_AU_CARBON_UI
#define RES_ID 2000
#define COMP_TYPE kAudioUnitCarbonViewComponentType
#define COMP_SUBTYPE JucePlugin_AUSubType
#define COMP_MANUF JucePlugin_AUManufacturerCode
#define VERSION JucePlugin_VersionCode
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name " View"
#define DESCRIPTION NAME
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "ViewEntry"

#include "AUResources.r"
#endif

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "AU/juce_AU_Wrapper.mm"

+ 66
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm View File

@@ -0,0 +1,66 @@
/*
==============================================================================
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.
==============================================================================
*/
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic ignored "-Wextra-tokens"
#pragma clang diagnostic ignored "-Wcomment"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wunused"
#endif
#ifdef _MSC_VER
#pragma warning (push)
// #pragma warning (disable : 4127)
#endif
#include "AU/CoreAudioUtilityClasses/AUBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUBuffer.cpp"
#include "AU/CoreAudioUtilityClasses/AUCarbonViewBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUCarbonViewControl.cpp"
#include "AU/CoreAudioUtilityClasses/AUCarbonViewDispatch.cpp"
#include "AU/CoreAudioUtilityClasses/AUDispatch.cpp"
#include "AU/CoreAudioUtilityClasses/AUInputElement.cpp"
#include "AU/CoreAudioUtilityClasses/AUMIDIBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUOutputBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUOutputElement.cpp"
#include "AU/CoreAudioUtilityClasses/AUScopeElement.cpp"
#include "AU/CoreAudioUtilityClasses/CAAUParameter.cpp"
#include "AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp"
#include "AU/CoreAudioUtilityClasses/CAMutex.cpp"
#include "AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp"
#include "AU/CoreAudioUtilityClasses/CAVectorUnit.cpp"
#include "AU/CoreAudioUtilityClasses/CarbonEventHandler.cpp"
#include "AU/CoreAudioUtilityClasses/ComponentBase.cpp"
#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "AU/juce_AUv3_Wrapper.mm"

+ 6
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS.r View File

@@ -0,0 +1,6 @@

/*
This dummy file is added to the resources section of the project to
force XCode to create some resources for the dpm. If there aren't any
resources, PT will refuse to load the plugin..
*/

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_1.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_Wrapper.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_2.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_DigiCode1.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_3.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_DigiCode2.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_4.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_DigiCode3.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_utils.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_WinUtilities.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_RTAS_utils.mm View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "RTAS/juce_RTAS_MacUtilities.mm"

+ 33
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp View File

@@ -0,0 +1,33 @@
/*
==============================================================================
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.
==============================================================================
*/
#if ! JUCE_MODULE_AVAILABLE_juce_audio_utils
#error To compile AudioUnitv3 and/or Standalone plug-ins, you need to add the juce_audio_utils and juce_audio_devices modules!
#endif
#include "Standalone/juce_StandaloneFilterApp.cpp"
#if ! JUCE_USE_CUSTOM_AU3_STANDALONE_APP
START_JUCE_APPLICATION (StandaloneFilterApp);
#endif

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "VST/juce_VST_Wrapper.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "VST3/juce_VST3_Wrapper.cpp"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST_utils.mm View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "VST/juce_VST_Wrapper.mm"

+ 25
- 0
libs/juce/source/modules/juce_audio_plugin_client/juce_audio_plugin_client_utils.cpp View File

@@ -0,0 +1,25 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "utility/juce_PluginUtilities.cpp"

+ 2
- 1
libs/juce/source/modules/juce_audio_plugin_client/utility/juce_CheckSettingMacros.h View File

@@ -26,7 +26,8 @@
// define all your plugin settings properly..
#if ! (JucePlugin_Build_VST || JucePlugin_Build_VST3 \
|| JucePlugin_Build_AU || JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
|| JucePlugin_Build_AU || JucePlugin_Build_AUv3 \
||JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
|| JucePlugin_Build_Standalone || JucePlugin_Build_LV2)
#error "You need to enable at least one plugin format!"
#endif


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save