来自:http://www.cnblogs.com/KeithDan/archive/2006/12/19/596833.html
应一个朋友委托,做一个录音程序.
我原本以为要用direct来做,先是在google上搜索了一把,收获不大。后来在codeproject上发现一篇文章A full-duplex audio player in C# using the waveIn/waveOut APIs ,原来可以很简单。在System32下原来有一个多媒体处理的API,winmm.dll,发现之非常兴奋,哈哈。
原来微软已经提供了一系列的wavein 和waveout方法,参考了里面一些东西做法。做了一些修改。由于我以前对音频并不怎么了解,特地查了一下音频的有关知识,不了解的朋友也可以了解一下,呵呵,知识共享拉。
其中音频采样率(位/bit),采样率包括32000Hz,44100Hz,48000Hz3种,采样大小分为16位和8位,声道通常就是2(立体声)和1(单声道)了。其中有一个重要的数据叫采样速率,计算公式为采样速率=采样率×采样大小×声道。我们通常比较熟悉的128K的MP3就是44100×16×2=1411.2Kb/s,这样的音频很大,通常10秒种就有1M多。而如果使用模拟信号的话并非采样率越高越好,只会盲目的增加我们文件的大小,只有数字信号的时候才会提高我们的效果。
对于音频这一块,希望其他朋友能提供给一些更多的知识与技术。特别是音频对比和频谱图等等。
那么我们往下看。
//wav头 long chunksize = fs.Length + 36; WriteChars(bw, "RIFF");//格式 bw.Write((int)chunksize);//文件长度(要加上头的36字节) WriteChars(bw, "WAVE");//标示 WriteChars(bw, "fmt ");//fmt bw.Write((int)16);//fmt长度 bw.Write(m_Format.wFormatTag);//压缩模式 bw.Write(m_Format.nChannels);//声道 bw.Write(m_Format.nSamplesPerSec);//采样率包含:32000Hz,44100Hz,48000Hz. bw.Write(m_Format.nAvgBytesPerSec);//每秒播放字节 bw.Write(m_Format.nBlockAlign);//位速 bw.Write(m_Format.wBitsPerSample);//采样大小 WriteChars(bw,"data");//data标志 bw.Write(fs.Length);//音频长度
// WaveIn calls [DllImport(mmdll)] public static extern int waveInGetNumDevs(); [DllImport(mmdll)] public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh); [DllImport(mmdll)] public static extern int waveInClose(IntPtr hwi); [DllImport(mmdll)] public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags); [DllImport(mmdll)] public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); [DllImport(mmdll)] public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); [DllImport(mmdll)] public static extern int waveInReset(IntPtr hwi); [DllImport(mmdll)] public static extern int waveInStart(IntPtr hwi); [DllImport(mmdll)] public static extern int waveInStop(IntPtr hwi);
private void DataArrived(IntPtr data, int size) { try { if (m_RecBuffer == null || m_RecBuffer.Length < size) { m_RecBuffer = new byte[size]; } System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size); bw_tmp.Write(m_RecBuffer); _recordSize+=m_RecBuffer.Length; } catch(Exception e) { return; } }