标题:
音频格式细节
[打印本页]
作者:
51黑tt
时间:
2016-3-5 17:36
标题:
音频格式细节
几个格式细节备记(混)
typedef struct _MediaType {
GUID majortype;
GUID subtype;
BOOL bFixedSizeSamples;
BOOL bTemporalCompression;
ULONG lSampleSize;
GUID formattype;
IUnknown *pUnk; //not use
ULONG cbFormat;
BYTE *pbFormat;
} AM_MEDIA_TYPE;
主要有
majortype 媒体类型大致说明
subtype 更一步的细致说明
formattype
包括有以下:其对应的不同的数据格式
FORMAT_None
FORMAT_DvInfo
FORMAT_MPEGVideo
FORMAT_MPEG2Video
FORMAT_VideoInfo
FORMAT_VideoInfo2
FORMAT_WaveFormatEx
GUID_NULL
cbForamt成员指定了格式块pbFormat的大小.
pbFormat指针指向格式子块。
pbFormat是一个void*的指针,因为格式块会因为媒体类型
的不同而有不同的指向。如音频填充的是WAVEFORMATEX结构
数据.
可以从中取出传来的数据格式。
//TWaveFormatEx 结构:
TWaveFormatEx = packed record
wFormatTag: Word; {指定格式类型; 默认 WAVE_FORMAT_PCM = 1;}
nChannels: Word; {指出波形数据的通道数; 单声道为 1, 立体声为 2}
nSamplesPerSec: DWORD; {指定样本速率(每秒的样本数)}一般为8000
nAvgBytesPerSec: DWORD; {指定数据传输的平均速率(每秒的字节数)} 每秒的字节数:
nBlockAlign: Word; {指定块对齐(单位字节), 块对齐是数据的最小单位}
wBitsPerSample: Word; {采样大小(字节)}每个样本的BIT数目,一般为16
cbSize: Word; {应该是该结构的大小}
end;
nChannels : 对于pcm,其nchannels不超过2,对于非pcm格式,则超过2.
nSamplesPerSec : 通常为8kHz, 11.025 kHz, 22.05 kHz, and 44.1 kHz.
nAvgBytesPerSec : 每秒传送字节数 = nSamplesPerSec * nBlockAlign
nBlockAlign : 对齐字节 = nChannels * wBitsPerSample / 8
就是表示一个样本的最小字节.
wBitsPerSample : 在格式默认情况下,一般为8,16,表示的是样本的bit 数
对于一个8位,11k传输的立体声则
nChannels = 2
nSamplesPerSec(每秒的样本数) = 11025 就是取样数
nBlockAlign = 2 * 8 / 8= 2 对齐字节,最小样本字节数
nAvgBytesPerSec = 11025 * 2 = 22050
wBitsPerSample = 8
下面的图列清楚从另一个方面表达样本
样本1
样本2
...n
8位单声道
0声道
0声道
8位立体声
0声道L 1声道R
0声道L 1声R道
16位单声道
0声道(低字节) 0声道(高字节)
0声道(低字节) 0声道(高字节)
16位立体声
0声道(低字节)0声道(高字节)1声道(低) 1声道(高)
同左
---------
waveform-audio 缓存格式
typedef struct {
LPSTR lpData; //内存指针,放置音频pcm样本数据
DWORD dwBufferLength; //长度
DWORD dwBytesRecorded; //已录音的字节长度
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops; //循环次数
struct wavehdr_tag* lpNext; //保留
DWORD reserved; //保留
} WAVEHDR;
其中lpdata 即为pcm格式样本数据。
采样大小为8位,则采样的动态范围为20*log(256)分贝=48db。
样本大小为16位,则采样动态范围为20*log(65536)大约是96分贝
振幅大小: 20*log(A1/A2)分贝,A1,A2为两个声音的振幅。
则对于的音频:
8位 20 * lg( lpData[0] /256)
16位 20 * lg( lpData[0]--lpData[1] / 65536)
考虑到单双道,还需要相应取出左右声道的值。
考虑到lg求值为负48至0之间,则在实际转换中需要+48or96.
样本大小 数据格式 最大值 最小值
8位PCM unsigned int 256 0
16位PCM int 32767 -32767
8位音频是unsigned 存放波形,取振幅要-127.
而16位因其存放为int 类型,直接套用公式.
audiometer左右声道音量探测程序(参考代码(delphi版)
posted @ 2009-01-05 14:16 kenlistian 阅读(274) | 评论 (0) | 编辑 收藏
2008年12月28日 #
可播放rm,rmvb格式播放器的方法
RealMediaSplitter.ax
Source(.rm/.rmvb)->RealMediaSplitter->Video(Audio)->real a/v decoder->A/V Render
其实复原并查找该ax很简单,安装暴风后在graphedit中,拖一个rm文件,
查看解码过程,然后在filter列表中找出该ax文件名,即可构建到自己的
播放器中。
posted @ 2008-12-28 11:21 kenlistian| 编辑 收藏
2008年12月27日 #
directsound的一些基本札记
1、配置DirectDound的开发环境
包含以下
#include <mmsystem.h>
#include <dsound.h>
添加Dsound.lib库
comctl32.lib dxerr9.lib winmm.lib dsound.lib dxguid.lib odbc32.lib odbccp32.lib,
2 DiectDound几个对象
创建一个设备对象,后通过设备对象创建缓冲区对象。
辅助缓冲区由应用程序创建和管理,DirectSound会自动地创建和管理主缓冲区,
3 播放音频文件开发的基本流程
a 创建一个设备对象,设置设备对象的协作度。
调用DirectSoundCreat8创建一个支持IDirectSound8接口的对象,
这个对象通常代表缺省的播放设备。
如果没有声音输出设备,这个函数就返回error,或者,在VXD驱动程序下,
如果声音输出设备正被某个应用程序通过waveform格式的api函数所控制,
该函数也返回error。
LPDIRECTSOUND8 lpDirectSound;
HRESULT hr
=
DirectSoundCreate8(NULL,
&
lpDirectSound, NULL));
当创建完设备对象后,调用IDirectSound8::SetCooperativeLevel来设置
协作度,否则听不到声音.
b.创建一个辅助Buffer,也叫后备缓冲区
(IDirectSound8::CreateSoundBuffer)
创建的buffer称作辅助缓冲区,Direcsound通过把几个后备缓冲区的声音
混合到主缓冲区中,然后输出到声音输出设备上,达到混音的效果。
c. 获取PCM类型的数据
将WAV文件或者其他资源的数据读取到缓冲区中。
d. 将数据读取到缓冲区
其中用到以下来锁缓冲区。
IDirectSoundBuffer8::Lock
IDirectSoundBuffer8::Unlock.
e. 播放缓冲区中的数据
IDirectSoundBuffer8::Play 播放缓冲区中的音频数据,
IDirectSoundBuffer8::Stop 暂停播放数据,
获取或者设置正在播放的音频的音量的大小
IDirectSoundBuffer8::GetVolume
IDirectSoundBuffer8::SetVolume
获取设置音频播放的频率
IDirectSoundBuffer8::GetFrequency
IDirectSoundBuffer8::SetFrequency
主缓冲区的频率不允许改动,
设置音频在左右声道播放的位置
IDirectSoundBuffer8::GetPan
IDirectSoundBuffer8::SetPan
包含全部音频数据的缓冲区我们称为静态的缓冲区,
尽管不同的声音可能会反复使用同一个内存buffer,但静态缓冲区的数据只写入一次。
静态缓冲区只填充一次数据,然后就可以play,
给静态缓冲区加载数据分下面几个步骤
1、用IDirectSoundBuffer8::Lock函数来锁定所有的内存,
指定你锁定内存中你开始写入数据的偏移位置,并且取回该偏移位置的地址。
2、采用标准的数据copy方法,将音频数据复制到返回的地址。
3、调用IDirectSoundBuffer8::Unlock.,解锁该地址。
用static buffer 播放wav方法
LPDIRECTSOUNDBUFFER8 g_pDSBuffer8
=
NULL;
//
buffer
LPDIRECTSOUND8 g_pDsd
=
NULL;
//
dsound
CWaveFile
*
g_pWaveFile
=
NULL;
//
初始化DirectSound工作
HRESULT hr;
if
(FAILED(hr
=
DirectSoundCreate8(NULL,
&
g_pDsd,NULL)))
return
FALSE;
//
设置设备的协作度
if
(FAILED(hr
=
g_pDsd
->
SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
return
FALSE;
g_pWaveFile
=
new
CWaveFile;
g_pWaveFile
->
Open(_T(
"
c:\\test.wav
"
), NULL, WAVEFILE_READ);
DSBUFFERDESC dsbd;
ZeroMemory(
&
dsbd,
sizeof
(DSBUFFERDESC) );
dsbd.dwSize
=
sizeof
(DSBUFFERDESC);
dsbd.dwFlags
=
DSBCAPS_GLOBALFOCUS
//
设置主播
|
DSBCAPS_CTRLFX
|
DSBCAPS_CTRLPOSITIONNOTIFY
|
DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes
=
g_pWaveFile
->
GetSize();
dsbd.lpwfxFormat
=
g_pWaveFile
->
m_pwfx;
LPDIRECTSOUNDBUFFER lPBuffer;
//
创建辅助缓冲区对象
if
(FAILED(hr
=
g_pDsd
->
CreateSoundBuffer(
&
dsbd,
&
lpbuffer,NULL)))
return
;
if
( FAILED(hr
=
lpbuffer
->
QueryInterface( IID_IDirectSoundBuffer8, (LPVOID
*
)
&
g_pDSBuffer8) ) )
return
;
lpbuffer
->
Release();
//
播放
LPVOID lplockbuf;
DWORD len;
DWORD dwWrite;
g_pDSBuffer8
->
Lock(
0
,
0
,
&
lplockbuf,
&
len, NULL, NULL, DSBLOCK_ENTIREBUFFER);
//
g_pWaveFile 声音写入到lplockbuf所指地址
g_pWaveFile
->
Read((BYTE
*
)lplockbuf, len,
&
dwWrite);
g_pDSBuffer8
->
Unlock(lplockbuf,len,NULL,
0
);
g_pDSBuffer8
->
SetCurrentPosition(
0
);
g_pDSBuffer8
->
Play(
0
,
0
,DSBPLAY_LOOPING);
f 流缓冲区播放超大型的wave文件
流缓冲区就是播放那些比较长的音频文件,边播放,边填充DirectSound缓冲区。
DirectSound的通知机制
因为Stream buffer 大小只够容纳一部分数据,在播放完缓冲区中的数据后,
DirectSound就会通知应用程序,将新的数据填充到DirectSound的缓冲区中。
#define
MAX_AUDIO_BUF 4
//
设置4个buffer
#define
BUFFERNOTIFYSIZE 1920
//
每个buffer尺寸为1920
BOOL g_bPlaying
=
FALSE;
//
是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify
=
NULL;
DSBPOSITIONNOTIFY g_aPosNotify[MAX_AUDIO_BUF];
//
设置通知标志的数组
HANDLE g_event[MAX_AUDIO_BUF];
for
(
int
i
=
0
; i
<
MAX_AUDIO_BUF;i
++
)
{
g_aPosNotify
.dwOffset
=
i
*
BUFFERNOTIFYSIZE ;
g_aPosNotify
.hEventNotify
=
g_event
;
}
if
(FAILED(hr
=
g_pDSBuffer8
->
QueryInterface(IID_IDirectSoundNotify,(LPVOID
*
)
&
g_pDSNotify )))
return
;
g_pDSNotify
->
SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
g_pDSNotify
->
Release();
当DirectSound播放到buffer的1920,3840,5760,7680等位置时,
Directsound就会通知应用程序,将g_event,设置为通知态;
应用程序就通过WaitForMultipleObjects 函数等待DirectSound的通知,
将数据填充到DirectSoun的辅助缓冲区。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1