应一个朋友委托,做一个录音程序.
我原本以为要用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);
//
音频长度
这就是我们需要给wave文件写上的头。
大家查一下winmm.dll就会发现,里面提供了很多有用的API,非常的棒。
//
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);
其中DataArrived方法是委托的方法,它将我们接收到的数据拷贝到m_RecBuffer中,再写入到文件里。在这里我并没有使用MenmoyStream,看到windows录音限制1分钟,我估计它(我并没有认真看过)是讲数据写入内存,再统一存储的,为了没有限制,所以直接用了FileStream,写到文件里了。
private
void
DataArrived(IntPtr data,
int
size)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
try
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (m_RecBuffer == null || m_RecBuffer.Length < size)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
m_RecBuffer = new byte[size];
}
System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size);
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
bw_tmp.Write(m_RecBuffer);
_recordSize+=m_RecBuffer.Length;
}
catch(Exception e)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
}
里面我加入了一些功能,包括开始,停止,暂停,继续等等。
在此,我想问一下其他朋友,音频的频谱图是基于怎样的算法呢?如何画的?这个我很想了解,有这方面知识的朋友望能告知,给点参考。在此谢过。
Source
--------------------------------------------
参考:
A full-duplex audio player in C# using the waveIn/waveOut APIs
PCM编码及其技术