从 UDP 接收到的消息播放音频,点击声音(Naudio API)

Posted

技术标签:

【中文标题】从 UDP 接收到的消息播放音频,点击声音(Naudio API)【英文标题】:Playing Audio from UDP received message, Clicking sound (Naudio API) 【发布时间】:2021-02-26 15:31:55 【问题描述】:

我正在创建一个具有用于语音聊天的 UDP 的聊天客户端,但是当我将音频(以字节为单位)发送到其他客户端时,客户端播放的音频一切都很清晰,但我听到后面有随机的点击声地面。我认为这可能是因为它是 UDP 而不是检查数据是否正确,但不是。即使我通过 TCP 发送,我仍然可以听到背景中的点击声。

要重新创建的代码:

using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace QuestionStack

    public partial class Form1 : Form
    
        UdpClient UDPc;
        private NAudio.Wave.WaveIn sourceStream;
        IPEndPoint ep;//where the client will send the udp data from recording
        public Form1()
        
            InitializeComponent();
        


        /// <summary>
        /// client clicks when he wants to start connection with other client
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartAudioButton_Click(object sender, EventArgs e)
        
            UDPc = new UdpClient(Int32.Parse(MyPortTextBox.Text));
            ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), Int32.Parse(OtherUserTextBoxPort.Text)); // endpoint where other clienr is listening
            UDPc.Connect(ep);
            UDPc.BeginReceive(new AsyncCallback(ReceiveUdpMessage), null);
            Thread.Sleep(100);
            StartAudioRecording();
        


        /// <summary>
        /// where the client takes the audio in bytes, he got from otehr client to convert and play the audio 
        /// </summary>
        /// <param name="ar"></param>
        private void ReceiveUdpMessage(IAsyncResult ar)
        

            try
            
                byte[] bytesRead = UDPc.EndReceive(ar, ref ep);

                BufferedWaveProvider provider = new BufferedWaveProvider(new WaveFormat(44100, 16, 2));
                provider.DiscardOnBufferOverflow = true;
                provider.AddSamples(bytesRead, 0, bytesRead.Length);
                DirectSoundOut _waveOut = new DirectSoundOut();
                _waveOut.Init(provider);
                _waveOut.Play();

                UDPc.BeginReceive(new AsyncCallback(ReceiveUdpMessage), null);
            
            catch (Exception ex)
            
                MessageBox.Show(ex.ToString());
            
        


        /// <summary>
        /// starts recording and sents to other client if check box to only listen is not on
        /// </summary>
        public void StartAudioRecording()
        
            if (!checkBoxOnlyListen.Checked)
            
                sourceStream = new NAudio.Wave.WaveIn();
                sourceStream.DeviceNumber = 0;
                sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(0).Channels);


                sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);

                sourceStream.StartRecording();
            
        


        /// <summary>
        /// if got recording, sends it to other client
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
        
            if (sourceStream == null) return;
            try
            
                UDPc.Send(e.Buffer, e.BytesRecorded);//sending data UPD
            
            catch (Exception ex)
            
                MessageBox.Show(ex.ToString());
            

        
    


FormsPicture 所以如果数据没问题,我翻译和播放它的方式就会导致问题。 我检查了,是否在方法之外创建 Wave out 对象并不重要。 我尝试了一百万种不同的方法来修复它。我不知道该怎么做。如果有人知道更好的翻译或修复方法,那将是我的一周。

提前致谢。

【问题讨论】:

请阅读how-to-ask page 和How to create a Minimal, Complete, and Verifiable example 以改进您的问题并帮助我们了解您的问题。 44Khz PCM 在没有压缩的情况下进行流式传输实在是太疯狂了。这可能只是延迟(网络跟不上实时)。如果您改为保存到磁盘,然后稍后再播放,听起来可能还不错。 但是,如果你保存到磁盘不会导致高延迟(我希望它是像不和谐这样的实时语音聊天),即使我将 PCM 降低到 11k 它仍然会产生点击 【参考方案1】:

您应该创建一个输出设备和一个BufferedWaveProvider,并在收到任何音频之前开始播放。然后在接收函数中,您唯一需要做的就是将接收到的音频添加到BufferedWaveProvider。但是,如果通过网络接收音频的速度不够快,您仍然会获得点击,这意味着您收到的音频会丢失。

【讨论】:

谢谢你的回答和API

以上是关于从 UDP 接收到的消息播放音频,点击声音(Naudio API)的主要内容,如果未能解决你的问题,请参考以下文章

从 socket.io 收到消息时从客户端播放音频 - node.js

实时播放接收到的TS流,怎么设置vlc控件

播放音乐时,我的音频应用程序中没有收到通知或消息的声音 | AV音频播放器

如何在 Raspberry Pi 上使用 C++ 将接收到的 UDP 音频数据正确写入 ALSA

socket TCP 从0实现音频传输 ALSA 播放

我正在尝试显示文本,单击时播放音频,当声音结束时出现新文本,单击时播放新音频