php wav文件生成波形图,WAV文件的数据结构以及绘制静态波形图的代码

WAV文件的数据结构以及绘制静态波形图的代码

一、结构分析

WAV文件格式是一种由微软和IBM联合开发的用于音频数字存储的标准,它采用RIFF文件格式结构。

1.WAVE文件由“块”组成。块的基本结构如下。

表1:块的基本结构

----------------------------------------------

偏移量 名称 字节数 类型 说明

----------------------------------------------

00 块标志 4 字符 由ASCII字符组成 04 块长度 4 长整型

08 块内容 数据 ----------------------------------------------

说明:

①块内容中所包含的数据是以字(WORD)为单位排列的,其长度必须为偶数,如果是奇数,则在最后添加一个空字节(NULL)。 ②块长度不包括标志符4字节以及块长度项本身所占用的4字节。

2.WAVE文件一般有四种块,它们是:RIFF块、格式块、附加块(可选),数据块。按照在文件中的出现位置,WAV文件的结构顺序如下:

表2:块在文件中的顺序

--------------- 名称 字节数

---------------

RIFF块 12

格式块 24或26

附加块 12

数据块 不定

---------------

说明:

①其中,RIFF块和格式块又合称为文件头,所以,如果没有附加块的话,WAV文件就是由文件头和数据体两大部分组成。

3.RIFF块的数据结构如表3。

表3:RIFF块的数据结构

---------------------------------------------------

偏移量

名称 字节数 数据类型 内容

---------------------------------------------------

00 标志符 4 字符 “RIFF”的Ascii码

04 文件长度 4 长整形 文件的总字节数

08 WAV标志 4 字符 “WAVE”的Ascii码

---------------------------------------------------

说明:

①RIFF是英文Resource Interchange File

Format的缩写,它是一种含有嵌套数据结构的二进制文件格式。

②文件长度不包括标志符4字节以及文件长度本身所占用的4字节。

③为什么还要有一个“WAVE”标志呢?这是因为除了波形格式(WAV)以外,能以RIFF文件格式存储的数据还包括:音频视频交错格式(AVI)、位图格式(RDI)、MIDI格式(RMI)、调色板格式(PAL)、多媒体电影(RMN)、动画光标(ANI)、其它RIFF文件(BND)。

4.格式块的数据结构如表4。

表4:格式块的数据结构

----------------------------------------------------------------------------

偏移地址 字节数 数据类型 内容

----------------------------------------------------------------------------

0C 4 字符 波形格式标志“fmt ”

10 4 长整形 格式块长度(一般=16,若=18表示最后有2字节附加信息)

14 2 整形 格式类别(值=1表示编码方式为PCMμ律编码)

16 2 整形 声道数(单声道=1,双声音=2)

18 4 长整形 采样频率(每秒样本数,表示每个通道的播放速度)

1C 4 长整形 数据传送速率(每秒字节=采样频率×每个样本字节数)

20 2 整形 每个样本字节数(又称基准块=每个样本位数×声道数÷8)

22 2 整形 每个样本位数(又称量化位数)

24 2 整形 附加信息(可选,通过块长度来判断有无)

----------------------------------------------------------------------------

说明:

①格式块长度不包括格式标志4字节以及块长度本身所占用的4个字节

②附加信息主要由一些软件制成的wav格式中含有该2个字节的 ③名词解释:

采样频率:将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。采样频率一般有11025Hz(11kHz)、22050Hz(22kHz)和44100Hz(44kHz)三种。

量化位数:样本的数据长度,它决定了模拟信号数字化以后的动态范围。常用的有8位、12位和16位。

声道数:有单声道和双声道之分,双声道中的左声道称为声道0,右声道称为声道1。

5.附加块是可选的,一般当wav文件是由某些软件转化而成时,则可能包含附加块。附加块的数据结构

如表5。

表5:附加块的数据结构

-----------------------------------------

偏移地址 字节数 数据类型 内容

-----------------------------------------

24 4 字符 标志符“fact”

28 4 长整形 块长度(=4)

2C 4 -----------------------------------------

说明:

①如果格式块中有附加信息,则偏移地址均后推2字节。

6.数据块的数据结构如表6。

表6:数据块的数据结构

------------------------------------------

偏移地址 字节数 类型 内容

------------------------------------------

24 4 字符 数据标志符“data” 28 4 长整型 样本数据长度 2C 样本数据 ------------------------------------------

说明:

①如果格式块中有附加信息,则偏移地址均后推2字节。

②如果文件中有附加块,则偏移地址均后推12字节。

③样本数据长度不包括标志符4字节以及长度数据本身所占用的4字节。

