### Call Action Examples Source: https://docs.switchboard.audio/kotlin-api Demonstrates starting an engine and loading an audio file into a player node using callAction. ```kotlin // Start the engine Switchboard.callAction(engineID, "start") // Load a file into a player node Switchboard.callAction("playerNode", "load", mapOf( "audioFilePath" to "AudioFiles/speech-mono-48k.wav" )) ``` -------------------------------- ### void start() const Source: https://docs.switchboard.audio/api-reference/sdk-api/cpp/html/classswitchboard_1_1_switchboard_web_socket_server.html Starts the WebSocket server. ```APIDOC ## void start() const ### Description Starts the WebSocket server. ``` -------------------------------- ### Import and start WebAudioEngine with Switchboard JSON Source: https://docs.switchboard.audio/integration/web Import WebAudioEngine, create an instance, define an audio graph in Switchboard JSON, and start the engine. The initialize method loads the JSON and resume starts audio playback, typically on a mouse interaction. ```javascript import { WebAudioEngine } from '@synervoz/switchboard-sdk-js' // Create an instance of an audio engine const switchboardAudioEngine = new WebAudioEngine() // Define audio graph in Switchboard JSON (string format supported too). const exampleSwitchboardJSON = { nodes: [ { id: 'myToneGenerator', type: 'Switchboard.SineGenerator', }, ], } async function startEngine(json) { // Load the JSON into the audio engine await switchboardAudioEngine.initialize(switchboardJSON) // Start the audio playback (usually on a mouse interaction) switchboardAudioEngine.resume() } startEngine(exampleSwitchboardJSON) ``` -------------------------------- ### start Source: https://docs.switchboard.audio/engines/realtime Starts the audio engine. No parameters are required and no return value is provided. ```APIDOC ## start ### Description Starts the audio engine. ### Parameters None. ### Return Value None. ``` -------------------------------- ### Get Value Example Source: https://docs.switchboard.audio/kotlin-api Shows how to retrieve a value and check for success before accessing the result. ```kotlin val framesResult = Switchboard.getValue("recorderNode", "framesRecorded") if (framesResult.isSuccess) { val frames = framesResult.value // ... } ``` -------------------------------- ### Audio Graph Setup and Playback Control in Kotlin Source: https://docs.switchboard.audio/examples/karaoke-app Builds an audio graph with music and voice players, gain nodes, reverb, compressor, and automatic vocal pitch correction, connects them to a mixer, and starts the audio engine. Provides methods for playback, rendering to WAV, volume control, and effect toggling. ```kotlin val automaticVocalPitchCorrectionNode = AutomaticVocalPitchCorrectionNode() private var mixedFilePath = SwitchboardSDK.getTemporaryDirectoryPath() + "mix.wav" init { audioGraphToRender.addNode(musicPlayer) audioGraphToRender.addNode(voicePlayer) audioGraphToRender.addNode(mixerNode) audioGraphToRender.addNode(musicGainNode) audioGraphToRender.addNode(voiceGainNode) audioGraphToRender.addNode(reverbNode) audioGraphToRender.addNode(compressorNode) audioGraphToRender.addNode(automaticVocalPitchCorrectionNode) audioGraphToRender.connect(musicPlayer, musicGainNode) audioGraphToRender.connect(musicGainNode, mixerNode) audioGraphToRender.connect(voicePlayer, voiceGainNode) audioGraphToRender.connect(voiceGainNode, automaticVocalPitchCorrectionNode) audioGraphToRender.connect(automaticVocalPitchCorrectionNode, compressorNode) audioGraphToRender.connect(compressorNode, reverbNode) audioGraphToRender.connect(reverbNode, mixerNode) audioGraphToRender.connect(mixerNode, audioGraphToRender.outputNode) audioEngine.start(audioGraphToRender) } fun isPlaying() = musicPlayer.isPlaying fun getRenderedMixPath(): String { val sampleRate = max(musicPlayer.getSourceSampleRate(), voicePlayer.getSourceSampleRate()) musicPlayer.position = 0.0 voicePlayer.position = 0.0 musicPlayer.play() voicePlayer.play() offlineGraphRenderer.setSampleRate(sampleRate) offlineGraphRenderer.setMaxNumberOfSecondsToRender(musicPlayer.getDuration()) offlineGraphRenderer.processGraph(audioGraphToRender, mixedFilePath, Codec.WAV) return mixedFilePath } fun play() { musicPlayer.play() voicePlayer.play() audioGraphToRender.start() } fun pause() { audioGraphToRender.stop() musicPlayer.pause() voicePlayer.pause() } fun stopAudioEngine() { audioEngine.stop() } fun startAudioEngine() { audioEngine.start(audioGraphToRender) } fun close() { audioGraphToRender.close() musicPlayer.close() voicePlayer.close() mixerNode.close() audioEngine.close() } fun loadSong(context: Context, songName: String) { musicPlayer.load(AssetLoader.load(context, songName), Codec.createFromFileName(songName)) } fun loadRecording(recordingPath: String) { voicePlayer.load(recordingPath, Codec.createFromFileName(recordingPath)) } fun getSongDurationInSeconds() : Double { return musicPlayer.getDuration() } fun getPositionInSeconds() : Double { return musicPlayer.position } fun setPositionInSeconds(position: Double) { musicPlayer.position = position if (voicePlayer.getDuration() > position) { voicePlayer.position = position } } fun getProgress(): Float { return (musicPlayer.position / musicPlayer.getDuration()).toFloat() } fun setMusicVolume(volume: Int) { musicGainNode.gain = volume / 100.0f; } fun setVoiceVolume(volume: Int) { voiceGainNode.gain = volume / 100.0f; } fun enableReverb(enable: Boolean) { reverbNode.isEnabled = enable } fun enableCompressor(enable: Boolean) { compressorNode.isEnabled = enable } fun enableAutomaticVocalPitchCorrection(enable: Boolean) { automaticVocalPitchCorrectionNode.isEnabled = enable } } ``` -------------------------------- ### virtual void onGraphStart() Source: https://docs.switchboard.audio/api-reference/extension-api/cpp/html/_audio_node_8hpp_source.html Called when the audio graph is started. Override to perform custom logic when the graph starts. ```APIDOC ## virtual void onGraphStart() ### Description Called when the audio graph is started. Override to perform custom logic when the graph starts. ### Parameters None. ### Returns No return value. ``` -------------------------------- ### Install Switchboard SDK for JavaScript Source: https://docs.switchboard.audio/integration/web Install the @synervoz/switchboard-sdk-js package from NPM. ```bash npm install @synervoz/switchboard-sdk-js ``` -------------------------------- ### Synchronized audio players example (coming soon) Source: https://docs.switchboard.audio/examples/audio-playback Placeholder for an example that synchronizes two audio players using SubgraphSourceNode to start and stop them exactly at the same time. The code is not yet available. ```text Coming soon... ``` -------------------------------- ### Read configuration values with defaults using get() Source: https://docs.switchboard.audio/guide/bring-your-own-node/configurations Use the instance method get() to retrieve a configuration value or a provided default if the key is missing. ```cpp MyNode(const SBAnyMap& config) { // Get value from config, or use the default if not present const uint numInputs = config.get("numberOfInputs", 2); const float frequency = config.get("frequency", 440.0f); } ``` -------------------------------- ### Kotlin: Multitrack recorder audio graph setup Source: https://docs.switchboard.audio/examples/multitrack-recorder-app Defines a Kotlin class that builds an audio graph with microphone, guitar, and drums inputs, each with dry/wet paths and effects, and connects them to a monitor mixer and recorder. Uses WAV codec and starts the audio engine. ```kotlin import com.synervoz.switchboard.sdk.Codec import com.synervoz.switchboard.sdk.audioengine.AudioEngine import com.synervoz.switchboard.sdk.audiograph.AudioGraph import com.synervoz.switchboard.sdk.audiographnodes.* class MultitrackRecorderExample(context: Context) { private val audioGraph = AudioGraph() private val audioEngine = AudioEngine(context) private val micInput = AudioSourceNode() private val micDrySplitter = BusSplitterNode() private val micDryRecorder = RecorderNode() private val micCompressor = CompressorNode() private val micReverb = ReverbNode() private val micWetSplitter = BusSplitterNode() private val micWetRecorder = RecorderNode() private val micGain = GainNode() private val guitarInput = AudioSourceNode() private val guitarDrySplitter = BusSplitterNode() private val guitarDryRecorder = RecorderNode() private val guitarFlanger = FlangerNode() private val guitarWetSplitter = BusSplitterNode() private val guitarWetRecorder = RecorderNode() private val guitarGain = GainNode() private val drumsInput = AudioSourceNode() private val drumsDrySplitter = BusSplitterNode() private val drumsDryRecorder = RecorderNode() private val drumsBitcrusher = BitcrusherNode() private val drumsWetSplitter = BusSplitterNode() private val drumsWetRecorder = RecorderNode() private val drumsGain = GainNode() private val monitorMixer = MixerNode() private val monitorSplitter = BusSplitterNode() private val monitorRecorder = RecorderNode() private val format = Codec.WAV init() { audioGraph.addNode(micInput) audioGraph.addNode(micDrySplitter) audioGraph.addNode(micDryRecorder) audioGraph.addNode(micCompressor) audioGraph.addNode(micReverb) audioGraph.addNode(micWetSplitter) audioGraph.addNode(micWetRecorder) audioGraph.addNode(micGain) audioGraph.addNode(guitarInput) audioGraph.addNode(guitarDrySplitter) audioGraph.addNode(guitarDryRecorder) audioGraph.addNode(guitarFlanger) audioGraph.addNode(guitarWetSplitter) audioGraph.addNode(guitarWetRecorder) audioGraph.addNode(guitarGain) audioGraph.addNode(drumsInput) audioGraph.addNode(drumsDrySplitter) audioGraph.addNode(drumsDryRecorder) audioGraph.addNode(drumsBitcrusher) audioGraph.addNode(drumsWetSplitter) audioGraph.addNode(drumsWetRecorder) audioGraph.addNode(drumsGain) audioGraph.addNode(monitorMixer) audioGraph.addNode(monitorSplitter) audioGraph.addNode(monitorRecorder) audioGraph.connect(micInput, micDrySplitter) audioGraph.connect(micDrySplitter, micDryRecorder) audioGraph.connect(micDrySplitter, micCompressor) audioGraph.connect(micCompressor, micReverb) audioGraph.connect(micReverb, micWetSplitter) audioGraph.connect(micWetSplitter, micWetRecorder) audioGraph.connect(micWetSplitter, micGain) ``` -------------------------------- ### HostAudioSystem class with Switchboard and Agora audio graph Source: https://docs.switchboard.audio/examples/online-radio-app Defines a Kotlin class that sets up an audio graph for a host using Switchboard SDK nodes and an Agora RoomManager. It connects input, music, effects, ducking, and output nodes, and provides methods to start, stop, play, pause, and close the system. The example assumes the RoomManager provides a sink node and audio bus. ```Kotlin import com.synervoz.switchboard.sdk.audioengine.AudioEngine import com.synervoz.switchboard.sdk.audiograph.AudioGraph import com.synervoz.switchboard.sdk.audiographnodes.AudioPlayerNode import com.synervoz.switchboard.sdk.audiographnodes.BusSplitterNode import com.synervoz.switchboard.sdk.audiographnodes.MixerNode import com.synervoz.switchboard.sdk.audiographnodes.MultiChannelToMonoNode import com.synervoz.switchboard.sdk.audiographnodes.MusicDuckingNode import com.synervoz.switchboard.sdk.audiographnodes.ResampledSinkNode import com.synervoz.switchboardagora.rooms.RoomManager class HostAudioSystem(roomManager: RoomManager) { val audioEngine = AudioEngine(enableInput = true) val audioGraph = AudioGraph() val agoraResampledSinkNode = ResampledSinkNode() val musicPlayerNode = AudioPlayerNode() val effectsPlayerNode = AudioPlayerNode() val playerMixerNode = MixerNode() val inputSplitterNode = BusSplitterNode() val inputMultiChannelToMonoNode = MultiChannelToMonoNode() val musicDuckingNode = MusicDuckingNode() val duckingSplitterNode = BusSplitterNode() val agoraOutputMixerNode = MixerNode() val multiChannelToMonoNode = MultiChannelToMonoNode() val isPlaying: Boolean get() = musicPlayerNode.isPlaying init { agoraResampledSinkNode.setSinkNode(roomManager.sinkNode) agoraResampledSinkNode.internalSampleRate = roomManager.getAudioBus().sampleRate musicPlayerNode.isLoopingEnabled = true audioGraph.addNode(agoraResampledSinkNode) audioGraph.addNode(musicPlayerNode) audioGraph.addNode(effectsPlayerNode) audioGraph.addNode(playerMixerNode) audioGraph.addNode(inputSplitterNode) audioGraph.addNode(inputMultiChannelToMonoNode) audioGraph.addNode(musicDuckingNode) audioGraph.addNode(duckingSplitterNode) audioGraph.addNode(agoraOutputMixerNode) audioGraph.addNode(multiChannelToMonoNode) audioGraph.connect(effectsPlayerNode, playerMixerNode) audioGraph.connect(musicPlayerNode, playerMixerNode) audioGraph.connect(playerMixerNode, musicDuckingNode) audioGraph.connect(audioGraph.inputNode, inputSplitterNode) audioGraph.connect(inputSplitterNode, inputMultiChannelToMonoNode) audioGraph.connect(inputMultiChannelToMonoNode, musicDuckingNode) audioGraph.connect(musicDuckingNode, duckingSplitterNode) audioGraph.connect(inputSplitterNode, agoraOutputMixerNode) audioGraph.connect(duckingSplitterNode, agoraOutputMixerNode) audioGraph.connect(agoraOutputMixerNode, multiChannelToMonoNode) audioGraph.connect(multiChannelToMonoNode, agoraResampledSinkNode) audioGraph.connect(duckingSplitterNode, audioGraph.outputNode) } fun start() { audioEngine.start(audioGraph) } fun stop() { audioEngine.stop() } fun playMusic() { musicPlayerNode.play() } fun pauseMusic() { musicPlayerNode.pause() } fun playSoundEffect() { effectsPlayerNode.stop() effectsPlayerNode.play() } fun close() { audioGraph.close() audioEngine.close() agoraResampledSinkNode.close() musicPlayerNode.close() effectsPlayerNode.close() playerMixerNode.close() inputSplitterNode.close() inputMultiChannelToMonoNode.close() musicDuckingNode.close() duckingSplitterNode.close() agoraOutputMixerNode.close() multiChannelToMonoNode.close() } } ``` -------------------------------- ### Offline Engine Configuration Example Source: https://docs.switchboard.audio/graph-config-schema Example configuration for the Switchboard.Offline engine, specifying input and output files and a simple gain graph. The graph connects the input node to a gain node and then to the output node. ```json { "type": "Switchboard.Offline", "config": { "inputFiles": [ { "filePath": "@system/input.wav" } ], "outputFiles": [ { "filePath": "@system/output.wav" } ], "graph": { "nodes": [ { "id": "gain", "type": "Switchboard.Gain", "properties": { "gain": 0.5 } } ], "connections": [ { "sourceNode": "inputNode", "destinationNode": "gain" }, { "sourceNode": "gain", "destinationNode": "outputNode" } ] } } } ``` -------------------------------- ### Example JSON Configuration for RealTimeGraphRenderer Source: https://docs.switchboard.audio/guide/engines Complete JSON example for a real-time engine with a voice processing pipeline. Contains engine type, config (microphone enabled, graph settings), nodes (MultiChannelToMono, Superpowered.Reverb), and connections from input through nodes to output. ```json { "type": "RealTimeGraphRenderer", "config": { "microphoneEnabled": true, "graph": { "config": { "sampleRate": 16000, "bufferSize": 512 }, "nodes": [ { "id": "multiChannelToMonoNode", "type": "MultiChannelToMono" }, { "id": "reverbNode", "type": "Superpowered.Reverb", "config": { "mix": 0.5, "roomSize": 0.7 } } ], "connections": [ { "sourceNode": "inputNode", "destinationNode": "multiChannelToMonoNode" }, { "sourceNode": "multiChannelToMonoNode", "destinationNode": "reverbNode" }, { "sourceNode": "reverbNode", "destinationNode": "outputNode" } ] } } } ``` -------------------------------- ### play Source: https://docs.switchboard.audio/nodes/audio-player Starts the audio playback. Takes no parameters and returns no value. ```APIDOC ## play ### Description Starts the audio playback. ### Parameters None. ### Return Value None. ``` -------------------------------- ### Getting and Setting Properties (C++) Source: https://docs.switchboard.audio/guide/switchboard-objects Demonstrates retrieving and modifying object properties using getValue and setValue. The example gets the 'gain' property of a 'gainNode' and sets it to 0.8. ```C++ // Getting the value of a property auto volume = Switchboard::getValue("gainNode", "gain"); // Setting the value of a property auto setResult = Switchboard::setValue("gainNode", "gain", 0.8); ``` -------------------------------- ### Initialize SDK Example Source: https://docs.switchboard.audio/kotlin-api Demonstrates initializing the SDK and handling potential errors using the result object. ```kotlin val result = Switchboard.initialize(context, "your-app-id", "your-app-secret") if (result.isError) { Log.e("SB", result.error ?: "unknown error") } ``` -------------------------------- ### Initialize Method Source: https://docs.switchboard.audio/json-rpc-api Initializes the SDK with the provided application credentials. ```json { "method": "initialize", "params": { "config": { "appID": "...", "appSecret": "..." } } } ``` -------------------------------- ### Get Value from Switchboard Object Source: https://docs.switchboard.audio/swift-api Reads a value from a key on a Switchboard object. The example retrieves framesRecorded and checks its success. ```Swift class func getValue(forKey key: String, object objectURI: String) -> SBResult ``` ```Swift let framesResult = Switchboard.getValue(forKey: "framesRecorded", object: "recorderNode") if framesResult.isSuccess, let frames = framesResult.value as? Int { // ... } ``` -------------------------------- ### initialize(withConfig:) Source: https://docs.switchboard.audio/swift-api Initializes the SDK with a config dictionary. Returns the SDK's object URI. ```APIDOC ## initialize(withConfig:) ### Description Initializes the SDK with a config dictionary. Returns the SDK's object URI. ### Method class func initialize(withConfig config: [String: Any]) -> SBResult ### Parameters - **config** ([String: Any]) - Required - Configuration dictionary containing appID and appSecret. ### Request Example swift let result = Switchboard.initialize(withConfig: [ "appID": "your-app-id", "appSecret": "your-app-secret", ]) if result.isError { print(result.error?.message ?? "unknown error") } ### Response Returns SBResult with the SDK's object URI on success. ``` -------------------------------- ### Define a data connection Source: https://docs.switchboard.audio/graph-config-schema Example of a data connection routing a speech started event from a VAD node to a recorder node. ```json { "dataConnections": [ { "source": "vad.speechStarted", "destination": "recorder.start" } ] } ``` -------------------------------- ### Get Value from Switchboard object Source: https://docs.switchboard.audio/javascript-api Reads a value from a key on a Switchboard object. The example retrieves the framesRecorded value from a recorder node. ```javascript const value = await Switchboard.getValue(objectURI, key); ``` ```javascript const frames = await Switchboard.getValue('recorderNode', 'framesRecorded'); ``` -------------------------------- ### Get Value from Switchboard object Source: https://docs.switchboard.audio/cpp-api Reads a value from a key on a Switchboard object. The example shows checking isSuccess() before using value(). ```cpp static Result getValue(const ObjectURI& objectURI, const std::string& key); ``` ```cpp auto framesResult = switchboard::Switchboard::getValue("recorderNode", "framesRecorded"); if (framesResult.isSuccess()) { auto frames = framesResult.value(); // ... } ``` -------------------------------- ### Create Engine Example Source: https://docs.switchboard.audio/kotlin-api Shows how to create an engine and retrieve its ObjectID from the result. ```kotlin val createResult = Switchboard.createEngine(engineConfig) if (createResult.isError) { /* handle */ } val engineID = createResult.value!! ``` -------------------------------- ### Import and call AudioEngineModule from React Native JavaScript Source: https://docs.switchboard.audio/integration/react-native Add this code to App.js to set up functions that start and stop the Switchboard SDK audio engine. After following the native setup steps, calling the start method should play a generated sine tone. ```JavaScript import { NativeModules } from 'react-native' const onStartButtonPressed = () => { NativeModules.AudioEngineModule.start() } const onStopButtonPressed = () => { NativeModules.AudioEngineModule.stop() } ``` -------------------------------- ### Call Action on Switchboard Object Source: https://docs.switchboard.audio/swift-api Invokes a named action on any Switchboard object. The example shows starting an engine and loading a file into a player node. ```Swift class func callAction( withObject objectURI: String, actionName: String, params: [String: Any]? ) -> SBResult ``` ```Swift // Start the engine Switchboard.callAction(withObject: engineID, actionName: "start", params: nil) // Load a file into a player node Switchboard.callAction(withObject: "playerNode", actionName: "load", params: [ "audioFilePath": "AudioFiles/speech-mono-48k.wav" ]) ``` -------------------------------- ### initialize Source: https://docs.switchboard.audio/api-reference/sdk-api/cpp/html/classswitchboard_1_1_switchboard.html Initializes the Switchboard SDK with the given configuration. ```APIDOC ## initialize ### Description Initializes the Switchboard SDK. ### Method static ### Signature static Result initialize(const SBAnyMap &config) ### Parameters - **config** (SBAnyMap) - Required - Configuration map for initialization. ### Returns Result - The result containing the object URI of the initialized SDK. ``` -------------------------------- ### Set Value Examples Source: https://docs.switchboard.audio/kotlin-api Demonstrates setting properties like looping and gain on specific nodes. ```kotlin Switchboard.setValue("playerNode", "isLoopingEnabled", true) Switchboard.setValue("gainNode", "gain", 0.5) ``` -------------------------------- ### Call Action on Switchboard object Source: https://docs.switchboard.audio/javascript-api Invokes a named action on any Switchboard object. The example shows starting the engine and loading a file into a player node. ```javascript await Switchboard.callAction(objectURI, actionName, params); ``` ```javascript // Start the engine await Switchboard.callAction(engineID, 'start'); // Load a file into a player node await Switchboard.callAction('playerNode', 'load', { audioFilePath: 'AudioFiles/speech-mono-48k.wav', }); ``` -------------------------------- ### Initialize SDK Source: https://docs.switchboard.audio/cpp-api Initializes the SDK with a config map. Returns the SDK instance's object URI (always "switchboard"). ```APIDOC ## Initialize SDK ### Description Initializes the SDK with a config map. Returns the SDK instance's object URI (always "switchboard"). ### Method static Result initialize(const SBAnyMap& config) ### Parameters - **config** (SBAnyMap) - Required - Configuration map containing appID and appSecret. ### Request Example ```cpp auto result = switchboard::Switchboard::initialize({ {"appID", "your-app-id"}, {"appSecret", "your-app-secret"}, }); if (result.isError()) { std::cerr << result.error().message << std::endl; return 1; } ``` ### Response Returns Result containing the SDK instance's object URI (always "switchboard"). ``` -------------------------------- ### Call Action on Switchboard object Source: https://docs.switchboard.audio/cpp-api Invokes a named action on any Switchboard object — start an engine, play a player, load a file, etc. Returns whatever the action returns (often empty). The example shows starting an engine and loading a file into a player node. ```cpp static Result callAction( const ObjectURI& objectURI, const std::string& actionName, const SBAnyMap& params = {} ); ``` ```cpp // Start the engine switchboard::Switchboard::callAction(engineID, "start"); // Load a file into a player node switchboard::Switchboard::callAction("playerNode", "load", { {"audioFilePath", "AudioFiles/speech-mono-48k.wav"}, }); ``` -------------------------------- ### C++: Tap audio buffers with TapAudioNode and BusSplitterNode Source: https://docs.switchboard.audio/tapping-audio C++ example using TapAudioNode and BusSplitterNode to capture audio buffers. The onBufferUpdate callback retrieves the buffer and demonstrates getting read and interleaved pointers. Note that onBufferUpdate runs on the audio thread, so file operations should be offloaded to a separate thread. ```C++ #include #include tapAudioNode.onBufferUpdate = [this]() { // get read pointer to buffers auto readPointer = tapAudioNode.buffer->getReadPointer() // you can also get pointer to interleaved buffer auto interleavedData = tapAudioNode.buffer->getInterleavedData() }; audioGraph.addNode(tapAudioNode); audioGraph.addNode(busSplitterNode); audioGraph.connect(audioGraph.getInputNode(), busSplitterNode); audioGraph.connect(busSplitterNode, tapAudioNode); audioGraph.connect(busSplitterNode, audioGraph.getOutputNode()); ``` -------------------------------- ### initialize(context, config) Source: https://docs.switchboard.audio/kotlin-api Initializes the Switchboard SDK using a full configuration map. Returns a SwitchboardResult indicating success or failure. ```APIDOC ## initialize(context, config) ### Description Initializes the Switchboard SDK using a full configuration map. Returns a SwitchboardResult indicating success or failure. ### Method initialize ### Signature ```kotlin fun initialize(context: Context, config: Map): SwitchboardResult ``` ### Parameters - **context** (Context) - Required - The application context. - **config** (Map) - Required - A map containing the full configuration. ### Response Returns a `SwitchboardResult` with `isSuccess`, `value`, and `error`. ``` -------------------------------- ### Swift: Create Audio Engine with Sine Tone Generator for iOS Native Module Source: https://docs.switchboard.audio/integration/react-native Sets up a Switchboard audio engine with a sine tone generator and exposes start, stop, and setFrequency methods to React Native via @objc. Requires the SwitchboardSDK framework and an iOS native module setup. ```Swift import SwitchboardSDK @objc(RCTAudioEngineModule) class RCTAudioEngineModule : NSObject { let audioEngine = SBAudioEngine() let audioGraph = SBAudioGraph() let sineGeneratorNode = SBSineGeneratorNode() override init() { super.init() audioGraph.addNode(sineGeneratorNode) audioGraph.connect(sineGeneratorNode, to: audioGraph.outputNode) } @objc func start() { audioEngine.start(audioGraph) } @objc func stop() { audioEngine.stop() } @objc func setFrequency(_ newValue: Float) { sineGeneratorNode.frequency = newValue } @objc static func requiresMainQueueSetup() -> Bool { return true } } ``` -------------------------------- ### Extension::initialize Source: https://docs.switchboard.audio/api-reference/extension-api/cpp/html/classswitchboard_1_1_extension.html Initializes the extension with the provided configuration map. This method is called to set up the extension before use. ```APIDOC ## Extension::initialize ### Description Initializes the extension with the provided configuration map. ### Method initialize ### Signature virtual Result initialize(const SBAnyMap &config) ### Parameters - **config** (SBAnyMap) - Required - Configuration map for the extension. ### Returns Result - Result of the initialization operation. ``` -------------------------------- ### Swift: Tap audio buffers with SBTapAudioNode and SBBusSplitterNode Source: https://docs.switchboard.audio/tapping-audio Swift example using SBTapAudioNode and SBBusSplitterNode to capture audio buffers. The onBufferUpdate callback retrieves the audio buffer and demonstrates getting read and interleaved pointers. Note that onBufferUpdate runs on the audio thread, so file operations should be offloaded to a separate thread. ```Swift import SwitchboardSDK let audioGraph = SBAudioGraph(maxNumberOfChannels: 2, maxNumberOfFrames: 512, sampleRate: 48000, bufferSize: 512) var audioBuffer = SBAudioBuffer() let tapAudioNode = SBTapAudioNode() let splitterNode = SBBusSplitterNode() tapAudioNode.onBufferUpdate = { [weak self] in guard let self = self else { return } audioBuffer = self.tapAudioNode.buffers // get pointer to buffers let buffers = audioBuffer.getReadPointer() // you can also get pointer to interleaved buffer let interleavedBuffer = audioBuffer.getInterleavedData() } audioGraph.addNode(tapAudioNode) audioGraph.addNode(splitterNode) audioGraph.connect(audioGraph.inputNode, to: splitterNode) audioGraph.connect(splitterNode, to: tapAudioNode) audioGraph.connect(splitterNode, to: audioGraph.outputNode) ``` -------------------------------- ### Initialize Switchboard SDK and Create Audio Graph in C++ Source: https://docs.switchboard.audio/integration/unity Initialize the Switchboard SDK and create a simple audio graph with a Gain node. Exposes C functions for initialization, start, and stop. Replace the placeholder app ID and secret with your own credentials. ```C++ #include "AudioEngine.hpp" #include "AudioGraph.hpp" #include "AudioGraphFactory.hpp" const std::string json = R"( { "title": "Audio Engine", "nodes": [ { "id": "gain", "type": "Gain" } ], "connections": [ { "sourceNode": "inputNode", "destinationNode": "gain" }, { "sourceNode": "gain", "destinationNode": "outputNode" } ] }) "; extern "C" { static AudioGraph* audioGraph { AudioGraphFactory::parseJSON(json) } static AudioEngine audioEngine { AudioIO::Core }; void initializeSwitchboardSDK() { SwitchboardSDK::initialize("Your app ID", "Your app secret"); } void start() { audioEngine.start(&audioGraph); } void stop() { audioEngine.stop(); } } ``` -------------------------------- ### Example graph configuration JSON Source: https://docs.switchboard.audio/graph-config-schema Shows a complete engine configuration with a graph containing two nodes (player and gain) and two connections, including the outputNode connection. ```json { "type": "Switchboard.Realtime", "config": { "graph": { "nodes": [ { "id": "player", "type": "Switchboard.AudioPlayer", "config": { "audioFilePath": "@system/music.wav" } }, { "id": "gain", "type": "Switchboard.Gain", "properties": { "gain": 0.5 } } ], "connections": [ { "sourceNode": "player", "destinationNode": "gain" }, { "sourceNode": "gain", "destinationNode": "outputNode" } ] } } } ``` -------------------------------- ### Produce and consume with AudioRingBuffer Source: https://docs.switchboard.audio/ring-buffers Demonstrates initializing an AudioRingBuffer and performing produce and consume operations to transfer audio data between buffers. ```cpp AudioRingBuffer ringBuffer(48000, 2, false); if (sourceBuffer.getNumberOfFrames() <= ringBuffer.getAvailableFramesToProduce()) { ringBuffer.produce(sourceBuffer, sourceBuffer.getNumberOfFrames()); } ringBuffer.consume(destinationBuffer, ringBuffer.getAvailableFramesToConsume()) ``` -------------------------------- ### initialize(config) Source: https://docs.switchboard.audio/api-reference/extension-api/cpp/html/classswitchboard_1_1_extension.html Inline virtual method that initializes the extension with the provided configuration. ```APIDOC ## initialize(config) ### Description Initializes the extension. ### Signature virtual Result switchboard::Extension::initialize(const SBAnyMap &config) ### Parameters - **config** (const SBAnyMap &) - Configuration values for the extension. ### Returns Result - A successful result if the extension was initialized successfully, an error result otherwise. ``` -------------------------------- ### switchboard::SBAnyMap - get Source: https://docs.switchboard.audio/api-reference/sdk-api/cpp/html/functions_func.html Gets an element from the map by key. ```APIDOC ## switchboard::SBAnyMap::get ### Description Gets an element from the map by key. ### Method get ### Parameters - **key** (type not specified) - Required - The key of the element to get. ### Returns Not specified. ``` -------------------------------- ### Initialize AudioBuffer with AudioData Source: https://docs.switchboard.audio/audio-buffers Demonstrates preallocating memory on a non-realtime thread and creating an AudioBuffer instance on the real-time thread. ```cpp // Preallocating memory on a non-realtime thread AudioData data(MONO, 480); ... // Creating audio buffer from preallocated memory on the real-time thread const AudioBuffer myAudioBuffer(MONO, 480, SAMPLE_RATE_48k, data.getBuffer()); ``` -------------------------------- ### MainAudioEngine Class Initialization and Node Connection Source: https://docs.switchboard.audio/examples/dj-app Initializes the audio graph, adds necessary nodes, and establishes connections between players, effects, and the mixer. ```kotlin package com.synervoz.djapp import android.content.Context import com.synervoz.switchboard.sdk.audioengine.AudioEngine import com.synervoz.switchboard.sdk.audiograph.AudioGraph import com.synervoz.switchboard.sdk.audiographnodes.GainNode import com.synervoz.switchboard.sdk.audiographnodes.MixerNode import com.synervoz.switchboardsuperpowered.audiographnodes.AdvancedAudioPlayerNode import com.synervoz.switchboardsuperpowered.audiographnodes.CompressorNode import com.synervoz.switchboardsuperpowered.audiographnodes.FilterNode import com.synervoz.switchboardsuperpowered.audiographnodes.FlangerNode import com.synervoz.switchboardsuperpowered.audiographnodes.ReverbNode import kotlin.math.cos class MainAudioEngine(context: Context) { val audioGraph = AudioGraph() val audioPlayerNodeAWithMasterControl = AdvancedAudioPlayerNode() val audioPlayerNodeB = AdvancedAudioPlayerNode() val gainNodeA = GainNode() val gainNodeB = GainNode() val compressorNodeA = CompressorNode() val compressorNodeB = CompressorNode() val flangerNodeA = FlangerNode() val flangerNodeB = FlangerNode() val reverbNodeA = ReverbNode() val reverbNodeB = ReverbNode() val filterNodeA = FilterNode() val filterNodeB = FilterNode() val mixerNode = MixerNode() val audioEngine = AudioEngine(context) init { audioGraph.addNode(audioPlayerNodeAWithMasterControl) audioGraph.addNode(audioPlayerNodeB) audioGraph.addNode(mixerNode) audioGraph.addNode(gainNodeA) audioGraph.addNode(gainNodeB) audioGraph.addNode(compressorNodeA) audioGraph.addNode(compressorNodeB) audioGraph.addNode(flangerNodeA) audioGraph.addNode(flangerNodeB) audioGraph.addNode(reverbNodeA) audioGraph.addNode(reverbNodeB) audioGraph.addNode(filterNodeA) audioGraph.addNode(filterNodeB) audioGraph.connect(audioPlayerNodeAWithMasterControl, gainNodeA) audioGraph.connect(gainNodeA, compressorNodeA) audioGraph.connect(compressorNodeA, flangerNodeA) audioGraph.connect(flangerNodeA, reverbNodeA) audioGraph.connect(reverbNodeA, filterNodeA) audioGraph.connect(filterNodeA, mixerNode) audioGraph.connect(audioPlayerNodeB, gainNodeB) audioGraph.connect(gainNodeB, compressorNodeB) audioGraph.connect(compressorNodeB, flangerNodeB) audioGraph.connect(flangerNodeB, reverbNodeB) audioGraph.connect(reverbNodeB, filterNodeB) audioGraph.connect(filterNodeB, mixerNode) audioGraph.connect(mixerNode, audioGraph.outputNode) audioPlayerNodeAWithMasterControl.isLoopingEnabled = true audioPlayerNodeB.isLoopingEnabled = true audioPlayerNodeAWithMasterControl.setNodeToSyncWith(audioPlayerNodeB) audioEngine.start(audioGraph) } val isPlaying: Boolean get() { ``` -------------------------------- ### Registering an action with parameters (load) Source: https://docs.switchboard.audio/guide/bring-your-own-node/actions Shows how to register an action named 'load' that accepts a required string parameter 'audioFilePath'. The parameter is defined using ACTION_FIELD_PARAMETERS and SBAnyMap, with metadata for name, description, type, and optionality. The handler is provided as a lambda. ```cpp registerAction( "load", { { ACTION_FIELD_DESCRIPTION, "Loads an audio file" }, { ACTION_FIELD_PARAMETERS, SBAnyMap({ { "audioFilePath", SBAnyMap({ { ACTION_PARAMETER_FIELD_NAME, "audioFilePath" }, { ACTION_PARAMETER_FIELD_DESCRIPTION, "The path of the audio file to load" }, { ACTION_PARAMETER_FIELD_TYPE, ACTION_PARAMETER_TYPE_STRING }, { ACTION_PARAMETER_FIELD_IS_OPTIONAL, false } }) } }) }, { ACTION_FIELD_HANDLER, std::function([this](const SBAnyMap& params) { return handleLoad(params); }) } } ); ``` -------------------------------- ### SwitchboardWebSocketServer::start() Source: https://docs.switchboard.audio/api-reference/sdk-api/cpp/html/_switchboard_web_socket_server_8hpp_source.html Starts the WebSocket server. This method initiates the server to begin accepting connections. ```APIDOC ## Method: start ### Description Starts the WebSocket server. ### Signature ```cpp void start() const; ``` ### Parameters None. ### Returns None. ``` -------------------------------- ### Add Event Listener Example Source: https://docs.switchboard.audio/kotlin-api Demonstrates registering a listener for playback progress events. ```kotlin val listenerResult = Switchboard.addEventListener("playerNode", "playbackProgress") { name, data -> // ... } val listenerID = listenerResult.value!! ``` -------------------------------- ### Switchboard Gain Node Example Source: https://docs.switchboard.audio/object-type-schema An example of a Switchboard.Gain node configuration, defining its display name, description, and a gain property with a range of 0.0 to 1.0. ```json { "type": "node", "subtype": "Switchboard.Gain", "displayName": "Gain", "description": "Applies a gain factor to the audio signal.", "categories": ["Audio Processing"], "properties": { "gain": { "type": "float", "readOnly": false, "description": "The gain of the audio signal. The range is [0, 1].", "min": 0.0, "max": 1.0 } } } ``` -------------------------------- ### Build Audio Graph with IVSBroadcastSinkNode on Android Source: https://docs.switchboard.audio/extensions/amazon-ivs/ivs-broadcast-sink-node This example demonstrates creating an audio graph, initializing an IVS broadcast session, creating an audio input source, and connecting the IVSBroadcastSinkNode to the graph. ```kotlin val audioGraph = AudioGraph() val audioEngine = AudioEngine(context) val audioPlayerNode = AudioPlayerNode() val busSplitterNode = BusSplitterNode() val channelSplitterNode = ChannelSplitterNode() // Create the IVS broadcast session and a custom AudioDevice source (mono, INT16, engine sample rate). val session = BroadcastSession(context, broadcastListener, broadcastConfiguration, null) val audioDevice = session.createAudioInputSource(1, sampleRate, AudioDevice.Format.INT16) // Build the sink node from the AudioDevice. val ivsSinkNode = IVSBroadcastSinkNode(audioDevice!!) audioGraph.addNode(audioPlayerNode) audioGraph.addNode(busSplitterNode) audioGraph.addNode(channelSplitterNode) audioGraph.addNode(ivsSinkNode) audioGraph.connect(audioPlayerNode, busSplitterNode) audioGraph.connect(busSplitterNode, channelSplitterNode) audioGraph.connect(channelSplitterNode, ivsSinkNode) audioGraph.connect(busSplitterNode, audioGraph.outputNode) // Start the engine and the broadcast. audioEngine.start(audioGraph) session.start(endpoint, streamKey) ``` -------------------------------- ### Create Engine from JSON in Swift Source: https://docs.switchboard.audio/guide/engines Swift (iOS/macOS) function to read a JSON file from the bundle, parse it into a dictionary, and create an engine with Switchboard.createEngine. It starts the engine with Switchboard.callAction using the action name 'start'. ```swift import SwitchboardSDK func createEngine() { // Read JSON file from bundle guard let filePath = Bundle.main.path(forResource: "AudioGraph", ofType: "json"), let jsonString = try? String(contentsOfFile: filePath, encoding: .utf8) else { print("Error reading JSON file") return } // Parse JSON string to dictionary guard let jsonData = jsonString.data(using: .utf8), let config = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any] else { print("Error parsing JSON") return } // Create engine from configuration let createEngineResult = Switchboard.createEngine(withConfig: config) if let engineID = createEngineResult.value as? String { print("Engine created: \(engineID)") // Start the engine let _ = Switchboard.callAction(engineID, actionName: "start", params: [:]) } } ``` -------------------------------- ### Create a node from an extension Source: https://docs.switchboard.audio/guide/bring-your-own-node/extensions Demonstrates how to instantiate a node using its fully-qualified type name, with or without initial configuration parameters. ```cpp // Create a node from your extension auto node = graph->createNode("MyExtension.NoiseFilter"); // Or with configuration auto node = graph->createNode("MyExtension.EchoNode", { { "delayMs", 500 }, { "feedback", 0.3f } }); ``` -------------------------------- ### getValue Source: https://docs.switchboard.audio/api-reference/extension-api/cpp/html/classswitchboard_1_1_node.html Gets a value from the object by key. ```APIDOC ## getValue ### Description Gets a value from the object. ### Signature `Result getValue(const std::string &key) override` ### Parameters - **key** (std::string) - Required - The key of the value to retrieve. ### Returns - **Result** - The result containing the value. ``` -------------------------------- ### Initialize Switchboard SDK Source: https://docs.switchboard.audio/swift-api Use this to initialize the SDK with a configuration dictionary. Returns the SDK's object URI as an SBResult. The example passes appID and appSecret and checks for an error. ```Swift class func initialize(withConfig config: [String: Any]) -> SBResult ``` ```Swift let result = Switchboard.initialize(withConfig: [ "appID": "your-app-id", "appSecret": "your-app-secret", ]) if result.isError { print(result.error?.message ?? "unknown error") } ``` -------------------------------- ### Create and render an audio graph with AudioEngine (Kotlin) Source: https://docs.switchboard.audio/best-practices Shows a Kotlin class that sets up an audio engine, graph, and white noise generator node, then renders the graph to a file using SBOfflineGraphRenderer. The audio engine must be stopped before rendering and started again afterward to avoid hearing the offline renderer. ```Kotlin class MyAudioEngine(context: Context) { val audioEngine = AudioEngine(context) val audioGraph = AudioGraph() val noiseGeneratorNode = WhiteNoiseGeneratorNode() init { audioGraph.addNode(noiseGeneratorNode) audioGraph.connect(noiseGeneratorNode, audioGraph.outputNode) audioEngine.start(audioGraph) } func renderGraph() { audioEngine.stop() let offlineGraphRenderer = SBOfflineGraphRenderer() // setup params like sample rate, etc. offlineGraphRenderer.processGraph(audioGraph, "mixedFilePath.wav", Codec.MP3) audioEngine.start() } } ```