Updated to JUCE 3.0.1

pull/1/head
asb2m10 11 years ago
parent 453bd181e5
commit 7bb4a809aa
  1. 14
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  3. 12
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 18
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 12
      Builds/VisualStudio2013/Dexed.vcxproj
  6. 18
      Builds/VisualStudio2013/Dexed.vcxproj.filters
  7. 4
      JuceLibraryCode/AppConfig.h
  8. 360
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  9. 7
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  10. 5
      JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp
  11. 2
      JuceLibraryCode/modules/juce_audio_basics/juce_module_info
  12. 138
      JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  13. 20
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  14. 36
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  15. 28
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  16. 2
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  17. 46
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h
  18. 2
      JuceLibraryCode/modules/juce_audio_devices/juce_module_info
  19. 57
      JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp
  20. 55
      JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  21. 56
      JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  22. 71
      JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
  23. 62
      JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
  24. 971
      JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  25. 58
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  26. 55
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
  27. 52
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  28. 3
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
  29. 36
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
  30. 10
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
  31. 14
      JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c
  32. 2
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
  33. 10
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp
  34. 9
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
  35. 2
      JuceLibraryCode/modules/juce_audio_formats/juce_module_info
  36. 11
      JuceLibraryCode/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  37. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
  38. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  39. 32
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  40. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/juce_module_info
  41. 4
      JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp
  42. 28
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  43. 12
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
  44. 266
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  45. 4
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h
  46. 4
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h
  47. 15
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  48. 2
      JuceLibraryCode/modules/juce_audio_processors/juce_module_info
  49. 4
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  50. 12
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  51. 6
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
  52. 4
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
  53. 19
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp
  54. 7
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h
  55. 2
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp
  56. 243
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
  57. 36
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h
  58. 45
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp
  59. 2
      JuceLibraryCode/modules/juce_audio_utils/juce_module_info
  60. 5
      JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h
  61. 4
      JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp
  62. 6
      JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h
  63. 12
      JuceLibraryCode/modules/juce_core/files/juce_File.cpp
  64. 2
      JuceLibraryCode/modules/juce_core/files/juce_File.h
  65. 4
      JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp
  66. 2
      JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h
  67. 14
      JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp
  68. 5
      JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp
  69. 1
      JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h
  70. 2
      JuceLibraryCode/modules/juce_core/juce_module_info
  71. 2
      JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp
  72. 4
      JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp
  73. 1
      JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp
  74. 2
      JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp
  75. 6
      JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp
  76. 6
      JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp
  77. 8
      JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp
  78. 4
      JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm
  79. 2
      JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm
  80. 8
      JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm
  81. 2
      JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h
  82. 4
      JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp
  83. 2
      JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp
  84. 4
      JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp
  85. 2
      JuceLibraryCode/modules/juce_core/network/juce_Socket.h
  86. 8
      JuceLibraryCode/modules/juce_core/network/juce_URL.cpp
  87. 2
      JuceLibraryCode/modules/juce_core/network/juce_URL.h
  88. 2
      JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h
  89. 17
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp
  90. 7
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h
  91. 9
      JuceLibraryCode/modules/juce_core/text/juce_String.cpp
  92. 3
      JuceLibraryCode/modules/juce_core/text/juce_String.h
  93. 2
      JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp
  94. 5
      JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp
  95. 2
      JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h
  96. 6
      JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp
  97. 2
      JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h
  98. 2
      JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp
  99. 2
      JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h
  100. 2
      JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

@ -86,6 +86,7 @@
0707C87B401DC983E3FF4263 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MathsFunctions.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h"; sourceTree = "SOURCE_ROOT"; };
0733471B6DA02299D2C9590A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StringArray.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp"; sourceTree = "SOURCE_ROOT"; };
075BB641199B15A84856DE6E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
076C4F22CCC47AFEAC2D0C68 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LuaCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
07CB27E064E2A82C2B1D3832 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AbstractFifo.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h"; sourceTree = "SOURCE_ROOT"; };
0A3CCDBDD4238A7F9CB559BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FilenameComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h"; sourceTree = "SOURCE_ROOT"; };
0A55490419140DC6D2FBB1DA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComboBox.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -129,6 +130,7 @@
17C3024C2A1EE03BC0ED9C96 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Windowing.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm"; sourceTree = "SOURCE_ROOT"; };
17ED00953353016B7E7492B0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ApplicationCommandInfo.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp"; sourceTree = "SOURCE_ROOT"; };
18AD1662D33E576F96C30A6A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TopLevelWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"; sourceTree = "SOURCE_ROOT"; };
18D52C793029AFCC92C77A75 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LiveConstantEditor.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp"; sourceTree = "SOURCE_ROOT"; };
1914E45DEAEBD1592581F1FD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioPluginFormatManager.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h"; sourceTree = "SOURCE_ROOT"; };
195B617C1FF754108A97F645 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyPressMappingSet.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h"; sourceTree = "SOURCE_ROOT"; };
19B56FF22ED0090A8D7A3E04 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_basics.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; };
@ -294,6 +296,7 @@
45F6575A7BDB9134EAEA7633 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ActiveXControlComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/embedding/juce_ActiveXControlComponent.h"; sourceTree = "SOURCE_ROOT"; };
462B768DFC2129F54233D51D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StretchableLayoutResizerBar.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h"; sourceTree = "SOURCE_ROOT"; };
46908987EEFC3623A53A95C2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LagrangeInterpolator.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp"; sourceTree = "SOURCE_ROOT"; };
46969E6B78BC89383358DCDA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_XMLCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
46B8FB88F2949700DD70A821 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WildcardFileFilter.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.h"; sourceTree = "SOURCE_ROOT"; };
46C20298CCB469481F5C8D36 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInactivityDetector.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h"; sourceTree = "SOURCE_ROOT"; };
4710CA869326390AF0CE2A0B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableEdgeComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h"; sourceTree = "SOURCE_ROOT"; };
@ -398,6 +401,7 @@
6D256DC39965C982ADAAFA81 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FillType.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h"; sourceTree = "SOURCE_ROOT"; };
6DC26B61BA1638AFAF142A6C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_extra.mm"; path = "../../JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.mm"; sourceTree = "SOURCE_ROOT"; };
6DCB546B40A962FCA3C74DB9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ColourGradient.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h"; sourceTree = "SOURCE_ROOT"; };
6DEFC761C7F27A8ED88790B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_XMLCodeTokeniser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.cpp"; sourceTree = "SOURCE_ROOT"; };
6E2A781F28B3F735F4FAB2A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyMappingEditorComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_KeyMappingEditorComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
6E84E300D2ECD62ED1ED3478 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputSource.h"; path = "../../JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h"; sourceTree = "SOURCE_ROOT"; };
6E8FC799E88893F8CD15BB71 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LADSPAPluginFormat.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -838,6 +842,7 @@
F957420DFF4D2354671B4116 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RectanglePlacement.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp"; sourceTree = "SOURCE_ROOT"; };
F9B29C9F01195D5A979AB5C9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SVGParser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp"; sourceTree = "SOURCE_ROOT"; };
F9FA29A5FF9C9921D785A1C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LookAndFeel_V1.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp"; sourceTree = "SOURCE_ROOT"; };
FA0406B777C1CB9C71F86BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LuaCodeTokeniser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.cpp"; sourceTree = "SOURCE_ROOT"; };
FA726CE9275EF0E84BBEA666 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LinkedListPointer.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h"; sourceTree = "SOURCE_ROOT"; };
FA98BC06299525310A31107B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Label.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h"; sourceTree = "SOURCE_ROOT"; };
FAC5045BEAA6C0B1AC904BED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; };
@ -847,6 +852,7 @@
FC452B781AEE181BEF7F948E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentPeer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp"; sourceTree = "SOURCE_ROOT"; };
FC856709502EE15E8D3F448B = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
FCABD85F0480D4972896F379 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ReverbAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; };
FCBA692E842A80D9618CA467 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LiveConstantEditor.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h"; sourceTree = "SOURCE_ROOT"; };
FD2285710D78FDBC856ADF13 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioProcessorPlayer.h"; path = "../../JuceLibraryCode/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h"; sourceTree = "SOURCE_ROOT"; };
FD333147C1339A81B846EC52 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RecentlyOpenedFilesList.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_RecentlyOpenedFilesList.h"; sourceTree = "SOURCE_ROOT"; };
FD799268DEA0EC4CDFD4DA10 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NewLine.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_NewLine.h"; sourceTree = "SOURCE_ROOT"; };
@ -1741,7 +1747,11 @@
5DE3DC6998A92F718C9683FA,
71DFB6F3C44390C0FD109073,
7E68BB771E88E0A2A323D365,
588255FD68989F1A03FDF31C ); name = "code_editor"; sourceTree = "<group>"; };
588255FD68989F1A03FDF31C,
FA0406B777C1CB9C71F86BC1,
076C4F22CCC47AFEAC2D0C68,
6DEFC761C7F27A8ED88790B4,
46969E6B78BC89383358DCDA ); name = "code_editor"; sourceTree = "<group>"; };
3BAE6D34CB0FFE32A18C6008 = { isa = PBXGroup; children = (
BAA44451865610A98B3A69AE,
346937AF08405CC63D570161 ); name = documents; sourceTree = "<group>"; };
@ -1757,6 +1767,8 @@
4F977F1C295B0D355391AAD3,
6E2A781F28B3F735F4FAB2A2,
A00DC4E59356AF5F1D9C02D1,
18D52C793029AFCC92C77A75,
FCBA692E842A80D9618CA467,
5BFC8D75FFE4E8DEE50B3B1A,
A062855D9DD17397012BC224,
AE8321756C03700EB12FF98A,

@ -1036,6 +1036,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
@ -1048,6 +1054,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
@ -1502,6 +1511,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/>
@ -1510,6 +1521,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/>

@ -1270,6 +1270,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClCompile>
@ -1282,6 +1288,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
@ -2556,6 +2565,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h">
<Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClInclude>
@ -2580,6 +2595,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>

@ -1036,6 +1036,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
@ -1048,6 +1054,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
@ -1502,6 +1511,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/>
@ -1510,6 +1521,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/>

@ -1270,6 +1270,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClCompile>
@ -1282,6 +1288,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
@ -2556,6 +2565,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h">
<Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClInclude>
@ -2580,6 +2595,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>

@ -168,6 +168,10 @@
//#define JUCE_WEB_BROWSER
#endif
#ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR
//#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR
#endif
//==============================================================================
// Audio plugin settings..

@ -22,10 +22,13 @@
==============================================================================
*/
#if JUCE_USE_SSE_INTRINSICS
namespace FloatVectorHelpers
{
#define JUCE_INCREMENT_SRC_DEST dest += 4; src += 4;
#define JUCE_INCREMENT_DEST dest += 4;
#if JUCE_USE_SSE_INTRINSICS
static bool sse2Present = false;
static bool isSSE2Available() noexcept
@ -44,7 +47,6 @@ namespace FloatVectorHelpers
static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
const int numLongOps = num / 4;
if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available())
@ -90,25 +92,23 @@ namespace FloatVectorHelpers
return localVal;
}
#endif
return isMinimum ? juce::findMinimum (src, num)
: juce::findMaximum (src, num);
}
}
#define JUCE_BEGIN_SSE_OP \
#define JUCE_BEGIN_SSE_OP \
if (FloatVectorHelpers::isSSE2Available()) \
{ \
const int numLongOps = num / 4;
#define JUCE_FINISH_SSE_OP(normalOp) \
#define JUCE_FINISH_SSE_OP(normalOp) \
num &= 3; \
if (num == 0) return; \
} \
for (int i = 0; i < num; ++i) normalOp;
#define JUCE_SSE_LOOP(sseOp, srcLoad, dstLoad, dstStore, locals, increment) \
#define JUCE_SSE_LOOP(sseOp, srcLoad, dstLoad, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (srcLoad, dstLoad); \
@ -116,21 +116,18 @@ namespace FloatVectorHelpers
increment; \
}
#define JUCE_INCREMENT_SRC_DEST dest += 4; src += 4;
#define JUCE_INCREMENT_DEST dest += 4;
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); const __m128 s = srcLoad (src);
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); const __m128 s = srcLoad (src);
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, sseOp, locals) \
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, sseOp, locals) \
JUCE_BEGIN_SSE_OP \
if (FloatVectorHelpers::isAligned (dest)) JUCE_SSE_LOOP (sseOp, dummy, _mm_load_ps, _mm_store_ps, locals, JUCE_INCREMENT_DEST) \
else JUCE_SSE_LOOP (sseOp, dummy, _mm_loadu_ps, _mm_storeu_ps, locals, JUCE_INCREMENT_DEST) \
JUCE_FINISH_SSE_OP (normalOp)
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) \
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) \
JUCE_BEGIN_SSE_OP \
if (FloatVectorHelpers::isAligned (dest)) \
{ \
@ -145,11 +142,92 @@ namespace FloatVectorHelpers
JUCE_FINISH_SSE_OP (normalOp)
#else
//==============================================================================
#elif JUCE_USE_ARM_NEON
static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
{
const int numLongOps = num / 4;
if (numLongOps > 1)
{
float32x4_t val;
#define JUCE_MINIMUMMAXIMUM_NEON_LOOP(loadOp, minMaxOp) \
val = loadOp (src); \
src += 4; \
for (int i = 1; i < numLongOps; ++i) \
{ \
const float32x4_t s = loadOp (src); \
val = minMaxOp (val, s); \
src += 4; \
}
if (isMinimum) { JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vminq_f32) }
else { JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vmaxq_f32) }
float localVal;
{
float vals[4];
vst1q_f32 (vals, val);
localVal = isMinimum ? jmin (vals[0], vals[1], vals[2], vals[3])
: jmax (vals[0], vals[1], vals[2], vals[3]);
}
num &= 3;
for (int i = 0; i < num; ++i)
localVal = isMinimum ? jmin (localVal, src[i])
: jmax (localVal, src[i]);
return localVal;
}
return isMinimum ? juce::findMinimum (src, num)
: juce::findMaximum (src, num);
}
#define JUCE_BEGIN_NEON_OP \
const int numLongOps = num / 4;
#define JUCE_FINISH_NEON_OP(normalOp) \
num &= 3; \
if (num == 0) return; \
for (int i = 0; i < num; ++i) normalOp;
#define JUCE_NEON_LOOP(neonOp, srcLoad, dstLoad, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (srcLoad, dstLoad); \
dstStore (dest, neonOp); \
increment; \
}
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const float32x4_t s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest); const float32x4_t s = srcLoad (src);
#define JUCE_PERFORM_NEON_OP_DEST(normalOp, neonOp, locals) \
JUCE_BEGIN_NEON_OP \
JUCE_NEON_LOOP (neonOp, dummy, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_DEST) \
JUCE_FINISH_NEON_OP (normalOp)
#define JUCE_PERFORM_NEON_OP_SRC_DEST(normalOp, neonOp, locals) \
JUCE_BEGIN_NEON_OP \
JUCE_NEON_LOOP (neonOp, vld1q_f32, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_SRC_DEST) \
JUCE_FINISH_NEON_OP (normalOp)
//==============================================================================
#else
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, unused1, unused2) for (int i = 0; i < num; ++i) normalOp;
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) for (int i = 0; i < num; ++i) normalOp;
#endif
#endif
}
//==============================================================================
void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
@ -163,11 +241,13 @@ void JUCE_CALLTYPE FloatVectorOperations::fill (float* dest, float valueToFill,
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vfill (&valueToFill, dest, 1, (size_t) num);
#elif JUCE_USE_ARM_NEON
const float32x4_t val = vld1q_dup_f32 (&valueToFill);
JUCE_PERFORM_NEON_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 val = _mm_load1_ps (&valueToFill);
#endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
#endif
}
@ -181,41 +261,59 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const f
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (src, 1, &multiplier, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vmulq_n_f32(s, multiplier), JUCE_LOAD_SRC)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier);
#endif
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier,
_mm_mul_ps (mult, s),
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, _mm_mul_ps (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept
{
#if JUCE_USE_ARM_NEON
const float32x4_t amountToAdd = vld1q_dup_f32(&amount);
JUCE_PERFORM_NEON_OP_DEST (dest[i] += amount, vaddq_f32 (d, amountToAdd), JUCE_LOAD_DEST)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 amountToAdd = _mm_load1_ps (&amount);
#endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount, _mm_add_ps (d, amountToAdd), JUCE_LOAD_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vadd (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vaddq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i],
_mm_add_ps (d, s),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i], _mm_add_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
const __m128 amountToAdd = _mm_load1_ps (&amount);
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsub (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] -= src[i], vsubq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] -= src[i], _mm_sub_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount,
_mm_add_ps (d, amountToAdd),
JUCE_LOAD_DEST)
}
void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
{
#if JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i] * multiplier,
vmlaq_n_f32 (d, s, multiplier),
JUCE_LOAD_SRC_DEST)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier);
#endif
@ -223,16 +321,18 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const fl
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i] * multiplier,
_mm_add_ps (d, _mm_mul_ps (mult, s)),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmul (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] *= src[i], vmulq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i],
_mm_mul_ps (d, s),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i], _mm_mul_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif
}
@ -240,14 +340,13 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (dest, 1, &multiplier, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_DEST (dest[i] *= multiplier, vmulq_n_f32 (d, multiplier), JUCE_LOAD_DEST)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier);
#endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier,
_mm_mul_ps (d, mult),
JUCE_LOAD_DEST)
JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier, _mm_mul_ps (d, mult), JUCE_LOAD_DEST)
#endif
}
@ -262,6 +361,11 @@ void FloatVectorOperations::negate (float* dest, const float* src, int num) noex
void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
{
#if JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] = src[i] * multiplier,
vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
JUCE_LOAD_NONE)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier);
#endif
@ -269,6 +373,7 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier,
_mm_mul_ps (mult, _mm_cvtepi32_ps (_mm_loadu_si128 ((const __m128i*) src))),
JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num, float& minResult, float& maxResult) noexcept
@ -315,6 +420,51 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n
localMax = jmax (localMax, s);
}
minResult = localMin;
maxResult = localMax;
return;
}
#elif JUCE_USE_ARM_NEON
const int numLongOps = num / 4;
if (numLongOps > 1)
{
float32x4_t mn, mx;
#define JUCE_MINMAX_NEON_LOOP(loadOp) \
mn = loadOp (src); \
mx = mn; \
src += 4; \
for (int i = 1; i < numLongOps; ++i) \
{ \
const float32x4_t s = loadOp (src); \
mn = vminq_f32 (mn, s); \
mx = vmaxq_f32 (mx, s); \
src += 4; \
}
JUCE_MINMAX_NEON_LOOP (vld1q_f32);
float localMin, localMax;
{
float mns[4], mxs[4];
vst1q_f32 (mns, mn);
vst1q_f32 (mxs, mx);
localMin = jmin (mns[0], mns[1], mns[2], mns[3]);
localMax = jmax (mxs[0], mxs[1], mxs[2], mxs[3]);
}
num &= 3;
for (int i = 0; i < num; ++i)
{
const float s = src[i];
localMin = jmin (localMin, s);
localMax = jmax (localMax, s);
}
minResult = localMin;
maxResult = localMax;
return;
@ -326,7 +476,7 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n
float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
return FloatVectorHelpers::findMinimumOrMaximum (src, num, true);
#else
return juce::findMinimum (src, num);
@ -335,7 +485,7 @@ float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int nu
float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
return FloatVectorHelpers::findMinimumOrMaximum (src, num, false);
#else
return juce::findMaximum (src, num);
@ -350,3 +500,129 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
#endif
(void) shouldEnable;
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
class FloatVectorOperationsTests : public UnitTest
{
public:
FloatVectorOperationsTests() : UnitTest ("FloatVectorOperations") {}
void runTest()
{
beginTest ("FloatVectorOperations");
for (int i = 100; --i >= 0;)
{
const int num = getRandom().nextInt (500) + 1;
HeapBlock<float> buffer1 (num + 16), buffer2 (num + 16);
HeapBlock<int> buffer3 (num + 16);
#if JUCE_ARM
float* const data1 = buffer1;
float* const data2 = buffer2;
int* const int1 = buffer3;
#else
float* const data1 = addBytesToPointer (buffer1.getData(), getRandom().nextInt (16));
float* const data2 = addBytesToPointer (buffer2.getData(), getRandom().nextInt (16));
int* const int1 = addBytesToPointer (buffer3.getData(), getRandom().nextInt (16));
#endif
fillRandomly (data1, num);
fillRandomly (data2, num);
float mn1, mx1, mn2, mx2;
FloatVectorOperations::findMinAndMax (data1, num, mn1, mx1);
juce::findMinAndMax (data1, num, mn2, mx2);
expect (mn1 == mn2);
expect (mx1 == mx2);
expect (FloatVectorOperations::findMinimum (data1, num) == juce::findMinimum (data1, num));
expect (FloatVectorOperations::findMaximum (data1, num) == juce::findMaximum (data1, num));
expect (FloatVectorOperations::findMinimum (data2, num) == juce::findMinimum (data2, num));
expect (FloatVectorOperations::findMaximum (data2, num) == juce::findMaximum (data2, num));
FloatVectorOperations::clear (data1, num);
expect (areAllValuesEqual (data1, num, 0));
FloatVectorOperations::fill (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 2.0f));
FloatVectorOperations::add (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 4.0f));
FloatVectorOperations::copy (data2, data1, num);
expect (areAllValuesEqual (data2, num, 4.0f));
FloatVectorOperations::add (data2, data1, num);
expect (areAllValuesEqual (data2, num, 8.0f));
FloatVectorOperations::copyWithMultiply (data2, data1, 4.0f, num);
expect (areAllValuesEqual (data2, num, 16.0f));
FloatVectorOperations::addWithMultiply (data2, data1, 4.0f, num);
expect (areAllValuesEqual (data2, num, 32.0f));
FloatVectorOperations::multiply (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 8.0f));
FloatVectorOperations::multiply (data1, data2, num);
expect (areAllValuesEqual (data1, num, 256.0f));
FloatVectorOperations::negate (data2, data1, num);
expect (areAllValuesEqual (data2, num, -256.0f));
FloatVectorOperations::subtract (data1, data2, num);
expect (areAllValuesEqual (data1, num, 512.0f));
fillRandomly (int1, num);
FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
convertFixed (data2, int1, 2.0f, num);
expect (buffersMatch (data1, data2, num));
}
}
void fillRandomly (float* d, int num)
{
while (--num >= 0)
*d++ = getRandom().nextFloat() * 1000.0f;
}
void fillRandomly (int* d, int num)
{
while (--num >= 0)
*d++ = getRandom().nextInt();
}
static void convertFixed (float* d, const int* s, float multiplier, int num)
{
while (--num >= 0)
*d++ = *s++ * multiplier;
}
static bool areAllValuesEqual (const float* d, int num, float target)
{
while (--num >= 0)
if (*d++ != target)
return false;
return true;
}
static bool buffersMatch (const float* d1, const float* d2, int num)
{
while (--num >= 0)
if (std::abs (*d1++ - *d2++) > std::numeric_limits<float>::epsilon())
return false;
return true;
}
};
static FloatVectorOperationsTests vectorOpTests;
#endif