④WAV文件的播放时间=样本数据长度÷数据传送速率

⑤8位单声道:每个样本数据由8位表示。

⑥16位单声道:每个样本数据由16位表示,其中低字节存放高位,高字节存放低位。

⑦8位立体声:每个样本数据由16位表示,每8位表示一个声道,高8位和低8位分别代表左右两个声道。

⑧16位立体声:每个样本数据由32位表示,每16位表示一个声道,高16位和低16位分别代表左右两个声道。

二、实例

1.让我们来做个实验,以加深理性认识。

启动系统自带的录音机,点击“录音”键,大吼一声,截取一秒钟,另保存为四种WAV文件:8KHZ/8位/单声道、8KHZ/16位/单声道、8KHZ/8位/立体声、8KHZ/16位/立体声。其全路径文件名分别为:D:\8_1.wav、D:\8_2.wav、D:\16_1.wav、D:\16_2.wav。

下面以 8_1.wav 文件为例进行简单分析。其前58个数据如下(也许你的数据会有差异):

8KHZ,8位,单声道

---------------------------------------------------

00: 52 49 46 46 9E 1F 00 00 57 41 56 45 66 6D 74 20

10: 12 00 00 00 01 00 01 00 40 1F 00 00 40 1F 00 00

20: 01 00 08 00 00 00 66 61 63 74 04 00 00 00 6B 1F

30: 00 00 64 61 74 61 6B 1F 00 00

---------------------------------------------------

2.分析:

00-0B:RIFF块,其中:

00-03:“RIFF”的Ascii字符

04-07:文件长度=&H1F9E字节,当然,实际长度还要+8

08-0B:“WAVE”的Ascii字符

0C-25:格式块,其中:

0C-0F:“fmt

”的Ascii字符

10-13:块长度=18(10进制),说明该块的最后有2字节的附加信息

14-15:格式类别=1,表示编码方式为PCMμ律编码

16-17:声道数=1,表示为单声道

18-1B:采样频率=&H1F40(8000HZ)

1C-1F:数据传输速率=&H1F40,这是每秒钟传输的字节数

20-21:每个样本字节数=1字节

22-23:每个样本位数=8位

24-25:附加信息2个字节 00 00

26-32:附加块,其中:

26-29:“fact”的Ascii码

2A-2D:块长度=4

2E-31:块内容,&H1F6B

32-39:数据块之一部分,其中:

32-35:“data”的Ascii字符

36-39:数据块长度=&H1F6B(8043),这个长度是波型音频压缩数据的实际长度

注意:数据块长度&H1F6B是个奇数,根据前面的说明,数据块的最后会加上一个空字节00。我们来计算一下:文件长度=8094(&H1F9E)+8=58+8043+1=8102,看看你的Hex编辑器,是不是这个数字?

最后计算一下这个文件的播放时间:数据块长度÷数据传输速率=&H1F6B÷&H1F40=1.0054(秒)

三、绘制静态波形图

下面让我们来绘制这四个文件的静态波形图。

新建一个窗体,添加一个CommonDialog控件,并生成一个名为“绘制”的菜单项,代码如下:

Option Explicit

Dim DAT() As

Byte '样本数据

Private Sub 绘制_Click()

On Error GoTo 100

Dim filename As String

Dim tagType As String * 4 '标记字符

Dim dataSum As

Long '样本数据个数

Dim Channels As Integer '声道数

Dim SampleBit As Integer '量化位数

Dim Temp1 As Long

CommonDialog1.filename = "*.wav"

CommonDialog1.DefaultExt = "wav"

CommonDialog1.ShowOpen

filename = CommonDialog1.filename

Open filename For Binary As #1

Get #1, , tagType

If tagType <> "RIFF" Then GoTo 100 '如果不是RIFF退出

Get #1, 9, tagType

If tagType <> "WAVE" Then GoTo 100 '如果不是WAVE退出

Get #1, , tagType

If tagType <> "fmt " Then GoTo 100 '如果不是fmt 退出

Get #1, ,

dataSum '格式块长度

Get #1, 23,

Channels '声道数

Get #1, 35,

SampleBit '量化位数

Get #1, 21 + dataSum, tagType

If tagType = "fact" Then '如果是附加块

Get #1, ,

Temp1 '废弃

Get #1, ,

Temp1 '废弃

Get #1, ,

tagType '废弃

Get #1, ,

dataSum '废弃

ElseIf tagType = "data" Then

Get #1, ,

dataSum '数据块长度

Else

GoTo 100

End If

ReDim DAT(dataSum)

Get #1, , DAT

