怎样才能分析出wav文件的1/3倍频程? ( 积分: 200 )

  • 主题发起人 主题发起人 eggplant_2000
  • 开始时间 开始时间
E

eggplant_2000

Unregistered / Unconfirmed
GUEST, unregistred user!
我用MMtool可以简单的看到音频的时域波形和线谱,但是我没有发现做1/3倍频程的控件,如果要是通过调用线谱的数据来画出1/3倍频程谱图,那么实现监测wav文件的话将需要非常大的数据量的处理(是希望在录音的同时可以看到这个声音信号的1/3倍频程,若干秒平均一次,当然这个时间也是可调的),不知道有没有好的控件,还是MMtool本身就可以实现这个功能。先感谢各位达人!!!
 
我用MMtool可以简单的看到音频的时域波形和线谱,但是我没有发现做1/3倍频程的控件,如果要是通过调用线谱的数据来画出1/3倍频程谱图,那么实现监测wav文件的话将需要非常大的数据量的处理(是希望在录音的同时可以看到这个声音信号的1/3倍频程,若干秒平均一次,当然这个时间也是可调的),不知道有没有好的控件,还是MMtool本身就可以实现这个功能。先感谢各位达人!!!
 
自己顶一下……
 
各位老大,帮个忙啊,我再开贴加200分好了!!!
 
各位老大,有清楚的吗?还是我没说明白?
 
哎,换一个问法好了。我怎么才能把MMTool画线谱的数据调处来,控件显示的FFT的点数最高为4096,而我希望最小是65536,但是不管怎么样,控件后面肯定是有一个很大的数组的,我怎么才能把它调出来,这样我才能够去算1/3倍频程谱图。
 
什么是Wav文件

Wav文件直接反映了一个声音在每个时刻的大小值,比如说以下一段波形:
我们按每人0.1秒取一点,得到的wav文件数值就是0,1,1,-1,0,1。因此,假如我们能把许多Wav文件的数据直接相加,你听到的就是所有的声音,这就是混音器的原理。
下面我们分析一下Wav文件结构:
我们可以打开一个Wav文件直接看其二进制码:
C:/user/wave/22.wav
00000000 5249 4646 9CB6 1E00 5741 5645 666D 7420
00000010 1000 0000 0100 0200 2256 0000 44AC 0000
00000020 0200 0800 6461 7461 78B6 1E00 7F7F 7F7F
00000030.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000040.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000050.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000060.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000070.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000080.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
00000090.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
000000A0.7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F 7F7F
大家可以看到wav文件存储格式如下:

"RIFF"

×××× 文件大小
"WAVE"

"fmt"

×××× PCMWAWFORMAT——数据结构大小
××××
…… 数据结构“PCMWAVEFORMAT”
××××
data
×××× 数据大小
∶ 数据

首先是字符串“RIFF”,表示此文件遵循一种标准格式名为“资源互换文件格式”(Resource Intercharge Format)。后面紧跟四个字节指明文件大小。其次是字符串“WAVE”和“fmt”,后面紧跟一个名为“PCMWAVEFORMAT”的结构,最后是字符串“data”,紧跟数据大小及所有数据。PIFF文件为一种树状结构,基本构成单位是“块”,图5.2中是wav文件中“块”关系图。


图 5.2
如图所示,wav文件结构为两层,由父块“RIFF”和两个子块“fmt”、“data”组成。“fmt”块包含wav文件格式信息,“data”块包含数据信息。



WAV 文件编辑(截取,合并,插入)的实现原理

确切地说 WAV 文件的编辑其实就是拼合文件,并重新生成文件头.
仅此而已.



多媒体处理的API

waveInAddBuffer向声音输入设备发送缓冲区
waveInClose关闭声音输入设备
waveInGetDevCaps获取声音输入设备性能
waveInGetErrorText获取声音出错的信息文本
waveInGetID获取声音输入设备ID
waveInGetNumDevs返回声音输入设备数量
waveInGetPosition获取声音设备输入位置
waveInMessage向声音输入设备发送信息
waveInOpen打开声音输入设备
waveInPrepareHeader预备声音输入缓冲区
waveInReset停止声音输入设备工作
waveInStart停止声音输入设备工作
waveInStop停止声音输入
waveInUnprepareHeader清除预备的声音文件头
waveOutBreakLoop中断声音输出循环
waveOutClose关闭声音输出设备
waveOutGetDevCaps获取声音输出设备性能
waveOutGetErrorText获取声音出错文本
waveOutGetID获取声音输出设备ID
waveOutGetNumDevs获取声音输出设备数量
waveOutGetPitch获取声音输出的强度
waveOutGetPlaybackRate获取声音回放率
waveOutGetPosition获取声音回放位置
waveOutGetVolume获取声音音量
waveOutMessage向声音输出设备发送消息
waveOutOpen打开声音输出设备
waveOutPause暂停声音回放
waveOutPrepareHeader预备声音回放数据块
waveOutReset停止声音回放
waveOutRestart重开始声音回放
waveOutSetPitch设置波形输出强度
waveOutSetPlaybackRate设置回放率
waveOutSetVolume设置输出音量
waveOutUnprepareHeader清除预备声音数据块
waveOutWrite写入声音输出设备



