Repository navigation
[QSTN] Streaming recorded audio with modifiers through Udp #111
Description
Activity
- addedquestionFurther information is requestedFurther information is requested
on May 2, 2026 @atabaysagin Great question. I've actually shipped this exact workflow before using SoundFlow, To stream audio over a network in SoundFlow, you need to decouple the capture process from the playback process and connect them using a network socket (
UdpClientin this case).- The Sender (Broadcaster): We can use the
Recordercomponent initialized with anAudioProcessCallback. We can add theWebRtcApmModifierdirectly to thisRecorder. This way, the callback will yield the clean, processed audio buffer every frame, which we can cast to bytes and send via UDP. - The Receiver (Player): We will use the
QueueDataProvider. This is a specialISoundDataProviderdesigned specifically for pushing chunks of audio dynamically (e.g., from network packets). ASoundPlayerwill read from this queue and play it through theAudioPlaybackDevice.
But I'd strongly recommend skipping raw UDP in favor of Socket.IO or WebRTC DataChannels. Both integrate seamlessly with SoundFlow's existing
Recorder→QueueDataProviderpipeline, and they solve the real-world headaches raw UDP brings (NAT traversal, packet reordering, encryption, and firewall blocking).The Pattern
Mic → WebRtcApmModifier → Recorder callback → Opus encode → Emit via Socket.IO / DataChannel ↓ Receive via Socket.IO / DataChannel → Opus decode → QueueDataProvider → SoundPlayer → SpeakersSender (Local)
var recorder = new Recorder(captureDevice, (samples, cap) => { // samples is already AEC+NS processed by WebRtcApmModifier var opusPacket = opusEncoder.Encode(samples, frameSize: 480); // 10ms @ 48kHz mono // Socket.IO: socket.Emit("audio-chunk", opusPacket); // WebRTC DC: dataChannel.Send(opusPacket); }); recorder.AddModifier(new WebRtcApmModifier(captureDevice, nsEnabled: true, aecEnabled: true)); recorder.StartRecording();
Receiver (Remote)
var queue = new QueueDataProvider(format, maxSamples: 96000, fullBehavior: QueueFullBehavior.Drop); var player = new SoundPlayer(engine, format, queue); playbackDevice.MasterMixer.AddComponent(player); playbackDevice.Start(); // Socket.IO or WebRTC DC message handler: socket.On("audio-chunk", (opPacket) => { var pcm = opusDecoder.Decode(opPacket); queue.AddSamples(pcm); // Thread-safe });
Some tips for production
- Opus is non-negotiable for WAN: Cuts raw PCM from ~384KB/s down to ~16-32KB/s while preserving voice clarity. Use
Concentuspackage. QueueFullBehavior.Drop: Prevents latency spiral when the network stutters. If you notice audible dropouts, bumpmaxSamplesslightly or add a tiny 10-20ms playout delay on the receiver.- WebRTC DC unreliable mode: If you want UDP-like latency with automatic NAT traversal, configure the DataChannel as
Reliable: false, Ordered: false. Minor packet loss is handled gracefully by Opus's built-in PLC. - Keep network I/O off the audio thread:
QueueDataProvider.AddSamples()is thread-safe, but decode network packets on a background task before pushing to the queue.
P.S. For the
CustomGainComponent, I recommend creating a dedicated modifier instead of relying on a customSoundComponent, which incurs significant overhead for a simple gain adjustment.- The Sender (Broadcaster): We can use the
- changed the title
[-][QSTN] Your question in a few words[/-][+][QSTN] Streaming recorded audio with modifiers through Udp[/+]on May 11, 2026 @LSXPrime Thank you for your reply. I am grateful.
The echo is still there, I don't know what I did wrong.
using Concentus;
using Concentus.Enums;
using Concentus.Structs;
using SoundFlow.Abstracts;
using SoundFlow.Abstracts.Devices;
using SoundFlow.Backends.MiniAudio;
using SoundFlow.Components;
using SoundFlow.Enums;
using SoundFlow.Extensions.WebRtc.Apm;
using SoundFlow.Extensions.WebRtc.Apm.Modifiers;
using SoundFlow.Providers;
using SoundFlow.Structs;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using static System.Windows.Forms.DataFormats;namespace EVKS.App_Code {
public class IMicrophone { readonly MiniAudioEngine engine = new MiniAudioEngine(); readonly AudioFormat format = AudioFormat.DvdHq; FullDuplexDevice fullDuplexDevice; Recorder? recorder; SoundPlayer? player; public QueueDataProvider queue; public Action<float[]>? OnAudioCaptured; readonly List<float> pcmBuffer = new List<float>(); public int frameSize = 960; public IMicrophone() { fullDuplexDevice = engine.InitializeFullDuplexDevice(playbackDeviceInfo: engine.PlaybackDevices.FirstOrDefault(d => d.IsDefault), captureDeviceInfo: engine.CaptureDevices.FirstOrDefault(d => d.IsDefault), format: format); queue = new QueueDataProvider(format, maxSamples: 4800, fullBehavior: QueueFullBehavior.Drop)!; } public void deviceConnection() { fullDuplexDevice.Start(); player = new SoundPlayer(engine, format, queue); fullDuplexDevice.PlaybackDevice.MasterMixer.AddComponent(player); player.Play(); var apmModifier = new WebRtcApmModifier(fullDuplexDevice, aecLatencyMs: 40, nsEnabled: true, aecEnabled: true, aecMobileMode: false, nsLevel: NoiseSuppressionLevel.VeryHigh); recorder = new Recorder(fullDuplexDevice.CaptureDevice, (samples, cap) => { lock (pcmBuffer) { pcmBuffer.AddRange(samples); while (pcmBuffer.Count >= frameSize) { float[] frame = new float[frameSize]; pcmBuffer.CopyTo(0, frame, 0, frameSize); pcmBuffer.RemoveRange(0, frameSize); OnAudioCaptured?.Invoke(frame); } } }); recorder.AddModifier(apmModifier); recorder.StartRecording(); } public void deviceStop() { recorder?.Dispose(); player?.Dispose(); fullDuplexDevice.Dispose(); queue?.Dispose(); engine?.Dispose(); } }}
Requirements
1. What are you trying to achieve?
I'm using the WebRtcApmModifier class to prevent acoustic echo from the microphone and I can receive the sound on my local computer. However, I want to send the clean sound from the microphone to a remote computer using the UDP protocol and play the sound on the remote computer. How can I do this?
2. What have you tried so far?
WebRtcApmModifier sınıfı ile mikrofondan gelen sesin akustik yankısını engelliyorum ve local bilgisayarımda sesi alabiliyorum.
3. What are you unsure about / What is your specific question?
mikrofondan gelen temiz sesi uzak bir bilgisayara udp protolkolu ile göndermek ve uzak bilgisayarda sesi çalmak isiyorum bunu nasıl yapabilirim
4. Relevant Code Snippet (if applicable)
SoundFlow Version
No response
.NET Version
No response
Operating System
No response
6. Additional Context
No response