Skip to content

Commit

Permalink
Windows: Added support for IAudioClient3 shared stream low latency mo…
Browse files Browse the repository at this point in the history
…de in the WASAPI audio device, removed JUCE_WASAPI_EXCLUSIVE config flag and refactored AudioIODeviceType creation
  • Loading branch information
ed95 committed Sep 4, 2020
1 parent b01e927 commit 6195a5a
Show file tree
Hide file tree
Showing 17 changed files with 480 additions and 314 deletions.
27 changes: 27 additions & 0 deletions BREAKING-CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@ JUCE breaking changes
Develop
=======

Change
------
The JUCE_WASAPI_EXCLUSIVE flag has been removed from juce_audio_devices and all
available WASAPI audio device modes (shared, shared low latency and exclusive)
are available by default when JUCE_WASAPI is enabled. The
AudioIODeviceType::createAudioIODeviceType_WASAPI() method which takes a single
boolean argument has also been deprecated in favour of a new method which takes
a WASAPIDeviceMode enum.

Possible Issues
---------------
Code that relied on the JUCE_WASAPI_EXCLUSIVE flag to disable WASAPI exclusive
mode will no longer work.

Workaround
----------
Override the AudioDeviceManager::createAudioDeviceTypes() method to omit the
WASAPI exclusive mode device if you do not want it to be available.

Rationale
---------
JUCE now supports shared low latency WASAPI audio devices via the AudioClient3
interface and instead of adding an additional compile time config flag to
enable this functionality, which adds complexity to the build process when not
using the Projucer, JUCE makes all WASAPI device modes available by default.


Change
------
The fields representing Mac OS X 10.4 to 10.6 inclusive have been removed from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType

void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
{
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (false));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (true));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::shared));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::exclusive));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::sharedLowLatency));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
Expand Down
101 changes: 79 additions & 22 deletions modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,48 +42,105 @@ void AudioIODeviceType::callDeviceChangeListeners()
}

//==============================================================================
#if ! JUCE_MAC
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_CoreAudio() { return nullptr; }
#if JUCE_MAC
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_CoreAudio() { return new CoreAudioClasses::CoreAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_CoreAudio() { return nullptr; }
#endif

#if ! JUCE_IOS
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio() { return nullptr; }
#if JUCE_IOS
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio() { return new iOSAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio() { return nullptr; }
#endif

#if ! (JUCE_WINDOWS && JUCE_WASAPI)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (bool) { return nullptr; }
#if JUCE_WINDOWS && JUCE_WASAPI
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode deviceMode)
{
auto windowsVersion = SystemStats::getOperatingSystemType();

if (windowsVersion < SystemStats::WinVista
|| (WasapiClasses::isLowLatencyMode (deviceMode) && windowsVersion < SystemStats::Windows10))
return nullptr;

return new WasapiClasses::WASAPIAudioIODeviceType (deviceMode);
}

AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (bool exclusiveMode)
{
return createAudioIODeviceType_WASAPI (exclusiveMode ? WASAPIDeviceMode::exclusive
: WASAPIDeviceMode::shared);
}
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode) { return nullptr; }
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (bool) { return nullptr; }
#endif

