首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

C# DirectX对声卡的操作解决办法

2013-07-09 
C# DirectX对声卡的操作我想实现的是通过采集的数字信号(这个数字信号可能是txt中保存的一些数据),输入到

C# DirectX对声卡的操作
我想实现的是通过采集的数字信号(这个数字信号可能是txt中保存的一些数据),输入到声卡,然后实时输出,不知如何处理,

还请各位高手帮忙!谢谢~~

下面是我写的代码:(但是输出的wave文件有,但是听不到声音)

    public partial class Form3 : Form
    {
        #region 用户变量
        private string strRecSaveFile = string.Empty;//文件保存路径
        private Notify myNotify = null;//缓冲区提示事件
        private FileStream fsWav = null;//保存的文件流
        private int iNotifyNum = 16;//通知的个数
        private int iBufferOffset = 0;//本次数据起始点, 上一次数据的终点。
        private int iSampleSize = 0;//所采集到的数据大小
        private int iNotifySize = 0;//通知所在区域大小
        private int iBufferSize = 0;//缓冲区大小
        private BinaryWriter mWriter;
        private Capture capture = null;//捕捉设备对象
        private CaptureBuffer capturebuffer = null;//捕捉缓冲区
        private AutoResetEvent notifyevent = null;
        private Thread notifythread = null;
        private WaveFormat mWavFormat;//PCM格式
        #endregion

        /// <summary>
        /// 设置PCM格式;
        /// </summary>
        /// <returns></returns>
        private WaveFormat SetWaveFormat()
        {
            WaveFormat format = new WaveFormat();
            format.FormatTag = WaveFormatTag.Pcm;//设置音频类型
            format.SamplesPerSecond = 22050;//采样率(单位:赫兹)典型值:11025、22050、44100Hz
            format.BitsPerSample = 16;//采样位数
            format.Channels = 1;//声道


            format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));//单位采样点的字节数
            format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;
            return format;
            //按照以上采样规格,可知采样1秒钟的字节数为22050*2=55100B 约为 53K
        }
        /// <summary>
        /// 创建wave文件;
        /// </summary>
        /// <param name="strFileName"></param>
        private void CreateWaveFile(string strFileName)
        {
            fsWav = new FileStream(strFileName, FileMode.CreateNew);
            mWriter = new BinaryWriter(fsWav);
            char[] ChunkRiff = { 'R', 'I', 'F', 'F' };
            char[] ChunkType = { 'W', 'A', 'V', 'E' };
            char[] ChunkFmt = { 'f', 'm', 't', ' ' };
            char[] ChunkData = { 'd', 'a', 't', 'a' };
            short shPad = 1;                // File padding
            int nFormatChunkLength = 0x10;  // Format chunk length.
            int nLength = 0;                // File length, minus first 8 bytes of RIFF description. This will be filled in later.
            short shBytesPerSample = 0;     // Bytes per sample.
            // 一个样本点的字节数目


            if (8 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels)
                shBytesPerSample = 1;
            else if ((8 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels) || (16 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels))
                shBytesPerSample = 2;
            else if (16 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels)
                shBytesPerSample = 4;
            // RIFF 块
            mWriter.Write(ChunkRiff);
            mWriter.Write(nLength);
            mWriter.Write(ChunkType);
            // WAVE块
            mWriter.Write(ChunkFmt);
            mWriter.Write(nFormatChunkLength);
            mWriter.Write(shPad);
            mWriter.Write(mWavFormat.Channels);
            mWriter.Write(mWavFormat.SamplesPerSecond);
            mWriter.Write(mWavFormat.AverageBytesPerSecond);
            mWriter.Write(shBytesPerSample);
            mWriter.Write(mWavFormat.BitsPerSample);
            // 数据块
            mWriter.Write(ChunkData);
            mWriter.Write((int)0);   // The sample length will be written in later.
        }
        /// <summary>
        /// 建立两个对象;


        /// </summary>
        /// <returns></returns>
        private bool CreateCaputerDevice()
        {
            //首先要玫举可用的捕捉设备
            CaptureDevicesCollection capturedev = new CaptureDevicesCollection();
            Guid devguid;
            if (capturedev.Count > 0)
            {
                devguid = capturedev[0].DriverGuid;
            }
            else
            {
                MessageBox.Show("当前没有可用于音频捕捉的设备", "系统提示");
                return false;
            }
            //利用设备GUID来建立一个捕捉设备对象
            capture = new Capture(devguid);
            return true;
        }

        private void CreateCaptureBuffer()
        {//想要创建一个捕捉缓冲区必须要两个参数:缓冲区信息(描述这个缓冲区中的格式等),缓冲设备。

            CaptureBufferDescription bufferdescription = new CaptureBufferDescription();
            bufferdescription.Format = mWavFormat;//设置缓冲区要捕捉的数据格式
            iNotifySize = 1024;//设置通知大小
            iBufferSize = iNotifyNum * iNotifySize;
            bufferdescription.BufferBytes = iBufferSize;
            capturebuffer = new CaptureBuffer(bufferdescription, capture);//建立设备缓冲区对象


        }

        /// <summary>
        /// 设置通知以及相应事件;
        /// </summary>
        private void CreateNotification()
        {
            BufferPositionNotify[] bpn = new BufferPositionNotify[iNotifyNum];//设置缓冲区通知个数
            //设置通知事件
            notifyevent = new AutoResetEvent(false);
            notifythread = new Thread(RecoData);
            notifythread.Start();
            for (int i = 0; i < iNotifyNum; i++)
            {
                bpn[i].Offset = iNotifySize + i * iNotifySize - 1;//设置具体每个的位置
                bpn[i].EventNotifyHandle = notifyevent.Handle;
            }
            myNotify = new Notify(capturebuffer);
            myNotify.SetNotificationPositions(bpn);

        }
        //线程中的事件
        private void RecoData()
        {
            while (true)
            {
                // 等待缓冲区的通知消息
                notifyevent.WaitOne(Timeout.Infinite, true);
                // 录制数据
                RecordCapturedData();
            }
        }



        //真正转移数据的事件,其实就是把数据转移到WAV文件中。
        private void RecordCapturedData()
        {
            byte[] capturedata = null;
            int readpos = 0, capturepos = 0, locksize = 0;
            capturebuffer.GetCurrentPosition(out capturepos, out readpos);
            locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小
            if (locksize == 0)
            {
                return;
            }
            if (locksize < 0)
            {//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处
                locksize += iBufferSize;
            }

            capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize);
            mWriter.Write(capturedata, 0, capturedata.Length);//写入到文件
            iSampleSize += capturedata.Length;
            iBufferOffset += capturedata.Length;
            iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。
        }

        /// <summary>
        /// 结束捕捉写入wave文件
        /// </summary>
        private void stoprec()
        {
            capturebuffer.Stop();//调用缓冲区的停止方法。停止采集声音
            if (notifyevent != null)


                notifyevent.Set();//关闭通知
            notifythread.Abort();//结束线程
            RecordCapturedData();//将缓冲区最后一部分数据写入到文件中
            //写WAV文件尾
            mWriter.Seek(4, SeekOrigin.Begin);
            mWriter.Write((int)(iSampleSize + 36));   // 写文件长度
            mWriter.Seek(40, SeekOrigin.Begin);
            mWriter.Write(iSampleSize);                // 写数据长度
            mWriter.Close();
            fsWav.Close();
            mWriter = null;
            fsWav = null;
        }
 
        public Form3()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           //设置格式;
            mWavFormat = SetWaveFormat();
            //设置缓冲区设备;
            CreateCaputerDevice();
            //设置缓冲区;
            CreateCaptureBuffer();
            CreateWaveFile(@"E:\aa.wav");
            // 建立通知消息,当缓冲区满的时候处理方法
            CreateNotification();
            capturebuffer.Start(true);  
        }

        private void button2_Click(object sender, EventArgs e)


        {
            stoprec();
        }
    }
[解决办法]
可不可以用medieaplayer播放呢
[解决办法]
嘿嘿,好像看过这个帖子了,也回答过了。没有结贴啊。我是来赚分的。
[解决办法]
没有放出声音,肯定是放的方法不对,或者是声音文件格式不对。或者设备没有就绪。只能提供个思路啊,要动手很花时间的。我忙着要赚分呢。哎,上班忙死了。
[解决办法]
 代码太长了 也没有调整好格式看起来比较费力.估计这是没有人帮你的原因吧.
[解决办法]

引用:
代码太长了 也没有调整好格式看起来比较费力.估计这是没有人帮你的原因吧.

同感,我是看晕了啊

Button1 button2的直接就出来别人知道这是干嘛的呢也不注释一下

热点排行