Compressor
About Compressor
A compressor effect is a widely used audio processing tool that helps control the dynamic range of a sound signal. It reduces the difference between the loudest and softest parts of the audio, resulting in a more consistent and balanced output. The most common parameters of a compressor effect include threshold, ratio, attack, release, and makeup gain. The threshold determines the level at which the compressor starts to work, while the ratio determines the amount of compression applied to the signal above the threshold. The attack parameter controls how quickly the compressor responds to the incoming signal, and the release parameter determines how long it takes for the compressor to stop compressing after the signal falls below the threshold. Lastly, the makeup gain compensates for the reduction in overall volume caused by compression, allowing the user to boost the output level if desired.
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": "compressorNode", "type": "Superpowered.CompressorNode" }
},
"connections": {
{ "sourceNode": "inputNode", "destinationNode": "compressorNode" },
{ "sourceNode": "compressorNode", "destinationNode": "outputNode" }
}
}
import SwitchboardSDK
import SwitchboardSuperpowered
class CompressorExample {
let audioGraph = SBAudioGraph()
let compressorNode = SBCompressorNode()
let audioEngine = SBAudioEngine()
init() {
compressorNode.isEnabled = true
audioGraph.addNode(compressorNode)
audioGraph.connect(audioGraph.inputNode, to: compressorNode)
audioGraph.connect(compressorNode, to: audioGraph.outputNode)
}
}
import com.synervoz.switchboard.sdk.audioengine.AudioEngine
import com.synervoz.switchboard.sdk.audiograph.AudioGraph
import com.synervoz.switchboardsuperpowered.audiographnodes.CompressorNode
class CompressorExample(context: Context) {
val audioEngine = AudioEngine(context)
val compressorNode = CompressorNode()
val audioGraph = AudioGraph()
init {
compressorNode.isEnabled = true
audioGraph.addNode(compressorNode)
audioGraph.connect(audioGraph.inputNode, compressorNode)
audioGraph.connect(compressorNode, audioGraph.outputNode)
audioEngine.start(audioGraph)
}
}
#include "AudioGraph.hpp"
#include "CompressorNode.hpp"
using namespace switchboard;
using namespace switchboard::extensions::superpowered;
class CompressorExample {
public:
CompressorExample() {
// Setting up node
compressorNode.setEnabled(true);
// Adding nodes to audio graph
audioGraph.addNode(compressorNode);
// Connecting audio nodes
audioGraph.connect(audioGraph.getInputNode(), compressorNode);
audioGraph.connect(compressorNode, 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;
CompressorNode compressorNode;
};
// Change the import to reflect the location of library
// relative to this publically accessible AudioWorklet
import '../../../libs/superpowered/Superpowered.js'
class SuperpoweredCompressorProcessor extends SuperpoweredWebAudio.AudioWorkletProcessor {
// Runs after the constructor
onReady() {
this.compressor = new this.Superpowered.Compressor(
this.samplerate // The initial sample rate in Hz.
)
this.compressor.enabled = true
this.sendMessageToMainScope({ event: 'ready' })
}
// Runs before the node is destroyed.
// Clean up memory and objects here (such as free allocated linear memory or destruct Superpowered objects).
onDestruct() {
this.compressor.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.inputGainDb !== 'undefined')
this.compressor.inputGainDb = message.inputGainDb
if (typeof message.outputGainDb !== 'undefined')
this.compressor.outputGainDb = message.outputGainDb
if (typeof message.wet !== 'undefined') this.compressor.wet = message.wet
if (typeof message.attackSec !== 'undefined')
this.compressor.attackSec = message.attackSec
if (typeof message.releaseSec !== 'undefined')
this.compressor.releaseSec = message.releaseSec
if (typeof message.ratio !== 'undefined')
this.compressor.ratio = message.ratio
if (typeof message.thresholdDb !== 'undefined')
this.compressor.thresholdDb = message.thresholdDb
if (typeof message.hpCutOffHz !== 'undefined')
this.compressor.hpCutOffHz = message.hpCutOffHz
if (typeof message.enabled !== 'undefined')
this.compressor.enabled = Boolean(message.enabled)
}
processAudio(inputBuffer, outputBuffer, buffersize, parameters) {
// Ensure the samplerate is in sync on every audio processing callback
this.compressor.samplerate = this.samplerate
// Render the output buffers
if (
!this.compressor.process(
inputBuffer.pointer,
outputBuffer.pointer,
buffersize
)
)
this.Superpowered.memoryCopy(
outputBuffer.pointer,
inputBuffer.pointer,
buffersize * 8
)
}
}
registerProcessor(
'SuperpoweredCompressorProcessor',
SuperpoweredCompressorProcessor
)