#if ! (JUCE_WINDOWS && JUCE_DIRECTSOUND)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() { return nullptr; }
#if JUCE_WINDOWS && JUCE_DIRECTSOUND
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() { return new DSoundAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() { return nullptr; }
#endif

#if ! (JUCE_WINDOWS && JUCE_ASIO)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ASIO() { return nullptr; }
#if JUCE_WINDOWS && JUCE_ASIO
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ASIO() { return new ASIOAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ASIO() { return nullptr; }
#endif

#if ! (JUCE_LINUX && JUCE_ALSA)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ALSA() { return nullptr; }
#if JUCE_LINUX && JUCE_ALSA
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ALSA() { return createAudioIODeviceType_ALSA_PCMDevices(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ALSA() { return nullptr; }
#endif

#if ! (JUCE_LINUX && JUCE_JACK)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK() { return nullptr; }
#if JUCE_LINUX && JUCE_JACK
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK() { return new JackAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK() { return nullptr; }
#endif

#if ! (JUCE_LINUX && JUCE_BELA)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Bela() { return nullptr; }
#if JUCE_LINUX && JUCE_BELA
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Bela() { return new BelaAudioIODeviceType(); }
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Bela() { return nullptr; }
#endif

#if ! JUCE_ANDROID
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Android() { return nullptr; }
#if JUCE_ANDROID
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Android()
{
#if JUCE_USE_ANDROID_OBOE
if (isOboeAvailable())
return nullptr;
#endif

#if JUCE_USE_ANDROID_OPENSLES
if (isOpenSLAvailable())
return nullptr;
#endif

return new AndroidAudioIODeviceType();
}
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Android() { return nullptr; }
#endif

#if ! (JUCE_ANDROID && JUCE_USE_ANDROID_OPENSLES)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES() { return nullptr; }
#if JUCE_ANDROID && JUCE_USE_ANDROID_OPENSLES
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES()
{
return isOpenSLAvailable() ? new OpenSLAudioDeviceType() : nullptr;
}
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES() { return nullptr; }
#endif

#if ! (JUCE_ANDROID && JUCE_USE_ANDROID_OBOE)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Oboe() { return nullptr; }
#if JUCE_ANDROID && JUCE_USE_ANDROID_OBOE
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Oboe()
{
return isOboeAvailable() ? new OboeAudioIODeviceType() : nullptr;
}
#else
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Oboe() { return nullptr; }
#endif

} // namespace juce
7 changes: 5 additions & 2 deletions modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ class JUCE_API AudioIODeviceType
static AudioIODeviceType* createAudioIODeviceType_CoreAudio();
/** Creates an iOS device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_iOSAudio();
/** Creates a WASAPI device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_WASAPI (bool exclusiveMode);
/** Creates a WASAPI device type in the specified mode if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_WASAPI (WASAPIDeviceMode deviceMode);
/** Creates a DirectSound device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_DirectSound();
/** Creates an ASIO device type if it's available on this platform, or returns null. */
Expand All @@ -168,6 +168,9 @@ class JUCE_API AudioIODeviceType
/** Creates a Bela device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_Bela();

/** This method has been deprecated. You should call the method which takes a WASAPIDeviceMode instead. */
JUCE_DEPRECATED (static AudioIODeviceType* createAudioIODeviceType_WASAPI (bool exclusiveMode));

protected:
explicit AudioIODeviceType (const String& typeName);

Expand Down
118 changes: 44 additions & 74 deletions modules/juce_audio_devices/juce_audio_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

#include "juce_audio_devices.h"

#include "native/juce_MidiDataConcatenator.h"

//==============================================================================
#if JUCE_MAC
#define Point CarbonDummyPointName
Expand All @@ -55,6 +57,9 @@
#undef Point
#undef Component

#include "native/juce_mac_CoreAudio.cpp"
#include "native/juce_mac_CoreMidi.cpp"

#elif JUCE_IOS
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
Expand All @@ -64,10 +69,18 @@
#import <CoreMIDI/MIDINetworkSession.h>
#endif

#include "native/juce_ios_Audio.cpp"
#include "native/juce_mac_CoreMidi.cpp"

//==============================================================================
#elif JUCE_WINDOWS
#if JUCE_WASAPI
#include <mmreg.h>
#include "native/juce_win32_WASAPI.cpp"
#endif

#if JUCE_DIRECTSOUND
#include "native/juce_win32_DirectSound.cpp"
#endif

#if JUCE_USE_WINRT_MIDI && JUCE_MSVC
Expand All @@ -93,6 +106,8 @@
JUCE_END_IGNORE_WARNINGS_MSVC
#endif

#include "native/juce_win32_Midi.cpp"

#if JUCE_ASIO
/* This is very frustrating - we only need to use a handful of definitions from
a couple of the header files in Steinberg's ASIO SDK, and it'd be easy to copy
Expand All @@ -114,6 +129,7 @@
needed - so to simplify things, you could just copy these into your JUCE directory).
*/
#include <iasiodrv.h>
#include "native/juce_win32_ASIO.cpp"
#endif

//==============================================================================
Expand All @@ -128,6 +144,7 @@
just set the JUCE_ALSA flag to 0.
*/
#include <alsa/asoundlib.h>
#include "native/juce_linux_ALSA.cpp"
#endif

#if JUCE_JACK
Expand All @@ -140,6 +157,7 @@
JUCE with low latency audio support, just set the JUCE_JACK flag to 0.
*/
#include <jack/jack.h>
#include "native/juce_linux_JackAudio.cpp"
#endif

#if JUCE_BELA
Expand All @@ -149,100 +167,44 @@
*/
#include <Bela.h>
#include <Midi.h>
#include "native/juce_linux_Bela.cpp"
#endif

#undef SIZEOF

//==============================================================================
#elif JUCE_ANDROID

#if JUCE_USE_ANDROID_OPENSLES
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>
#endif

#if JUCE_USE_ANDROID_OBOE
#if JUCE_USE_ANDROID_OPENSLES
#error "Oboe cannot be enabled at the same time as openSL! Please disable JUCE_USE_ANDROID_OPENSLES"
#endif

JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter",
"-Wzero-as-null-pointer-constant",
"-Winconsistent-missing-destructor-override",
"-Wshadow-field-in-constructor",
"-Wshadow-field")
#include <oboe/Oboe.h>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

#endif

#include "audio_io/juce_AudioDeviceManager.cpp"
#include "audio_io/juce_AudioIODevice.cpp"
#include "audio_io/juce_AudioIODeviceType.cpp"
#include "midi_io/juce_MidiMessageCollector.cpp"
#include "midi_io/juce_MidiDevices.cpp"
#include "sources/juce_AudioSourcePlayer.cpp"
#include "sources/juce_AudioTransportSource.cpp"
#include "native/juce_MidiDataConcatenator.h"

//==============================================================================
#if JUCE_MAC
#include "native/juce_mac_CoreAudio.cpp"
#include "native/juce_mac_CoreMidi.cpp"

//==============================================================================
#elif JUCE_IOS
#include "native/juce_ios_Audio.cpp"
#include "native/juce_mac_CoreMidi.cpp"

//==============================================================================
#elif JUCE_WINDOWS

#if JUCE_WASAPI
#include "native/juce_win32_WASAPI.cpp"
#endif

#if JUCE_DIRECTSOUND
#include "native/juce_win32_DirectSound.cpp"
#endif

#include "native/juce_win32_Midi.cpp"

#if JUCE_ASIO
#include "native/juce_win32_ASIO.cpp"
#endif

//==============================================================================
#elif JUCE_LINUX
#if JUCE_ALSA
#include "native/juce_linux_ALSA.cpp"
#endif

#if JUCE_JACK
#include "native/juce_linux_JackAudio.cpp"
#endif

#if JUCE_BELA
#include "native/juce_linux_Bela.cpp"
#else
#if ! JUCE_BELA
#include "native/juce_linux_Midi.cpp"
#endif

//==============================================================================
#elif JUCE_ANDROID

#include "native/juce_android_Audio.cpp"
#include "native/juce_android_Midi.cpp"

#if JUCE_USE_ANDROID_OPENSLES || JUCE_USE_ANDROID_OBOE
#include "native/juce_android_HighPerformanceAudioHelpers.h"

#if JUCE_USE_ANDROID_OPENSLES
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>
#include "native/juce_android_OpenSL.cpp"
#endif

#if JUCE_USE_ANDROID_OBOE
#if JUCE_USE_ANDROID_OPENSLES
#error "Oboe cannot be enabled at the same time as openSL! Please disable JUCE_USE_ANDROID_OPENSLES"
#endif

JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter",
"-Wzero-as-null-pointer-constant",
"-Winconsistent-missing-destructor-override",
"-Wshadow-field-in-constructor",
"-Wshadow-field")
#include <oboe/Oboe.h>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE

#include "native/juce_android_Oboe.cpp"
#endif
#endif
Expand All @@ -259,3 +221,11 @@ namespace juce
bool JUCE_CALLTYPE SystemAudioVolume::setMuted (bool) { jassertfalse; return false; }
}
#endif

#include "audio_io/juce_AudioDeviceManager.cpp"
#include "audio_io/juce_AudioIODevice.cpp"
#include "audio_io/juce_AudioIODeviceType.cpp"
#include "midi_io/juce_MidiMessageCollector.cpp"
#include "midi_io/juce_MidiDevices.cpp"
#include "sources/juce_AudioSourcePlayer.cpp"
#include "sources/juce_AudioTransportSource.cpp"
Loading

0 comments on commit 6195a5a

Please sign in to comment.