博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AAC---音频重采样
阅读量:3919 次
发布时间:2019-05-23

本文共 4479 字,大约阅读时间需要 14 分钟。

音频处理中,有时不同的编解码器支持的音频格式不一样,原始采样的音频数据可能没法直接直接为编解码器支持,如FFMPEG编码MP3格式的音频,就要求样本采用AV_SAMPLE_FMT_S16P格式保存。

这就需要对不同的音频格式转换,需要重采样。

1、如果PCM文件采用交叉存储方式,视频帧的概念可能没什么影响,因为数据都是LRLRLR...LR方式;2、如果采用平行存储方式,L...LR...RL...LR...R,一帧必须按照指定的数据读取了,如MP3读取一帧需要读取1152*2(通道数)个样本,然后前1152为左声道,后1152为右声道。

/*******************************************************************************Copyright (c) wubihe Tech. Co., Ltd. All rights reserved.--------------------------------------------------------------------------------Date Created:	2014-10-25Author:			wubihe QQ:1269122125 Email:1269122125@qq.comDescription:	代码实现音频重采样 把交叉存储的双声道立体声转换成平行存储的双声道				立体声--------------------------------------------------------------------------------Modification HistoryDATE          AUTHOR          DESCRIPTION--------------------------------------------------------------------------------********************************************************************************/#include 
#define __STDC_CONSTANT_MACROS#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswresample/swresample.h" int main(){
static char*pFormatName[]= {
"FMT_U8","FMT_S16","FMT_S32","FMT_FLT","FMT_DBL", "FMT_U8P","FMT_S16P","FMT_S32P","FMT_FLTP","FMT_DBLP" }; //原始PCM文件 FILE *pInputFile = fopen("huangdun_r48000_FMT_S16_c2.pcm", "rb"); uint64_t iInputLayout = AV_CH_LAYOUT_STEREO; int iInputChans = av_get_channel_layout_nb_channels(iInputLayout); AVSampleFormat eInputSampleFormat = AV_SAMPLE_FMT_S16; int iInputSampleRate = 48000; //转换后PCM文件 uint64_t iOutputLayout = AV_CH_LAYOUT_STEREO; int iOutputChans = av_get_channel_layout_nb_channels(iOutputLayout); AVSampleFormat eOutputSampleFormat = AV_SAMPLE_FMT_S16P; int iOutputSampleRate = 48000; bool bOutPutPlaner=true; char szOutFileName[256]={
0}; sprintf(szOutFileName,"huangdun_r%d_%s_c%d.pcm",iOutputSampleRate,pFormatName[eOutputSampleFormat],iOutputChans); FILE *pOutputFile = fopen(szOutFileName, "wb"); //初始化转换上下文 SwrContext *pSwrCtx = swr_alloc_set_opts(NULL,iOutputLayout, eOutputSampleFormat, iOutputSampleRate, iInputLayout,eInputSampleFormat , iInputSampleRate,0, NULL); swr_init(pSwrCtx); //1帧数据样本数 int iFrameSamples = 1024; //保存转换后的数据 /*uint8_t **ppConvertData = (uint8_t**)calloc(iOutputChans,sizeof(*ppConvertData)); int iConvertLineSize = 0; int iConvertDataSize = av_samples_alloc(ppConvertData, &iConvertLineSize,iOutputChans, iFrameSamples,eOutputSampleFormat, 0);*/ //音频处理是以帧为单位处理的 //分配存储原始数据内存空间 int iRawLineSize = 0; int iRawBuffSize = av_samples_get_buffer_size(&iRawLineSize, iInputChans, iFrameSamples, eInputSampleFormat, 0); uint8_t *pRawBuff = (uint8_t *)av_malloc(iRawBuffSize); //原始数据保存在AVFrame结构体中 AVFrame* pRawframe = av_frame_alloc(); pRawframe->nb_samples = iFrameSamples; pRawframe->format = eInputSampleFormat; pRawframe->channels = iInputChans; //把分配内存挂到AVFrame结构体中 avcodec_fill_audio_frame(pRawframe, iInputChans, eInputSampleFormat, (const uint8_t*)pRawBuff, iRawBuffSize, 0); // 计算并申请一段buf用于存放数据 int iConvertLineSize = 0; int iConvertBuffSize = av_samples_get_buffer_size(&iConvertLineSize, iOutputChans, iFrameSamples, eOutputSampleFormat, 0); uint8_t *pConvertBuff = (uint8_t *)av_malloc(iConvertBuffSize); //转换后数据保存在AVFrame结构体中 AVFrame* pConvertframe = av_frame_alloc(); pConvertframe->nb_samples = iFrameSamples; pConvertframe->format = eOutputSampleFormat; pConvertframe->channels = iOutputChans; avcodec_fill_audio_frame(pConvertframe, iOutputChans, eOutputSampleFormat, (const uint8_t*)pConvertBuff, iConvertBuffSize, 0); //将数据buf给avframe的date* 如果需要平面音频,则分配AVFrame extended_data通道指针。 int iFrameNum =0; //读取一帧音频数据 int iRealRead = fread(pRawBuff, 1, iRawBuffSize, pInputFile); while(iRealRead>0) {
//完成音频帧转换 swr_convert(pSwrCtx, (uint8_t**)pConvertframe->data, iFrameSamples ,(const uint8_t**)pRawframe->data, iFrameSamples ); if(bOutPutPlaner) {
//只保存一个通道数据 便于分析 因为PCM工具不支持这种平行存储方式数据查看 //一般情况平行存储方式pConvertframe->data[i]为i声道数据 pConvertframe->linesize[i]为i声道长度, //但是音频各个声道的数据长度是相同的,所以只有pConvertframe->linesize[0]表示长度, //其他pConvertframe->linesize[1]==0 fwrite(pConvertframe->data[0],pConvertframe->linesize[0],1,pOutputFile); } printf("Convert Frame :%d\n",++iFrameNum); iRealRead = fread(pRawBuff, 1, iRawBuffSize, pInputFile); } fclose(pInputFile); fclose(pOutputFile); av_free(pRawBuff); av_free(pConvertBuff); swr_free(&pSwrCtx); printf("Convert Success!!\n"); getchar(); return 0; }

转载地址:http://ybhrn.baihongyu.com/

你可能感兴趣的文章
mount(挂载)详解
查看>>
Centos7安装pssh2.3版本
查看>>
pssh(1) - Linux man page
查看>>
pssh参数及例子
查看>>
linux grep指令
查看>>
grep -w和grep -e使用
查看>>
ks.cfg文件参数详解
查看>>
Linux 标准目录结构
查看>>
Centos7 tftp安装配置
查看>>
TFTP相关指令内容
查看>>
Centos7 安装http
查看>>
log目录
查看>>
Centos7安装DHCP服务
查看>>
dhcpd.conf配置
查看>>
systemctl命令
查看>>
Windows域帐户的好处 域控制器的优点介绍
查看>>
swap分区
查看>>
固态硬盘与普通硬盘区别
查看>>
Linux压缩文件格式总结
查看>>
ethtool命令
查看>>