Mixing buses allow you to group and control multiple audio sources together. A mixing bus acts as a virtual audio mixer channel that enables:
- Group audio sources: Route multiple sounds through a single bus
- Collective volume control: Adjust the volume of all sounds on a bus with a single call
- Shared effects: Apply filters to all sounds routed through the bus
- Dynamic routing: Move live sounds between buses at runtime
Mixing buses are particularly useful for games and applications that need to manage different audio categories like music, SFX, voiceovers, and ambience independently.
// Create a new mixing bus with an optional name
final sfxBus = SoLoud.instance.createMixingBus(name: 'SFX');
final musicBus = SoLoud.instance.createMixingBus(name: 'Music');A bus must be "played" on the main engine before its output becomes audible:
// Play the bus on the engine (required!)
final busHandle = sfxBus.playOnEngine();
// You can also set initial volume and paused state
musicBus.playOnEngine(volume: 0.8, paused: false);// Load audio assets
final explosion = await SoLoud.instance.loadAsset('assets/explosion.mp3');
final backgroundMusic = await SoLoud.instance.loadAsset('assets/music.mp3');
// Play sounds through the bus (supports scale, looping, and loop regions)...
final sfxHandle = sfxBus.play(explosion);
final musicHandle = musicBus.play(
backgroundMusic,
looping: true,
scale: 1.0,
);
// ...or play it with the usual `play()` method
final explosionHandle = SoLoud.instance.play(explosion, busId: sfxBus.busId);// Adjust volume for all sounds on the bus
SoLoud.instance.setVolume(sfxBus.soundHandle!, 0.5);
// Apply effects to the entire bus
sfxBus.filters.echoFilter.activate();
sfxBus.filters.echoFilter.delay.value = 0.3;
// Get the number of active voices on the bus
final voiceCount = sfxBus.getActiveVoiceCount();Use the Buses singleton to manage all active buses:
// Get all active buses
final allBuses = Buses().buses;
// Find a bus by name
final sfxBus = Buses().byName('SFX');
// Find a bus by ID
final bus = Buses().byId(1);When you're done with a bus, dispose it to free resources:
// Dispose a bus (stops all sounds playing through it)
sfxBus.dispose();Move a live sound from one bus to another (or from the engine to a bus):
// Play a sound on the main engine
final handle = await SoLoud.instance.play(someSound);
// Later, move it to a bus
sfxBus.annexSound(handle);This is useful for:
- Dynamically grouping sounds at runtime
- Moving sounds between audio categories
- Applying effects to sounds that are already playing
You can play 3D positioned sounds through a bus:
// Play a 3D sound through the bus
final handle = sfxBus.play3d(
explosion,
10.0, // posX
0.0, // posY
5.0, // posZ
velX: 0, velY: 0, velZ: 0,
volume: 1.0,
scale: 1.0,
looping: false,
);Apply filters to affect all sounds on a bus:
// Activate pitch shift filter on the bus
sfxBus.filters.pitchShiftFilter.activate();
sfxBus.filters.pitchShiftFilter
..shift(soundHandle: sfxBus.soundHandle).value = 1.5;
// Apply low-fi effect to all music
musicBus.filters.lofiFilter.activate();
musicBus.filters.lofiFilter
..sampleRate.value = 8000
..bitDepth.value = 4;
// Deactivate filters
sfxBus.filters.pitchShiftFilter.deactivate();Configure the number of output channels and monitor levels:
// Set bus to mono or stereo (default is stereo)
sfxBus.setChannels(channels: Channels.mono);
// Get approximate output volume for VU meters
final leftVolume = sfxBus.getChannelVolume(0);
final rightVolume = sfxBus.getChannelVolume(1);class AudioManager {
late Bus musicBus;
late Bus sfxBus;
late Bus voiceBus;
Future<void> init() async {
await SoLoud.instance.init();
// Create buses for different audio categories
musicBus = SoLoud.instance.createMixingBus(name: 'Music');
sfxBus = SoLoud.instance.createMixingBus(name: 'SFX');
voiceBus = SoLoud.instance.createMixingBus(name: 'Voice');
// Play all buses on the engine
musicBus.playOnEngine(volume: 0.7);
sfxBus.playOnEngine(volume: 1.0);
voiceBus.playOnEngine(volume: 0.9);
}
Future<void> playMusic(String path) async {
final music = await SoLoud.instance.loadAsset(path);
await musicBus.play(music, looping: true);
}
Future<void> playSfx(String path) async {
final sfx = await SoLoud.instance.loadAsset(path);
await sfxBus.play(sfx);
}
Future<void> playVoice(String path) async {
final voice = await SoLoud.instance.loadAsset(path);
await voiceBus.play(voice);
}
// Duck music when voice plays
void duckMusicForVoice() {
SoLoud.instance.setVolume(musicBus.soundHandle!, 0.3);
}
void restoreMusicVolume() {
SoLoud.instance.setVolume(musicBus.soundHandle!, 0.7);
}
void dispose() {
musicBus.dispose();
sfxBus.dispose();
voiceBus.dispose();
}
}- Always call
playOnEngine()after creating a bus - sounds won't be audible until you do - Use meaningful names when creating buses to make them easier to identify
- Group logically - create buses for audio categories (music, SFX, UI, voice)
- Clean up - dispose buses when they're no longer needed
- Monitor voice count - use
getActiveVoiceCount()to debug audio issues - Use buses for effects - apply filters to buses rather than individual sounds when possible
- Volume categories - use buses to implement user-adjustable volume settings per category
- Bus class API - Full API documentation
- SoLoud Mixing Bus Documentation - Official SoLoud docs