C# UDP+NAUDIO局域网声音组播传送与播放

C# UDP+NAUDIO局域网声音组播传送与播放

本实例通过采集麦克声音数据,利用udp组播方式在局域网中进行组播传送(类似在组内进行广播,udp广播、组播、单播请自行查阅相关资料),组内成员通过接收并播放到扬声器。
程序中引用了 Naudio 声音处理类库进行声音的采集与播放,可通过VS NuGet 查找并引用,关于声音处理相关技术请查阅相关文档。
防火墙要做好响应放行或直接关闭,否则数据无法接收和发送。另外可网管交换机也要做相应放行,否则也无法通讯。

运行效果:
在这里插入图片描述
注意:两台pc要设置相同广播端口才可以。

using System;
using System.Windows.Forms;
using NAudio.Wave;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace Test
{
    public partial class FormNetSound : Form
    {
        private WaveIn mic;//音频输入,从mic采集,如果电脑硬件没有mic会报错
        private WaveOut speaker;//音频输出

        private BufferedWaveProvider _BWP;//接收声音缓冲
       
        private UdpClient2 receiver;//接收用
        private UdpClient2 multicaster;//组播用

        public FormNetSound()
        {
            InitializeComponent();

            lbl_mic.Visible = false;//声音输入设备打开标志
            lbl_speaker.Visible = false;//声音输出设备打开标志
         
        }
        /// <summary>
        /// udp音频接收响应
        /// </summary>
        /// <param name="obj">pcm音频数据</param>
        private void receive_sound(byte[] obj)
        { 
            _BWP.AddSamples(obj, 0, obj.Length);//添加到待播放缓存中
        }      
        /// <summary>
        /// mic声音udp组播
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
        {
            if (!lbl_mic.Visible) return;            

            multicaster.SendMessageByMulticast(e.Buffer,int.Parse(tb_dest_port.Text));           

        }

        private void btn_receive_Click(object sender, EventArgs e)
        {
            if (btn_receive.Text.Equals("静音"))
            {
                //接收udp组播数据用
                receiver = new UdpClient2(int.Parse(tb_dest_port.Text) , tb_dest_ip.Text);
                
                //生成默认声音播放对象
                speaker = new WaveOut();
                //设置声音格式
                WaveFormat wf = new WaveFormat(16000, 16, 1);

                //初始化待播放声音缓存对象
                _BWP = new BufferedWaveProvider(wf);

                //初始化播放设备
                speaker.Init(_BWP);

                if (receiver.recvMessageEvent == null)
                {
                    //绑定udpclient接收数据响应事件
                    receiver.recvMessageEvent += new Action<byte[]>(receive_sound);
                }

                
                receiver.Start();//开始接收数据
                btn_receive.Text = "打开";
                
                speaker.Play();//开始播放声音
                lbl_speaker.Visible = true;
                
            }else
            {
                btn_receive.Text = "静音";
                speaker.Stop();//停止播放声音
                receiver.CloseUdpCliend();//关闭接收           
                lbl_speaker.Visible = false;
            }
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            if (btn_send.Text.Equals("静音"))
            {
               //发送声音数据用
                multicaster = new UdpClient2(int.Parse(tb_local_port.Text) , tb_dest_ip.Text);

                mic = new WaveIn();//生成音频输入设备
                mic.WaveFormat = new WaveFormat(16000, 16 ,1); // 16bit,16KHz,Mono的录音格式
                
              
                //绑定声音输入处理事件
                mic.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);              

                multicaster.Start();//开始广播
                btn_send.Text = "打开";

                mic.StartRecording();//开始采集声音
                lbl_mic.Visible = true;
            }
            else
            {
                btn_send.Text = "静音";
                mic.StopRecording();//停止采集声音
                multicaster.CloseUdpCliend();//关闭组播
                lbl_mic.Visible = false;
            }
        }

      


    }
    
    public class UdpClient2
    {
        //接收数据事件
        public Action<byte[]> recvMessageEvent = null;
        //发送结果事件
        public Action<int> sendResultEvent = null;
        //本地监听端口
        public int localPort = 0;
        //组播地址
        public string MultiCastHost = "";

        

        private UdpClient udpClient = null;

        public UdpClient2(int localPort, string MultiCastHost)
        {
            if (localPort < 0 || localPort > 65535)
                throw new ArgumentOutOfRangeException("localPort is out of range");
            if (string.IsNullOrEmpty(MultiCastHost))
                throw new ArgumentNullException("message cant not null");

            this.localPort = localPort;
            this.MultiCastHost = MultiCastHost;
        }

        public void Start()
        {
            while (true)
            {
                try
                {
                    udpClient = new UdpClient(localPort);
                    udpClient.JoinMulticastGroup(IPAddress.Parse(MultiCastHost));
                    ReceiveMessage();
                    break;
                }
                catch (Exception)
                {
                    Thread.Sleep(100);
                }
            }
        }

        private async void ReceiveMessage()
        {
            while (true)
            {
                if (udpClient == null)
                    return;

                try
                {
                    
                    UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
                    byte[] message = udpReceiveResult.Buffer;
                    if (recvMessageEvent != null)
                        recvMessageEvent(message);
                }
                catch (Exception ex)
                {
                }
            }
        }

        public async void SendMessageByMulticast(byte[] message,int destport)
        {
           
            if (udpClient == null) return;
            

            byte[] buffer = message;
            int len = 0;
            for (int i = 0; i < 1; i++)
            {
                try
                {
                    len = await udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(IPAddress.Parse(MultiCastHost), destport));
                }
                catch (Exception)
                {
                    len = 0;
                }

                if (len <= 0)
                    Thread.Sleep(100);
                else
                    break;
            }

            if (sendResultEvent != null)
                sendResultEvent(len);
        }

        public void CloseUdpCliend()
        {
            if (udpClient == null)
                throw new ArgumentNullException("udpClient cant not null");

            try
            {
                udpClient.Client.Shutdown(SocketShutdown.Both);
            }
            catch (Exception)
            {
            }
            udpClient.Close();
            udpClient = null;
        }
    }
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用NAudio播放WAV文件非常简单,你可以按照以下步骤来实现: 1. 首先,你需要从NAudio的官方网站下载并安装NAudio库,或者使用NuGet包管理器安装NAudio。 2. 在C# WinForm应用程序中,添加一个“打开文件”按钮和一个“播放”按钮,并在按钮的单击事件中编写代码。 3. 在打开文件按钮的单击事件中,打开文件对话框并选择要播放的WAV文件,并将文件名存储在一个字符串变量中。 4. 在播放按钮的单击事件中,创建一个WaveFileReader对象,用于读取WAV文件的数据。然后,创建一个WaveOut对象,用于播放WAV文件的数据。最后,调用WaveOut对象的Play方法,开始播放WAV文件。 以下是示例代码: ``` using NAudio.Wave; private string fileName; private void btnOpenFile_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "WAV files (*.wav)|*.wav"; if (openFileDialog.ShowDialog() == DialogResult.OK) { fileName = openFileDialog.FileName; } } private void btnPlay_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(fileName)) { WaveFileReader waveFileReader = new WaveFileReader(fileName); WaveOut waveOut = new WaveOut(); waveOut.Init(waveFileReader); waveOut.Play(); } } ``` 在上面的代码中,我们首先在btnOpenFile_Click事件中打开文件对话框并选择要播放的WAV文件,并将文件名存储在fileName变量中。然后,在btnPlay_Click事件中,我们创建一个WaveFileReader对象,用于读取WAV文件的数据。然后,我们创建一个WaveOut对象,并调用其Init方法,将WaveFileReader对象传递给它。最后,我们调用WaveOut对象的Play方法,开始播放WAV文件。 请注意,以上代码只是一个简单的示例,你可能需要根据自己的需求进行适当的修改和调整。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值