C#中使用DirectSound来获取麦克音量,该如何解决

C#中使用DirectSound来获取麦克音量
大家好,我最近在做一个程序需要使用DirectSound, 当用户说话时我要开始录音,当用户说完了自动停止录音,然后这样循环下去.

  现在的问题是如何知道用户是否在说话.请下看下以下代码:

C# code
        private void RecordCapturedData()
        {
            byte[] CaptureData = null;
            int ReadPos;
            int CapturePos;
            int LockSize;
            mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos);
            LockSize = ReadPos - mNextCaptureOffset;
            if (LockSize < 0)
                LockSize += mBufferSize;
            LockSize -= (LockSize % mNotifySize);
            if (0 == LockSize)
                return;
            CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize);
            mNextCaptureOffset += CaptureData.Length;
            mNextCaptureOffset %= mBufferSize;
            //check state
            if (state == State.Recording || state == State.PreRecording)
            {
                secondBuffer.Add(CaptureData);
            }           
        }


  上面的代码是C# DirectSound的捕获到数据后的处理方法.也就是说,麦克风得到的信号转换成数字信号,在程序里变为一个byte[]数组放到缓存区,然后我可以一个一个的从缓冲区里得到这个byte[]对象,以前我在这里提问过,一些朋友说计算这个byte[]的平均值或方差可以得到用户说话的音量,可是效果不理想.有时好用有时不好用.

  所以来到这里请大家帮忙!是否有办法通过计算缓冲区得到的byte[]数据来得到麦克音量,或通过其他API(最好是DirectSound的)能知道用户当前的说话的音量大小.无论你能否帮上忙,先谢谢你!


以下的信息或许会有帮助:

1.我找到的声音探测的软件(含源码),不过功能太复杂了,不容易分离出来,并且使用的不是DirectSound如果用他的整个程序得重写.
http://www.dreamincode.net/forums/showtopic38890.htm

2.我已经完成的不带自动探测声音的录音的源代码

C# code

public class Recorder
    {
        //由于长度限制,变量略
          public void Initialize()
        {
            // Create capture buffer.
            CreateCaptureBuffer();
            // Create notification system.
            InitNotifications();
            mRecBuffer.Start(true);
        }
        public void Dispose()
        {
            // Close notification
            if (null != mNotificationEvent)
                mNotificationEvent.Set();
            // Stop recording
            mRecBuffer.Stop();
        }
  
       
               #endregion
        #region Initialize Recorder
        public Recorder()
        {
            InitCaptureDevice();
            mWavFormat = CreateWaveFormat();     
            buffDes = new BufferDescription();
            buffDes.GlobalFocus = true;
            buffDes.ControlVolume = true;
            buffDes.ControlPan = true;            
            secDev = new Device();
            bufferStates = new List<int>();
        }
        private void RecordCapturedData()
        {
            byte[] CaptureData = null;
            int ReadPos;
            int CapturePos;
            int LockSize;
            mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos);
            LockSize = ReadPos - mNextCaptureOffset;
            if (LockSize < 0)
                LockSize += mBufferSize;
            LockSize -= (LockSize % mNotifySize);
            if (0 == LockSize)
                return;
            CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize);
            mNextCaptureOffset += CaptureData.Length;
            mNextCaptureOffset %= mBufferSize;
            //check state
            if (state == State.Recording || state == State.PreRecording)
            {
                secondBuffer.Add(CaptureData);
            }           
        }
        private void CreateCaptureBuffer()
        {
            CaptureBufferDescription bufferdescription = new CaptureBufferDescription();
            if (null != mNotify)
            {
                mNotify.Dispose();
                mNotify = null;
            }
            if (null != mRecBuffer)
            {
                mRecBuffer.Dispose();
                mRecBuffer = null;
            }
            // set notification's size: 1 second
            mNotifySize = (1024 > mWavFormat.AverageBytesPerSecond / 8) ? 1024 : (mWavFormat.AverageBytesPerSecond / 8);
            mNotifySize -= mNotifySize % mWavFormat.BlockAlign;
            // set size of buffer
            mBufferSize = mNotifySize * cNotifyNum;

            bufferdescription.BufferBytes = mBufferSize;
            bufferdescription.Format = mWavFormat;

            mRecBuffer = new CaptureBuffer(bufferdescription, mCapDev);
            mNextCaptureOffset = 0;
        }
        private bool InitNotifications()
        {
            if (null == mRecBuffer)
            {
                MessageBox.Show("Record buffer is not found!");
                return false;
            }
            mNotificationEvent = new AutoResetEvent(false);
            if (null == mNotifyThread)
            {
                mNotifyThread = new Thread(new ThreadStart(WaitThread));
                mNotifyThread.Start();
            }
            BufferPositionNotify[] PositionNotify = new BufferPositionNotify[cNotifyNum + 1];
            for (int i = 0; i < cNotifyNum; i++)
            {
                PositionNotify[i].Offset = (mNotifySize * i) + mNotifySize - 1;
                PositionNotify[i].EventNotifyHandle = mNotificationEvent.Handle;
            }
            mNotify = new Notify(mRecBuffer);
            mNotify.SetNotificationPositions(PositionNotify, cNotifyNum);

            return true;
        }
        private bool InitCaptureDevice()
        {
            CaptureDevicesCollection devices = new CaptureDevicesCollection();
            Guid deviceGuid = Guid.Empty;
            if (devices.Count > 0)
                deviceGuid = devices[0].DriverGuid;
            else
            {
                MessageBox.Show("No device to capture wave!");
                return false;
            }
            try
            {
                mCapDev = new Capture(deviceGuid);
            }
            catch (DirectXException e)
            {
                MessageBox.Show(e.ToString());
                return false;
            }
            return true;
        }
        private WaveFormat CreateWaveFormat()
        {
            WaveFormat format = new WaveFormat();
            format.FormatTag = WaveFormatTag.Pcm;   // PCM
            format.SamplesPerSecond = 16000;        // 16KHz
            format.BitsPerSample = 16;              // 16Bit
            format.Channels = 1;                    // Mono
            format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));
            format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;
            return format;

        }
        private void WaitThread()
        {
            while (true)
            {
                // waiting for notification
                mNotificationEvent.WaitOne(Timeout.Infinite, true);
                // process data captured
                RecordCapturedData();
            }
        }
        #endregion
    }