none
不是有效的 Win32 应用程序。 (异常来自 HRESULT:0x800700C1) RRS feed

  • 问题

  • 我想用DirectSound来做一个录音的实验。并把录音的过程放在了Record类中。在窗体上放有一个“开始录音”的按钮。当点击按钮时,会跳转到Main函数中的这句话:

     Application.Run(new Form1());

    并提示

    “不是有效的 Win32 应用程序。 (异常来自 HRESULT:0x800700C1)  。”

    按钮的代码如下:

        private void button1_Click(object sender, EventArgs e)
        {
          //// 录音设置 
    
          //// 
    
          string wavfile = "test.wav"; 
    
          //wavfile = "test.wav"; 
    	
          recorder.SetFileName(wavfile); 
    
          //recorder.RecStart(); 
        }

    如果把“recorder.SetFileName(wavfile);”这句注释掉,就不会有错误......

    实在不知道是什么问题,麻烦各位帮帮忙。多谢了

    2011年1月27日 17:50

答案

全部回复

  • recorder是你自己的类?跟踪进去看看执行了什么
    http://feiyun0112.cnblogs.com/
    • 已标记为答案 FuN_ch 2011年1月28日 5:55
    2011年1月28日 1:20
    版主
  • recorder是SoundRecorder类的对象,网上贴的,主要是音频录制的操作。

    一个很奇怪的现象是,如果代码中包含有对recorder的操作,就算是窗体初始化函数也不会被执行....

    此外,我的电脑是Win7 , 64位系统,VSC# 2008 IDE。好像自动生成64位应用程序,不知道这个错误和着有没有关系?

     

    窗体类

      public partial class Form1 : Form
      {
        private SoundRecord recorder;
    
        public Form1()
        {
          InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
          MessageBox.Show("ksksksksksk");
          
          recorder = new SoundRecord(); 
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          //// 录音设置 
    
          //// 
          recorder = new SoundRecord(); 
          string wavfile = "test.wav"; 
    
          //wavfile = "test.wav"; 
    
          recorder.SetFileName(wavfile); 
    
          recorder.RecStart(); 
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
          recorder.RecStop();
    
          //recorder = null;
        }
      }

     

    SoundRecord类

      class SoundRecord
      {
        public const int cNotifyNum = 16;    // 缓冲队列的数目
        private int mNextCaptureOffset = 0;   // 该次录音缓冲区的起始点
    
        private int mSampleCount = 0;      // 录制的样本数目
        private int mNotifySize = 0;       // 每次通知大小 
    
        private int mBufferSize = 0;       // 缓冲队列大小
    
        private string mFileName = string.Empty;   // 文件名 
    
        private FileStream mWaveFile = null;     // 文件流 
    
        private BinaryWriter mWriter = null;     // 写文件
        private Capture mCapDev = null;       // 音频捕捉设备 
    
        private CaptureBuffer mRecBuffer = null;   // 缓冲区对象 
    
        private Notify mNotify = null;        // 消息通知对象
        private WaveFormat mWavFormat;            // 录音的格式 
    
        private Thread mNotifyThread = null;         // 处理缓冲区消息的线程 
    
        private AutoResetEvent mNotificationEvent = null;  // 通知事件
    
        /// <summary> 
    
        /// 构造函数,设定录音设备,设定录音格式. 
    
        /// </summary> 
    
        public SoundRecord()
        {
    
          // 初始化音频捕捉设备 
    
          InitCaptureDevice();
    
          // 设定录音格式 
    
          mWavFormat = CreateWaveFormat();
    
        }
        /// <summary> 
    
        /// 设定录音结束后保存的文件,包括路径 
    
        /// </summary> 
    
        /// <param name="filename">保存wav文件的路径名</param> 
    
        public void SetFileName(string filename)
        {
    
          // mFileName = filename;
    
        }
        /// <summary> 
    
        /// 开始录音 
    
        /// </summary> 
    
        public void RecStart()
        {
    
          // 创建录音文件 
    
          CreateSoundFile();
          // 创建一个录音缓冲区,并开始录音 
    
          CreateCaptureBuffer();
          // 建立通知消息,当缓冲区满的时候处理方法 
    
          InitNotifications();
    
          mRecBuffer.Start(true);
    
        }
        /// <summary> 
    
        /// 停止录音 
    
        /// </summary>
    
        public void RecStop()
        {
    
          // 关闭通知消息 
    
          if (null != mNotificationEvent)
    
            mNotificationEvent.Set();
          // 停止录音 
    
          mRecBuffer.Stop();
          // 写入缓冲区最后的数据 
    
          RecordCapturedData();
    
          // 回写长度信息 
    
          mWriter.Seek(4, SeekOrigin.Begin);
    
          mWriter.Write((int)(mSampleCount + 36));  // 写文件长度 
    
          mWriter.Seek(40, SeekOrigin.Begin);
    
          mWriter.Write(mSampleCount);        // 写数据长度 
    
          mWriter.Close();
    
          mWaveFile.Close();
    
          mWriter = null;
    
          mWaveFile = null;
    
        }
    
        /// <summary> 
    
        /// 初始化录音设备,此处使用主录音设备. 
    
        /// </summary> 
    
        /// <returns>调用成功返回true,否则返回false</returns>
    
        private bool InitCaptureDevice()
        {
    
          // 获取默认音频捕捉设备 
    
          CaptureDevicesCollection devices = new CaptureDevicesCollection(); // 枚举音频捕捉设备 
    
          Guid deviceGuid = Guid.Empty;                    // 音频捕捉设备的ID
          if (devices.Count > 0)
    
            deviceGuid = devices[0].DriverGuid;
    
          else
          {
    
            MessageBox.Show("系统中没有音频捕捉设备");
    
            return false;
    
          }
          // 用指定的捕捉设备创建Capture对象 
    
          try
          {
    
            mCapDev = new Capture(deviceGuid);
    
          }
    
          catch (DirectXException e)
          {
    
            MessageBox.Show(e.ToString());
    
            return false;
    
          }
    
          return true;
    
        }
        /// <summary> 
    
        /// 创建录音格式,此处使用16bit,16KHz,Mono的录音格式
    
        /// </summary> 
    
        /// <returns>WaveFormat结构体</returns> 
    
        private WaveFormat CreateWaveFormat()
        {
    
          // WaveFormat format = new WaveFormat();
          ConstructorInfo constructor = typeof(WaveFormat).GetConstructor(Type.EmptyTypes); 
          WaveFormat format = (WaveFormat)constructor.Invoke(null); 
    
          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;
    
        }
        /// <summary> 
    
        /// 创建录音使用的缓冲区 
    
        /// </summary> 
    
        private void CreateCaptureBuffer()
        {
    
          // 缓冲区的描述对象 
    
          // CaptureBufferDescription bufferdescription = new CaptureBufferDescription();
    
          ConstructorInfo constructor = typeof(CaptureBufferDescription).GetConstructor(Type.EmptyTypes);
          CaptureBufferDescription bufferdescription = (CaptureBufferDescription)constructor.Invoke(null); 
    
          if (null != mNotify)
          {
    
            mNotify.Dispose();
    
            mNotify = null;
    
          }
    
          if (null != mRecBuffer)
          {
    
            mRecBuffer.Dispose();
    
            mRecBuffer = null;
    
          }
          // 设定通知的大小,默认为1s钟 
    
          mNotifySize = (1024 > mWavFormat.AverageBytesPerSecond / 8) ? 1024 : (mWavFormat.AverageBytesPerSecond / 8);
    
          mNotifySize -= mNotifySize % mWavFormat.BlockAlign;
          // 设定缓冲区大小 
    
          mBufferSize = mNotifySize * cNotifyNum;
          // 创建缓冲区描述 
    
          bufferdescription.BufferBytes = mBufferSize;
    
          bufferdescription.Format = mWavFormat;      // 录音格式
          // 创建缓冲区 
    
          mRecBuffer = new CaptureBuffer(bufferdescription, mCapDev);
    
          mNextCaptureOffset = 0;
    
        }
        /// <summary>
    
        /// 初始化通知事件,将原缓冲区分成16个缓冲队列,在每个缓冲队列的结束点设定通知点.
    
        /// </summary> 
    
        /// <returns>是否成功</returns> 
    
        private bool InitNotifications()
        {
    
          if (null == mRecBuffer)
          {
    
            MessageBox.Show("未创建录音缓冲区");
    
            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;
    
        }
        /// <summary> 
    
        /// 将录制的数据写入wav文件 
    
        /// </summary> 
    
        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);
          // 写入Wav文件
    
          mWriter.Write(CaptureData, 0, CaptureData.Length);
          // 更新已经录制的数据长度. 
    
          mSampleCount += CaptureData.Length;
          // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置 
    
          mNextCaptureOffset += CaptureData.Length;
    
          mNextCaptureOffset %= mBufferSize; // Circular buffer
    
        }
    
        /// <summary> 
    
        /// 接收缓冲区满消息的处理线程 
    
        /// </summary> 
    
        private void WaitThread()
        {
    
          while (true)
          {
    
            // 等待缓冲区的通知消息 
    
            mNotificationEvent.WaitOne(Timeout.Infinite, true);
    
            // 录制数据 
    
            RecordCapturedData();
    
          }
    
        }
    
        /// <summary> 
    
        /// 创建保存的波形文件,并写入必要的文件头. 
    
        /// </summary> 
    
        private void CreateSoundFile()
        {
    
          /************************************************************************** 
    
         Here is where the file will be created. A 
    
         wave file is a RIFF file, which has chunks 
    
         of data that describe what the file contains. 
    
         A wave RIFF file is put together like this:
         The 12 byte RIFF chunk is constructed like this: 
    
         Bytes 0 - 3 : 'R' 'I' 'F' 'F'
    
         Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description. 
    
                  (4 bytes for "WAVE" + 24 bytes for format chunk length + 
    
                  8 bytes for data chunk description + actual sample data size.) 
    
         Bytes 8 - 11: 'W' 'A' 'V' 'E'
         The 24 byte FORMAT chunk is constructed like this: 
    
         Bytes 0 - 3 : 'f' 'm' 't' ' ' 
    
         Bytes 4 - 7 : The format chunk length. This is always 16.
    
         Bytes 8 - 9 : File padding. Always 1. 
    
         Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo. 
    
         Bytes 12- 15: Sample rate. 
    
         Bytes 16- 19: Number of bytes per second. 
    
         Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or 
    
                 16 bit mono, 4 for 16 bit stereo. 
    
         Bytes 22- 23: Number of bits per sample.
         The DATA chunk is constructed like this: 
    
         Bytes 0 - 3 : 'd' 'a' 't' 'a' 
    
         Bytes 4 - 7 : Length of data, in bytes. 
    
         Bytes 8 -...: Actual sample data. 
    
              ***************************************************************************/
    
          // Open up the wave file for writing. 
    
          mWaveFile = new FileStream(mFileName, FileMode.Create);
    
          mWriter = new BinaryWriter(mWaveFile);
          // Set up file with RIFF chunk info. 
    
          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. 
    
        }
      }


    2011年1月28日 4:31
  • 试试项目属性,选择目标平台为any cup 或者x86
    http://feiyun0112.cnblogs.com/
    2011年1月28日 4:35
    版主
  • 是对象声明时候的问题

      private Capture mCapDev = null;    // 音频捕捉设备 
    
      private CaptureBuffer mRecBuffer = null;  // 缓冲区对象 
    
      private Notify mNotify = null;    // 消息通知对象
      private WaveFormat mWavFormat;      // 录音的格式 
    
      private Thread mNotifyThread = null;     // 处理缓冲区消息的线程 
    
      private AutoResetEvent mNotificationEvent = null; // 通知事件
    

    把"null"取消就好了,不过现在的问题是在WaveFormat那里,不知道怎么处理。

    此外,我的C#2008是express版本的,没有找到“目标平台”的设置选项.....是没有么?

    2011年1月28日 5:38
  • 问题已经确定在 “WaveFormat mWavFormat;” 这句话上了。

    不知道为什么,只要有这句话,程序就会报错....

    烦人的是我找不到这方面的资料.....

    多谢了

    2011年1月28日 5:57