媒体控制接口

MCI(Media Control Interface)媒体控制接口是MircroSoft提供的一组多媒体设备和文件的标准接口,它的好处是可以方便地控制绝大多数多媒体设备包括音频、视频、影碟、录像等多媒体设备,而不需要知道它们的内部工作状况。但是古人云:成也萧何,败也萧何。MCI虽然看上去高大全,但对于一些高级应用来说,它是远远不够的。好比Visual C++虽然看上去无所不能,却需要程序员自己开发多媒体引擎一样。对于MCI指令集,我们将只作简单介绍,重点放在后面的波形文件混音器上。

MCI的控制方式:

一般说来,程序员使用两个函数就可以与MCI打交道了:

MCIERROR mciSendCommand(MCIDEVICEID wDeviceID, UINT uMsg,
DWORD dwFlags, DWORD dwParam );

命令字符串方式,用接近于日常生活用语的方式发送控制命令,适用于高级编程如VB、TOOLBOOK等。

MCIERROR mciSendString(LPCTSTR lpszCommand,LPTSTR lpszReturnStr
ing, UINT cchReturn, HANDLE hwndCallback);


命令消息方式,用专业语法发送控制消息,适用于VC等语言编程,此方式直接与MCI设备打交道。

 

对于mciSendCommand,第一个参数指定了设备标识,这个标识会在程序员打开MCI设备时由系统提供。第二个参数指定将如何控制设备,详细请查阅后面“MCI指令”一栏。第三个参数为访问标识,第四个参数一般是一个数据结构,标识程序在访问MCI时要的一些信息。有关详细资料,请查阅本光盘配套书。

对于mciSendString,第一个参数为一串控制字符串,返回信息由系统填入第二个参数,第三个参数指明返回信息的最大长度,若对MCI装置设定了"notify"标志则需要在第四个参数填上返回窗口句柄。

举例:

mciSendCommand(DeviceID,MCI_CLOSE,NULL,NULL);//关闭一个MCI设备;

mciSendString("open aaa.avi",0,0,0);
//打开文件"aaa.avi";


MCI的设备类型:

MCI的设备类型有:

设备描述 描述字符串 说明

MCI_ALL_DEVICE_ID   所有设备

MCI_DEVTYPE_ANIMATION Animation 动画设备

MCI_DEVTYPE_CD_AUDIO Cdaudio CD音频

MCI_DEVTYPE_DAT Dat 数字音频

MCI_DEVTYPE_DIGITAL_VIDEO Digitalvideo 数字视频

MCI_DEVTYPE_OTHER Other 未定义设备

MCI_DEVTYPE_OVERLAY Overlay 重叠视频

MCI_DEVTYPE_SCANNER Scanner 扫描仪

MCI_DEVTYPE_SEQUENCER Sequencer MIDI 序列器

MCI_DEVTYPE_VCR Vcr 合式录像机

MCI_DEVTYPE_VIDEODIS Videodisc 激光视盘

MCI_DEVTYPE_WAVEFORM_AUDIO waveaudio Wave 音频

对于未在上面定义的MCI设备,用户可查看system.ini文件中[mci]部分,例如:

[mci]

cdaudio=mcicda.drv
sequencer=mciseq.drv
waveaudio=mciwave.drv
avivideo=mciavi.drv
videodisc=mcipionr.drv
vcr=mcivisca.drv
ActiveMovie=mciqtz.drv
QTWVideo=mciqtw.drv
MPEGVideo=C:/PROGRA~1/XING/XINGMP~1/xmdrv95.dll
其中最后两句分别指明了Apple的QuickTime设备,设备名为"QTWVidio"、MPEG影像设备,设备名为"MPEGVideo"。

在MCI编程中,既可以将设备描述当设备名,也可以将描述字符串当设备名,一个极端偷懒的办法是程序员不要在程序中指定设备名,Windows将自动根据文件扩展名识别设备类型。

