音频相关
Posted xianjian_x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音频相关相关的知识,希望对你有一定的参考价值。
音频帧概念详解
正常人听觉的频率范围大约在20Hz~20kHz之间。
采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。
根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。
常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质。
对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。
通常是按1024个采样点一帧
分析:
AAC
一个AAC原始帧包含某段时间内1024个采样点相关数据。用1024主要是因为AAC是用的1024点的mdct。
音频帧的播放时间 = 一个AAC帧对应的采样样本的个数 / 采样频率(单位为s)。
采样率(samplerate)为 44100Hz,表示每秒 44100个采样点,
所以,根据公式,
音频帧的播放时长 = 一个AAC帧对应的采样点个数 / 采样频率
则,当前一帧的播放时间 = 1024 * 1000000/44100= 22.32ms(单位为ms)
48kHz采样率:
则,当前一帧的播放时间 = 1024 * 1000000/48000= 21.32ms(单位为ms)
22.05kHz采样率,
则,当前一帧的播放时间 = 1024 * 1000000/22050= 46.43ms(单位为ms)
MP3
mp3 每帧均为1152个字节,
则:
每帧播放时长 = 1152 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时,
计算出的时长为26.122ms,
这就是经常听到的mp3每帧播放时间固定为26ms的由来。
mp3 和 aac 格式音频文件都是压缩过的文件,如果要送入windows播放还需要解码,此时要有 一个转化,一般用ffmpeg 的 swr_convert :
解码之后的数据帧一般都是 AV_SAMPLE_FMT_S16 格式的,这个就是pcm数据。
关于PCM格式如下:
音频编解码·格式篇(1)Wave PCM audio format(WAV)
示例代码,附上我写的一个mp3 播放器
WAVEPLAY.h:
#pragma once
#include "stdafx.h"
#include <Windows.h>
#include <mmsystem.h>
#include <stdio.h>
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
#define BLOCKCOUNT 10
#define BLOCKSIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 4)
class WAVEPLAY
public:
BOOL OpenDevice(void);
void StartDevice(void);
void StopDevice(void);
BOOL IsPLayOver(void);
private:
HWAVEOUT m_hWaveout;
WAVEFORMATEX m_wfx;
WAVEHDR m_waveHdr[BLOCKCOUNT];
void * m_Block[BLOCKCOUNT];
BOOL AddWaveOutBuffer(UINT nIndex,int len);
void WriteBuffer(PWAVEHDR);
BOOL m_bStop;
HANDLE m_hStop;
BOOL m_bPlayOver;
CRITICAL_SECTION m_csWaveOut;
void PlayProc(UINT, DWORD_PTR);
static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR);
////ffmpeg相关数据
SwrContext * m_pSwrCtx;
AVFormatContext * m_pFmtCtx;
AVCodecContext * m_pCodecCtx;
AVCodec* m_pCodec;
AVFrame * m_pAVFrame;
AVPacket m_AudioPkt;
int m_StreamIndex;
int OpenCodecContext(enum AVMediaType type);
public:
WAVEPLAY(void);
virtual ~WAVEPLAY(void);
;
WAVEPLAY.cpp:
#include "StdAfx.h"
#include "WAVEPLAY.h"
#pragma comment(lib, "./avformat.lib")
#pragma comment(lib, "./avutil.lib")
#pragma comment(lib, "./avcodec.lib")
#pragma comment(lib, "./avdevice.lib")
#pragma comment(lib, "./avfilter.lib")
#pragma comment(lib, "./swresample.lib")
#pragma comment(lib, "./swscale.lib")
#pragma comment(lib,"winmm.lib")
DECLARE_ALIGNED(16,uint8_t,audio_buf) [AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];
int WAVEPLAY::OpenCodecContext( enum AVMediaType type)
int ret;
AVDictionary * opts = NULL;
ret = av_find_best_stream(m_pFmtCtx, type, -1, -1, NULL, 0);
if (ret >= 0)
m_StreamIndex = ret;
m_pCodecCtx = m_pFmtCtx->streams[m_StreamIndex]->codec;
/* find decoder for the stream */
m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);
if (!m_pCodec)
return AVERROR(EINVAL);
if(avcodec_open2(m_pCodecCtx, m_pCodec ,NULL) < 0 )
printf("error opencodec!!\\n");
else
return ret;
return 0;
BOOL WAVEPLAY::OpenDevice(void)
char filename[256];
int err;
WAVEFORMATEX m_wfx = 0;
avcodec_register_all();
av_register_all();
//strcpy(filename,"F:\\\\Ring08.wav");
strcpy(filename,"F:\\\\work\\\\testfile\\\\zhushalei.mp3");
err = avformat_open_input(&m_pFmtCtx, filename, NULL, NULL);
if(err < 0)
printf("can not open file %s.\\n", filename);
return -1;
err = avformat_find_stream_info(m_pFmtCtx,NULL );
if(err < 0)
printf("can not find stream info of file %s.\\n", filename);
return -1;
av_dump_format(m_pFmtCtx , 0, 0 , 0);
OpenCodecContext( AVMEDIA_TYPE_AUDIO);
m_wfx.nSamplesPerSec = m_pCodecCtx->sample_rate;
switch(m_pCodecCtx->sample_fmt)
case AV_SAMPLE_FMT_U8:
m_wfx.wBitsPerSample = 8;
break;
case AV_SAMPLE_FMT_S16:
m_wfx.wBitsPerSample = 16;
break;
case AV_SAMPLE_FMT_S16P:
m_wfx.wBitsPerSample = 16;
break;
case AV_SAMPLE_FMT_S32:
m_wfx.wBitsPerSample = 32;
break;
case AV_SAMPLE_FMT_FLT:
m_wfx.wBitsPerSample = sizeof(double) * 8;
break;
default:
m_wfx.wBitsPerSample = 0;
break;
m_wfx.nChannels = FFMIN(2, m_pCodecCtx->channels);
m_wfx.cbSize = 0;
m_wfx.wFormatTag = WAVE_FORMAT_PCM;
m_wfx.nBlockAlign = (m_wfx.wBitsPerSample * m_wfx.nChannels) >> 3;
m_wfx.nAvgBytesPerSec = m_wfx.nBlockAlign * m_wfx.nSamplesPerSec;
printf("sample rate: %d\\n", m_wfx.nSamplesPerSec);
printf("channel count: %d\\n", m_wfx.nChannels);
printf("bit per sample: %d\\n", m_wfx.wBitsPerSample);
m_pAVFrame = av_frame_alloc();
av_init_packet(&m_AudioPkt);
m_AudioPkt.data = NULL;
m_AudioPkt.size = 0;
MMRESULT mRet = waveOutOpen(&m_hWaveout,
WAVE_MAPPER,
&m_wfx,
(DWORD_PTR)waveOutProc,
(DWORD)this,
CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
if (mRet != MMSYSERR_NOERROR)
return FALSE;
int i = 0;
for (i; i < BLOCKCOUNT; i++)
m_Block[i] = malloc(BLOCKSIZE);
if (m_Block[i] == NULL)
return FALSE;
else
memset(m_Block[i], 0, BLOCKSIZE);
m_hStop = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hStop == INVALID_HANDLE_VALUE)
return FALSE;
InitializeCriticalSection(&m_csWaveOut);
return TRUE;
void WAVEPLAY::StartDevice(void)
int i = 0; //
for (i; i < BLOCKCOUNT; i++)
AddWaveOutBuffer(i, 512);
BOOL WAVEPLAY::AddWaveOutBuffer(UINT index,int len)
m_waveHdr[index].lpData = (LPSTR)m_Block[index];
m_waveHdr[index].dwBufferLength = len;
m_waveHdr[index].dwBytesRecorded = 0;
m_waveHdr[index].dwFlags = 0;
m_waveHdr[index].dwLoops = 0;
m_waveHdr[index].dwUser = index;
MMRESULT mRet = waveOutPrepareHeader(m_hWaveout, &m_waveHdr[index], sizeof(WAVEHDR));
if (mRet != MMSYSERR_NOERROR)
return FALSE;
mRet = waveOutWrite(m_hWaveout, &m_waveHdr[index], sizeof(WAVEHDR));
if (mRet != MMSYSERR_NOERROR)
return FALSE;
return TRUE;
void WAVEPLAY::StopDevice(void)
int i = 0;
for (i; i < BLOCKCOUNT; i++)
if (m_waveHdr[i].dwFlags == WHDR_PREPARED)
waveOutUnprepareHeader(m_hWaveout, &m_waveHdr[i], sizeof(WAVEHDR));
MMRESULT mRet;
while (!m_bStop)
mRet = waveOutClose(m_hWaveout);
WaitForSingleObject(m_hStop, INFINITE);
for (i=0; i < BLOCKCOUNT; i++)
free(m_Block[i]);
m_Block[i] = NULL;
if(m_pSwrCtx != NULL)
swr_free(&m_pSwrCtx);
av_free(m_pAVFrame);
avcodec_close(m_pCodecCtx);
/*******************************************************************************************/
/*******************************************************************************************/
typedef class WAVEPLAY * PWAVEPALY;
void CALLBACK WAVEPLAY::waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3)
PWAVEPALY pWavePlay = (PWAVEPALY)dwParam1;
pWavePlay->PlayProc(uMsg, dwParam2);
void WAVEPLAY::PlayProc(UINT uMsg, DWORD_PTR hdr)
PWAVEHDR waveOutHdr = (PWAVEHDR)hdr;
switch (uMsg)
case WOM_OPEN:
m_bStop = FALSE;
break;
case WOM_CLOSE:
m_bStop = TRUE;
SetEvent(m_hStop);
break;
case WOM_DONE:
if (!m_bPlayOver)
EnterCriticalSection(&m_csWaveOut);
WriteBuffer(waveOutHdr);
LeaveCriticalSection(&m_csWaveOut);
break;
void WAVEPLAY::WriteBuffer(PWAVEHDR pWaveHdr)
int cnt,len2;
int decodesize;
DWORD index = pWaveHdr->dwUser;
uint8_t * out[] = audio_buf ;
waveOutUnprepareHeader(m_hWaveout, pWaveHdr, sizeof(WAVEHDR));
memset(m_Block[index], 0, BLOCKSIZE);
av_read_frame(m_pFmtCtx, &m_AudioPkt);
int got_frame;
int packet_size = m_AudioPkt.size;
cnt = 0;
do
if (m_AudioPkt.stream_index == m_StreamIndex )
decodesize = avcodec_decode_audio4(m_pCodecCtx ,m_pAVFrame , &got_frame, &m_AudioPkt);
if(decodesize > 0 )
if(m_pSwrCtx == NULL)
m_pSwrCtx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, m_pCodecCtx->sample_rate,
av_get_default_channel_layout(m_pAVFrame->channels), (AVSampleFormat)m_pAVFrame->format ,m_pAVFrame->sample_rate,
0, NULL);
swr_init(m_pSwrCtx);
len2 = swr_convert(m_pSwrCtx, out, AVCODEC_MAX_AUDIO_FRAME_SIZE * 4,
(const uint8_t **)m_pAVFrame->extended_data, m_pAVFrame->nb_samples);
memcpy(m_Block[index],audio_buf,len2 * 4);
cnt += len2 * 4 ;
packet_size -= decodesize;
else
packet_size = 0;
while (packet_size > 0);
m_bPlayOver = FALSE;
AddWaveOutBuffer(index,cnt);
BOOL WAVEPLAY::IsPLayOver(void)
return m_bPlayOver;
WAVEPLAY::WAVEPLAY(void)
m_pFmtCtx = NULL;
m_pCodecCtx = NULL;
m_pCodec = NULL;;
m_pAVFrame = NULL;
m_pSwrCtx = NULL;
m_bPlayOver = FALSE;
WAVEPLAY::~WAVEPLAY(void)
CloseHandle(m_hStop);
DeleteCriticalSection(&m_csWaveOut);
play1.cpp :
#include "stdafx.h"
#include "WAVEPLAY.h"
int _tmain(int argc, _TCHAR* argv[])
WAVEPLAY wpPlayPCM;
wpPlayPCM.OpenDevice();
wpPlayPCM.StartDevice();
while (!wpPlayPCM.IsPLayOver())
Sleep(10);
wpPlayPCM.StopDevice();
return 0;
以上是关于音频相关的主要内容,如果未能解决你的问题,请参考以下文章