调用API实现录音

应一个朋友委托,做一个录音程序.
我原本以为要用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多。而如果使用模拟信号的话并非采样率越高越好,只会盲目的增加我们文件的大小,只有数字信号的时候才会提高我们的效果。
对于音频这一块,希望其他朋友能提供给一些更多的知识与技术。特别是音频对比和频谱图等等。
那么我们往下看。

None.gif // wav头
None.gif
                 long  chunksize  =  fs.Length  +   36 ;
None.gif                WriteChars(bw, 
" RIFF " ); // 格式
None.gif
                bw.Write(( int )chunksize); // 文件长度(要加上头的36字节)
None.gif
                WriteChars(bw,  " WAVE " ); // 标示
None.gif
                WriteChars(bw,  " fmt  " ); // fmt
None.gif
                bw.Write(( int ) 16 ); // fmt长度
None.gif
                bw.Write(m_Format.wFormatTag); // 压缩模式
None.gif
                bw.Write(m_Format.nChannels); // 声道
None.gif
                bw.Write(m_Format.nSamplesPerSec); // 采样率包含:32000Hz,44100Hz,48000Hz.
None.gif
                bw.Write(m_Format.nAvgBytesPerSec); // 每秒播放字节
None.gif
                bw.Write(m_Format.nBlockAlign); // 位速
None.gif
                bw.Write(m_Format.wBitsPerSample); // 采样大小
None.gif
                WriteChars(bw, " data " ); // data标志
None.gif
                bw.Write(fs.Length); // 音频长度

这就是我们需要给wave文件写上的头。
大家查一下winmm.dll就会发现,里面提供了很多有用的API,非常的棒。
None.gif //  WaveIn calls
None.gif
        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInGetNumDevs();
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInAddBuffer(IntPtr hwi,  ref  WaveHdr pwh,  int  cbwh);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInClose(IntPtr hwi);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInOpen( out  IntPtr phwi,  int  uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback,  int  dwInstance,  int  dwFlags);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInPrepareHeader(IntPtr hWaveIn,  ref  WaveHdr lpWaveInHdr,  int  uSize);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInUnprepareHeader(IntPtr hWaveIn,  ref  WaveHdr lpWaveInHdr,  int  uSize);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInReset(IntPtr hwi);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInStart(IntPtr hwi);
None.gif        [DllImport(mmdll)]
None.gif        
public   static   extern   int  waveInStop(IntPtr hwi);
其中DataArrived方法是委托的方法,它将我们接收到的数据拷贝到m_RecBuffer中,再写入到文件里。在这里我并没有使用MenmoyStream,看到windows录音限制1分钟,我估计它(我并没有认真看过)是讲数据写入内存,再统一存储的,为了没有限制,所以直接用了FileStream,写到文件里了。
None.gif private   void  DataArrived(IntPtr data,  int  size)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (m_RecBuffer == null || m_RecBuffer.Length < size)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    m_RecBuffer 
= new byte[size];
ExpandedSubBlockEnd.gif                }

InBlock.gif                System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 
0, size);
InBlock.gif
InBlock.gif                bw_tmp.Write(m_RecBuffer);
InBlock.gif                _recordSize
+=m_RecBuffer.Length;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

里面我加入了一些功能,包括开始,停止,暂停,继续等等。

在此,我想问一下其他朋友,音频的频谱图是基于怎样的算法呢?如何画的?这个我很想了解,有这方面知识的朋友望能告知,给点参考。在此谢过。

Source
--------------------------------------------
参考:
A full-duplex audio player in C# using the waveIn/waveOut APIs
PCM编码及其技术

转载于:https://www.cnblogs.com/KeithDan/archive/2006/12/19/596833.html

你可能感兴趣的:(调用API实现录音)