c# 利用WaveOut播放音频流

来源:互联网 发布:数据直报系统 编辑:程序博客网 时间:2024/06/05 00:28

具体请参考这篇文章 http://www.kavenblog.com/?p=3970

为了更好理解,对文章内项目进行了简化和说明,功能是从UDP接收到音频来播放

1.下载文中示例项目 http://www.kavenblog.com/?download=3992

2.仅修改TestDemo.cs中的代码

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 WaveOutPlayer{    public partial class TestDemo : Form    {        private WaveOut m_Player;        private         Socket severSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);        public TestDemo()        {            InitializeComponent();            WaveFormat m_Format = new WaveFormat(8000, 1);//采样率8000,通道数1            m_Player = new WaveOut(-1, m_Format, 960, 50, new BufferFillEventHandler(Filler));            m_Player.Play();            IPAddress ipaddr = IPAddress.Parse("127.0.0.1");            severSocket.Bind(new IPEndPoint(ipaddr, 7074));            Thread th2 = new Thread(new ThreadStart(VoiceReceive));            th2.Start();        }        byte[] voicedata = new byte[960*10];//自定义缓冲区        int w_voicedata_idx = 0;//待读取位        int r_voicedata_idx = 0;//待写入位        bool has_voice = false;//是否有声音的标识

        void VoiceReceive()//UDP接收        {            while (true)            {                byte[] tmp = new byte[10240];                int rcv_len = severSocket.Receive(tmp);                short timer = (short)((tmp[3] << 8) | tmp[2]);                byte slot = (byte)(timer>>11);                byte fn_num = (byte)((timer >> 6) & 0x1f);                if (rcv_len == 972 && slot == play_slot)                {                    Array.Copy(tmp, 12, voicedata, w_voicedata_idx, 960);//将数据写入缓冲区                    w_voicedata_idx = (w_voicedata_idx == 8640) ? 0 : w_voicedata_idx + 960;                                        has_voice = true;                }             }                   }        //由播放类调用,将缓冲区内的数据给入data中进行播放        private int Filler(IntPtr data, int size)        {            byte[] b = new byte[size];            if (has_voice & (r_voicedata_idx != w_voicedata_idx))            {                Array.Copy(voicedata, r_voicedata_idx, b, 0, 960);                r_voicedata_idx = (r_voicedata_idx == 8640) ? 0 : r_voicedata_idx + 960;            }            else            {                for (int i = 0; i < b.Length; i++)                    b[i] = 0;            }            System.Runtime.InteropServices.Marshal.Copy(b, 0, data, size);//将数据写入播放区            //System.Threading.Thread.Sleep(100);            return size;        }        private void TestDemo_FormClosed(object sender, FormClosedEventArgs e)        {            m_Player.Stop();            System.Environment.Exit(0);        }    }}



使用详解:

1. 建立UDP接收和用于委托的Filler方法

2. 建立byte[] voicedata 自定义缓冲区

3. 自定义Filler方法,用于从自定义缓冲区提取数据进行播放(由WaveOut类自动调用)

4. 将数据由UDP接收后写入自定义缓冲区(VoiceReceive方法)


改写后项目下载:    //增加的注释

http://download.csdn.net/download/www89574622/10149690

原创粉丝点击