Flanger
About Flanger
A flanger effect is an audio effect commonly used in music production to create a unique and swirling sound. It is achieved by duplicating the original audio signal and slightly delaying one of the copies. The delayed copy is then modulated in time, creating a sweeping effect that resembles the sound of a jet plane or a spaceship taking off. The most common parameters of a flanger effect include the speed or rate of modulation, which determines how fast the sweeping effect occurs, and the depth, which controls the intensity of the effect. Additionally, the feedback parameter adjusts the amount of the delayed signal that is fed back into the effect, creating a more pronounced or subtle flanging effect. The mix parameter allows for blending the original and flanged signals, enabling the user to control the overall balance of the effect in the mix.
Switchboard Editor example
This example uses the Superpowered Extension.
Why use the Superpowered Extension instead of Superpowered directly?
Code Example
- JSON
- Swift
- Kotlin
- C++
- JavaScript
{
"nodes": {
{ "id": "flangerNode", "type": "Superpowered.Flanger" }
},
"connections": {
{ "sourceNode": "inputNode", "destinationNode": "flangerNode" },
{ "sourceNode": "flangerNode", "destinationNode": "outputNode" }
}
}
import SwitchboardSDK
import SwitchboardSuperpowered
class FlangerExample {
let audioGraph = SBAudioGraph()
let flangerNode = SBFlangerNode()
let audioEngine = SBAudioEngine()
init() {
flangerNode.wet = 0.65
flangerNode.depth = 1
flangerNode.lfoBeats = 16
flangerNode.bpm = 200
flangerNode.stereo = true
flangerNode.isEnabled = true
audioGraph.addNode(flangerNode)
audioGraph.connect(audioGraph.inputNode, to: flangerNode)
audioGraph.connect(flangerNode, to: audioGraph.outputNode)
}
}
import com.synervoz.switchboard.sdk.audioengine.AudioEngine
import com.synervoz.switchboard.sdk.audiograph.AudioGraph
import com.synervoz.switchboardsuperpowered.audiographnodes.FlangerNode
class FlangerExample(context: Context) {
val audioEngine = AudioEngine(context)
val flangerNode = FlangerNode()
val audioGraph = AudioGraph()
init {
flangerNode.wet = 0.65f
flangerNode.depth = 1f
flangerNode.lfoBeats = 16f
flangerNode.bpm = 200f
flangerNode.stereo = true
flangerNode.isEnabled = true
audioGraph.addNode(flangerNode)
audioGraph.connect(audioGraph.inputNode, flangerNode)
audioGraph.connect(flangerNode, audioGraph.outputNode)
audioEngine.start(audioGraph)
}
}
#include "AudioGraph.hpp"
#include "FlangerNode.hpp"
using namespace switchboard;
using namespace switchboard::extensions::superpowered;
class FlangerExample {
public:
FlangerExample() {
// Setting up node
flangerNode.setWet(0.65f);
flangerNode.setDepth(1f);
flangerNode.setLFOBeats(16f);
flangerNode.setBPM(200f);
flangerNode.setStereo(true);
flangerNode.setEnabled(true);
// Adding nodes to audio graph
audioGraph.addNode(flangerNode);
// Connecting audio nodes
audioGraph.connect(audioGraph.getInputNode(), flangerNode);
audioGraph.connect(flangerNode, 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;
FlangerNode flangerNode;
};
// Change the import to reflect the location of library
// relative to this publically accessible AudioWorklet
import '../../../libs/superpowered/Superpowered.js'
class SuperpoweredFlangerProcessor extends SuperpoweredWebAudio.AudioWorkletProcessor {
onReady() {
this.flanger = new this.Superpowered.Flanger(
this.samplerate // the samplerate
)
this.flanger.enabled = true
}
onDestruct() {
this.flanger.destruct()
}
applyPreset(preset) {
for (const effectName of Object.keys(preset)) {
for (const property of Object.keys(preset[effectName])) {
this[effectName][property] = preset[effectName][property]
uiDefinitions.parameters.find((p) => p.id === property).defaultValue =
preset[effectName][property]
}
}
}
// messages are received from the main scope through this method.
onMessageFromMainScope(message) {
if (message.command === 'requestUiDefinitions') {
this.sendMessageToMainScope({ uiDefinitions: uiDefinitions })
}
if (message.command === 'applyPreset') {
this.applyPreset(message.preset)
this.sendMessageToMainScope({ updateUiDefinitions: uiDefinitions })
}
if (typeof message.wet !== 'undefined') this.flanger.wet = message.wet
if (typeof message.depth !== 'undefined') this.flanger.depth = message.depth
if (typeof message.lfoBeats !== 'undefined')
this.flanger.lfoBeats = message.lfoBeats
if (typeof message.bpm !== 'undefined') this.flanger.bpm = message.bpm
if (typeof message.clipperThresholdDb !== 'undefined')
this.flanger.clipperThresholdDb = message.clipperThresholdDb
if (typeof message.clipperMaximumDb !== 'undefined')
this.flanger.clipperMaximumDb = message.clipperMaximumDb
if (typeof message.stereo !== 'undefined')
this.flanger.stereo = Boolean(message.stereo)
if (typeof message.enabled !== 'undefined')
this.flanger.enabled = Boolean(message.enabled)
}
processAudio(inputBuffer, outputBuffer, buffersize, parameters) {
this.flanger.samplerate = this.samplerate
if (
!this.flanger.process(
inputBuffer.pointer,
outputBuffer.pointer,
buffersize
)
)
this.Superpowered.memoryCopy(
outputBuffer.pointer,
inputBuffer.pointer,
buffersize * 8
)
}
}
registerProcessor('SuperpoweredFlangerProcessor', SuperpoweredFlangerProcessor)