举个例子来说,打开一个多媒体文件有以下三种方式:
[1]:自动识别:打开一个"WAV"文件
MCI_OPEN_PARMS mciOpen;
mciOpen.lpstrDeviceType=0;
mciOpen.lpstrElementName="aaa.wav";
mciSendCommand(NULL,MCI_OPEN, MCI_OPEN_ELEMENT,
(DWORD)&mciOpen);

[2]:指定设备描述:打开CD播放器
MCI_OPEN_PARMS mciOpen;
mciOpen.lpstrDeviceType=(LPSTR)MCI_DEVTYPE_CD_AUDIO ;
mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID,
(DWORD)&mciOpen);

[3]:指定描述字符串: 打开一个AVI文件
MCI_OPEN_PARMS mciOpen;
mciOpen.lpstrDeviceType="avivideo";
mciOpen.lpstrElementName="aaa.avi";
mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)&mciOpen);


注意三种打开方式中,函数第三个参数的区别,后面会讲到这种区别。

 

MCI指令

MCI使用如下指令:

MCI_BREAK
设置中断键,缺省是”CTRL+BREAK"

MCI_CAPTURE
抓取当前帧并存入指定文件,仅用于数字视频

MCI_CLOSE
关闭设备

MCI_CONFIGURE
弹出配置对话框,仅用于数字视频

MCI_COPY
拷贝数据至剪贴板

MCI_CUE
延时播放或录音

MCI_CUT
删除数据

MCI_DELETE
删除数据

MCI_ESCAPE
仅用于激光视频

MCI_FREEZE
将显示定格

MCI_GETDEVCAPS
获取设备信息

MCI_INDEX
当前屏幕显示与否,仅用于VCR设备

MCI_INFO
获取字符串信息

MCI_LIST
获取输入设备数量,支持数字视频和VCR设备

MCI_LOAD
装入一个文件

MCI_MARK
取消或做一个记号,与MCI_SEEK配套

MCI_MARK
取消或做一个记号,与MCI_SEEK配套

MCI_MONITOR
为数字视频指定报告设备

MCI_OPEN
打开设备

MCI_PASTE
粘帖数据

MCI_PAUSE
暂停当前动作

MCI_PLAY
播放

MCI_PUT
设置源、目的和边框矩形

MCI_QUALITY
定义设备缺省质量

MCI_RECORD
开始录制

MCI_RESERVE
分配硬盘空间

MCI_RESTORE
拷贝一个bmp文件至帧缓冲

MCI_RESUME
使一个暂停设备重新启动

MCI_SAVE
保存数据

MCI_SEEK
更改媒体位置

MCI_SET
设置设备信息

MCI_SETAUDIO
设置音量

MCI_SETTIMECODE
启用或取消VCR设备的时间码

MCI_SETTUNER
设置VCR设备频道

MCI_SETVIDEO
设置video参数

MCI_SIGNAL
在工作区上设置指定空间

MCI_STATUS
获取设备信息

MCI_STEP
使播放设备跳帧

MCI_STOP
停止播放

MCI_SYSINFO
返回MCI设备信息

MCI_UNDO
取消操作

MCI_UNFREEZE
使使用MCI_UNFREEZE的视频缓冲区恢复运动

MCI_UPDATE
更新显示区域

MCI_WHERE
获取设备裁减矩形

MCI_WINDOW
指定图形设备窗口和窗口特性


其中比较常用的指令有MCI_OPEN、MCI_CLOSE、MCI_PLAY、MCI_STOP、MCI_PAUSE、MCI_STATUS等等。
 
……晕倒,那我岂不是要重新去自己解析wav文件了。但是最关键的是我要通过声卡来监测信号,而得到一个高精度的谱线图。今天发现,MMTool里的Peak的控件,FFT的点数最高为16384(1秒钟抽点16384个),也是说我的线谱的频率分辨率最高可以到2.9Hz左右,也就是说在作1/3倍频程谱图的时候,20Hz的中心频率下我只能得到2根频率下的线谱(20*23%=4.6Hz),精度太低了,作40Hz以下的通过特性时是几乎不可信的。各位高手,帮着想想办法吧,作个揖先了!简单点说就是做一个实时监测用的宽带谱分析软件。
自己重新去解析wav倒不是非常费尽,Matlab可以很简单的实现以上的功能,但是太慢了;要是用Delphi来自己写傅立叶变换就是没有人家的算法好,一样的很慢,当然还要包括各种窗函数;要是用低通滤波器的方法来直接作宽带谱分析的话,得到的数据又不是很准确……N多种方法都想了,郁闷阿!!!
 
各位老大,没人知道吗?
 
已经搞到线谱的数据了,好费劲啊,结贴了!
 
后退
顶部