Chorus
About Chorus
A chorus effect is an audio processing technique that creates the illusion of multiple voices or instruments playing simultaneously. It adds depth and richness to the sound by duplicating the original signal and slightly altering its pitch, timing, and amplitude. The most common parameters of a chorus effect include the rate, depth, and feedback. The rate determines the speed at which the duplicated signals fluctuate, while the depth controls the intensity of the modulation. Feedback adjusts the amount of the processed signal that is fed back into the effect, creating a more pronounced and sustained chorus effect. Additionally, some chorus effects offer parameters like delay time, mix level, and stereo width, allowing further customization and control over the resulting sound.
Switchboard Editor example
Code Example
- JSON
- Swift
- Kotlin
- C++
- JavaScript
{
"nodes": {
{ "id": "chorusNode", "type": "AudioEffects.ChorusNode" }
},
"connections": {
{ "sourceNode": "inputNode", "destinationNode": "chorusNode" },
{ "sourceNode": "chorusNode", "destinationNode": "outputNode" }
}
}
import SwitchboardSDK
import SwitchboardAudioEffects
class ChorusExample {
let audioGraph = SBAudioGraph()
let chorusNode = SBChorusNode()
let audioEngine = SBAudioEngine()
init() {
chorusNode.isEnabled = true
audioGraph.addNode(chorusNode)
audioGraph.connect(audioGraph.inputNode, to: chorusNode)
audioGraph.connect(chorusNode, to: audioGraph.outputNode)
}
}
import com.synervoz.switchboard.sdk.audioengine.AudioEngine
import com.synervoz.switchboard.sdk.audiograph.AudioGraph
import com.synervoz.switchboardaudioeffects.audiographnodes.ChorusNode
class ChorusExample(context: Context) {
val audioEngine = AudioEngine(context)
val chorusNode = ChorusNode()
val audioGraph = AudioGraph()
init {
chorusNode.isEnabled = true
audioGraph.addNode(chorusNode)
audioGraph.connect(audioGraph.inputNode, chorusNode)
audioGraph.connect(chorusNode, audioGraph.outputNode)
audioEngine.start(audioGraph)
}
}
#include "AudioGraph.hpp"
#include "ChorusNode.hpp"
using namespace switchboard;
using namespace switchboard::extensions::audioeffects;
class ChorusExample {
public:
ChorusExample() {
// Setting up node
chorusNode.setEnabled(true);
// Adding nodes to audio graph
audioGraph.addNode(chorusNode);
// Connecting audio nodes
audioGraph.connect(audioGraph.getInputNode(), chorusNode);
audioGraph.connect(chorusNode, audioGraph.getOutputNode());
// Starting the graph
audioGraph.start();
}
// 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> inBuffer = AudioBuffer<float>(numberOfChannels, numberOfFrames, false, sampleRate, buffers);
AudioBuffer<float> outBuffer = AudioBuffer<float>(numberOfChannels, numberOfFrames, false, sampleRate, buffers);
const bool result = audioGraph->process(&inBuffer, &outBuffer);
return result;
}
private:
AudioGraph audioGraph;
ChorusNode chorusNode;
};
// Change the import to reflect the location of library
// relative to this publically accessible AudioWorklet
import '../../../libs/superpowered/Superpowered.js'
class ChorusProcessor extends AudioWorkletProcessor {
constructor(options) {
super()
this.sampleRate = options.processorOptions.sampleRate
this.port.onmessage = (event) => this.onMessage(event.data)
}
sendMessage(message, transfer = []) {
this.port.postMessage(message, transfer)
}
onMessage(message) {
if (message.command === 'requestUiDefinitions') {
this.sendMessage({ uiDefinitions: uiDefinitions })
}
if (message.wasmArrayBuffer) {
const switchboardSdkConfigObject = {
extensions: [],
wasmBytes: message.wasmArrayBuffer,
}
this.configure(switchboardSdkConfigObject)
}
if (typeof message.enabled !== 'undefined') this.setEnabled(message.enabled)
}
configure(sdkConfig) {
this.switchboard = new SwitchboardSDK()
this.switchboard.configure(sdkConfig).then((response) => {
this.constructAudioGraph()
})
}
constructAudioGraph() {
const inputChannelLayout = [2]
const outputChannelLayout = [2]
const maxNumFrames = 128
let chorusNode = new this.switchboard.classes.ChorusNode(2)
chorusNode.setIsEnabled(true)
let audioGraph = this.switchboard.createAudioGraph(
inputChannelLayout,
outputChannelLayout,
maxNumFrames,
this.sampleRate
)
let audioGraphInputNode = audioGraph.getInputNode()
let audioGraphOutputNode = audioGraph.getOutputNode()
audioGraph.addNode(chorusNode)
audioGraph.connect(audioGraphInputNode, chorusNode)
audioGraph.connect(chorusNode, audioGraphOutputNode)
audioGraph.start()
this.chorusNode = chorusNode
this.audioGraph = audioGraph
}
destruct() {
this.audioGraph.destruct()
this.chorusNode.destruct()
}
setEnabled(newEnabled) {
if (this.chorusNode) this.chorusNode.setIsEnabled(newEnabled)
}
process(inputs, outputs, parameters) {
if (this.audioGraph) return this.audioGraph.processGraph(inputs, outputs)
return true
}
}
registerProcessor('ChorusProcessor', ChorusProcessor)