@ -47,11 +47,14 @@ public:
/** Copies a vector of floats, multiplying each value by a given multiplier */
static void JUCE_CALLTYPE copyWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amount, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amount, int numValues) noexcept;
/** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;

@ -58,6 +58,11 @@
#undef JUCE_USE_VDSP_FRAMEWORK
#endif
#if __ARM_NEON__ && ! (JUCE_USE_VDSP_FRAMEWORK || defined (JUCE_USE_ARM_NEON))
#define JUCE_USE_ARM_NEON 1
#include <arm_neon.h>
#endif
namespace juce
{

@ -1,7 +1,7 @@
{
"id": "juce_audio_basics",
"name": "JUCE audio and midi data classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -945,29 +945,38 @@ const char* MidiMessage::getGMInstrumentName (const int n)
{
static const char* names[] =
{
"Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano",
"Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel",
"Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Drawbar Organ",
"Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica",
"Tango Accordion", "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)",
"Electric Guitar (clean)", "Electric Guitar (mute)", "Overdriven Guitar", "Distortion Guitar",
"Guitar Harmonics", "Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)",
"Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin",
"Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp",
"Timpani", "String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2",
"Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba",
"Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", "Soprano Sax",
"Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet",
"Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle",
"Ocarina", "Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)",
"Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass+lead)", "Pad 1 (new age)",
"Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)", "Pad 5 (bowed)", "Pad 6 (metallic)",
"Pad 7 (halo)", "Pad 8 (sweep)", "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)",
"FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)",
"Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", "Tinkle Bell",
"Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal",
"Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter",
"Applause", "Gunshot"
NEEDS_TRANS("Acoustic Grand Piano"), NEEDS_TRANS("Bright Acoustic Piano"), NEEDS_TRANS("Electric Grand Piano"), NEEDS_TRANS("Honky-tonk Piano"),
NEEDS_TRANS("Electric Piano 1"), NEEDS_TRANS("Electric Piano 2"), NEEDS_TRANS("Harpsichord"), NEEDS_TRANS("Clavinet"),
NEEDS_TRANS("Celesta"), NEEDS_TRANS("Glockenspiel"), NEEDS_TRANS("Music Box"), NEEDS_TRANS("Vibraphone"),
NEEDS_TRANS("Marimba"), NEEDS_TRANS("Xylophone"), NEEDS_TRANS("Tubular Bells"), NEEDS_TRANS("Dulcimer"),
NEEDS_TRANS("Drawbar Organ"), NEEDS_TRANS("Percussive Organ"), NEEDS_TRANS("Rock Organ"), NEEDS_TRANS("Church Organ"),
NEEDS_TRANS("Reed Organ"), NEEDS_TRANS("Accordion"), NEEDS_TRANS("Harmonica"), NEEDS_TRANS("Tango Accordion"),
NEEDS_TRANS("Acoustic Guitar (nylon)"), NEEDS_TRANS("Acoustic Guitar (steel)"), NEEDS_TRANS("Electric Guitar (jazz)"), NEEDS_TRANS("Electric Guitar (clean)"),
NEEDS_TRANS("Electric Guitar (mute)"), NEEDS_TRANS("Overdriven Guitar"), NEEDS_TRANS("Distortion Guitar"), NEEDS_TRANS("Guitar Harmonics"),
NEEDS_TRANS("Acoustic Bass"), NEEDS_TRANS("Electric Bass (finger)"), NEEDS_TRANS("Electric Bass (pick)"), NEEDS_TRANS("Fretless Bass"),
NEEDS_TRANS("Slap Bass 1"), NEEDS_TRANS("Slap Bass 2"), NEEDS_TRANS("Synth Bass 1"), NEEDS_TRANS("Synth Bass 2"),
NEEDS_TRANS("Violin"), NEEDS_TRANS("Viola"), NEEDS_TRANS("Cello"), NEEDS_TRANS("Contrabass"),
NEEDS_TRANS("Tremolo Strings"), NEEDS_TRANS("Pizzicato Strings"), NEEDS_TRANS("Orchestral Harp"), NEEDS_TRANS("Timpani"),
NEEDS_TRANS("String Ensemble 1"), NEEDS_TRANS("String Ensemble 2"), NEEDS_TRANS("SynthStrings 1"), NEEDS_TRANS("SynthStrings 2"),
NEEDS_TRANS("Choir Aahs"), NEEDS_TRANS("Voice Oohs"), NEEDS_TRANS("Synth Voice"), NEEDS_TRANS("Orchestra Hit"),
NEEDS_TRANS("Trumpet"), NEEDS_TRANS("Trombone"), NEEDS_TRANS("Tuba"), NEEDS_TRANS("Muted Trumpet"),
NEEDS_TRANS("French Horn"), NEEDS_TRANS("Brass Section"), NEEDS_TRANS("SynthBrass 1"), NEEDS_TRANS("SynthBrass 2"),
NEEDS_TRANS("Soprano Sax"), NEEDS_TRANS("Alto Sax"), NEEDS_TRANS("Tenor Sax"), NEEDS_TRANS("Baritone Sax"),
NEEDS_TRANS("Oboe"), NEEDS_TRANS("English Horn"), NEEDS_TRANS("Bassoon"), NEEDS_TRANS("Clarinet"),
NEEDS_TRANS("Piccolo"), NEEDS_TRANS("Flute"), NEEDS_TRANS("Recorder"), NEEDS_TRANS("Pan Flute"),
NEEDS_TRANS("Blown Bottle"), NEEDS_TRANS("Shakuhachi"), NEEDS_TRANS("Whistle"), NEEDS_TRANS("Ocarina"),
NEEDS_TRANS("Lead 1 (square)"), NEEDS_TRANS("Lead 2 (sawtooth)"), NEEDS_TRANS("Lead 3 (calliope)"), NEEDS_TRANS("Lead 4 (chiff)"),
NEEDS_TRANS("Lead 5 (charang)"), NEEDS_TRANS("Lead 6 (voice)"), NEEDS_TRANS("Lead 7 (fifths)"), NEEDS_TRANS("Lead 8 (bass+lead)"),
NEEDS_TRANS("Pad 1 (new age)"), NEEDS_TRANS("Pad 2 (warm)"), NEEDS_TRANS("Pad 3 (polysynth)"), NEEDS_TRANS("Pad 4 (choir)"),
NEEDS_TRANS("Pad 5 (bowed)"), NEEDS_TRANS("Pad 6 (metallic)"), NEEDS_TRANS("Pad 7 (halo)"), NEEDS_TRANS("Pad 8 (sweep)"),
NEEDS_TRANS("FX 1 (rain)"), NEEDS_TRANS("FX 2 (soundtrack)"), NEEDS_TRANS("FX 3 (crystal)"), NEEDS_TRANS("FX 4 (atmosphere)"),
NEEDS_TRANS("FX 5 (brightness)"), NEEDS_TRANS("FX 6 (goblins)"), NEEDS_TRANS("FX 7 (echoes)"), NEEDS_TRANS("FX 8 (sci-fi)"),
NEEDS_TRANS("Sitar"), NEEDS_TRANS("Banjo"), NEEDS_TRANS("Shamisen"), NEEDS_TRANS("Koto"),
NEEDS_TRANS("Kalimba"), NEEDS_TRANS("Bag pipe"), NEEDS_TRANS("Fiddle"), NEEDS_TRANS("Shanai"),
NEEDS_TRANS("Tinkle Bell"), NEEDS_TRANS("Agogo"), NEEDS_TRANS("Steel Drums"), NEEDS_TRANS("Woodblock"),
NEEDS_TRANS("Taiko Drum"), NEEDS_TRANS("Melodic Tom"), NEEDS_TRANS("Synth Drum"), NEEDS_TRANS("Reverse Cymbal"),
NEEDS_TRANS("Guitar Fret Noise"), NEEDS_TRANS("Breath Noise"), NEEDS_TRANS("Seashore"), NEEDS_TRANS("Bird Tweet"),
NEEDS_TRANS("Telephone Ring"), NEEDS_TRANS("Helicopter"), NEEDS_TRANS("Applause"), NEEDS_TRANS("Gunshot")
};
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
@ -977,10 +986,10 @@ const char* MidiMessage::getGMInstrumentBankName (const int n)
{
static const char* names[] =
{
"Piano", "Chromatic Percussion", "Organ", "Guitar",
"Bass", "Strings", "Ensemble", "Brass",
"Reed", "Pipe", "Synth Lead", "Synth Pad",
"Synth Effects", "Ethnic", "Percussive", "Sound Effects"
NEEDS_TRANS("Piano"), NEEDS_TRANS("Chromatic Percussion"), NEEDS_TRANS("Organ"), NEEDS_TRANS("Guitar"),
NEEDS_TRANS("Bass"), NEEDS_TRANS("Strings"), NEEDS_TRANS("Ensemble"), NEEDS_TRANS("Brass"),
NEEDS_TRANS("Reed"), NEEDS_TRANS("Pipe"), NEEDS_TRANS("Synth Lead"), NEEDS_TRANS("Synth Pad"),
NEEDS_TRANS("Synth Effects"), NEEDS_TRANS("Ethnic"), NEEDS_TRANS("Percussive"), NEEDS_TRANS("Sound Effects")
};
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
@ -990,15 +999,18 @@ const char* MidiMessage::getRhythmInstrumentName (const int n)
{
static const char* names[] =
{
"Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare",
"Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom",
"Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", "Low-Mid Tom", "Hi-Mid Tom", "Crash Cymbal 1",
"High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal",
"Cowbell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "Hi Bongo", "Low Bongo",
"Mute Hi Conga", "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo",
"Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro",
"Long Guiro", "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica",
"Mute Triangle", "Open Triangle"
NEEDS_TRANS("Acoustic Bass Drum"), NEEDS_TRANS("Bass Drum 1"), NEEDS_TRANS("Side Stick"), NEEDS_TRANS("Acoustic Snare"),
NEEDS_TRANS("Hand Clap"), NEEDS_TRANS("Electric Snare"), NEEDS_TRANS("Low Floor Tom"), NEEDS_TRANS("Closed Hi-Hat"),
NEEDS_TRANS("High Floor Tom"), NEEDS_TRANS("Pedal Hi-Hat"), NEEDS_TRANS("Low Tom"), NEEDS_TRANS("Open Hi-Hat"),
NEEDS_TRANS("Low-Mid Tom"), NEEDS_TRANS("Hi-Mid Tom"), NEEDS_TRANS("Crash Cymbal 1"), NEEDS_TRANS("High Tom"),
NEEDS_TRANS("Ride Cymbal 1"), NEEDS_TRANS("Chinese Cymbal"), NEEDS_TRANS("Ride Bell"), NEEDS_TRANS("Tambourine"),
NEEDS_TRANS("Splash Cymbal"), NEEDS_TRANS("Cowbell"), NEEDS_TRANS("Crash Cymbal 2"), NEEDS_TRANS("Vibraslap"),
NEEDS_TRANS("Ride Cymbal 2"), NEEDS_TRANS("Hi Bongo"), NEEDS_TRANS("Low Bongo"), NEEDS_TRANS("Mute Hi Conga"),
NEEDS_TRANS("Open Hi Conga"), NEEDS_TRANS("Low Conga"), NEEDS_TRANS("High Timbale"), NEEDS_TRANS("Low Timbale"),
NEEDS_TRANS("High Agogo"), NEEDS_TRANS("Low Agogo"), NEEDS_TRANS("Cabasa"), NEEDS_TRANS("Maracas"),
NEEDS_TRANS("Short Whistle"), NEEDS_TRANS("Long Whistle"), NEEDS_TRANS("Short Guiro"), NEEDS_TRANS("Long Guiro"),
NEEDS_TRANS("Claves"), NEEDS_TRANS("Hi Wood Block"), NEEDS_TRANS("Low Wood Block"), NEEDS_TRANS("Mute Cuica"),
NEEDS_TRANS("Open Cuica"), NEEDS_TRANS("Mute Triangle"), NEEDS_TRANS("Open Triangle")
};
return (n >= 35 && n <= 81) ? names [n - 35] : nullptr;
@ -1008,28 +1020,38 @@ const char* MidiMessage::getControllerName (const int n)
{
static const char* names[] =
{
"Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)",
0, "Foot Pedal (coarse)", "Portamento Time (coarse)",
"Data Entry (coarse)", "Volume (coarse)", "Balance (coarse)",
0, "Pan position (coarse)", "Expression (coarse)", "Effect Control 1 (coarse)",
"Effect Control 2 (coarse)", 0, 0, "General Purpose Slider 1", "General Purpose Slider 2",
"General Purpose Slider 3", "General Purpose Slider 4", 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, "Bank Select (fine)", "Modulation Wheel (fine)", "Breath controller (fine)",
0, "Foot Pedal (fine)", "Portamento Time (fine)", "Data Entry (fine)", "Volume (fine)",
"Balance (fine)", 0, "Pan position (fine)", "Expression (fine)", "Effect Control 1 (fine)",
"Effect Control 2 (fine)", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
"Hold Pedal (on/off)", "Portamento (on/off)", "Sustenuto Pedal (on/off)", "Soft Pedal (on/off)",
"Legato Pedal (on/off)", "Hold 2 Pedal (on/off)", "Sound Variation", "Sound Timbre",
"Sound Release Time", "Sound Attack Time", "Sound Brightness", "Sound Control 6",
"Sound Control 7", "Sound Control 8", "Sound Control 9", "Sound Control 10",
"General Purpose Button 1 (on/off)", "General Purpose Button 2 (on/off)",
"General Purpose Button 3 (on/off)", "General Purpose Button 4 (on/off)",
0, 0, 0, 0, 0, 0, 0, "Reverb Level", "Tremolo Level", "Chorus Level", "Celeste Level",
"Phaser Level", "Data Button increment", "Data Button decrement", "Non-registered Parameter (fine)",
"Non-registered Parameter (coarse)", "Registered Parameter (fine)", "Registered Parameter (coarse)",
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "All Sound Off", "All Controllers Off",
"Local Keyboard (on/off)", "All Notes Off", "Omni Mode Off", "Omni Mode On", "Mono Operation",
"Poly Operation"
NEEDS_TRANS("Bank Select"), NEEDS_TRANS("Modulation Wheel (coarse)"), NEEDS_TRANS("Breath controller (coarse)"),
nullptr,
NEEDS_TRANS("Foot Pedal (coarse)"), NEEDS_TRANS("Portamento Time (coarse)"), NEEDS_TRANS("Data Entry (coarse)"),
NEEDS_TRANS("Volume (coarse)"), NEEDS_TRANS("Balance (coarse)"),
nullptr,
NEEDS_TRANS("Pan position (coarse)"), NEEDS_TRANS("Expression (coarse)"), NEEDS_TRANS("Effect Control 1 (coarse)"),
NEEDS_TRANS("Effect Control 2 (coarse)"),
nullptr, nullptr,
NEEDS_TRANS("General Purpose Slider 1"), NEEDS_TRANS("General Purpose Slider 2"),
NEEDS_TRANS("General Purpose Slider 3"), NEEDS_TRANS("General Purpose Slider 4"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("Bank Select (fine)"), NEEDS_TRANS("Modulation Wheel (fine)"), NEEDS_TRANS("Breath controller (fine)"),
nullptr,
NEEDS_TRANS("Foot Pedal (fine)"), NEEDS_TRANS("Portamento Time (fine)"), NEEDS_TRANS("Data Entry (fine)"), NEEDS_TRANS("Volume (fine)"),
NEEDS_TRANS("Balance (fine)"), nullptr, NEEDS_TRANS("Pan position (fine)"), NEEDS_TRANS("Expression (fine)"),
NEEDS_TRANS("Effect Control 1 (fine)"), NEEDS_TRANS("Effect Control 2 (fine)"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("Hold Pedal (on/off)"), NEEDS_TRANS("Portamento (on/off)"), NEEDS_TRANS("Sustenuto Pedal (on/off)"), NEEDS_TRANS("Soft Pedal (on/off)"),
NEEDS_TRANS("Legato Pedal (on/off)"), NEEDS_TRANS("Hold 2 Pedal (on/off)"), NEEDS_TRANS("Sound Variation"), NEEDS_TRANS("Sound Timbre"),
NEEDS_TRANS("Sound Release Time"), NEEDS_TRANS("Sound Attack Time"), NEEDS_TRANS("Sound Brightness"), NEEDS_TRANS("Sound Control 6"),
NEEDS_TRANS("Sound Control 7"), NEEDS_TRANS("Sound Control 8"), NEEDS_TRANS("Sound Control 9"), NEEDS_TRANS("Sound Control 10"),
NEEDS_TRANS("General Purpose Button 1 (on/off)"), NEEDS_TRANS("General Purpose Button 2 (on/off)"),
NEEDS_TRANS("General Purpose Button 3 (on/off)"), NEEDS_TRANS("General Purpose Button 4 (on/off)"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("Reverb Level"), NEEDS_TRANS("Tremolo Level"), NEEDS_TRANS("Chorus Level"), NEEDS_TRANS("Celeste Level"),
NEEDS_TRANS("Phaser Level"), NEEDS_TRANS("Data Button increment"), NEEDS_TRANS("Data Button decrement"), NEEDS_TRANS("Non-registered Parameter (fine)"),
NEEDS_TRANS("Non-registered Parameter (coarse)"), NEEDS_TRANS("Registered Parameter (fine)"), NEEDS_TRANS("Registered Parameter (coarse)"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("All Sound Off"), NEEDS_TRANS("All Controllers Off"), NEEDS_TRANS("Local Keyboard (on/off)"), NEEDS_TRANS("All Notes Off"),
NEEDS_TRANS("Omni Mode Off"), NEEDS_TRANS("Omni Mode On"), NEEDS_TRANS("Mono Operation"), NEEDS_TRANS("Poly Operation")
};
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;

@ -56,6 +56,8 @@ void SynthesiserVoice::clearCurrentNote()
currentlyPlayingSound = nullptr;
}
void SynthesiserVoice::aftertouchChanged (int) {}
//==============================================================================
Synthesiser::Synthesiser()
: sampleRate (0),
@ -191,6 +193,10 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m)
handlePitchWheel (channel, wheelPos);
}
else if (m.isAftertouch())
{
handleAftertouch (m.getChannel(), m.getNoteNumber(), m.getAfterTouchValue());
}
else if (m.isController())
{
handleController (m.getChannel(), m.getControllerNumber(), m.getControllerValue());
@ -338,6 +344,20 @@ void Synthesiser::handleController (const int midiChannel,
}
}
void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
voice->aftertouchChanged (aftertouchValue);
}
}
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
{
jassert (midiChannel > 0 && midiChannel <= 16);

@ -116,7 +116,6 @@ public:
virtual bool canPlaySound (SynthesiserSound*) = 0;
/** Called to start a new note.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void startNote (int midiNoteNumber,
@ -142,12 +141,17 @@ public:
/** Called to let the voice know that the pitch wheel has been moved.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void pitchWheelMoved (int newValue) = 0;
virtual void pitchWheelMoved (int newPitchWheelValue) = 0;
/** Called to let the voice know that a midi controller has been moved.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void controllerMoved (int controllerNumber, int newValue) = 0;
virtual void controllerMoved (int controllerNumber, int newControllerValue) = 0;
/** Called to let the voice know that the aftertouch has changed.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void aftertouchChanged (int newAftertouchValue);
//==============================================================================
/** Renders the next block of data for this voice.
@ -186,6 +190,14 @@ public:
*/
void setCurrentPlaybackSampleRate (double newRate);
/** Returns true if the key that triggered this voice is still held down.
Note that the voice may still be playing after the key was released (e.g because the
sostenuto pedal is down).
*/
bool isKeyDown() const noexcept { return keyIsDown; }
/** Returns true if the sostenuto pedal is currently active for this voice. */
bool isSostenutoPedalDown() const noexcept { return sostenutoPedalDown; }
protected:
//==============================================================================
@ -218,8 +230,7 @@ private:
int currentlyPlayingNote;
uint32 noteOnTime;
SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown; // the voice may still be playing when the key is not down (i.e. sustain pedal)
bool sostenutoPedalDown;
bool keyIsDown, sostenutoPedalDown;
JUCE_LEAK_DETECTOR (SynthesiserVoice)
};
@ -400,6 +411,21 @@ public:
int controllerNumber,
int controllerValue);
/** Sends an aftertouch message.
This will send an aftertouch message to any voices that are playing sounds on
the given midi channel and note number.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
@param midiChannel the midi channel, from 1 to 16 inclusive
@param midiNoteNumber the midi note number, 0 to 127
@param aftertouchValue the aftertouch value, between 0 and 127,
as returned by MidiMessage::getAftertouchValue()
*/
virtual void handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue);
/** Handles a sustain pedal event. */
virtual void handleSustainPedal (int midiChannel, bool isDown);

