Skip to content

Commit

Permalink
Set audio to mix on for iOS (simulator) and Catalyst
Browse files Browse the repository at this point in the history
Sets audio on iOS (simulator) and Catalyst to mix rather than duck (default). This builds on #7366 by attempting to clean the code up a little, as well as make the changes only have effect when building for Apple platforms.

- [x] Update AudioEngine to contain a pointer to the engine context
  - This is not exposed via public getter since it's not used outside of the AudioEngine, but was required for memory management
- [x] Configure the audio context to mix for Core Audio (only when building for Apple platforms)

Tested on:
- [x] iOS
- [x] iPadOS
- [x] macOS Catalyst
- [x] macOS

Diffs=
238bf2fe1 Set audio to mix on for iOS (simulator) and Catalyst (#7555)

Co-authored-by: David Skuza <[email protected]>
  • Loading branch information
dskuza and dskuza committed Jul 16, 2024
1 parent fa95d87 commit 590a4fd
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ca56d756514d50c68ea3306739e6ad177caee2ab
238bf2fe1872740896a75629e8e349f53938b589
4 changes: 3 additions & 1 deletion include/rive/audio/audio_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef struct ma_engine ma_engine;
typedef struct ma_sound ma_sound;
typedef struct ma_device ma_device;
typedef struct ma_node_base ma_node_base;
typedef struct ma_context ma_context;

namespace rive
{
Expand Down Expand Up @@ -67,9 +68,10 @@ class AudioEngine : public RefCnt<AudioEngine>
size_t playingSoundCount();
#endif
private:
AudioEngine(ma_engine* engine);
AudioEngine(ma_engine* engine, ma_context* context);
ma_device* m_device;
ma_engine* m_engine;
ma_context* m_context;
std::mutex m_mutex;

void soundCompleted(rcp<AudioSound> sound);
Expand Down
54 changes: 51 additions & 3 deletions src/audio/audio_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,40 @@ void AudioEngine::stop() { ma_engine_stop(m_engine); }

rcp<AudioEngine> AudioEngine::Make(uint32_t numChannels, uint32_t sampleRate)
{
// I _think_ MA_NO_DEVICE_IO is defined when building for Unity; otherwise, it seems to pass
// "standard" building When defined, pContext is unavailable, which causes build errors when
// building Unity for iOS. - David
#if defined(MA_HAS_COREAUDIO) && !defined(MA_NO_DEVICE_IO)
// Used for configuration only, and isn't referenced past the usage of ma_context_init; thus,
// can be locally scoped. Uses the "logical" defaults from miniaudio, and updates only what we
// need. This should automatically set available backends in priority order based on the target
// it's built for, which in the case of Apple is Core Audio first.
ma_context_config contextConfig = ma_context_config_init();
contextConfig.coreaudio.sessionCategoryOptions = ma_ios_session_category_option_mix_with_others;

// We only need to initialize space for the context if we're targeting Apple platforms
ma_context* context = (ma_context*)malloc(sizeof(ma_context));

if (ma_context_init(NULL, 0, &contextConfig, context) != MA_SUCCESS)
{
free(context);
context = nullptr;
}
#else
ma_context* context = nullptr;
#endif

ma_engine_config engineConfig = ma_engine_config_init();
engineConfig.channels = numChannels;
engineConfig.sampleRate = sampleRate;

#if defined(MA_HAS_COREAUDIO) && !defined(MA_NO_DEVICE_IO)
if (context != nullptr)
{
engineConfig.pContext = context;
}
#endif

#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
engineConfig.noDevice = MA_TRUE;
#endif
Expand All @@ -175,19 +205,27 @@ rcp<AudioEngine> AudioEngine::Make(uint32_t numChannels, uint32_t sampleRate)

if (ma_engine_init(&engineConfig, engine) != MA_SUCCESS)
{
#if defined(MA_HAS_COREAUDIO) && !defined(MA_NO_DEVICE_IO)
if (context != nullptr)
{
ma_context_uninit(context);
free(context);
context = nullptr;
}
#endif
fprintf(stderr, "AudioEngine::Make - failed to init engine\n");
delete engine;
return nullptr;
}

return rcp<AudioEngine>(new AudioEngine(engine));
return rcp<AudioEngine>(new AudioEngine(engine, context));
}

uint32_t AudioEngine::channels() const { return ma_engine_get_channels(m_engine); }
uint32_t AudioEngine::sampleRate() const { return ma_engine_get_sample_rate(m_engine); }

AudioEngine::AudioEngine(ma_engine* engine) :
m_device(ma_engine_get_device(engine)), m_engine(engine)
AudioEngine::AudioEngine(ma_engine* engine, ma_context* context) :
m_device(ma_engine_get_device(engine)), m_engine(engine), m_context(context)
{}

rcp<AudioSound> AudioEngine::play(rcp<AudioSource> source,
Expand Down Expand Up @@ -367,6 +405,16 @@ AudioEngine::~AudioEngine()
}
m_completedSounds.clear();

#if defined(MA_HAS_COREAUDIO) && !defined(MA_NO_DEVICE_IO)
// m_context is only set when Core Audio is available
if (m_context != nullptr)
{
ma_context_uninit(m_context);
free(m_context);
m_context = nullptr;
}
#endif

ma_engine_uninit(m_engine);
delete m_engine;

Expand Down

0 comments on commit 590a4fd

Please sign in to comment.