WAV音频文件结构及录制

  1.WAV音频文件结构
WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。
而每个Chunk都有自己的id做为该chunk开始的标志.下面我们来看下一个wav文件的具体信息:
 标识大小
RIFF
Chunk
ID4 Bytes"RIFF"
Size4 BytesFile.length - 8
Type4 Bytes"WAVE"
    
Format
Chunk
ID4 Bytes"fmt "
Size4 Bytes数值为16或18,18则最后又附加信息
FormatTag2 Bytes编码方式,一般为0x0001
Channels2 Bytes声道数目,1--单声道;2--双声道
SamplesPerSecond4 Bytes采样频率 8000, 44100, 等
AvgBytesPerSec4 Bytes每秒所需字节数 (BlockAlign * SamplesPerSecond)
BlockAlign2 Bytes数据块对齐单位(每个采样需要的字节数) Channels * (BitsPerSample / 8)
BitsPerSample2 Bytes每个采样需要的bit数 8或者是16
 2 Bytes附加信息(可选,通过Size来判断有无)
    
data
Chunk
ID4 Bytes"data"
SIZE4 Bytes 
data 音频数据
Data Chunk是真正保存wav数据的地方,以"data"作为该Chunk的标示。然后是数据的大小。紧接着就是wav数据。

2.制作WAV文件
有了wav文件的结构加上音频数据那么我们很快就能制作出一个wav文件.
这里我们使用DirectSound来获取麦克风上录入的音频数据,然后制作wav文件(即DirectSound录音);
这里使用winform来编写一个简单的录音程序.
准备工作:
	vs2008 
	DirectX SDK(这样才能引入程序集Microsoft.DirectX.DirectSound,Microsoft.DirectX)
那么接下来的问题是我们如何获取音频数据.
使用CaptureBuffer中的Read方法就可以获得:
	byte[] data = (byte[])CaptureBuffer.Read();
这个流程也就很明显了.
首先.创建CaptureBuffer.
	创建CaptureBuffer之前需要创建两个实例即WaveFormat(Wav文件的Format Chunk的描述结构), Capture(声卡设备的抽象描述);
//创建Capture
protected Capture CreateCapture()
{
	Capture capture = null;
	try
	{
		capture = new Capture(DSoundHelper.DefaultVoiceCaptureDevice);
		//DSoundHelper.DefaultVoiceCaptureDevice 使用默认声卡的GUID
	   
	}
	catch (DirectXException e)
	{
		MessageBox.Show(e.ErrorString);
	}
	return capture;
}

//创建WaveFormat 
protected WaveFormat CreateFormat()
{
	WaveFormat format = new WaveFormat();
	format.FormatTag = WaveFormatTag.Pcm;
	format.Channels = 1;
	format.SamplesPerSecond = 16000;
	format.BitsPerSample = 16;
	format.BlockAlign = (short)(format.Channels * format.BitsPerSample / 8);
	format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign;
	return format;
}

//创建CaptureBuffer
protected CaptureBuffer CreateBuffer(WaveFormat format, Capture capture)
{
	CaptureBufferDescription desc = new CaptureBufferDescription();
	desc.Format = format;
	desc.BufferBytes = BUFFER_SIZE;//设置CaptureBuffer的大小,这里BUFFER_SIZE=2m
	
	CaptureBuffer buffer = new CaptureBuffer(desc, capture);
	return buffer;
}
//buffer.start(true); 意味着录音开始
	
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
最后.读取CaptureBuffer中的数据保存为wav文件.
	
	
//读取缓冲区中的音频数据
protected byte[] GetRecordBuffer(CaptureBuffer buffer)
{
	byte[] data = null;
	int readPos;
	int capturePos;
	buffer.GetCurrentPosition(out capturePos, out readPos);
	if (readPos < 0)
	readPos += BUFFER_SIZE;
	if (readPos == 0)
	return null;
	data = (byte[])buffer.Read(0, typeof(byte), LockFlag.None, readPos);
	return data;
}

private void StopRecord()
{

	byte[] data = GetRecordBuffer(buffer);
	buffer.Stop();//录音结束
	if (data != null)
	{
	SaveFileDialog dlg = new SaveFileDialog();
	dlg.Title = "Save Audio File";
	dlg.InitialDirectory = 
		Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
	dlg.FileName = "test.wav";
	if (dlg.ShowDialog() != DialogResult.OK)
		return;
	string path = dlg.FileName;
	dlg.Dispose();

	FileStream file = new FileStream(path, 
		FileMode.Create, FileAccess.Write, FileShare.None);
	char[] chunkRiff = { "R", "I", "F", "F" };
	char[] chunkType = { "W", "A", "V", "E" };
	char[] chunkFmt = { "f", "m", "t", " " };
	char[] chunkData = { "d", "a", "t", "a" };
	
	//RIFF WAVE Chunk
	BinaryWriter writer = new BinaryWriter(file);
	writer.Write(chunkRiff);
	writer.Write((int)(data.Length + 36));
	writer.Write(chunkType);
	
	//Format Chunk
	writer.Write(chunkFmt);
	writer.Write((int)16);
	writer.Write((ushort)1);
	writer.Write(format.Channels);
	writer.Write(format.SamplesPerSecond);
	writer.Write(format.AverageBytesPerSecond);

	writer.Write(format.BlockAlign);
	writer.Write(format.BitsPerSample);
	
	//data Chunk
	writer.Write(chunkData);
	writer.Write((int)data.Length);

	writer.Write(data, 0, data.Length);
	writer.Write((int)0);
	writer.Close();
	file.Close();
	file.Dispose();
	}
}
		
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
哈哈,大功告成了,也许你注意到了,我们设置的缓冲区的大小是2M,如果我们录制的文件大于2M呢,那岂不是在缓冲区中放不下吗?是的,没错.DirectSound的解决方案是,当缓冲区内的数据满时,通知你,你转移到别的地方去.
详细的可以参看这里;
或者是查看类
Microsoft.DirectX.DirectSound.BufferPositionNotify
Microsoft.DirectX.DirectSound.Notify
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值