@ -361,8 +361,8 @@ void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup)
void AudioDeviceManager::deleteCurrentDevice()
{
currentAudioDevice = nullptr;
currentSetup.inputDeviceName = String::empty;
currentSetup.outputDeviceName = String::empty;
currentSetup.inputDeviceName.clear();
currentSetup.outputDeviceName.clear();
}
void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
@ -408,15 +408,15 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
jassert (&newSetup != &currentSetup); // this will have no effect
if (newSetup == currentSetup && currentAudioDevice != nullptr)
return String::empty;
return String();
if (! (newSetup == currentSetup))
sendChangeMessage();
stopDevice();
const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName);
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);
const String newInputDeviceName (numInputChansNeeded == 0 ? String() : newSetup.inputDeviceName);
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String() : newSetup.outputDeviceName);
String error;
AudioIODeviceType* type = getCurrentDeviceTypeObject();
@ -428,7 +428,7 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
if (treatAsChosenDevice)
updateXml();
return String::empty;
return String();
}
if (currentSetup.inputDeviceName != newInputDeviceName
@ -524,16 +524,16 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const
{
jassert (currentAudioDevice != nullptr);
if (rate > 0)
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
if (currentAudioDevice->getSampleRate (i) == rate)
const Array<double> rates (currentAudioDevice->getAvailableSampleRates());
if (rate > 0 && rates.contains (rate))
return rate;
double lowestAbove44 = 0.0;
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
for (int i = rates.size(); --i >= 0;)
{
const double sr = currentAudioDevice->getSampleRate (i);
const double sr = rates[i];
if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
lowestAbove44 = sr;
@ -542,16 +542,14 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const
if (lowestAbove44 > 0.0)
return lowestAbove44;
return currentAudioDevice->getSampleRate (0);
return rates[0];
}
int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
{
jassert (currentAudioDevice != nullptr);
if (bufferSize > 0)
for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;)
if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize)
if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
return bufferSize;
return currentAudioDevice->getDefaultBufferSize();

@ -190,7 +190,7 @@ public:
int numOutputChannelsNeeded,
const XmlElement* savedState,
bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName = String::empty,
const String& preferredDefaultDeviceName = String(),
const AudioDeviceSetup* preferredSetupOptions = 0);
/** Returns some XML representing the current state of the manager.

@ -157,47 +157,19 @@ public:
virtual StringArray getInputChannelNames() = 0;
//==============================================================================
/** Returns the number of sample-rates this device supports.
To find out which rates are available on this device, use this method to
find out how many there are, and getSampleRate() to get the rates.
@see getSampleRate
*/
virtual int getNumSampleRates() = 0;
/** Returns one of the sample-rates this device supports.
To find out which rates are available on this device, use getNumSampleRates() to
find out how many there are, and getSampleRate() to get the individual rates.
The sample rate is set by the open() method.
(Note that for DirectSound some rates might not work, depending on combinations
of i/o channels that are being opened).
@see getNumSampleRates
/** Returns the set of sample-rates this device supports.
@see getCurrentSampleRate
*/
virtual double getSampleRate (int index) = 0;
/** Returns the number of sizes of buffer that are available.
virtual Array<double> getAvailableSampleRates() = 0;
@see getBufferSizeSamples, getDefaultBufferSize
/** Returns the set of buffer sizes that are available.
@see getCurrentBufferSizeSamples, getDefaultBufferSize
*/
virtual int getNumBufferSizesAvailable() = 0;
/** Returns one of the possible buffer-sizes.
@param index the index of the buffer-size to use, from 0 to getNumBufferSizesAvailable() - 1
@returns a number of samples
@see getNumBufferSizesAvailable, getDefaultBufferSize
*/
virtual int getBufferSizeSamples (int index) = 0;
virtual Array<int> getAvailableBufferSizes() = 0;
/** Returns the default buffer-size to use.
@returns a number of samples
@see getNumBufferSizesAvailable, getBufferSizeSamples
@see getAvailableBufferSizes
*/
virtual int getDefaultBufferSize() = 0;
@ -209,9 +181,9 @@ public:
@param outputChannels a BigInteger in which a set bit indicates that the corresponding
output channel should be enabled
@param sampleRate the sample rate to try to use - to find out which rates are
available, see getNumSampleRates() and getSampleRate()
available, see getAvailableSampleRates()
@param bufferSizeSamples the size of i/o buffer to use - to find out the available buffer
sizes, see getNumBufferSizesAvailable() and getBufferSizeSamples()
sizes, see getAvailableBufferSizes()
@returns an error description if there's a problem, or an empty string if it succeeds in
opening the device
@see close

