AAC audio resampling ---

Audio Processing, sometimes different codec supports audio formats are not the same, the original audio data may be sampled directly not directly codec support, such as MP3 format audio encoding FFMPEG, requires samples taken AV_SAMPLE_FMT_S16P save format.
This requires different audio format conversion requires re-sampling.

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

Code for storing audio resampling the intersection of two-channel stereo two-channel stereo is converted into parallel storage

/*******************************************************************************
Copyright (c) wubihe Tech. Co., Ltd. All rights reserved.
--------------------------------------------------------------------------------
Date Created:	2014-10-25
Author:			wubihe QQ:1269122125 Email:[email protected]
Description:	代码实现音频重采样 把交叉存储的双声道立体声转换成平行存储的双声道
				立体声
--------------------------------------------------------------------------------
Modification History
DATE          AUTHOR          DESCRIPTION
--------------------------------------------------------------------------------
********************************************************************************/
#include <stdio.h>
 
#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;
 
}
 

Published 81 original articles · won praise 1 · views 2838

Guess you like

Origin blog.csdn.net/qq_42024067/article/details/104582326