C# - 通过套接字连接的实时流音频

ama*_*iKy 3 c# sockets audio naudio cscore

我正在尝试通过 tcp 套接字连接将音频从一台计算机单向流式传输到另一台计算机。

计算机 1 ---> 交换机 ---> 计算机 2

计算机 1 是发送方/客户端,计算机 2 是播放音频的接收方/服务器。

我设法让它发挥作用,但收到了很多噪音。

CS核心:

这是我目前用来发送数据的代码:

CaptureInstance = new WasapiLoopbackCapture();
CaptureInstance.Initialize();
CaptureInstance.DataAvailable += (s, a) => onStart(s, a);
CaptureInstance.Start();
Run Code Online (Sandbox Code Playgroud)

其中 onStart 只是使用 BinaryWriter 将字节写入套接字的流:

writer.Write(a.Data, a.Offset, a.ByteCount);
Run Code Online (Sandbox Code Playgroud)

这是我目前在接收计算机上用于播放音频的代码:

int size = 3840;
WriteableBufferingSource src = new WriteableBufferingSource(new CSCore.WaveFormat(48000, 32, 2)) { FillWithZeros = true };

WasapiOut soundOut = new WasapiOut();
soundOut.Initialize(src);
soundOut.Play();

while (true)
{
    byte[] bytes = reader.ReadBytes(size); // BinaryReader
    src.Write(bytes, 0, size);
}
Run Code Online (Sandbox Code Playgroud)

NA音频:

经过进一步的搜索、试验和错误,我设法使用 NAudio 拼凑出一个新的解决方案,它也遇到了同样的问题。噪音很大,而且声音很大。

客户端(发送者)在套接字连接时使用以下代码:

var capture = new WasapiLoopbackCapture();

capture.DataAvailable += (obj, args) =>
{
    stream.Write(args.Buffer, 0, args.BytesRecorded); // NetworkStream(socket)
    stream.Flush();
};

capture.StartRecording();
Run Code Online (Sandbox Code Playgroud)

服务器(接收者)正在使用这个:

// ---------------------------- Init --------------------------------
provider = new BufferedWaveProvider(new WaveFormat(48000, 32, 2));

WaveOut o = new WaveOut();
o.Init(provider);
o.Play();
Run Code Online (Sandbox Code Playgroud)
// --------------------------- Callback -------------------------------
socket = (Socket)ar.AsyncState;

int received = socket.EndReceive(ar);
byte[] dataBuffer = new byte[received];
Array.Copy(buffer, dataBuffer, received);

provider.AddSamples(dataBuffer, 0, received);

socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
Run Code Online (Sandbox Code Playgroud)

我尝试让提供商在播放前缓冲 5-10 秒,以防出现缓冲问题,但没有成功。

我检查了 WaveFormat,两台 PC 上都是 48k、32 位 2 通道。不管怎样,我玩弄了价值观,失败了。

我尝试使用 UdpClient,但情况更糟。如果需要的话我可以展示代码。播放速度变慢了,而且噪音也更大了。我使用此链接进行设置。

我在客户端/服务器上运行一个循环,显示每个块接收/发送的字节,打印出第一个和最后一个字节,它们似乎很好并且按顺序,但是在调试我之前使用 MemoryStream 进行的设置时,出现了内存流的长度存在 12 字节的差异(一个在客户端,写入发送到服务器的相同字节,另一个在服务器上,写入接收到的字节),并且某些字节已关闭。

在客户端上录制音频 15 秒并立即播放即可。当发送到另一台计算机时,它会变得非常吵闹。

我认为问题出在我的套接字设置上,但我不太确定,而且我已经没有选择了。

太长;博士;问题是:什么可能导致这种巨大的噪音?NAudio/CSCore 设置似乎都遇到了同样的问题。同样的结果。

或者我该如何继续解决问题?

ama*_*iKy 6

我想到了。

new WaveFormat(48000, 32, 2)
Run Code Online (Sandbox Code Playgroud)

创建 PCM 编码格式,而捕获实例的格式是 Ieefloat 编码。

如果有人需要这个,替换

new WaveFormat(48000, 32, 2)
Run Code Online (Sandbox Code Playgroud)

WaveFormat.CreateIeeeFloatWaveFormat(48000, 2)
Run Code Online (Sandbox Code Playgroud)

解决了这个问题。

有关 WaveFormat 的更多内容请阅读此处