@ -1,7 +1,7 @@
{
"id": "juce_audio_devices",
"name": "JUCE audio and midi I/O device classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes to play and record from audio and midi i/o devices.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -105,7 +105,7 @@ public:
close();
}
StringArray getOutputChannelNames()
StringArray getOutputChannelNames() override
{
StringArray s;
s.add ("Left");
@ -113,7 +113,7 @@ public:
return s;
}
StringArray getInputChannelNames()
StringArray getInputChannelNames() override
{
StringArray s;
@ -130,36 +130,43 @@ public:
return s;
}
int getNumSampleRates() { return 1;}
double getSampleRate (int index) { return sampleRate; }
int getDefaultBufferSize() { return 2048; }
int getNumBufferSizesAvailable() { return 50; }
Array<double> getAvailableSampleRates() override
{
Array<double> r;
r.add ((double) sampleRate);
return r;
}
int getBufferSizeSamples (int index)
Array<int> getAvailableBufferSizes() override
{
Array<int> b;
int n = 16;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
b.add (n);
n += n < 64 ? 16
: (n < 512 ? 32
: (n < 1024 ? 64
: (n < 2048 ? 128 : 256)));
}
return n;
return b;
}
int getDefaultBufferSize() override { return 2048; }
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double requestedSampleRate,
int bufferSize)
int bufferSize) override
{
close();
if (sampleRate != (int) requestedSampleRate)
return "Sample rate not allowed";
lastError = String::empty;
lastError.clear();
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
numDeviceInputChannels = 0;
@ -227,7 +234,7 @@ public:
return lastError;
}
void close()
void close() override
{
if (isRunning)
{
@ -237,18 +244,18 @@ public:
}
}
int getOutputLatencyInSamples() { return (minBufferSizeOut * 3) / 4; }
int getInputLatencyInSamples() { return (minBufferSizeIn * 3) / 4; }
bool isOpen() { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
int getCurrentBitDepth() { return 16; }
double getCurrentSampleRate() { return sampleRate; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
String getLastError() { return lastError; }
bool isPlaying() { return isRunning && callback != 0; }
int getOutputLatencyInSamples() override { return (minBufferSizeOut * 3) / 4; }
int getInputLatencyInSamples() override { return (minBufferSizeIn * 3) / 4; }
bool isOpen() override { return isRunning; }
int getCurrentBufferSizeSamples() override { return actualBufferSize; }
int getCurrentBitDepth() override { return 16; }
double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
BigInteger getActiveInputChannels() const override { return activeInputChans; }
String getLastError() override { return lastError; }
bool isPlaying() override { return isRunning && callback != 0; }
void start (AudioIODeviceCallback* newCallback)
void start (AudioIODeviceCallback* newCallback) override
{
if (isRunning && callback != newCallback)
{
@ -260,7 +267,7 @@ public:
}
}
void stop()
void stop() override
{
if (isRunning)
{

@ -30,9 +30,6 @@ bool isOpenSLAvailable()
return library.open ("libOpenSLES.so");
}
const unsigned short openSLRates[] = { 8000, 16000, 32000, 44100, 48000 };
const unsigned short openSLBufferSizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
//==============================================================================
class OpenSLAudioIODevice : public AudioIODevice,
public Thread
@ -66,7 +63,7 @@ public:
bool openedOk() const { return engine.outputMixObject != nullptr; }
StringArray getOutputChannelNames()
StringArray getOutputChannelNames() override
{
StringArray s;
s.add ("Left");
@ -74,38 +71,33 @@ public:
return s;
}
StringArray getInputChannelNames()
StringArray getInputChannelNames() override
{
StringArray s;
s.add ("Audio Input");
return s;
}
int getNumSampleRates() { return numElementsInArray (openSLRates); }
double getSampleRate (int index)
Array<double> getAvailableSampleRates() override
{
jassert (index >= 0 && index < getNumSampleRates());
return (int) openSLRates [index];
static const double rates[] = { 8000.0, 16000.0, 32000.0, 44100.0, 48000.0 };
return Array<double> (rates, numElementsInArray (rates));
}
int getDefaultBufferSize() { return 1024; }
int getNumBufferSizesAvailable() { return numElementsInArray (openSLBufferSizes); }
int getBufferSizeSamples (int index)
Array<int> getAvailableBufferSizes() override
{
jassert (index >= 0 && index < getNumBufferSizesAvailable());
return (int) openSLBufferSizes [index];
static const int sizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
return Array<int> (sizes, numElementsInArray (sizes));
}
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double requestedSampleRate,
int bufferSize)
int bufferSize) override
{
close();
lastError = String::empty;
lastError.clear();
sampleRate = (int) requestedSampleRate;
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
@ -133,7 +125,7 @@ public:
return lastError;
}
void close()
void close() override
{
stop();
stopThread (6000);
@ -142,18 +134,19 @@ public:
player = nullptr;
}
int getOutputLatencyInSamples() { return outputLatency; }
int getInputLatencyInSamples() { return inputLatency; }
bool isOpen() { return deviceOpen; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
int getCurrentBitDepth() { return 16; }
double getCurrentSampleRate() { return sampleRate; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
String getLastError() { return lastError; }
bool isPlaying() { return callback != nullptr; }
int getDefaultBufferSize() override { return 1024; }
int getOutputLatencyInSamples() override { return outputLatency; }
int getInputLatencyInSamples() override { return inputLatency; }
bool isOpen() override { return deviceOpen; }
int getCurrentBufferSizeSamples() override { return actualBufferSize; }
int getCurrentBitDepth() override { return 16; }
double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
BigInteger getActiveInputChannels() const override { return activeInputChans; }
String getLastError() override { return lastError; }
bool isPlaying() override { return callback != nullptr; }
void start (AudioIODeviceCallback* newCallback)
void start (AudioIODeviceCallback* newCallback) override
{
stop();
@ -166,7 +159,7 @@ public:
}
}
void stop()
void stop() override
{
if (AudioIODeviceCallback* const oldCallback = setCallback (nullptr))
oldCallback->audioDeviceStopped();

@ -48,7 +48,7 @@ public:
close();
}
StringArray getOutputChannelNames()
StringArray getOutputChannelNames() override
{
StringArray s;
s.add ("Left");
@ -56,7 +56,7 @@ public:
return s;
}
StringArray getInputChannelNames()
StringArray getInputChannelNames() override
{
StringArray s;
if (audioInputIsAvailable)
@ -67,20 +67,27 @@ public:
return s;
}
int getNumSampleRates() { return jmax (1, sampleRates.size()); }
double getSampleRate (int index) { return sampleRates.size() > 0 ? sampleRates [index] : sampleRate; }
Array<double> getAvailableSampleRates() override { return sampleRates; }
int getNumBufferSizesAvailable() { return 6; }
int getBufferSizeSamples (int index) { return 1 << (jlimit (0, 5, index) + 6); }
int getDefaultBufferSize() { return 1024; }
Array<int> getAvailableBufferSizes() override
{
Array<int> r;
for (int i = 6; i < 12; ++i)
r.add (1 << i);
return r;
}
int getDefaultBufferSize() override { return 1024; }
String open (const BigInteger& inputChannelsWanted,
const BigInteger& outputChannelsWanted,
double targetSampleRate, int bufferSize)
double targetSampleRate, int bufferSize) override
{
close();
lastError = String::empty;
lastError.clear();
preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
// xxx set up channel mapping
@ -127,7 +134,7 @@ public:
return lastError;
}
void close()
void close() override
{
if (isRunning)
{
@ -146,19 +153,19 @@ public:
}
}
bool isOpen() { return isRunning; }
bool isOpen() override { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
double getCurrentSampleRate() { return sampleRate; }
int getCurrentBitDepth() { return 16; }
int getCurrentBufferSizeSamples() override { return actualBufferSize; }
double getCurrentSampleRate() override { return sampleRate; }
int getCurrentBitDepth() override { return 16; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
BigInteger getActiveInputChannels() const override { return activeInputChans; }
int getOutputLatencyInSamples() { return 0; } //xxx
int getInputLatencyInSamples() { return 0; } //xxx
int getOutputLatencyInSamples() override { return 0; } //xxx
int getInputLatencyInSamples() override { return 0; } //xxx
void start (AudioIODeviceCallback* newCallback)
void start (AudioIODeviceCallback* newCallback) override
{
if (isRunning && callback != newCallback)
{
@ -170,7 +177,7 @@ public:
}
}
void stop()
void stop() override
{
if (isRunning)
{
@ -187,8 +194,8 @@ public:
}
}
bool isPlaying() { return isRunning && callback != nullptr; }
String getLastError() { return lastError; }
bool isPlaying() override { return isRunning && callback != nullptr; }
String getLastError() override { return lastError; }
private:
//==================================================================================================
@ -436,6 +443,11 @@ private:
isRunning = true;
AudioSessionSetActive (true);
AudioOutputUnitStart (audioUnit);
const ScopedLock sl (callbackLock);
if (callback != nullptr)
callback->audioDeviceError ("iOS audio session resumed");
}
}

@ -47,7 +47,7 @@ namespace
#define JUCE_ALSA_FAILED(x) failed (x)
static void getDeviceSampleRates (snd_pcm_t* handle, Array <int>& rates)
static void getDeviceSampleRates (snd_pcm_t* handle, Array<double>& rates)
{
const int ratesToTry[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
@ -59,7 +59,7 @@ static void getDeviceSampleRates (snd_pcm_t* handle, Array <int>& rates)
if (snd_pcm_hw_params_any (handle, hwParams) >= 0
&& snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0)
{
rates.addIfNotAlreadyThere (ratesToTry[i]);
rates.addIfNotAlreadyThere ((double) ratesToTry[i]);
}
}
}
@ -91,7 +91,7 @@ static void getDeviceProperties (const String& deviceID,
unsigned int& maxChansOut,
unsigned int& minChansIn,
unsigned int& maxChansIn,
Array <int>& rates,
Array<double>& rates,
bool testOutput,
bool testInput)
{
@ -482,7 +482,7 @@ public:
{
close();
error = String::empty;
error.clear();
sampleRate = newSampleRate;
bufferSize = newBufferSize;
@ -722,7 +722,7 @@ public:
int bufferSize, outputLatency, inputLatency;
BigInteger currentInputChans, currentOutputChans;
Array <int> sampleRates;
Array<double> sampleRates;
StringArray channelNamesOut, channelNamesIn;
AudioIODeviceCallback* callback;
@ -798,31 +798,34 @@ public:
close();
}
StringArray getOutputChannelNames() { return internal.channelNamesOut; }
StringArray getInputChannelNames() { return internal.channelNamesIn; }
StringArray getOutputChannelNames() override { return internal.channelNamesOut; }
StringArray getInputChannelNames() override { return internal.channelNamesIn; }
int getNumSampleRates() { return internal.sampleRates.size(); }
double getSampleRate (int index) { return internal.sampleRates [index]; }
Array<double> getAvailableSampleRates() override { return internal.sampleRates; }
int getDefaultBufferSize() { return 512; }
int getNumBufferSizesAvailable() { return 50; }
int getBufferSizeSamples (int index)
Array<int> getAvailableBufferSizes() override
{
Array<int> r;
int n = 16;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
r.add (n);
n += n < 64 ? 16
: (n < 512 ? 32
: (n < 1024 ? 64
: (n < 2048 ? 128 : 256)));
}
return n;
return r;
}
int getDefaultBufferSize() override { return 512; }
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sampleRate,
int bufferSizeSamples)
int bufferSizeSamples) override
{
close();
@ -831,11 +834,13 @@ public:
if (sampleRate <= 0)
{
for (int i = 0; i < getNumSampleRates(); ++i)
for (int i = 0; i < internal.sampleRates.size(); ++i)
{
if (getSampleRate (i) >= 44100)
double rate = internal.sampleRates[i];
if (rate >= 44100)
{
sampleRate = getSampleRate (i);
sampleRate = rate;
break;
}
}
@ -848,28 +853,28 @@ public:
return internal.error;
}
void close()
void close() override
{
stop();
internal.close();
isOpen_ = false;
}
bool isOpen() { return isOpen_; }
bool isPlaying() { return isStarted && internal.error.isEmpty(); }
String getLastError() { return internal.error; }
bool isOpen() override { return isOpen_; }
bool isPlaying() override { return isStarted && internal.error.isEmpty(); }
String getLastError() override { return internal.error; }
int getCurrentBufferSizeSamples() { return internal.bufferSize; }
double getCurrentSampleRate() { return internal.sampleRate; }
int getCurrentBitDepth() { return internal.getBitDepth(); }
int getCurrentBufferSizeSamples() override { return internal.bufferSize; }
double getCurrentSampleRate() override { return internal.sampleRate; }
int getCurrentBitDepth() override { return internal.getBitDepth(); }
BigInteger getActiveOutputChannels() const { return internal.currentOutputChans; }
BigInteger getActiveInputChannels() const { return internal.currentInputChans; }
BigInteger getActiveOutputChannels() const override { return internal.currentOutputChans; }
BigInteger getActiveInputChannels() const override { return internal.currentInputChans; }
int getOutputLatencyInSamples() { return internal.outputLatency; }
int getInputLatencyInSamples() { return internal.inputLatency; }
int getOutputLatencyInSamples() override { return internal.outputLatency; }
int getInputLatencyInSamples() override { return internal.inputLatency; }
void start (AudioIODeviceCallback* callback)
void start (AudioIODeviceCallback* callback) override
{
if (! isOpen_)
callback = nullptr;
@ -882,7 +887,7 @@ public:
isStarted = (callback != nullptr);
}
void stop()
void stop() override
{
AudioIODeviceCallback* const oldCallback = internal.callback;
@ -1002,7 +1007,7 @@ private:
{
unsigned int minChansOut = 0, maxChansOut = 0;
unsigned int minChansIn = 0, maxChansIn = 0;
Array <int> rates;
Array<double> rates;
bool isInput = inputName.isNotEmpty(), isOutput = outputName.isNotEmpty();
getDeviceProperties (id, minChansOut, maxChansOut, minChansIn, maxChansIn, rates, isOutput, isInput);

@ -218,16 +218,36 @@ public:
return names;
}
StringArray getOutputChannelNames() { return getChannelNames (false); }
StringArray getInputChannelNames() { return getChannelNames (true); }
int getNumSampleRates() { return client != nullptr ? 1 : 0; }
double getSampleRate (int /*index*/) { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
int getNumBufferSizesAvailable() { return client != nullptr ? 1 : 0; }
int getBufferSizeSamples (int /*index*/) { return getDefaultBufferSize(); }
int getDefaultBufferSize() { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
StringArray getOutputChannelNames() override { return getChannelNames (false); }
StringArray getInputChannelNames() override { return getChannelNames (true); }
Array<double> getAvailableSampleRates() override
{
Array<double> rates;
if (client != nullptr)
rates.add (juce::jack_get_sample_rate (client));
return rates;
}
Array<int> getAvailableBufferSizes() override
{
Array<int> sizes;
if (client != nullptr)
sizes.add (juce::jack_get_buffer_size (client));
return sizes;
}
int getDefaultBufferSize() override { return getCurrentBufferSizeSamples(); }
int getCurrentBufferSizeSamples() override { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
double getCurrentSampleRate() override { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
double /* sampleRate */, int /* bufferSizeSamples */)
double /* sampleRate */, int /* bufferSizeSamples */) override
{
if (client == nullptr)
{
@ -235,7 +255,7 @@ public:
return lastError;
}
lastError = String::empty;
lastError.clear();
close();
juce::jack_set_process_callback (client, processCallback, this);
@ -273,7 +293,7 @@ public:
return lastError;
}
void close()
void close() override
{
stop();
@ -288,7 +308,7 @@ public:
deviceIsOpen = false;
}
void start (AudioIODeviceCallback* newCallback)
void start (AudioIODeviceCallback* newCallback) override
{
if (deviceIsOpen && newCallback != callback)
{
@ -307,22 +327,20 @@ public:
}
}
void stop()
void stop() override
{
start (nullptr);
}
bool isOpen() { return deviceIsOpen; }
bool isPlaying() { return callback != nullptr; }
int getCurrentBufferSizeSamples() { return getBufferSizeSamples (0); }
double getCurrentSampleRate() { return getSampleRate (0); }
int getCurrentBitDepth() { return 32; }
String getLastError() { return lastError; }
bool isOpen() override { return deviceIsOpen; }
bool isPlaying() override { return callback != nullptr; }
int getCurrentBitDepth() override { return 32; }
String getLastError() override { return lastError; }
BigInteger getActiveOutputChannels() const { return activeOutputChannels; }
BigInteger getActiveInputChannels() const { return activeInputChannels; }
BigInteger getActiveOutputChannels() const override { return activeOutputChannels; }
BigInteger getActiveInputChannels() const override { return activeInputChannels; }
int getOutputLatencyInSamples()
int getOutputLatencyInSamples() override
{
int latency = 0;
@ -332,7 +350,7 @@ public:
return latency;
}
int getInputLatencyInSamples()
int getInputLatencyInSamples() override
{
int latency = 0;

@ -366,13 +366,13 @@ public:
{
// find a list of sample rates..
const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
Array<int> newRates;
Array<double> newRates;
if (asioObject != nullptr)
{
for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index)
if (asioObject->canSampleRate ((double) possibleSampleRates[index]) == 0)
newRates.add (possibleSampleRates[index]);
newRates.add ((double) possibleSampleRates[index]);
}
if (newRates.size() == 0)
@ -398,19 +398,16 @@ public:
}
}
StringArray getOutputChannelNames() { return outputChannelNames; }
StringArray getInputChannelNames() { return inputChannelNames; }
StringArray getOutputChannelNames() override { return outputChannelNames; }
StringArray getInputChannelNames() override { return inputChannelNames; }
int getNumSampleRates() { return sampleRates.size(); }
double getSampleRate (int index) { return sampleRates [index]; }
int getNumBufferSizesAvailable() { return bufferSizes.size(); }
int getBufferSizeSamples (int index) { return bufferSizes [index]; }
int getDefaultBufferSize() { return preferredSize; }
Array<double> getAvailableSampleRates() override { return sampleRates; }
Array<int> getAvailableBufferSizes() override { return bufferSizes; }
int getDefaultBufferSize() override { return preferredSize; }
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sr, int bufferSizeSamples)
double sr, int bufferSizeSamples) override
{
if (isOpen())
close();
@ -436,7 +433,7 @@ public:
bufferSizeSamples = readBufferSizes (bufferSizeSamples);
int sampleRate = roundToInt (sr);
double sampleRate = sr;
currentSampleRate = sampleRate;
currentBlockSizeSamples = bufferSizeSamples;
currentChansOut.clear();
@ -451,12 +448,12 @@ public:
jassert (sampleRate != 0);
if (sampleRate == 0)
sampleRate = 44100;
sampleRate = 44100.0;
updateClockSources();
currentSampleRate = getSampleRate();
error = String::empty;
error.clear();
buffersCreated = false;
setSampleRate (sampleRate);
@ -615,9 +612,9 @@ public:
return error;
}
void close()
void close() override
{
error = String::empty;
error.clear();
stopTimer();
stop();
@ -643,20 +640,20 @@ public:
}
}
bool isOpen() { return deviceIsOpen || insideControlPanelModalLoop; }
bool isPlaying() { return asioObject != nullptr && currentCallback != nullptr; }
bool isOpen() override { return deviceIsOpen || insideControlPanelModalLoop; }
bool isPlaying() override { return asioObject != nullptr && currentCallback != nullptr; }
int getCurrentBufferSizeSamples() { return currentBlockSizeSamples; }
double getCurrentSampleRate() { return currentSampleRate; }
int getCurrentBitDepth() { return currentBitDepth; }
int getCurrentBufferSizeSamples() override { return currentBlockSizeSamples; }
double getCurrentSampleRate() override { return currentSampleRate; }
int getCurrentBitDepth() override { return currentBitDepth; }
BigInteger getActiveOutputChannels() const { return currentChansOut; }
BigInteger getActiveInputChannels() const { return currentChansIn; }
BigInteger getActiveOutputChannels() const override { return currentChansOut; }
BigInteger getActiveInputChannels() const override { return currentChansIn; }
int getOutputLatencyInSamples() { return outputLatency + currentBlockSizeSamples / 4; }
int getInputLatencyInSamples() { return inputLatency + currentBlockSizeSamples / 4; }
int getOutputLatencyInSamples() override { return outputLatency + currentBlockSizeSamples / 4; }
int getInputLatencyInSamples() override { return inputLatency + currentBlockSizeSamples / 4; }
void start (AudioIODeviceCallback* callback)
void start (AudioIODeviceCallback* callback) override
{
if (callback != nullptr)
{
@ -667,7 +664,7 @@ public:
}
}
void stop()
void stop() override
{
AudioIODeviceCallback* const lastCallback = currentCallback;
@ -764,7 +761,8 @@ private:
long totalNumInputChans, totalNumOutputChans;
StringArray inputChannelNames, outputChannelNames;
Array<int> sampleRates, bufferSizes;
Array<double> sampleRates;
Array<int> bufferSizes;
long inputLatency, outputLatency;
long minSize, maxSize, preferredSize, granularity;
ASIOClockSource clocks[32];
@ -951,7 +949,7 @@ private:
return cr;
}
void setSampleRate (int newRate)
void setSampleRate (double newRate)
{
if (currentSampleRate != newRate)
{
@ -1181,7 +1179,7 @@ private:
numActiveOutputChans = 0;
currentCallback = nullptr;
error = String::empty;
error.clear();
if (getName().isEmpty())
return error;

@ -755,7 +755,7 @@ public:
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sampleRate, int bufferSizeSamples)
double sampleRate, int bufferSizeSamples) override
{
lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples);
isOpen_ = lastError.isEmpty();
@ -763,7 +763,7 @@ public:
return lastError;
}
void close()
void close() override
{
stop();
@ -774,38 +774,41 @@ public:
}
}
bool isOpen() { return isOpen_ && isThreadRunning(); }
int getCurrentBufferSizeSamples() { return bufferSizeSamples; }
double getCurrentSampleRate() { return sampleRate; }
BigInteger getActiveOutputChannels() const { return enabledOutputs; }
BigInteger getActiveInputChannels() const { return enabledInputs; }
int getOutputLatencyInSamples() { return (int) (getCurrentBufferSizeSamples() * 1.5); }
int getInputLatencyInSamples() { return getOutputLatencyInSamples(); }
StringArray getOutputChannelNames() { return outChannels; }
StringArray getInputChannelNames() { return inChannels; }
int getNumSampleRates() { return 4; }
int getDefaultBufferSize() { return 2560; }
int getNumBufferSizesAvailable() { return 50; }
bool isOpen() override { return isOpen_ && isThreadRunning(); }
int getCurrentBufferSizeSamples() override { return bufferSizeSamples; }
double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveOutputChannels() const override { return enabledOutputs; }
BigInteger getActiveInputChannels() const override { return enabledInputs; }
int getOutputLatencyInSamples() override { return (int) (getCurrentBufferSizeSamples() * 1.5); }
int getInputLatencyInSamples() override { return getOutputLatencyInSamples(); }
StringArray getOutputChannelNames() override { return outChannels; }
StringArray getInputChannelNames() override { return inChannels; }
double getSampleRate (int index)
Array<double> getAvailableSampleRates() override
{
const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 };
return samps [jlimit (0, 3, index)];
static const double rates[] = { 44100.0, 48000.0, 88200.0, 96000.0 };
return Array<double> (rates, numElementsInArray (rates));
}
int getBufferSizeSamples (int index)
Array<int> getAvailableBufferSizes() override
{
Array<int> r;
int n = 64;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
r.add (n);
n += (n < 512) ? 32
: ((n < 1024) ? 64
: ((n < 2048) ? 128 : 256));
}
return n;
return r;
}
int getCurrentBitDepth()
int getDefaultBufferSize() override { return 2560; }
int getCurrentBitDepth() override
{
int bits = 256;
@ -821,7 +824,7 @@ public:
return bits;
}
void start (AudioIODeviceCallback* call)
void start (AudioIODeviceCallback* call) override
{
if (isOpen_ && call != nullptr && ! isStarted)
{
@ -840,7 +843,7 @@ public:
}
}
void stop()
void stop() override
{
if (isStarted)
{
@ -856,8 +859,8 @@ public:
}
}
bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); }
String getLastError() { return lastError; }
bool isPlaying() override { return isStarted && isOpen_ && isThreadRunning(); }
String getLastError() override { return lastError; }
//==============================================================================
StringArray inChannels, outChannels;

