MasterSubmix
MasterSubmix
#Overview
name: MasterSubmix
The value of this variable can be defined or overridden in .ini config files. 2
.ini config files referencing this setting variable.
It is referenced in 11
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of MasterSubmix is to serve as the default submix through which all sounds are routed to and ultimately outputs to the audio hardware. It is a crucial component of the audio system in Unreal Engine 5.
This setting variable is primarily used by the audio system in Unreal Engine 5. It is referenced in various audio-related modules and plugins, including:
- AudioInsights plugin
- MediaIOCore plugin
- MovieRenderPipelineCore plugin
- AudioEditor module
- AudioMixer module
- Engine module
The value of this variable is set in the Audio Settings of the project. It is defined as a FSoftObjectPath in the UAudioSettings class, which allows for lazy loading of the submix asset.
MasterSubmix interacts with other audio-related variables and systems, such as:
- BaseDefaultSubmix: Another submix setting used for implicit submix sends.
- Audio device and mixer device objects.
- Submix analyzers and listeners.
Developers should be aware of the following when using this variable:
- The MasterSubmix cannot be set to a submix that has a parent submix. It must be a top-level submix.
- Changing the MasterSubmix may require a restart of the engine or project.
- It’s used for initializing the audio system and setting up submix hierarchies.
Best practices when using this variable include:
- Ensure the MasterSubmix is properly set in the project’s Audio Settings.
- Avoid frequently changing the MasterSubmix during runtime, as it may have significant impact on the audio system.
- When creating custom audio systems or plugins, reference the MasterSubmix through the audio settings rather than hard-coding it.
- Be cautious when modifying the MasterSubmix, as it affects the entire audio output of the game or application.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:1598, section: [/Script/Engine.AudioSettings]
- INI Section:
/Script/Engine.AudioSettings
- Raw value:
/Engine/EngineSounds/Submixes/MasterSubmixDefault.MasterSubmixDefault
- Is Array:
False
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:251, section: [/Script/Engine.AudioSettings]
- INI Section:
/Script/Engine.AudioSettings
- Raw value:
/Game/Audio/Submixes/MainSubmix.MainSubmix
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/AudioInsights/Source/AudioInsights/Private/Views/OutputMeterDashboardViewFactory.cpp:44
Scope (from outer to inner):
file
namespace UE::Audio::Insights
function TSharedRef<SWidget> FOutputMeterDashboardViewFactory::MakeWidget
Source code excerpt:
AudioSettings.IsValid())
{
MainSubmix = Cast<USoundSubmix>(AudioSettings->MasterSubmix.ResolveObject());
if (MainSubmix)
{
OutputMeterSubmixAnalyzer = MakeShared<FAudioMeterSubmixAnalyzer>(MainSubmix);
FDashboardFactory::OnActiveAudioDeviceChanged.AddSP(this, &FOutputMeterDashboardViewFactory::HandleOnActiveAudioDeviceChanged);
#Loc: <Workspace>/Engine/Plugins/AudioInsights/Source/AudioInsights/Private/Views/OutputOscilloscopeDashboardViewFactory.cpp:42
Scope (from outer to inner):
file
namespace UE::Audio::Insights
function TSharedRef<SWidget> FOutputOscilloscopeDashboardViewFactory::MakeWidget
Source code excerpt:
AudioSettings.IsValid())
{
MainSubmix = Cast<USoundSubmix>(AudioSettings->MasterSubmix.ResolveObject());
if (MainSubmix)
{
OutputOscilloscopeAnalyzer = MakeShared<FAudioOscilloscopeAnalyzer>(MainSubmix);
FDashboardFactory::OnActiveAudioDeviceChanged.AddSP(this, &FOutputOscilloscopeDashboardViewFactory::HandleOnActiveAudioDeviceChanged);
#Loc: <Workspace>/Engine/Plugins/Media/MediaIOFramework/Source/MediaIOCore/Private/MediaIOCoreAudioOutput.cpp:168
Scope (from outer to inner):
file
function void FMediaIOAudioCapture::RegisterBufferListener
Source code excerpt:
NumChannels = MixerDevice->GetDeviceOutputChannels();
SampleRate = MixerDevice->GetSampleRate();
PrimarySubmixName = *GetDefault<UAudioSettings>()->MasterSubmix.GetAssetName();
AudioDevice->RegisterSubmixBufferListener(AsShared(), AudioDevice->GetMainSubmixObject());
}
}
const FString& FMediaIOAudioCapture::GetListenerName() const
{
#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/Graph/MovieGraphDefaultAudioRenderer.cpp:22
Scope (from outer to inner):
file
function void UMovieGraphDefaultAudioRenderer::StartAudioRecording
Source code excerpt:
if (Audio::FMixerDevice* MixerDevice = UE::MovieGraph::Audio::GetAudioMixerDeviceFromWorldContext(this))
{
const TWeakPtr<Audio::FMixerSubmix> MasterSubmix = MixerDevice->GetMasterSubmix();
if (MasterSubmix.Pin())
{
AudioState.ActiveSubmixes.Add(MasterSubmix);
}
for (TWeakPtr<Audio::FMixerSubmix>& WeakSubmix : AudioState.ActiveSubmixes)
{
constexpr float ExpectedDuration = 30.f;
WeakSubmix.Pin()->OnStartRecordingOutput(ExpectedDuration);
#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/MoviePipelineAudioRendering.cpp:76
Scope (from outer to inner):
file
function void UMoviePipeline::StartAudioRecording
Source code excerpt:
if (MixerDevice)
{
TWeakPtr<Audio::FMixerSubmix, ESPMode::ThreadSafe> MasterSubmix = MixerDevice->GetMasterSubmix();
if (MasterSubmix.Pin())
{
AudioState.ActiveSubmixes.Add(MasterSubmix);
}
for (TWeakPtr<Audio::FMixerSubmix, ESPMode::ThreadSafe> WeakSubmix : AudioState.ActiveSubmixes)
{
const float ExpectedDuration = 30.f;
WeakSubmix.Pin()->OnStartRecordingOutput(ExpectedDuration);
#Loc: <Workspace>/Engine/Source/Editor/AudioEditor/Private/SoundSubmixGraphSchema.cpp:125
Scope (from outer to inner):
file
function bool USoundSubmixGraphSchema::ConnectionCausesLoop
Source code excerpt:
if (const UAudioSettings* Settings = GetDefault<UAudioSettings>())
{
if (USoundSubmix* MasterSubmix = Cast<USoundSubmix>(Settings->MasterSubmix.TryLoad()))
{
if (OutputNode->SoundSubmix == MasterSubmix)
{
return true;
}
if (SubmixUtils::FindInGraph(MasterSubmix, OutputNode->SoundSubmix, false))
{
return true;
}
}
}
#Loc: <Workspace>/Engine/Source/Runtime/AudioMixer/Private/AudioMixerDevice.cpp:1164
Scope (from outer to inner):
file
namespace Audio
function void FMixerDevice::InitSoundSubmixes
Source code excerpt:
// 1. Load or reload all sound submixes/instances
LoadRequiredSubmix(ERequiredSubmixes::Main, TEXT("MasterSubmixDefault"), false /* DefaultMuteWhenBackgrounded */, AudioSettings->MasterSubmix);
// BaseDefaultSubmix is an optional master submix type set by project settings
if (AudioSettings->BaseDefaultSubmix.IsValid())
{
LoadRequiredSubmix(ERequiredSubmixes::BaseDefault, TEXT("BaseDefault"), false /* DefaultMuteWhenBackgrounded */, AudioSettings->BaseDefaultSubmix);
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Sound/AudioSettings.h:154
Scope (from outer to inner):
file
class class UAudioSettings : public UDeveloperSettings
Source code excerpt:
/** The default submix through which all sounds are routed to. The root submix that outputs to audio hardware. */
UPROPERTY(config, EditAnywhere, Category="Mix", meta=(AllowedClasses="/Script/Engine.SoundSubmix"))
FSoftObjectPath MasterSubmix;
/** The default submix to use for implicit submix sends (i.e. if the base submix send is null or if a submix parent is null) */
UPROPERTY(config, EditAnywhere, Category = "Mix", meta = (AllowedClasses = "/Script/Engine.SoundSubmix"), AdvancedDisplay)
FSoftObjectPath BaseDefaultSubmix;
/** The submix through which all sounds set to use reverb are routed */
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioSettings.cpp:48
Scope (from outer to inner):
file
function void UAudioSettings::PreEditChange
Source code excerpt:
// Cache master submix in case user tries to set to submix that isn't a top-level submix
CachedMasterSubmix = MasterSubmix;
// Cache at least the first entry in case someone tries to clear the array
CachedQualityLevels = QualityLevels;
}
void UAudioSettings::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioSettings.cpp:64
Scope (from outer to inner):
file
function void UAudioSettings::PostEditChangeChainProperty
Source code excerpt:
LoadDefaultObjects();
if (PropertyName == GET_MEMBER_NAME_CHECKED(UAudioSettings, MasterSubmix))
{
if (USoundSubmix* NewSubmix = Cast<USoundSubmix>(MasterSubmix.TryLoad()))
{
if (NewSubmix->ParentSubmix)
{
FNotificationInfo Info(LOCTEXT("AudioSettings_InvalidMasterSubmix", "'Master Submix' cannot be set to submix with parent."));
Info.bFireAndForget = true;
Info.ExpireDuration = 2.0f;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioSettings.cpp:76
Scope (from outer to inner):
file
function void UAudioSettings::PostEditChangeChainProperty
Source code excerpt:
FSlateNotificationManager::Get().AddNotification(Info);
MasterSubmix = CachedMasterSubmix;
}
}
bPromptRestartRequired = true;
}
else if (PropertyName == GET_MEMBER_NAME_CHECKED(UAudioSettings, BaseDefaultSubmix))