Mixing
About Audio Mixing
Audio signal mixing is the process of combining multiple audio signals into a single output. This is commonly done in music production, live sound reinforcement, and broadcasting. The goal of mixing is to create a balanced and cohesive sound that enhances the overall listening experience. Mixing involves adjusting the levels, panning, and equalization of each individual signal to create a harmonious blend.
Code Example
This example loads two mp3 audio files and mixes them together using the MixerNode
. The two GainNode
instances can be used to control the volume of the individual audio players.
- JSON
- Swift
- Kotlin
- C++
- JavaScript
{
"nodes": {
{ "id": "drumsPlayerNode", "type": "AudioPlayerNode" },
{ "id": "drumsGainNode", "type": "GainNode" },
{ "id": "bassPlayerNode", "type": "AudioPlayerNode" },
{ "id": "bassGainNode", "type": "GainNode" },
{ "id": "mixerNode", "type": "MixerNode" }
},
"connections": {
{ "sourceNode": "drumsPlayerNode", "destinationNode": "drumsGainNode" },
{ "sourceNode": "bassPlayerNode", "destinationNode": "bassGainNode" },
{ "sourceNode": "drumsGainNode", "destinationNode": "mixerNode" },
{ "sourceNode": "bassGainNode", "destinationNode": "mixerNode" },
{ "sourceNode": "mixerNode", "destinationNode": "outputNode" }
},
"tracks": {
"drumsPlayerNode": "drums.mp3",
"bassPlayerNode": "bass.mp3"
}
}
import SwitchboardSDK
class MixerExample {
let audioEngine = SBAudioEngine()
let audioGraph = SBAudioGraph()
let drumsPlayerNode = SBAudioPlayerNode()
let drumsGainNode = SBGainNode()
let bassPlayerNode = SBAudioPlayerNode()
let bassGainNode = SBGainNode()
let mixerNode = SBMixerNode()
init() {
drumsPlayerNode.load("drums.mp3", withFormat: .mp3)
bassPlayerNode.load("bass.mp3", withFormat: .mp3)
audioGraph.addNode(drumsPlayerNode)
audioGraph.addNode(drumsGainNode)
audioGraph.addNode(bassPlayerNode)
audioGraph.addNode(bassGainNode)
audioGraph.addNode(mixerNode)
audioGraph.connect(drumsPlayerNode, to: drumsGainNode)
audioGraph.connect(bassPlayerNode, to: bassGainNode)
audioGraph.connect(drumsGainNode, to: mixerNode)
audioGraph.connect(bassGainNode, to: mixerNode)
audioGraph.connect(mixerNode, to: audioGraph.outputNode)
audioEngine.start(audioGraph)
}
func play() {
drumsPlayerNode.play()
bassPlayerNode.play()
}
func pause() {
drumsPlayerNode.pause()
bassPlayerNode.pause()
}
func setDrumsVolume(_ newValue: Float) {
drumsGainNode.setGain(newValue)
}
func setBassVolume(_ newValue: Float) {
bassGainNode.setGain(newValue)
}
}
import com.synervoz.switchboard.sdk.AudioEngine
import com.synervoz.switchboard.sdk.Codec
import com.synervoz.switchboard.sdk.audiograph.AudioGraph
import com.synervoz.switchboard.sdk.audiographnodes.AudioPlayerNode
import com.synervoz.switchboard.sdk.audiographnodes.GainNode
import com.synervoz.switchboard.sdk.audiographnodes.MixerNode
class MixerExample(context: Context) {
val audioEngine = AudioEngine(context)
val audioGraph = AudioGraph()
val drumsPlayerNode = AudioPlayerNode()
val drumsGainNode = GainNode()
val bassPlayerNode = AudioPlayerNode()
val bassGainNode = GainNode()
val mixerNode = MixerNode()
init {
drumsPlayerNode.load("drums.mp3", Codec.MP3)
bassPlayerNode.load("bass.mp3", Codec.MP3)
audioGraph.addNode(drumsPlayerNode)
audioGraph.addNode(drumsGainNode)
audioGraph.addNode(bassPlayerNode)
audioGraph.addNode(bassGainNode)
audioGraph.addNode(mixerNode)
audioGraph.connect(drumsPlayerNode, drumsGainNode)
audioGraph.connect(bassPlayerNode, bassGainNode)
audioGraph.connect(drumsGainNode, mixerNode)
audioGraph.connect(bassGainNode, mixerNode)
audioGraph.connect(mixerNode, audioGraph.outputNode)
audioEngine.start(audioGraph)
}
fun play() {
drumsPlayerNode.play()
bassPlayerNode.play()
}
fun pause() {
drumsPlayerNode.pause()
bassPlayerNode.pause()
}
fun setDrumsVolume(newValue: Float) {
drumsGainNode.setGain(newValue)
}
fun setBassVolume(newValue: Float) {
bassGainNode.setGain(newValue)
}
}
#include "AudioGraph.hpp"
#include "AudioPlayerNode.hpp"
#include "GainNode.hpp"
#include "MixerNode.hpp"
using namespace switchboard;
class MixerExample {
public:
MixerExample() {
// Adding nodes to audio graph
audioGraph.addNode(drumsPlayerNode);
audioGraph.addNode(drumsGainNode);
audioGraph.addNode(bassPlayerNode);
audioGraph.addNode(bassGainNode);
audioGraph.addNode(mixerNode);
// Connecting audio nodes
audioGraph.connect(drumsPlayerNode, drumsGainNode);
audioGraph.connect(bassPlayerNode, bassGainNode);
audioGraph.connect(drumsGainNode, mixerNode);
audioGraph.connect(bassGainNode, mixerNode);
audioGraph.connect(mixerNode, audioGraph.getOutputNode());
// Loading the tracks
drumsPlayerNode.load("drums.mp3", ::Mp3);
bassPlayerNode.load("bass.mp3", ::Mp3);
// Starting the graph
audioGraph.start();
}
void play() {
drumsPlayerNode.play();
bassPlayerNode.play();
}
void pause() {
drumsPlayerNode.pause();
bassPlayerNode.pause();
}
void setDrumsVolume(float gain) {
drumsGainNode.setGain(gain);
}
void setBassVolume(float gain) {
bassGainNode.setGain(gain);
}
// Example method called by the audio processing pipeline on each buffer
bool process(float** buffers, const uint numberOfChannels, const uint numberOfFrames, const uint sampleRate) {
AudioBuffer<float> outBuffer = AudioBuffer<float>(numberOfChannels, numberOfFrames, false, sampleRate, buffers);
const bool result = audioGraph->processBuffer(nullptr, &outBuffer);
return result;
}
private:
AudioGraph audioGraph;
AudioPlayerNode drumsPlayerNode;
AudioPlayerNode bassPlayerNode;
GainNode drumsGainNode;
GainNode bassGainNode;
MixerNode mixerNode;
};
Coming soon...
Please note that the two audio players are not guaranteed to be precisely aligned in time. Please check out our Synchronized Audio Players example to see how to create synchronized audio players.