@ -882,7 +882,7 @@ public:
return false;
}
StringArray getOutputChannelNames()
StringArray getOutputChannelNames() override
{
StringArray outChannels;
@ -893,7 +893,7 @@ public:
return outChannels;
}
StringArray getInputChannelNames()
StringArray getInputChannelNames() override
{
StringArray inChannels;
@ -904,31 +904,29 @@ public:
return inChannels;
}
int getNumSampleRates() { return sampleRates.size(); }
double getSampleRate (int index) { return sampleRates [index]; }
int getNumBufferSizesAvailable() { return bufferSizes.size(); }
int getBufferSizeSamples (int index) { return bufferSizes [index]; }
int getDefaultBufferSize() { return defaultBufferSize; }
Array<double> getAvailableSampleRates() override { return sampleRates; }
Array<int> getAvailableBufferSizes() override { return bufferSizes; }
int getDefaultBufferSize() override { return defaultBufferSize; }
int getCurrentBufferSizeSamples() { return currentBufferSizeSamples; }
double getCurrentSampleRate() { return currentSampleRate; }
int getCurrentBitDepth() { return 32; }
int getOutputLatencyInSamples() { return latencyOut; }
int getInputLatencyInSamples() { return latencyIn; }
BigInteger getActiveOutputChannels() const { return outputDevice != nullptr ? outputDevice->channels : BigInteger(); }
BigInteger getActiveInputChannels() const { return inputDevice != nullptr ? inputDevice->channels : BigInteger(); }
String getLastError() { return lastError; }
int getCurrentBufferSizeSamples() override { return currentBufferSizeSamples; }
double getCurrentSampleRate() override { return currentSampleRate; }
int getCurrentBitDepth() override { return 32; }
int getOutputLatencyInSamples() override { return latencyOut; }
int getInputLatencyInSamples() override { return latencyIn; }
BigInteger getActiveOutputChannels() const override { return outputDevice != nullptr ? outputDevice->channels : BigInteger(); }
BigInteger getActiveInputChannels() const override { return inputDevice != nullptr ? inputDevice->channels : BigInteger(); }
String getLastError() override { return lastError; }
String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
double sampleRate, int bufferSizeSamples)
double sampleRate, int bufferSizeSamples) override
{
close();
lastError = String::empty;
lastError.clear();
if (sampleRates.size() == 0 && inputDevice != nullptr && outputDevice != nullptr)
{
lastError = "The input and output devices don't share a common sample rate!";
lastError = TRANS("The input and output devices don't share a common sample rate!");
return lastError;
}
@ -939,14 +937,14 @@ public:
if (inputDevice != nullptr && ! inputDevice->open (currentSampleRate, inputChannels))
{
lastError = "Couldn't open the input device!";
lastError = TRANS("Couldn't open the input device!");
return lastError;
}
if (outputDevice != nullptr && ! outputDevice->open (currentSampleRate, outputChannels))
{
close();
lastError = "Couldn't open the output device!";
lastError = TRANS("Couldn't open the output device!");
return lastError;
}
@ -963,7 +961,7 @@ public:
if (! check (inputDevice->client->Start()))
{
close();
lastError = "Couldn't start the input device!";
lastError = TRANS("Couldn't start the input device!");
return lastError;
}
}
@ -975,7 +973,7 @@ public:
if (! check (outputDevice->client->Start()))
{
close();
lastError = "Couldn't start the output device!";
lastError = TRANS("Couldn't start the output device!");
return lastError;
}
}
@ -984,7 +982,7 @@ public:
return lastError;
}
void close()
void close() override
{
stop();
signalThreadShouldExit();
@ -1000,10 +998,10 @@ public:
isOpen_ = false;
}
bool isOpen() { return isOpen_ && isThreadRunning(); }
bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); }
bool isOpen() override { return isOpen_ && isThreadRunning(); }
bool isPlaying() override { return isStarted && isOpen_ && isThreadRunning(); }
void start (AudioIODeviceCallback* call)
void start (AudioIODeviceCallback* call) override
{
if (isOpen_ && call != nullptr && ! isStarted)
{
@ -1022,7 +1020,7 @@ public:
}
}
void stop()
void stop() override
{
if (isStarted)
{

@ -65,8 +65,7 @@ public:
void setSource (AudioSource* newSource);
/** Returns the source that's playing.
May return 0 if there's no source.
May return nullptr if there's no source.
*/
AudioSource* getCurrentSource() const noexcept { return source; }

@ -44,15 +44,12 @@ AudioTransportSource::AudioTransportSource()
AudioTransportSource::~AudioTransportSource()
{
setSource (nullptr);
releaseMasterResources();
}
void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
int readAheadBufferSize_,
TimeSliceThread* readAheadThread,
double sourceSampleRateToCorrectFor,
int maxNumChannels)
int readAheadSize, TimeSliceThread* readAheadThread,
double sourceSampleRateToCorrectFor, int maxNumChannels)
{
if (source == newSource)
{
@ -62,7 +59,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
}
readAheadBufferSize = readAheadBufferSize_;
readAheadBufferSize = readAheadSize;
sourceSampleRate = sourceSampleRateToCorrectFor;
ResamplingAudioSource* newResamplerSource = nullptr;
@ -70,15 +67,15 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
PositionableAudioSource* newPositionableSource = nullptr;
AudioSource* newMasterSource = nullptr;
ScopedPointer <ResamplingAudioSource> oldResamplerSource (resamplerSource);
ScopedPointer <BufferingAudioSource> oldBufferingSource (bufferingSource);
ScopedPointer<ResamplingAudioSource> oldResamplerSource (resamplerSource);
ScopedPointer<BufferingAudioSource> oldBufferingSource (bufferingSource);
AudioSource* oldMasterSource = masterSource;
if (newSource != nullptr)
{
newPositionableSource = newSource;
if (readAheadBufferSize_ > 0)
if (readAheadSize > 0)
{
// If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
// for it to use!
@ -86,7 +83,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
newPositionableSource = newBufferingSource
= new BufferingAudioSource (newPositionableSource, *readAheadThread,
false, readAheadBufferSize_, maxNumChannels);
false, readAheadSize, maxNumChannels);
}
newPositionableSource->setNextReadPosition (0);
@ -115,6 +112,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
masterSource = newMasterSource;
positionableSource = newPositionableSource;
inputStreamEOF = false;
playing = false;
}
@ -170,7 +168,10 @@ double AudioTransportSource::getCurrentPosition() const
double AudioTransportSource::getLengthInSeconds() const
{
if (sampleRate > 0.0)
return getTotalLength() / sampleRate;
return 0.0;
}
void AudioTransportSource::setNextReadPosition (int64 newPosition)
@ -181,6 +182,7 @@ void AudioTransportSource::setNextReadPosition (int64 newPosition)
newPosition = (int64) (newPosition * sourceSampleRate / sampleRate);
positionableSource->setNextReadPosition (newPosition);
inputStreamEOF = false;
}
}
@ -189,7 +191,6 @@ int64 AudioTransportSource::getNextReadPosition() const
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getNextReadPosition() * ratio);
}
@ -203,7 +204,6 @@ int64 AudioTransportSource::getTotalLength() const
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getTotalLength() * ratio);
}
@ -213,9 +213,7 @@ int64 AudioTransportSource::getTotalLength() const
bool AudioTransportSource::isLooping() const
{
const ScopedLock sl (callbackLock);
return positionableSource != nullptr
&& positionableSource->isLooping();
return positionableSource != nullptr && positionableSource->isLooping();
}
void AudioTransportSource::setGain (const float newGain) noexcept
@ -236,6 +234,7 @@ void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, double ne
if (resamplerSource != nullptr && sourceSampleRate > 0)
resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
inputStreamEOF = false;
isPrepared = true;
}
@ -258,8 +257,6 @@ void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info
{
const ScopedLock sl (callbackLock);
inputStreamEOF = false;
if (masterSource != nullptr && ! stopped)
{
masterSource->getNextAudioBlock (info);
@ -285,10 +282,7 @@ void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info
stopped = ! playing;
for (int i = info.buffer->getNumChannels(); --i >= 0;)
{
info.buffer->applyGainRamp (i, info.startSample, info.numSamples,
lastGain, gain);
}
info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
}
else
{

@ -45,7 +45,6 @@ class JUCE_API AudioTransportSource : public PositionableAudioSource,
public:
//==============================================================================
/** Creates an AudioTransportSource.
After creating one of these, use the setSource() method to select an input source.
*/
AudioTransportSource();
@ -94,7 +93,6 @@ public:
void setPosition (double newPosition);
/** Returns the position that the next data block will be read from
This is a time in seconds.
*/
double getCurrentPosition() const;
@ -102,8 +100,7 @@ public:
/** Returns the stream's length in seconds. */
double getLengthInSeconds() const;
/** Returns true if the player has stopped because its input stream ran out of data.
*/
/** Returns true if the player has stopped because its input stream ran out of data. */
bool hasStreamFinished() const noexcept { return inputStreamEOF; }
//==============================================================================
@ -126,19 +123,16 @@ public:
//==============================================================================
/** Changes the gain to apply to the output.
@param newGain a factor by which to multiply the outgoing samples,
so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc.
*/
void setGain (float newGain) noexcept;
/** Returns the current gain setting.
@see setGain
*/
float getGain() const noexcept { return gain; }
//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
@ -175,7 +169,7 @@ private:
bool volatile playing, stopped;
double sampleRate, sourceSampleRate;
int blockSize, readAheadBufferSize;
bool isPrepared, inputStreamEOF;
bool volatile isPrepared, inputStreamEOF;
void releaseMasterResources();

@ -1348,12 +1348,12 @@ FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id)
FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
unsigned i, id;
unsigned i, id_;
FLAC__bool first = true;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
for(i = id = 0; i < 4; ) {
for(i = id_ = 0; i < 4; ) {
if(decoder->private_->cached) {
x = (FLAC__uint32)decoder->private_->lookahead;
decoder->private_->cached = false;
@ -1365,19 +1365,19 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
if(x == FLAC__STREAM_SYNC_STRING[i]) {
first = true;
i++;
id = 0;
id_ = 0;
continue;
}
if(x == ID3V2_TAG_[id]) {
id++;
if(x == ID3V2_TAG_[id_]) {
id_++;
i = 0;
if(id == 3) {
if(id_ == 3) {
if(!skip_id3v2_tag_(decoder))
return false; /* skip_id3v2_tag_ sets the state for us */
}
continue;
}
id = 0;
id_ = 0;
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->header_warmup[0] = (FLAC__byte)x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))

@ -343,7 +343,7 @@ namespace AiffFileHelpers
out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue());
out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue());
const String comment (values.getValue (prefix + "Text", String::empty));
const String comment (values.getValue (prefix + "Text", String()));
const size_t commentLength = jmin (comment.getNumBytesAsUTF8(), (size_t) 65534);
out.writeShortBigEndian ((short) commentLength + 1);

@ -28,7 +28,7 @@ class LAMEEncoderAudioFormat::Writer : public AudioFormatWriter
{
public:
Writer (OutputStream* destStream, const String& formatName,
const File& lameApp, int vbr, int cbr,
const File& appFile, int vbr, int cbr,
double sampleRate, unsigned int numberOfChannels,
unsigned int bitsPerSample, const StringPairArray& metadata)
: AudioFormatWriter (destStream, formatName, sampleRate,
@ -43,7 +43,7 @@ public:
writer = wavFormat.createWriterFor (out, sampleRate, numChannels,
bitsPerSample, metadata, 0);
args.add (lameApp.getFullPathName());
args.add (appFile.getFullPathName());
args.add ("--quiet");
@ -72,7 +72,7 @@ public:
void addMetadataArg (const StringPairArray& metadata, const char* key, const char* lameFlag)
{
const String value (metadata.getValue (key, String::empty));
const String value (metadata.getValue (key, String()));
if (value.isNotEmpty())
{
@ -103,11 +103,11 @@ private:
ScopedPointer<AudioFormatWriter> writer;
StringArray args;
bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& args) const
bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& processArgs) const
{
ChildProcess cp;
if (cp.start (args))
if (cp.start (processArgs))
{
const String childOutput (cp.readAllProcessOutput());
DBG (childOutput); (void) childOutput;

@ -3095,7 +3095,14 @@ private:
const int64 streamSize = stream.stream.getTotalLength();
if (streamSize > 0)
numFrames = (streamSize - streamStartPos) / (stream.frame.frameSize);
{
const int bytesPerFrame = stream.frame.frameSize + 4;
if (bytesPerFrame == 417 || bytesPerFrame == 418)
numFrames = roundToInt ((streamSize - streamStartPos) / 417.95918); // more accurate for 128k
else
numFrames = (streamSize - streamStartPos) / bytesPerFrame;
}
}
return numFrames * 1152;

@ -1,7 +1,7 @@
{
"id": "juce_audio_formats",
"name": "JUCE audio file format codecs",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes for reading and writing various audio file formats.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -945,9 +945,10 @@ public:
(juce::uint8) inData2 };
incomingEvents.addEvent (data, 3, (int) inStartFrame);
#endif
return noErr;
#else
return kAudioUnitErr_PropertyNotInUse;
#endif
}
OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) override
@ -955,8 +956,10 @@ public:
#if JucePlugin_WantsMidiInput
const ScopedLock sl (incomingMidiLock);
incomingEvents.addEvent (inData, (int) inLength, 0);
#endif
return noErr;
#else
return kAudioUnitErr_PropertyNotInUse;
#endif
}
//==============================================================================
@ -1369,7 +1372,7 @@ private:
JUCE_AUTORELEASEPOOL
{
jassert (ed != nullptr);
addAndMakeVisible (&editor);
addAndMakeVisible (editor);
setOpaque (true);
setVisible (true);
setBroughtToFrontOnMouseClick (true);

@ -861,7 +861,7 @@ private:
void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const
{
// Pro-tools expects all your parameters to have valid names!
jassert (juceFilter->getParameterName (index).isNotEmpty());
jassert (juceFilter->getParameterName (index, maxLength).isNotEmpty());
juceFilter->getParameterName (index, maxLength).copyToUTF8 (name, (size_t) maxLength + 1);
}

@ -54,7 +54,7 @@ public:
{
setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false);
Component::addAndMakeVisible (&optionsButton);
Component::addAndMakeVisible (optionsButton);
optionsButton.addListener (this);
optionsButton.setTriggeredOnMouseDown (true);

@ -40,13 +40,6 @@
#undef STRICT
#define STRICT 1
#include <windows.h>
#ifdef __MINGW32__
struct MOUSEHOOKSTRUCTEX : public MOUSEHOOKSTRUCT
{
DWORD mouseData;
};
#endif
#elif defined (LINUX)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -62,12 +55,6 @@
#endif
//==============================================================================
/* These files come with the Steinberg VST SDK - to get them, you'll need to
visit the Steinberg website and jump through some hoops to sign up as a
VST developer.
Then, you'll need to make sure your include path contains your "vstsdk2.4" directory.
*/
#ifndef _MSC_VER
#define __cdecl
#endif
@ -80,7 +67,15 @@
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
#endif
// VSTSDK V2.4 includes..
/* These files come with the Steinberg VST SDK - to get them, you'll need to
visit the Steinberg website and agree to whatever is currently required to
get them. The best version to get is the VST3 SDK, which also contains
the older VST2.4 files.
Then, you'll need to make sure your include path contains your "VST SDK3"
directory (or whatever you've named it on your machine). The introjucer has
a special box for setting this path.
*/
#include <public.sdk/source/vst2.x/audioeffectx.h>
#include <public.sdk/source/vst2.x/aeffeditor.h>
#include <public.sdk/source/vst2.x/audioeffectx.cpp>
@ -181,7 +176,10 @@ namespace
{
if (nCode >= 0 && wParam == WM_MOUSEWHEEL)
{
const MOUSEHOOKSTRUCTEX& hs = *(MOUSEHOOKSTRUCTEX*) lParam;
// using a local copy of this struct to support old mingw libraries
struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; };
const MOUSEHOOKSTRUCTEX_& hs = *(MOUSEHOOKSTRUCTEX_*) lParam;
if (Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, hs.pt.y)))
if (comp->getWindowHandle() != 0)
@ -835,7 +833,7 @@ public:
if (filter != nullptr)
{
jassert (isPositiveAndBelow (index, filter->getNumParameters()));
filter->getParameterText (index).copyToUTF8 (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
filter->getParameterText (index, 24).copyToUTF8 (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
}
}
@ -844,7 +842,7 @@ public:
if (filter != nullptr)
{
jassert (isPositiveAndBelow (index, filter->getNumParameters()));
filter->getParameterName (index).copyToUTF8 (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
filter->getParameterName (index, 16).copyToUTF8 (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
}
}

@ -1,7 +1,7 @@
{
"id": "juce_audio_plugin_client",
"name": "JUCE audio plugin wrapper classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes for building VST, RTAS and AU plugins.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -22,7 +22,7 @@
==============================================================================
*/
#if _MSC_VER
#if _MSC_VER || JUCE_MINGW
#include <windows.h>
#endif
@ -33,7 +33,7 @@
#include "../utility/juce_CheckSettingMacros.h"
#include "juce_IncludeModuleHeaders.h"
#if _MSC_VER
#if _MSC_VER || JUCE_MINGW
#if JucePlugin_Build_RTAS
extern "C" BOOL WINAPI DllMainRTAS (HINSTANCE, DWORD, LPVOID);

@ -58,7 +58,9 @@ namespace juce
namespace AudioUnitFormatHelpers
{
static int insideCallback = 0;
#if JUCE_DEBUG
static ThreadLocalValue<int> insideCallback;
#endif
String osTypeToString (OSType type)
{
@ -136,7 +138,7 @@ namespace AudioUnitFormatHelpers
fileOrIdentifier.lastIndexOfChar ('/')) + 1));
StringArray tokens;
tokens.addTokens (s, ",", String::empty);
tokens.addTokens (s, ",", String());
tokens.removeEmptyStrings();
if (tokens.size() == 3)
@ -290,7 +292,9 @@ public:
{
using namespace AudioUnitFormatHelpers;
++insideCallback;
#if JUCE_DEBUG
++*insideCallback;
#endif
JUCE_AU_LOG ("Opening AU: " + fileOrIdentifier);
@ -306,14 +310,20 @@ public:
}
}
--insideCallback;
#if JUCE_DEBUG
--*insideCallback;
#endif
}
~AudioUnitPluginInstance()
{
const ScopedLock sl (lock);
jassert (AudioUnitFormatHelpers::insideCallback == 0);
#if JUCE_DEBUG
// this indicates that some kind of recursive call is getting triggered that's
// deleting this plugin while it's still under construction.
jassert (AudioUnitFormatHelpers::insideCallback.get() == 0);
#endif
if (eventListenerRef != 0)
{
@ -570,7 +580,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels()))
return "Input " + String (index + 1);
return String::empty;
return String();
}
const String getOutputChannelName (int index) const override
@ -578,7 +588,7 @@ public:
if (isPositiveAndBelow (index, getNumOutputChannels()))
return "Output " + String (index + 1);
return String::empty;
return String();
}
bool isInputChannelStereoPair (int index) const override { return isPositiveAndBelow (index, getNumInputChannels()); }
@ -652,7 +662,7 @@ public:
if (const ParamInfo* p = parameters[index])
return p->name;
return String::empty;
return String();
}
const String getParameterText (int index) override { return String (getParameter (index)); }
@ -1293,7 +1303,7 @@ public:
: AudioProcessorEditor (&p),
plugin (p)
{
addAndMakeVisible (&wrapper);
addAndMakeVisible (wrapper);
setOpaque (true);
setVisible (true);

@ -222,7 +222,7 @@ public:
desc.lastFileModTime = module->file.getLastModificationTime();
desc.pluginFormatName = "LADSPA";
desc.category = getCategory();
desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String::empty;
desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String();
desc.version = getVersion();
desc.numInputChannels = getNumInputChannels();
desc.numOutputChannels = getNumOutputChannels();
@ -338,7 +338,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels()))
return String (plugin->PortNames [inputs [index]]).trim();
return String::empty;
return String();
}
const String getOutputChannelName (const int index) const
@ -346,7 +346,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels()))
return String (plugin->PortNames [outputs [index]]).trim();
return String::empty;
return String();
}
//==============================================================================
@ -390,7 +390,7 @@ public:
return String (plugin->PortNames [parameters [index]]).trim();
}
return String::empty;
return String();
}
const String getParameterText (int index)
@ -407,7 +407,7 @@ public:
return String (parameterValues[index].scaled, 4);
}
return String::empty;
return String();
}
//==============================================================================
@ -424,7 +424,7 @@ public:
const String getProgramName (int index)
{
// XXX
return String::empty;
return String();
}
void changeProgramName (int index, const String& newName)

