通过 UDP 的实时音频流

Seb*_*n S 5 c# audio stream uwp

正如标题所说,我正在尝试通过 UDP 传输音频。我正在使用连接了麦克风的树莓派 (v3)(使用 Windows 10 IoT)。我记录到一个流,并使用该流通过 UDP 发送数据。

var socket = new DatagramSocket();
        var outputStream = (await socket.GetOutputStreamAsync(new Windows.Networking.HostName(target), targetPortNo)).AsStreamForWrite();

        byte[] buffer = new byte[1024];
        var streamForRead = _stream.AsStreamForRead();
        int bytesRead;
        while((bytesRead = await streamForRead.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await outputStream.WriteAsync(buffer, 0, buffer.Length);
            await outputStream.FlushAsync();
        }
Run Code Online (Sandbox Code Playgroud)

在接收端,我将数据放回到 MediaElement 控件使用的流中。

private IRandomAccessStream _stream = new MemoryStream().AsRandomAccessStream();
private async void MessageReceivedFromSocket(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    var incomingStream = args.GetDataStream().AsStreamForRead();
    var writeStream = _stream.AsStreamForWrite();
    var buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = await incomingStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
    {
        await writeStream.WriteAsync(buffer, 0, buffer.Length);
        await writeStream.FlushAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在 mediaelement 上设置源:

mediaElement.SetSource(_stream, "audio/x-wav");
mediaElement.Play();
Run Code Online (Sandbox Code Playgroud)

我现在遇到的问题是音频无法播放。数据传输正确,但 mediaelement 不会播放它。在对不使用 UDP 的流音频进行了一些测试后,我得出的结论是,如果文件完全写入流中,mediaelement 只会播放音频。我已经用这个代码测试过这个:

var folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
var file = await folder.GetFileAsync("WP_20160625_13_36_33_Pro.mp4");
var stream = (await file.OpenAsync(Windows.Storage.FileAccessMode.Read)).AsStreamForRead();
var writeStream = _stream.AsStreamForWrite();

var buffer = new byte[1];
int bytesRead;
while((bytesRead = await stream.ReadAsync(buffer,0,buffer.Length)) > 0)
{
    await writeStream.WriteAsync(buffer, 0, buffer.Length);
    await writeStream.FlushAsync();
}
Run Code Online (Sandbox Code Playgroud)

我使用的文件是 350Mb。所以花了一段时间。起初我认为是因为 async-await 并且只有在任务完成时才会调用播放,但在调试后我注意到事实并非如此。只要流被“填满”,似乎媒体元素就不会播放。有什么方法可以在将数据添加到流时播放。

我对流没有太多经验。所以我不知道我的做法是否正确。您可以将流用于实时数据吗?对我来说,你可以使用它是有道理的。我一直认为流就像一个异步队列。数据正在从前面获取,而其他数据正在添加到后面。