Close #1

Select Case

Channels '根据声道数绘制波形

Case

1 '单声道

Select Case

SampleBit

Case 8: DrawWaves8_1 '如果是8位

Case 16: DrawWaves16_1 '如果是16位

End

Select

Case

2 '立体声

Select Case

SampleBit

Case 8: DrawWaves8_2 '如果是8位

Case 16: DrawWaves16_2 '如果是16位

End

Select

End Select

Exit Sub

100

Close #1

End Sub

Private Sub DrawWaves8_1()

Dim i As Long

Dim exten As Long '波幅

Dim lastX As Long '水平坐标

Dim curY1 As Long '垂直坐标

Dim curY2 As Long '垂直坐标

ScaleWidth = UBound(DAT) '图片框宽度=样本个数

exten = ScaleHeight / 2 '波幅=图片框高度的二分之一

Cls

For i = 0 To ScaleWidth

curY1 = (DAT(i) - 128) / 128 * exten

'垂直坐标=样本数据*最大波幅

Line (lastX, exten + curY2)-(i, exten +

curY1)

curY2 = curY1: lastX = i

Next

End Sub

Private Sub DrawWaves8_2()

Dim i As Long

Dim exten As

Long '波幅

Dim lastX As

Long '水平坐标

Dim curLY1 As Long '左声道垂直坐标

Dim curLY2 As Long '左声道垂直坐标

Dim curRY1 As Long '右声道垂直坐标

Dim curRY2 As Long '右声道垂直坐标

Dim LYOffset As Long '左声道垂直偏移量

Dim RYOffset As Long '右声道垂直偏移量

ScaleWidth = UBound(DAT) / 2 '图片框宽度=单声道样本个数

exten = ScaleHeight /

4 '最大波幅为图片框高度的四分之一

LYOffset = exten

RYOffset = exten * 3

Cls

For i = 0 To ScaleWidth

curLY1 = (DAT(i * 2) - 128) / 128 * exten

curRY1 = (DAT(i * 2 + 1) - 128) / 128 *

exten

Line (lastX, LYOffset + curLY2)-(i, LYOffset +

curLY1) '画左声道波形

Line (lastX, RYOffset + curRY2)-(i, RYOffset +

curRY1) '画右声道波形

curLY2 = curLY1: curRY2 = curRY1: lastX =

i

Next

End Sub

Private Sub DrawWaves16_1()

Dim i As Long, d As String

Dim exten As Long '波幅

Dim lastX As Long '水平坐标

Dim curY1 As Long '垂直坐标

Dim curY2 As Long '垂直坐标

ScaleWidth = UBound(DAT) / 2 '图片框宽度=样本个数

exten = ScaleHeight / 2 '波幅=图片框高度的二分之一

Cls

For i = 0 To ScaleWidth

d = "&H" & Hex(DAT(i * 2 + 1)) &

Hex(DAT(i * 2))

curY1 = Val(d) / 32768 * exten

Line (lastX, exten + curY2)-(i, exten +

curY1)

curY2 = curY1: lastX = i

Next

End Sub

Private Sub DrawWaves16_2()

Dim i As Long, j As Long, dL As String, dR As String

Dim exten As

Long '最大波幅

Dim lastX As

Long '水平坐标

Dim curLY1 As Long '左声道垂直坐标

Dim curLY2 As Long '左声道垂直坐标

Dim curRY1 As Long '右声道垂直坐标

Dim curRY2 As Long '右声道垂直坐标

Dim LYOffset As Long '左声道垂直偏移量

Dim RYOffset As Long '右声道垂直偏移量

ScaleWidth = UBound(DAT) / 4 '图片框宽度=立体声样本个数/4

exten = ScaleHeight /

4 '最大波幅为图片框高度的四分之一

LYOffset = exten

RYOffset = exten * 3

Cls

For i = 0 To ScaleWidth

j = i * 4

dL = "&H" & Hex(DAT(j + 1)) &

Hex(DAT(j))

dR = "&H" & Hex(DAT(j + 3)) &

Hex(DAT(j + 2))

curLY1 = Val(dL) / 32768 * exten

curRY1 = Val(dR) / 32768 * exten

Line (lastX, LYOffset + curLY2)-(i, LYOffset +

curLY1) '画左声道波形

Line (lastX, RYOffset + curRY2)-(i, RYOffset +

curRY1) '画右声道波形

curLY2 = curLY1: curRY2 = curRY1: lastX =

i

Next

End Sub

提示:如果你懒得打字,可到163信箱去下载本代码,帐号是:vb62013@163.com,密码是:vb620132013

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值