@ -40,11 +40,17 @@
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Woverloaded-virtual"
#pragma clang diagnostic ignored "-Wshadow"
#endif
// Got an include error here? If so, you'll need to install the VST3 SDK somewhere,
// and use the introjucer or your IDE to add it to your include path. The introjucer
// has a special box for specifying this path for each export target.
/* These files come with the Steinberg VST3 SDK - to get them, you'll need to
visit the Steinberg website and agree to whatever is currently required to
get them.
Then, you'll need to make sure your include path contains your "VST SDK3"
directory (or whatever you've named it on your machine). The introjucer has
a special box for setting this path.
*/
#include <base/source/baseiids.cpp>
#include <base/source/fatomic.cpp>
#include <base/source/fbuffer.cpp>
@ -85,11 +91,12 @@
#undef DBPRT3
#undef DBPRT4
#undef DBPRT5
#undef calloc
#undef free
#undef malloc
#undef realloc
#undef NEW
#undef NEWVEC
#undef realloc
#undef VERIFY
#undef VERIFY_IS
#undef VERIFY_NOT
@ -98,6 +105,7 @@
#undef SINGLE_CREATE_FUNC
#undef _META_CLASS
#undef _META_CLASS_IFACE
#undef _META_CLASS_SINGLE
#undef META_CLASS
#undef META_CLASS_IFACE
#undef META_CLASS_SINGLE
@ -306,8 +314,8 @@ static void activateAllBussesOfType (Vst::IComponent* component,
}
//==============================================================================
/** Assigns an AudioSampleBuffer's channels to an AudioBusBuffers' */
static void associateBufferTo (Vst::AudioBusBuffers& vstBuffers, const AudioSampleBuffer& buffer) noexcept
/** Assigns a complete AudioSampleBuffer's channels to an AudioBusBuffers' */
static void associateWholeBufferTo (Vst::AudioBusBuffers& vstBuffers, const AudioSampleBuffer& buffer) noexcept
{
vstBuffers.channelBuffers32 = buffer.getArrayOfChannels();
vstBuffers.numChannels = buffer.getNumChannels();
@ -566,30 +574,36 @@ public:
for (Steinberg::int32 i = 0; i < eventList.getEventCount(); ++i)
{
Event event;
Event e;
if (eventList.getEvent (i, event) == kResultOk)
if (eventList.getEvent (i, e) == kResultOk)
{
switch (event.type)
switch (e.type)
{
case Event::kNoteOnEvent:
result.addEvent (MidiMessage::noteOn (event.noteOn.channel + 1, event.noteOn.pitch, (uint8) (event.noteOn.velocity * 127.0f)),
event.sampleOffset);
result.addEvent (MidiMessage::noteOn (createSafeChannel (e.noteOn.channel),
createSafeNote (e.noteOn.pitch),
(uint8) denormaliseToMidiValue (e.noteOn.velocity)),
e.sampleOffset);
break;
case Event::kNoteOffEvent:
result.addEvent (MidiMessage::noteOff (event.noteOff.channel + 1, event.noteOff.pitch, (uint8) (event.noteOff.velocity * 127.0f)),
event.sampleOffset);
result.addEvent (MidiMessage::noteOff (createSafeChannel (e.noteOff.channel),
createSafeNote (e.noteOff.pitch),
(uint8) denormaliseToMidiValue (e.noteOff.velocity)),
e.sampleOffset);
break;
case Event::kPolyPressureEvent:
result.addEvent (MidiMessage::aftertouchChange (event.polyPressure.channel + 1, event.polyPressure.pitch, (int) (event.polyPressure.pressure * 127.0f)),
event.sampleOffset);
result.addEvent (MidiMessage::aftertouchChange (createSafeChannel (e.polyPressure.channel),
createSafeNote (e.polyPressure.pitch),
denormaliseToMidiValue (e.polyPressure.pressure)),
e.sampleOffset);
break;
case Event::kDataEvent:
result.addEvent (MidiMessage::createSysExMessage (event.data.bytes, event.data.size),
event.sampleOffset);
result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, e.data.size),
e.sampleOffset);
break;
default:
@ -607,42 +621,58 @@ public:
MidiMessage msg;
int midiEventPosition = 0;
enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states no more than 2048 events are allowed at once
int numEvents = 0;
while (iterator.getNextEvent (msg, midiEventPosition))
{
Event event = { 0 };
if (++numEvents > maxNumEvents)
break;
Event e = { 0 };
if (msg.isNoteOn())
{
event.type = Event::kNoteOnEvent;
event.noteOn.channel = (Steinberg::int16) msg.getChannel() - 1;
event.noteOn.pitch = (Steinberg::int16) msg.getNoteNumber();
event.noteOn.velocity = msg.getVelocity() / 127.0f;
e.type = Event::kNoteOnEvent;
e.noteOn.channel = createSafeChannel (msg.getChannel());
e.noteOn.pitch = createSafeNote (msg.getNoteNumber());
e.noteOn.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOn.length = 0;
e.noteOn.tuning = 0.0f;
e.noteOn.noteId = -1;
}
else if (msg.isNoteOff())
{
event.type = Event::kNoteOffEvent;
event.noteOff.channel = (Steinberg::int16) msg.getChannel() - 1;
event.noteOff.pitch = (Steinberg::int16) msg.getNoteNumber();
event.noteOff.velocity = msg.getVelocity() / 127.0f;
e.type = Event::kNoteOffEvent;
e.noteOff.channel = createSafeChannel (msg.getChannel());
e.noteOff.pitch = createSafeNote (msg.getNoteNumber());
e.noteOff.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOff.tuning = 0.0f;
e.noteOff.noteId = -1;
}
else if (msg.isSysEx())
{
event.type = Event::kDataEvent;
event.data.bytes = msg.getSysExData();
event.data.size = msg.getSysExDataSize();
e.type = Event::kDataEvent;
e.data.bytes = msg.getSysExData();
e.data.size = msg.getSysExDataSize();
e.data.type = DataEvent::kMidiSysEx;
}
else if (msg.isAftertouch())
{
event.type = Event::kPolyPressureEvent;
event.polyPressure.channel = (Steinberg::int16) msg.getChannel() - 1;
event.polyPressure.pitch = (Steinberg::int16) msg.getNoteNumber();
event.polyPressure.pressure = msg.getAfterTouchValue() / 127.0f;
e.type = Event::kPolyPressureEvent;
e.polyPressure.channel = createSafeChannel (msg.getChannel());
e.polyPressure.pitch = createSafeNote (msg.getNoteNumber());
e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue());
}
else
{
continue;
}
event.busIndex = 0;
event.sampleOffset = midiEventPosition;
e.busIndex = 0;
e.sampleOffset = midiEventPosition;
result.addEvent (event);
result.addEvent (e);
}
}
@ -650,6 +680,15 @@ private:
Array<Vst::Event, CriticalSection> events;
Atomic<int32> refCount;
static Steinberg::int16 createSafeChannel (int channel) noexcept { return (Steinberg::int16) jlimit (0, 15, channel - 1); }
static int createSafeChannel (Steinberg::int16 channel) noexcept { return (int) jlimit (1, 16, channel + 1); }
static Steinberg::int16 createSafeNote (int note) noexcept { return (Steinberg::int16) jlimit (0, 127, note); }
static int createSafeNote (Steinberg::int16 note) noexcept { return jlimit (0, 127, (int) note); }
static float normaliseMidiValue (int value) noexcept { return jlimit (0.0f, 1.0f, (float) value / 127.0f); }
static int denormaliseToMidiValue (float value) noexcept { return roundToInt (jlimit (0.0f, 127.0f, value * 127.0f)); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList)
};
@ -1448,16 +1487,16 @@ private:
}
//==============================================================================
bool open (const File& file, const PluginDescription& description)
bool open (const File& f, const PluginDescription& description)
{
dllHandle = new DLLHandle (file.getFullPathName());
dllHandle = new DLLHandle (f.getFullPathName());
ComSmartPtr<IPluginFactory> pluginFactory (dllHandle->getPluginFactory());
ComSmartPtr<VST3HostContext> host (new VST3HostContext (nullptr));
MatchingDescriptionFinder finder (host, pluginFactory, description);
const Result result (finder.findDescriptionsAndPerform (file));
const Result result (finder.findDescriptionsAndPerform (f));
if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString())
{
@ -1506,14 +1545,8 @@ public:
#endif
}
Steinberg::uint32 PLUGIN_API addRef() override { return 1; }
Steinberg::uint32 PLUGIN_API release() override { return 1; }
tresult PLUGIN_API queryInterface (const TUID, void** obj) override
{
*obj = nullptr;
return kNotImplemented;
}
JUCE_DECLARE_VST3_COM_REF_METHODS
JUCE_DECLARE_VST3_COM_QUERY_METHODS
void paint (Graphics& g) override
{
@ -1602,13 +1635,15 @@ public:
private:
//==============================================================================
Atomic<int> refCount;
ComSmartPtr<IPlugView> view;
#if JUCE_WINDOWS
struct ChildComponent : public Component
class ChildComponent : public Component
{
public:
ChildComponent() {}
void paint (Graphics& g) { g.fillAll (Colours::cornflowerblue); }
void paint (Graphics& g) override { g.fillAll (Colours::cornflowerblue); }
using Component::createNewPeer;
@ -1652,7 +1687,7 @@ private:
pluginHandle = (HandleFormat) peer->getNativeHandle();
#elif JUCE_MAC
dummyComponent.setBounds (getBounds().withZeroOrigin());
addAndMakeVisible (&dummyComponent);
addAndMakeVisible (dummyComponent);
pluginHandle = [[NSView alloc] init];
dummyComponent.setView (pluginHandle);
#endif
@ -1676,9 +1711,9 @@ class VST3PluginInstance : public AudioPluginInstance
public:
VST3PluginInstance (const VST3ModuleHandle::Ptr& handle)
: module (handle),
result (1, 1),
numInputAudioBusses (0),
numOutputAudioBusses (0),
resultBuffer (1, 1),
inputParameterChanges (new ParameterChangeList()),
outputParameterChanges (new ParameterChangeList()),
midiInputs (new MidiEventList()),
@ -1761,6 +1796,62 @@ public:
return module != nullptr ? module->name : String::empty;
}
typedef Array<Array<float*> > BusMap;
/** Assigns a series of AudioSampleBuffer's channels to an AudioBusBuffers'
@warning For speed, does not check the channel count and offsets
according to the AudioSampleBuffer
*/
void associateBufferTo (Vst::AudioBusBuffers& vstBuffers,
BusMap& busMap,
const AudioSampleBuffer& buffer,
int numChannels, int channelStartOffset,
int sampleOffset = 0) noexcept
{
const int channelEnd = numChannels + channelStartOffset;
jassert (channelEnd >= 0 && channelEnd <= buffer.getNumChannels());
busMap.add (Array<float*>());
Array<float*>& chans = busMap.getReference (busMap.size() - 1);
for (int i = channelStartOffset; i < channelEnd; ++i)
chans.add (buffer.getSampleData (i, sampleOffset));
vstBuffers.channelBuffers32 = chans.getRawDataPointer();
vstBuffers.numChannels = numChannels;
vstBuffers.silenceFlags = 0;
}
void mapAudioSampleBufferToBusses (Array<Vst::AudioBusBuffers>& result,
AudioSampleBuffer& source,
int numBusses, bool isInput)
{
result.clearQuick();
BusMap& busMapToUse = isInput ? inputBusMap : outputBusMap;
busMapToUse.clearQuick();
int channelIndexOffset = 0;
for (int i = 0; i < numBusses; ++i)
{
Vst::SpeakerArrangement arrangement = 0;
processor->getBusArrangement (isInput ? Vst::kInput : Vst::kOutput,
(Steinberg::int32) i, arrangement);
const int numChansForBus = BigInteger ((int64) arrangement).countNumberOfSetBits();
result.add (Vst::AudioBusBuffers());
associateBufferTo (result.getReference (i), busMapToUse, source,
BigInteger ((int64) arrangement).countNumberOfSetBits(),
channelIndexOffset);
channelIndexOffset += numChansForBus;
}
}
void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) override
{
using namespace Vst;
@ -1777,6 +1868,8 @@ public:
setup.sampleRate = sampleRate;
setup.processMode = isNonRealtime() ? kOffline : kRealtime;
resultBuffer.setSize (numOutputs, estimatedSamplesPerBlock, false, true, true);
warnOnFailure (processor->setupProcessing (setup));
if (! isComponentInitialised)
@ -1787,22 +1880,20 @@ public:
warnOnFailure (component->setActive (true));
warnOnFailure (processor->setProcessing (true));
result.setSize (numOutputs, estimatedSamplesPerBlock, false, true, true);
Array<SpeakerArrangement> inArrangements, outArrangements;
fillWithCorrespondingSpeakerArrangements (inArrangements, numInputs);
fillWithCorrespondingSpeakerArrangements (outArrangements, numOutputs);
warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(),
getNumSingleDirectionBussesFor (component, true, true),
outArrangements.getRawDataPointer(),
getNumSingleDirectionBussesFor (component, false, true)));
warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), numInputAudioBusses,
outArrangements.getRawDataPointer(), numOutputAudioBusses));
}
void releaseResources() override
{
result.setSize (1, 1, false, true, true);
JUCE_TRY
{
resultBuffer.setSize (1, 1, false, true, true);
if (processor != nullptr)
processor->setProcessing (false);
@ -1810,6 +1901,8 @@ public:
if (component != nullptr)
component->setActive (false);
}
JUCE_CATCH_ALL_ASSERT
}
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override
{
@ -1823,8 +1916,8 @@ public:
ProcessData data;
data.processMode = isNonRealtime() ? kOffline : kRealtime;
data.symbolicSampleSize = kSample32;
data.numInputs = 1; // Number of busses, not channels!
data.numOutputs = 1; // Number of busses, not channels!
data.numInputs = numInputAudioBusses;
data.numOutputs = numOutputAudioBusses;
data.inputParameterChanges = inputParameterChanges;
data.outputParameterChanges = outputParameterChanges;
data.numSamples = (Steinberg::int32) numSamples;
@ -2057,14 +2150,17 @@ private:
mutable ComSmartPtr<IPlugView> view;
AudioSampleBuffer result;
Vst::AudioBusBuffers inputs, outputs;
// The number of IO busses MUST match that of the plugin's, as very poorly specified by the Steinberg SDK
/** The number of IO busses MUST match that of the plugin,
even if there aren't enough channels to process,
as very poorly specified by the Steinberg SDK
*/
int numInputAudioBusses, numOutputAudioBusses;
AudioSampleBuffer resultBuffer;
BusMap inputBusMap, outputBusMap;
Array<Vst::AudioBusBuffers> inputBusses, outputBusses;
//==============================================================================
template<class Type>
template <typename Type>
static void appendStateFrom (XmlElement& head, ComSmartPtr<Type>& object, const String& identifier)
{
if (object != nullptr)
@ -2133,10 +2229,10 @@ private:
{
jassert (numClasses >= 0); // The plugin must provide at least an IComponent and IEditController!
for (Steinberg::int32 i = 0; i < numClasses; ++i)
for (Steinberg::int32 j = 0; j < numClasses; ++j)
{
info = new PClassInfo();
factory->getClassInfo (i, info);
factory->getClassInfo (j, info);
if (std::strcmp (info->category, kVstAudioEffectClass) != 0)
continue;
@ -2153,7 +2249,7 @@ private:
if (pf2.loadFrom (factory))
{
info2 = new PClassInfo2();
pf2->getClassInfo2 (i, info2);
pf2->getClassInfo2 (j, info2);
}
else
{
@ -2164,7 +2260,7 @@ private:
{
pf3->setHostContext (host->getFUnknown());
infoW = new PClassInfoW();
pf3->getClassInfoUnicode (i, infoW);
pf3->getClassInfoUnicode (j, infoW);
}
else
{
@ -2251,6 +2347,7 @@ private:
Steinberg::MemoryStream stream;
if (component->getState (&stream) == kResultTrue)
if (stream.seek (0, Steinberg::IBStream::kIBSeekSet, nullptr) == kResultTrue)
warnOnFailure (editController->setComponentState (&stream));
}
@ -2304,6 +2401,7 @@ private:
component->getBusInfo (forAudio ? Vst::kAudio : Vst::kEvent,
forInput ? Vst::kInput : Vst::kOutput,
(Steinberg::int32) index, busInfo);
return busInfo;
}
@ -2322,23 +2420,15 @@ private:
}
//==============================================================================
struct AudioBusBuffersWrapper
{
AudioBusBuffersWrapper() {}
~AudioBusBuffersWrapper() {}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioBusBuffersWrapper)
};
void associateTo (Vst::ProcessData& destination, AudioSampleBuffer& buffer)
{
result.clear();
resultBuffer.clear();
associateBufferTo (inputs, buffer);
associateBufferTo (outputs, result);
mapAudioSampleBufferToBusses (inputBusses, buffer, numInputAudioBusses, true);
mapAudioSampleBufferToBusses (outputBusses, resultBuffer, numOutputAudioBusses, false);
destination.inputs = &inputs;
destination.outputs = &outputs;
destination.inputs = inputBusses.getRawDataPointer();
destination.outputs = outputBusses.getRawDataPointer();
}
void associateTo (Vst::ProcessData& destination, MidiBuffer& midiBuffer)
@ -2360,22 +2450,22 @@ private:
Vst::ParameterInfo getParameterInfoForIndex (int index) const
{
Vst::ParameterInfo info = { 0 };
Vst::ParameterInfo paramInfo = { 0 };
if (processor != nullptr)
editController->getParameterInfo (index, info);
editController->getParameterInfo (index, paramInfo);
return info;
return paramInfo;
}
Vst::ProgramListInfo getProgramListInfo (int index) const
{
Vst::ProgramListInfo info = { 0 };
Vst::ProgramListInfo paramInfo = { 0 };
if (unitInfo != nullptr)
unitInfo->getProgramListInfo (index, info);
unitInfo->getProgramListInfo (index, paramInfo);
return info;
return paramInfo;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginInstance)

@ -68,5 +68,5 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginFormat)
};
#endif //JUCE_PLUGINHOST_VST3
#endif //JUCE_VST3PLUGINFORMAT_H_INCLUDED
#endif // JUCE_PLUGINHOST_VST3
#endif // JUCE_VST3PLUGINFORMAT_H_INCLUDED

@ -22,12 +22,11 @@
==============================================================================
*/
#ifdef __aeffect__
#ifdef __aeffect__ // NB: this must come first, *before* the header-guard.
#ifndef JUCE_VSTMIDIEVENTLIST_H_INCLUDED
#define JUCE_VSTMIDIEVENTLIST_H_INCLUDED
//==============================================================================
/** Holds a set of VSTMidiEvent objects and makes it easy to add
events to the list.
@ -184,6 +183,5 @@ private:
}
};
#endif // JUCE_VSTMIDIEVENTLIST_H_INCLUDED
#endif

@ -1831,17 +1831,22 @@ private:
int versionBits[32];
int n = 0;
while (v != 0)
for (int vv = v; vv != 0; vv /= 10)
versionBits [n++] = vv % 10;
if (n > 4) // if the number ends up silly, it's probably encoded as hex instead of decimal..
{
versionBits [n++] = v % 10;
v /= 10;
}
n = 0;
s << 'V';
for (int vv = v; vv != 0; vv >>= 8)
versionBits [n++] = vv & 255;
}
while (n > 1 && versionBits [n - 1] == 0)
--n;
s << 'V';
while (n > 0)
{
s << versionBits [--n];

@ -1,7 +1,7 @@
{
"id": "juce_audio_processors",
"name": "JUCE audio plugin hosting classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes for loading and playing VST, AU, or internally-generated audio processors.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -201,7 +201,7 @@ void AudioProcessor::updateHostDisplay()
l->audioProcessorChanged (this);
}
String AudioProcessor::getParameterLabel (int) const { return String::empty; }
String AudioProcessor::getParameterLabel (int) const { return String(); }
bool AudioProcessor::isParameterAutomatable (int) const { return true; }
bool AudioProcessor::isMetaParameter (int) const { return false; }
@ -266,7 +266,7 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock&
MemoryOutputStream out (destData, false);
out.writeInt (magicXmlNumber);
out.writeInt (0);
xml.writeToStream (out, String::empty, true, false);
xml.writeToStream (out, String(), true, false);
out.writeByte (0);
}

@ -1367,7 +1367,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const
default: break;
}
return String::empty;
return String();
}
void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (PluginDescription& d) const
@ -1469,7 +1469,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getInputChannelName (in
default: break;
}
return String::empty;
return String();
}
const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (int channelIndex) const
@ -1481,7 +1481,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (i
default: break;
}
return String::empty;
return String();
}
bool AudioProcessorGraph::AudioGraphIOProcessor::isInputChannelStereoPair (int /*index*/) const
@ -1501,17 +1501,17 @@ bool AudioProcessorGraph::AudioGraphIOProcessor::hasEditor() const
AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; }
int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String::empty; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String(); }
float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String::empty; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String(); }
void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { }
int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; }
int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; }
void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { }
const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String::empty; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String(); }
void AudioProcessorGraph::AudioGraphIOProcessor::changeProgramName (int, const String&) {}
void AudioProcessorGraph::AudioGraphIOProcessor::getStateInformation (juce::MemoryBlock&) {}

@ -372,15 +372,15 @@ public:
AudioProcessorEditor* createEditor() { return nullptr; }
int getNumParameters() { return 0; }
const String getParameterName (int) { return String::empty; }
const String getParameterName (int) { return String(); }
float getParameter (int) { return 0; }
const String getParameterText (int) { return String::empty; }
const String getParameterText (int) { return String(); }
void setParameter (int, float) { }
int getNumPrograms() { return 0; }
int getCurrentProgram() { return 0; }
void setCurrentProgram (int) { }
const String getProgramName (int) { return String::empty; }
const String getProgramName (int) { return String(); }
void changeProgramName (int, const String&) { }
void getStateInformation (juce::MemoryBlock&);

@ -35,7 +35,7 @@ public:
slider (p, index_)
{
startTimer (100);
addAndMakeVisible (&slider);
addAndMakeVisible (slider);
owner.addListener (this);
}
@ -123,7 +123,7 @@ GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const
jassert (p != nullptr);
setOpaque (true);
addAndMakeVisible (&panel);
addAndMakeVisible (panel);
Array <PropertyComponent*> params;

@ -241,7 +241,8 @@ void KnownPluginList::clearBlacklistedFiles()
//==============================================================================
struct PluginSorter
{
PluginSorter (KnownPluginList::SortMethod sortMethod) noexcept : method (sortMethod) {}
PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept
: method (sortMethod), direction (forwards ? 1 : -1) {}
int compareElements (const PluginDescription* const first,
const PluginDescription* const second) const
@ -252,6 +253,7 @@ struct PluginSorter
{
case KnownPluginList::sortByCategory: diff = first->category.compareLexicographically (second->category); break;
case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareLexicographically (second->manufacturerName); break;
case KnownPluginList::sortByFormat: diff = first->pluginFormatName.compare (second->pluginFormatName); break;
case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break;
default: break;
}
@ -259,7 +261,7 @@ struct PluginSorter
if (diff == 0)
diff = first->name.compareLexicographically (second->name);
return diff;
return diff * direction;
}
private:
@ -268,14 +270,17 @@ private:
return path.replaceCharacter ('\\', '/').upToLastOccurrenceOf ("/", false, false);
}
KnownPluginList::SortMethod method;
const KnownPluginList::SortMethod method;
const int direction;
JUCE_DECLARE_NON_COPYABLE (PluginSorter)
};
void KnownPluginList::sort (const SortMethod method)
void KnownPluginList::sort (const SortMethod method, bool forwards)
{
if (method != defaultOrder)
{
PluginSorter sorter (method);
PluginSorter sorter (method, forwards);
types.sort (sorter, true);
sendChangeMessage();
@ -477,7 +482,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM
Array <PluginDescription*> sorted;
{
PluginSorter sorter (sortMethod);
PluginSorter sorter (sortMethod, true);
for (int i = 0; i < types.size(); ++i)
sorted.addSorted (sorter, types.getUnchecked(i));
@ -485,7 +490,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM
PluginTree* tree = new PluginTree();
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer)
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat)
{
PluginTreeUtils::buildTreeByCategory (*tree, sorted, sortMethod);
}

@ -132,6 +132,7 @@ public:
sortAlphabetically,
sortByCategory,
sortByManufacturer,
sortByFormat,
sortByFileSystemLocation
};
@ -143,7 +144,7 @@ public:
Use getIndexChosenByMenu() to find out the type that was chosen.
*/
void addToMenu (PopupMenu& menu, const SortMethod sortMethod) const;
void addToMenu (PopupMenu& menu, SortMethod sortMethod) const;
/** Converts a menu item index that has been chosen into its index in this list.
Returns -1 if it's not an ID that was used.
@ -153,7 +154,7 @@ public:
//==============================================================================
/** Sorts the list. */
void sort (const SortMethod method);
void sort (SortMethod method, bool forwards);
//==============================================================================
/** Creates some XML that can be used to store the state of this list. */
@ -195,7 +196,7 @@ public:
private:
//==============================================================================
OwnedArray <PluginDescription> types;
OwnedArray<PluginDescription> types;
StringArray blacklist;
ScopedPointer<CustomScanner> scanner;
CriticalSection scanLock;

@ -120,7 +120,7 @@ bool PluginDirectoryScanner::skipNextFile()
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
{
if (deadMansPedalFile != File::nonexistent)
if (deadMansPedalFile.getFullPathName().isNotEmpty())
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
}

@ -22,10 +22,116 @@
==============================================================================
*/
PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager,
KnownPluginList& listToEdit,
const File& deadMansPedal,
PropertiesFile* const props)
class PluginListComponent::TableModel : public TableListBoxModel
{
public:
TableModel (PluginListComponent& c, KnownPluginList& l) : owner (c), list (l) {}
int getNumRows() override
{
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void paintRowBackground (Graphics& g, int /*rowNumber*/, int /*width*/, int /*height*/, bool rowIsSelected) override
{
if (rowIsSelected)
g.fillAll (owner.findColour (TextEditor::highlightColourId));
}
enum
{
nameCol = 1,
typeCol = 2,
categoryCol = 3,
manufacturerCol = 4,
descCol = 5
};
void paintCell (Graphics& g, int row, int columnId, int width, int height, bool /*rowIsSelected*/) override
{
String text;
bool isBlacklisted = row >= list.getNumTypes();
if (isBlacklisted)
{
if (columnId == nameCol)
text = list.getBlacklistedFiles() [row - list.getNumTypes()];
else if (columnId == descCol)
text = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const desc = list.getType (row))
{
switch (columnId)
{
case nameCol: text = desc->name; break;
case typeCol: text = desc->pluginFormatName; break;
case categoryCol: text = desc->category.isNotEmpty() ? desc->category : "-"; break;
case manufacturerCol: text = desc->manufacturerName; break;
case descCol: text = getPluginDescription (*desc); break;
default: jassertfalse; break;
}
}
if (text.isNotEmpty())
{
g.setColour (isBlacklisted ? Colours::red
: columnId == nameCol ? Colours::black
: Colours::grey);
g.setFont (Font (height * 0.7f, Font::bold));
g.drawFittedText (text, 4, 0, width - 6, height, Justification::centredLeft, 1, 0.9f);
}
}
void deleteKeyPressed (int lastRowSelected) override
{
removePluginItem (list, lastRowSelected);
}
void sortOrderChanged (int newSortColumnId, bool isForwards) override
{
switch (newSortColumnId)
{
case nameCol: list.sort (KnownPluginList::sortAlphabetically, isForwards); break;
case typeCol: list.sort (KnownPluginList::sortByFormat, isForwards); break;
case categoryCol: list.sort (KnownPluginList::sortByCategory, isForwards); break;
case manufacturerCol: list.sort (KnownPluginList::sortByManufacturer, isForwards); break;
case descCol: break;
default: jassertfalse; break;
}
}
static void removePluginItem (KnownPluginList& list, int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
static String getPluginDescription (const PluginDescription& desc)
{
StringArray items;
if (desc.descriptiveName != desc.name)
items.add (desc.descriptiveName);
items.add (desc.version);
items.removeEmptyStrings();
return items.joinIntoString (" - ");
}
PluginListComponent& owner;
KnownPluginList& list;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableModel)
};
//==============================================================================
PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, KnownPluginList& listToEdit,
const File& deadMansPedal, PropertiesFile* const props)
: formatManager (manager),
list (listToEdit),
deadMansPedalFile (deadMansPedal),
@ -33,10 +139,22 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager,
propertiesToUse (props),
numThreads (0)
{
listBox.setModel (this);
addAndMakeVisible (&listBox);
tableModel = new TableModel (*this, listToEdit);
TableHeaderComponent& header = table.getHeader();
addAndMakeVisible (&optionsButton);
header.addColumn (TRANS("Name"), TableModel::nameCol, 200, 100, 700, TableHeaderComponent::defaultFlags | TableHeaderComponent::sortedForwards);
header.addColumn (TRANS("Format"), TableModel::typeCol, 80, 80, 80, TableHeaderComponent::notResizable);
header.addColumn (TRANS("Category"), TableModel::categoryCol, 100, 100, 200);
header.addColumn (TRANS("Manufacturer"), TableModel::manufacturerCol, 200, 100, 300);
header.addColumn (TRANS("Description"), TableModel::descCol, 300, 100, 500, TableHeaderComponent::notSortable);
table.setHeaderHeight (22);
table.setRowHeight (20);
table.setModel (tableModel);
addAndMakeVisible (table);
addAndMakeVisible (optionsButton);
optionsButton.addListener (this);
optionsButton.setTriggeredOnMouseDown (true);
@ -66,9 +184,13 @@ void PluginListComponent::setNumberOfThreadsForScanning (int num)
void PluginListComponent::resized()
{
listBox.setBounds (0, 0, getWidth(), getHeight() - 30);
Rectangle<int> r (getLocalBounds().reduced (2));
optionsButton.setBounds (r.removeFromBottom (24));
optionsButton.changeWidthToFitText (24);
optionsButton.setTopLeftPosition (0, getHeight() - 28);
r.removeFromBottom (3);
table.setBounds (r);
}
void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
@ -78,89 +200,22 @@ void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
void PluginListComponent::updateList()
{
listBox.updateContent();
listBox.repaint();
}
int PluginListComponent::getNumRows()
{
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void PluginListComponent::paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected)
{
if (rowIsSelected)
g.fillAll (findColour (TextEditor::highlightColourId));
String name, desc;
bool isBlacklisted = false;
if (row >= list.getNumTypes())
{
isBlacklisted = true;
name = list.getBlacklistedFiles() [row - list.getNumTypes()];
desc = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const pd = list.getType (row))
{
name = pd->name;
desc << pd->pluginFormatName
<< (pd->isInstrument ? " instrument" : " effect")
<< " - " << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins")
<< " / " << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs");
if (pd->manufacturerName.isNotEmpty()) desc << " - " << pd->manufacturerName;
if (pd->version.isNotEmpty()) desc << " - " << pd->version;
if (pd->category.isNotEmpty()) desc << " - category: '" << pd->category << '\'';
}
if (name.isNotEmpty())
{
GlyphArrangement ga;
ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold),
name, 8.0f, height * 0.8f, width - 10.0f, true);
g.setColour (isBlacklisted ? Colours::red : Colours::black);
ga.draw (g);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
ga.clear();
ga.addCurtailedLineOfText (Font (height * 0.6f), desc,
jmax (bb.getRight() + 10.0f, width / 3.0f), height * 0.8f,
width - bb.getRight() - 12.0f, true);
g.setColour (isBlacklisted ? Colours::red : Colours::grey);
ga.draw (g);
}
}
static void removePluginItem (KnownPluginList& list, int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
void PluginListComponent::deleteKeyPressed (int lastRowSelected)
{
removePluginItem (list, lastRowSelected);
table.updateContent();
table.repaint();
}
void PluginListComponent::removeSelected()
{
const SparseSet <int> selected (listBox.getSelectedRows());
const SparseSet<int> selected (table.getSelectedRows());
for (int i = list.getNumTypes(); --i >= 0;)
if (selected.contains (i))
removePluginItem (list, i);
TableModel::removePluginItem (list, i);
}
bool PluginListComponent::canShowSelectedFolder() const
{
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow()))
if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists();
return false;
@ -169,7 +224,7 @@ bool PluginListComponent::canShowSelectedFolder() const
void PluginListComponent::showSelectedFolder()
{
if (canShowSelectedFolder())
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow()))
if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
}
@ -192,12 +247,9 @@ void PluginListComponent::optionsMenuCallback (int result)
{
case 0: break;
case 1: list.clear(); break;
case 2: list.sort (KnownPluginList::sortAlphabetically); break;
case 3: list.sort (KnownPluginList::sortByCategory); break;
case 4: list.sort (KnownPluginList::sortByManufacturer); break;
case 5: removeSelected(); break;
case 6: showSelectedFolder(); break;
case 7: removeMissingPlugins(); break;
case 2: removeSelected(); break;
case 3: showSelectedFolder(); break;
case 4: removeMissingPlugins(); break;
default:
if (AudioPluginFormat* format = formatManager.getFormat (result - 10))
@ -213,13 +265,9 @@ void PluginListComponent::buttonClicked (Button* button)
{
PopupMenu menu;
menu.addItem (1, TRANS("Clear list"));
menu.addItem (5, TRANS("Remove selected plug-in from list"), listBox.getNumSelectedRows() > 0);
menu.addItem (6, TRANS("Show folder containing selected plug-in"), canShowSelectedFolder());
menu.addItem (7, TRANS("Remove any plug-ins whose files no longer exist"));
menu.addSeparator();
menu.addItem (2, TRANS("Sort alphabetically"));
menu.addItem (3, TRANS("Sort by category"));
menu.addItem (4, TRANS("Sort by manufacturer"));
menu.addItem (2, TRANS("Remove selected plug-in from list"), table.getNumSelectedRows() > 0);
menu.addItem (3, TRANS("Show folder containing selected plug-in"), canShowSelectedFolder());
menu.addItem (4, TRANS("Remove any plug-ins whose files no longer exist"));
menu.addSeparator();
for (int i = 0; i < formatManager.getNumFormats(); ++i)
@ -262,10 +310,7 @@ void PluginListComponent::setLastSearchPath (PropertiesFile& properties, AudioPl
class PluginListComponent::Scanner : private Timer
{
public:
Scanner (PluginListComponent& plc,
AudioPluginFormat& format,
PropertiesFile* properties,
int threads)
Scanner (PluginListComponent& plc, AudioPluginFormat& format, PropertiesFile* properties, int threads)
: owner (plc), formatToScan (format), propertiesToUse (properties),
pathChooserWindow (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon),
progressWindow (TRANS("Scanning for plug-ins..."),

@ -33,7 +33,6 @@
*/
class JUCE_API PluginListComponent : public Component,
public FileDragAndDropTarget,
private ListBoxModel,
private ChangeListener,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
{
@ -53,7 +52,7 @@ public:
/** Destructor. */
~PluginListComponent();
/** Changes the text in the panel's button. */
/** Changes the text in the panel's options button. */
void setOptionsButtonText (const String& newText);
/** Sets how many threads to simultaneously scan for plugins.
@ -62,42 +61,32 @@ public:
void setNumberOfThreadsForScanning (int numThreads);
/** Returns the last search path stored in a given properties file for the specified format. */
static FileSearchPath getLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format);
static FileSearchPath getLastSearchPath (PropertiesFile&, AudioPluginFormat&);
/** Stores a search path in a properties file for the given format. */
static void setLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format,
const FileSearchPath& newPath);
static void setLastSearchPath (PropertiesFile&, AudioPluginFormat&, const FileSearchPath&);
/** Triggers an asynchronous scan for the given format. */
void scanFor (AudioPluginFormat& format);
void scanFor (AudioPluginFormat&);
/** Returns true if there's currently a scan in progress. */
bool isScanning() const noexcept;
//==============================================================================
/** @internal */
void resized() override;
/** @internal */
bool isInterestedInFileDrag (const StringArray&) override;
/** @internal */
void filesDropped (const StringArray&, int, int) override;
/** @internal */
int getNumRows() override;
/** @internal */
void paintListBoxItem (int row, Graphics&, int width, int height, bool rowIsSelected) override;
/** @internal */
void deleteKeyPressed (int lastRowSelected) override;
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
KnownPluginList& list;
File deadMansPedalFile;
ListBox listBox;
TableListBox table;
TextButton optionsButton;
PropertiesFile* propertiesToUse;
int numThreads;
class TableModel;
friend class TableModel;
friend struct ContainerDeletePolicy<TableModel>;
ScopedPointer<TableModel> tableModel;
class Scanner;
friend class Scanner;
friend struct ContainerDeletePolicy<Scanner>;
@ -107,11 +96,14 @@ private:
static void optionsMenuStaticCallback (int, PluginListComponent*);
void optionsMenuCallback (int);
void updateList();
void removeSelected();
void showSelectedFolder();
bool canShowSelectedFolder() const;
void removeSelected();
void removeMissingPlugins();
void resized() override;
bool isInterestedInFileDrag (const StringArray&) override;
void filesDropped (const StringArray&, int, int) override;
void buttonClicked (Button*) override;
void changeListenerCallback (ChangeBroadcaster*) override;

@ -352,7 +352,7 @@ public:
if (error.isNotEmpty())
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
TRANS ("Error when trying to open audio device!"),
TRANS("Error when trying to open audio device!"),
error);
}
@ -410,7 +410,7 @@ public:
addAndMakeVisible (outputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType,
TRANS ("(no audio output channels found)")));
outputChanLabel = new Label (String::empty, TRANS ("active output channels:"));
outputChanLabel = new Label (String::empty, TRANS("Active output channels:"));
outputChanLabel->attachToComponent (outputChanList, true);
}
@ -429,8 +429,8 @@ public:
{
addAndMakeVisible (inputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType,
TRANS ("(no audio input channels found)")));
inputChanLabel = new Label (String::empty, TRANS ("active input channels:"));
TRANS("(no audio input channels found)")));
inputChanLabel = new Label (String::empty, TRANS("Active input channels:"));
inputChanLabel->attachToComponent (inputChanList, true);
}
@ -525,8 +525,8 @@ private:
if (currentDevice != nullptr && currentDevice->hasControlPanel())
{
addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"),
TRANS ("opens the device's own control panel")));
addAndMakeVisible (showUIButton = new TextButton (TRANS ("Show this device's control panel"),
TRANS ("Opens the device's own control panel")));
showUIButton->addListener (this);
}
@ -544,13 +544,13 @@ private:
addAndMakeVisible (outputDeviceDropDown);
outputDeviceLabel = new Label (String::empty,
type.hasSeparateInputsAndOutputs() ? TRANS ("output:")
: TRANS ("device:"));
type.hasSeparateInputsAndOutputs() ? TRANS("Output:")
: TRANS("Device:"));
outputDeviceLabel->attachToComponent (outputDeviceDropDown, true);
if (setup.maxNumOutputChannels > 0)
{
addAndMakeVisible (testButton = new TextButton (TRANS ("Test")));
addAndMakeVisible (testButton = new TextButton (TRANS("Test")));
testButton->addListener (this);
}
}
@ -571,7 +571,7 @@ private:
inputDeviceDropDown->addListener (this);
addAndMakeVisible (inputDeviceDropDown);
inputDeviceLabel = new Label (String::empty, TRANS ("input:"));
inputDeviceLabel = new Label (String::empty, TRANS("Input:"));
inputDeviceLabel->attachToComponent (inputDeviceDropDown, true);
addAndMakeVisible (inputLevelMeter
@ -590,7 +590,7 @@ private:
{
addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty));
sampleRateLabel = new Label (String::empty, TRANS ("sample rate:"));
sampleRateLabel = new Label (String::empty, TRANS("Sample rate:"));
sampleRateLabel->attachToComponent (sampleRateDropDown, true);
}
else
@ -599,11 +599,11 @@ private:
sampleRateDropDown->removeListener (this);
}
const int numRates = currentDevice->getNumSampleRates();
const Array<double> rates (currentDevice->getAvailableSampleRates());
for (int i = 0; i < numRates; ++i)
for (int i = 0; i < rates.size(); ++i)
{
const int rate = roundToInt (currentDevice->getSampleRate (i));
const int rate = roundToInt (rates[i]);
sampleRateDropDown->addItem (String (rate) + " Hz", rate);
}
@ -617,7 +617,7 @@ private:
{
addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty));
bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:"));
bufferSizeLabel = new Label (String::empty, TRANS("Audio buffer size:"));
bufferSizeLabel->attachToComponent (bufferSizeDropDown, true);
}
else
@ -626,19 +626,16 @@ private:
bufferSizeDropDown->removeListener (this);
}
const int numBufferSizes = currentDevice->getNumBufferSizesAvailable();
const Array<int> bufferSizes (currentDevice->getAvailableBufferSizes());
double currentRate = currentDevice->getCurrentSampleRate();
if (currentRate == 0)
currentRate = 48000.0;
for (int i = 0; i < numBufferSizes; ++i)
for (int i = 0; i < bufferSizes.size(); ++i)
{
const int bs = currentDevice->getBufferSizeSamples (i);
bufferSizeDropDown->addItem (String (bs)
+ " samples ("
+ String (bs * 1000.0 / currentRate, 1)
+ " ms)",
bs);
const int bs = bufferSizes[i];
bufferSizeDropDown->addItem (String (bs) + " samples (" + String (bs * 1000.0 / currentRate, 1) + " ms)", bs);
}
bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), dontSendNotification);
@ -936,7 +933,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
addAndMakeVisible (deviceTypeDropDown);
deviceTypeDropDown->addListener (this);
deviceTypeDropDownLabel = new Label (String::empty, TRANS ("Audio device type:"));
deviceTypeDropDownLabel = new Label (String::empty, TRANS("Audio device type:"));
deviceTypeDropDownLabel->setJustificationType (Justification::centredRight);
deviceTypeDropDownLabel->attachToComponent (deviceTypeDropDown, true);
}

@ -1,7 +1,7 @@
{
"id": "juce_audio_utils",
"name": "JUCE extra audio utility classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "Classes for audio-related GUI and miscellaneous tasks.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",

@ -505,10 +505,7 @@ public:
jassert (numElementsToAdd <= 0 || data.elements != nullptr);
while (--numElementsToAdd >= 0)
{
data.elements [numUsed] = new ObjectClass (*arrayToAddFrom.getUnchecked (startIndex++));
++numUsed;
}
data.elements [numUsed++] = createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++));
}
/** Inserts a new object into the array assuming that the array is sorted.

@ -155,8 +155,8 @@ void PropertySet::removeValue (StringRef keyName)
void PropertySet::setValue (const String& keyName, const XmlElement* const xml)
{
setValue (keyName, xml == nullptr ? var::null
: var (xml->createDocument (String::empty, true)));
setValue (keyName, xml == nullptr ? var()
: var (xml->createDocument ("", true)));
}
bool PropertySet::containsKey (StringRef keyName) const noexcept

@ -69,7 +69,7 @@ public:
@param keyName the name of the property to retrieve
@param defaultReturnValue a value to return if the named property doesn't actually exist
*/
String getValue (StringRef keyName, const String& defaultReturnValue = String::empty) const noexcept;
String getValue (StringRef keyName, const String& defaultReturnValue = String()) const noexcept;
/** Returns one of the properties as an integer.
@ -109,8 +109,8 @@ public:
/** Returns one of the properties as an XML element.
The result will a new XMLElement object that the caller must delete. If may return 0 if the
key isn't found, or if the entry contains an string that isn't valid XML.
The result will a new XMLElement object that the caller must delete. If may return nullptr
if the key isn't found, or if the entry contains an string that isn't valid XML.
If the value isn't found in this set, then this will look for it in a fallback
property set (if you've specified one with the setFallbackPropertySet() method),

@ -75,7 +75,7 @@ const File File::nonexistent;
String File::parseAbsolutePath (const String& p)
{
if (p.isEmpty())
return String::empty;
return String();
#if JUCE_WINDOWS
// Windows..
@ -322,7 +322,7 @@ String File::getFileNameWithoutExtension() const
bool File::isAChildOf (const File& potentialParent) const
{
if (potentialParent == File::nonexistent)
if (potentialParent.fullPath.isEmpty())
return false;
const String ourPath (getPathUpToLastSlash());
@ -482,11 +482,11 @@ bool File::loadFileAsData (MemoryBlock& destBlock) const
String File::loadFileAsString() const
{
if (! existsAsFile())
return String::empty;
return String();
FileInputStream in (*this);
return in.openedOk() ? in.readEntireStreamAsString()
: String::empty;
: String();
}
void File::readLines (StringArray& destLines) const
@ -598,7 +598,7 @@ String File::getFileExtension() const
if (indexOfDot > fullPath.lastIndexOfChar (separator))
return fullPath.substring (indexOfDot);
return String::empty;
return String();
}
bool File::hasFileExtension (StringRef possibleSuffix) const
@ -629,7 +629,7 @@ bool File::hasFileExtension (StringRef possibleSuffix) const
File File::withFileExtension (StringRef newExtension) const
{
if (fullPath.isEmpty())
return File::nonexistent;
return File();
String filePart (getFileName());

@ -741,7 +741,7 @@ public:
@see revealToUser
*/
bool startAsProcess (const String& parameters = String::empty) const;
bool startAsProcess (const String& parameters = String()) const;
/** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
@see startAsProcess

@ -50,7 +50,7 @@ TemporaryFile::TemporaryFile (const File& target, const int optionFlags)
targetFile (target)
{
// If you use this constructor, you need to give it a valid target file!
jassert (targetFile != File::nonexistent);
jassert (targetFile != File());
}
TemporaryFile::TemporaryFile (const File& target, const File& temporary)
@ -79,7 +79,7 @@ bool TemporaryFile::overwriteTargetFileWithTemporary() const
{
// This method only works if you created this object with the constructor
// that takes a target file!
jassert (targetFile != File::nonexistent);
jassert (targetFile != File());
if (temporaryFile.exists())
{

@ -89,7 +89,7 @@ public:
The file will not be created until you write to it. And remember that when
this object is deleted, the file will also be deleted!
*/
TemporaryFile (const String& suffix = String::empty,
TemporaryFile (const String& suffix = String(),
int optionFlags = 0);
/** Creates a temporary file in the same directory as a specified file.

@ -35,7 +35,7 @@ public:
switch (t.getAndAdvance())
{
case 0: result = var::null; return Result::ok();
case 0: result = var(); return Result::ok();
case '{': return parseObject (t, result);
case '[': return parseArray (t, result);
}
@ -148,7 +148,7 @@ private:
if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
{
t = t2;
result = var::null;
result = var();
return Result::ok();
}
break;
@ -254,7 +254,7 @@ private:
if (c2 != ':')
return createFail ("Expected ':', but found", &oldT);
resultProperties.set (propertyName, var::null);
resultProperties.set (propertyName, var());
var* propertyValue = resultProperties.getVarPointer (propertyName);
Result r2 (parseAny (t, *propertyValue));
@ -300,7 +300,7 @@ private:
return createFail ("Unexpected end-of-input in array declaration");
t = oldT;
destArray->add (var::null);
destArray->add (var());
Result r (parseAny (t, destArray->getReference (destArray->size() - 1)));
if (r.failed())
@ -514,7 +514,7 @@ var JSON::parse (const String& text)
var result;
if (! JSONParser::parseObjectOrArray (text.getCharPointer(), result))
result = var::null;
result = var();
return result;
}
@ -610,7 +610,7 @@ public:
{
switch (r.nextInt (depth > 3 ? 6 : 8))
{
case 0: return var::null;
case 0: return var();
case 1: return r.nextInt();
case 2: return r.nextInt64();
case 3: return r.nextBool();
@ -638,7 +638,7 @@ public:
}
default:
return var::null;
return var();
}
}

@ -298,11 +298,10 @@ struct JavascriptEngine::RootObject : public DynamicObject
if (r == returnWasHit) return r;
if (r == breakWasHit) break;
if (r == continueWasHit) continue;
iterator->perform (s, nullptr);
if (isDoLoop && ! condition->getResult (s))
if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
break;
}
@ -1244,7 +1243,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1));
if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0));
if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var::null));
if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var()));
if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location));
if (currentType == TokenTypes::literal)

@ -26,7 +26,6 @@
==============================================================================
*/
/**
A simple javascript interpreter!

@ -1,7 +1,7 @@
{
"id": "juce_core",
"name": "JUCE core classes",
"version": "3.0.0",
"version": "3.0.1",
"description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.",
"website": "http://www.juce.com/juce",
"license": "ISC Permissive",

@ -951,7 +951,7 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con
else
{
jassertfalse; // can't do the specified base!
return String::empty;
return String();
}
s = s.paddedLeft ('0', minimumNumCharacters);

@ -53,7 +53,7 @@ public:
virtual String getName() const
{
jassertfalse; // You shouldn't call this for an expression that's not actually a function!
return String::empty;
return String();
}
virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
@ -1181,5 +1181,5 @@ void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) c
String Expression::Scope::getScopeUID() const
{
return String::empty;
return String();
}

@ -26,7 +26,6 @@
==============================================================================
*/
Uuid::Uuid()
{
Random r;

@ -80,7 +80,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
break;
}
return File::nonexistent;
return File();
}
bool File::moveToTrash() const

@ -72,7 +72,7 @@ bool File::isOnRemovableDrive() const
String File::getVersion() const
{
return String::empty; // xxx not yet implemented
return String(); // xxx not yet implemented
}
//==============================================================================
@ -115,7 +115,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
if (struct passwd* const pw = getpwuid (getuid()))
return File (CharPointer_UTF8 (pw->pw_dir));
return File::nonexistent;
return File();
}
case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~");
@ -163,7 +163,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
break;
}
return File::nonexistent;
return File();
}
//==============================================================================

@ -309,7 +309,7 @@ private:
{
char c = 0;
if (read (&c, 1) != 1)
return String::empty;
return String();
buffer.writeByte (c);
@ -324,7 +324,7 @@ private:
if (header.startsWithIgnoreCase ("HTTP/"))
return header;
return String::empty;
return String();
}
static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value)
@ -432,7 +432,7 @@ private:
if (lines[i].startsWithIgnoreCase (itemName))
return lines[i].substring (itemName.length()).trim();
return String::empty;
return String();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)

@ -44,7 +44,7 @@ String SystemStats::getOperatingSystemName()
String SystemStats::getDeviceDescription()
{
return String::empty;
return String();
}
bool SystemStats::isOperatingSystem64Bit()
@ -69,7 +69,7 @@ namespace LinuxStatsHelpers
if (lines[i].startsWithIgnoreCase (key))
return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
return String::empty;
return String();
}
}
@ -107,7 +107,7 @@ String SystemStats::getLogonName()
if (struct passwd* const pw = getpwuid (getuid()))
return CharPointer_UTF8 (pw->pw_name);
return String::empty;
return String();
}
String SystemStats::getFullUserName()
@ -121,7 +121,7 @@ String SystemStats::getComputerName()
if (gethostname (name, sizeof (name) - 1) == 0)
return name;
return String::empty;
return String();
}
static String getLocaleValue (nl_item key)

@ -257,7 +257,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File (resultPath.convertToPrecomposedUnicode());
}
return File::nonexistent;
return File();
}
//==============================================================================
@ -271,7 +271,7 @@ String File::getVersion() const
return nsStringToJuce (name);
}
return String::empty;
return String();
}
//==============================================================================

@ -29,7 +29,7 @@
String String::fromCFString (CFStringRef cfString)
{
if (cfString == 0)
return String::empty;
return String();
CFRange range = { 0, CFStringGetLength (cfString) };
HeapBlock <UniChar> u ((size_t) range.length + 1);

@ -124,7 +124,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
return iOS;
#else
StringArray parts;
parts.addTokens (getOSXVersion(), ".", String::empty);
parts.addTokens (getOSXVersion(), ".", String());
jassert (parts[0].getIntValue() == 10);
const int major = parts[1].getIntValue();
@ -148,7 +148,7 @@ String SystemStats::getDeviceDescription()
#if JUCE_IOS
return nsStringToJuce ([[UIDevice currentDevice] model]);
#else
return String::empty;
return String();
#endif
}
@ -182,7 +182,7 @@ String SystemStats::getCpuVendor()
return String (reinterpret_cast <const char*> (vendor), 12);
#else
return String::empty;
return String();
#endif
}
@ -218,7 +218,7 @@ String SystemStats::getComputerName()
if (gethostname (name, sizeof (name) - 1) == 0)
return String (name).upToLastOccurrenceOf (".local", false, true);
return String::empty;
return String();
}
static String getLocaleValue (CFStringRef key)

@ -636,7 +636,7 @@ String File::getVolumeLabel() const
}
#endif
return String::empty;
return String();
}
int File::getVolumeSerialNumber() const

@ -93,7 +93,7 @@ namespace WindowsFileHelpers
if (SHGetSpecialFolderPath (0, path, type, FALSE))
return File (String (path));
return File::nonexistent;
return File();
}
File getModuleFileName (HINSTANCE moduleHandle)
@ -542,7 +542,7 @@ File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type)
default:
jassertfalse; // unknown type?
return File::nonexistent;
return File();
}
return WindowsFileHelpers::getSpecialFolderPath (csidlType);

@ -55,7 +55,7 @@ IPAddress::IPAddress (uint32 n) noexcept
IPAddress::IPAddress (const String& adr)
{
StringArray tokens;
tokens.addTokens (adr, ".", String::empty);
tokens.addTokens (adr, ".", String());
for (int i = 0; i < 4; ++i)
address[i] = (uint8) tokens[i].getIntValue();

@ -386,7 +386,7 @@ void StreamingSocket::close()
::close (handle);
#endif
hostName = String::empty;
hostName.clear();
portNumber = 0;
handle = -1;
isListener = false;
@ -506,7 +506,7 @@ void DatagramSocket::close()
::close (handle);
#endif
hostName = String::empty;
hostName.clear();
portNumber = 0;
handle = -1;
}

@ -146,7 +146,7 @@ public:
@see waitForNextConnection
*/
bool createListener (int portNumber, const String& localHostName = String::empty);
bool createListener (int portNumber, const String& localHostName = String());
/** When in "listener" mode, this waits for a connection and spawns it as a new
socket.

@ -181,7 +181,7 @@ namespace URLHelpers
<< "\"; filename=\"" << file.getFileName() << "\"\r\n";
const String mimeType (url.getMimeTypesOfUploadFiles()
.getValue (paramName, String::empty));
.getValue (paramName, String()));
if (mimeType.isNotEmpty())
data << "Content-Type: " << mimeType << "\r\n";
@ -253,7 +253,7 @@ String URL::getSubPath() const
{
const int startOfPath = URLHelpers::findStartOfPath (url);
return startOfPath <= 0 ? String::empty
return startOfPath <= 0 ? String()
: url.substring (startOfPath);
}
@ -363,7 +363,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const
if (in != nullptr)
return in->readEntireStreamAsString();
return String::empty;
return String();
}
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const
@ -470,5 +470,5 @@ bool URL::launchInDefaultBrowser() const
if (u.containsChar ('@') && ! u.containsChar (':'))
u = "mailto:" + u;
return Process::openDocument (u, String::empty);
return Process::openDocument (u, String());
}

@ -251,7 +251,7 @@ public:
InputStream* createInputStream (bool usePostCommand,
OpenStreamProgressCallback* progressCallback = nullptr,
void* progressCallbackContext = nullptr,
String extraHeaders = String::empty,
String extraHeaders = String(),
int connectionTimeOutMs = 0,
StringPairArray* responseHeaders = nullptr) const;

@ -36,7 +36,7 @@
*/
#define JUCE_MAJOR_VERSION 3
#define JUCE_MINOR_VERSION 0
#define JUCE_BUILDNUMBER 0
#define JUCE_BUILDNUMBER 1
/** Current Juce version number.

@ -43,11 +43,17 @@ LocalisedStrings::~LocalisedStrings()
//==============================================================================
String LocalisedStrings::translate (const String& text) const
{
if (fallback != nullptr && ! translations.containsKey (text))
return fallback->translate (text);
return translations.getValue (text, text);
}
String LocalisedStrings::translate (const String& text, const String& resultIfNotFound) const
{
if (fallback != nullptr && ! translations.containsKey (text))
return fallback->translate (text, resultIfNotFound);
return translations.getValue (text, resultIfNotFound);
}
@ -73,7 +79,7 @@ namespace
SpinLock currentMappingsLock;
ScopedPointer<LocalisedStrings> currentMappings;
int findCloseQuote (const String& text, int startPos)
static int findCloseQuote (const String& text, int startPos)
{
juce_wchar lastChar = 0;
String::CharPointerType t (text.getCharPointer() + startPos);
@ -92,7 +98,7 @@ namespace
return startPos;
}
String unescapeString (const String& s)
static String unescapeString (const String& s)
{
return s.replace ("\\\"", "\"")
.replace ("\\\'", "\'")
@ -141,6 +147,8 @@ void LocalisedStrings::loadFromText (const String& fileContents, bool ignoreCase
countryCodes.removeEmptyStrings();
}
}
translations.minimiseStorageOverheads();
}
void LocalisedStrings::addStrings (const LocalisedStrings& other)
@ -151,6 +159,11 @@ void LocalisedStrings::addStrings (const LocalisedStrings& other)
translations.addArray (other.translations);
}
void LocalisedStrings::setFallback (LocalisedStrings* f)
{
fallback = f;
}
//==============================================================================
void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations)
{

@ -183,11 +183,18 @@ public:
*/
void addStrings (const LocalisedStrings&);
/** Gives this object a set of strings to use as a fallback if a string isn't found.
The object that is passed-in will be owned and deleted by this object
when no longer needed. It can be nullptr to clear the existing fallback object.
*/
void setFallback (LocalisedStrings* fallbackStrings);
private:
//==============================================================================
String languageName;
StringArray countryCodes;
StringPairArray translations;
ScopedPointer<LocalisedStrings> fallback;
void loadFromText (const String&, bool ignoreCase);

@ -259,6 +259,12 @@ void String::swapWith (String& other) noexcept
std::swap (text, other.text);
}
void String::clear() noexcept
{
StringHolder::release (text);
text = &(emptyString.text);
}
String& String::operator= (const String& other) noexcept
{
StringHolder::retain (other.text);
@ -419,7 +425,8 @@ namespace NumberToStringConverters
{
explicit StackArrayStream (char* d)
{
imbue (std::locale::classic());
static const std::locale classicLocale (std::locale::classic());
imbue (classicLocale);
setp (d, d + charsNeededForDouble);
}

@ -307,6 +307,9 @@ public:
*/
inline bool isNotEmpty() const noexcept { return text[0] != 0; }
/** Resets this string to be empty. */
void clear() noexcept;
/** Case-insensitive comparison with another string. */
bool equalsIgnoreCase (const String& other) const noexcept;

@ -293,7 +293,7 @@ String StringArray::joinIntoString (StringRef separator, int start, int numberTo
start = 0;
if (start >= last)
return String::empty;
return String();
if (start == last - 1)
return strings.getReference (start);

@ -78,6 +78,11 @@ String StringPairArray::getValue (StringRef key, const String& defaultReturnValu
return defaultReturnValue;
}
bool StringPairArray::containsKey (StringRef key) const noexcept
{
return keys.contains (key);
}
void StringPairArray::set (const String& key, const String& value)
{
const int i = keys.indexOf (key, ignoreCase);

@ -85,6 +85,8 @@ public:
*/
String getValue (StringRef, const String& defaultReturnValue) const;
/** Returns true if the given key exists. */
bool containsKey (StringRef key) const noexcept;
/** Returns a list of all keys in the array. */
const StringArray& getAllKeys() const noexcept { return keys; }

@ -81,7 +81,7 @@ namespace StringPoolHelpers
String::CharPointerType StringPool::getPooledString (const String& s)
{
if (s.isEmpty())
return String::empty.getCharPointer();
return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
}
@ -89,7 +89,7 @@ String::CharPointerType StringPool::getPooledString (const String& s)
String::CharPointerType StringPool::getPooledString (const char* const s)
{
if (s == nullptr || *s == 0)
return String::empty.getCharPointer();
return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
}
@ -97,7 +97,7 @@ String::CharPointerType StringPool::getPooledString (const char* const s)
String::CharPointerType StringPool::getPooledString (const wchar_t* const s)
{
if (s == nullptr || *s == 0)
return String::empty.getCharPointer();
return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
}

@ -247,7 +247,7 @@ public:
/** Returns one of the jobs in the queue.
Note that this can be a very volatile list as jobs might be continuously getting shifted
around in the list, and this method may return 0 if the index is currently out-of-range.
around in the list, and this method may return nullptr if the index is currently out-of-range.
*/
ThreadPoolJob* getJob (int index) const;

@ -28,7 +28,7 @@
static void appendToFile (const File& f, const String& s)
{
if (f != File::nonexistent)
if (f.getFullPathName().isNotEmpty())
{
FileOutputStream out (f);

@ -65,7 +65,7 @@ public:
*/
PerformanceCounter (const String& counterName,
int runsPerPrintout = 100,
const File& loggingFile = File::nonexistent);
const File& loggingFile = File());
/** Destructor. */
~PerformanceCounter();

@ -210,7 +210,7 @@ XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToPar
}
else
{
lastError = String::empty;
lastError.clear();
ScopedPointer<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement));

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

Loading…
Cancel
Save