上篇文章讲了如何用最新的技术采集声卡和麦克风,但是在工作中通常需要进行重采样为(44100、FLTP),再进行推流,所以本篇是在上次的基础上完成了重采样,重采样的核心代码如下:
// audiocap.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "AudioCapT.h"
#include <conio.h>
extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
}
#include <iostream>
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
#pragma comment(lib,"swresample.lib")
bool FillFltpSample(double *dst, int nb_samples, int nb_channels, char * pPcmBuffer, int nPcmBufLen)
{
int nTotal = nb_samples*nb_channels * 4;
if (!dst || !pPcmBuffer)
return false;
memset(dst, 0, nb_samples*nb_channels * 4);
int nTmp = 0;
if (nTotal >= nPcmBufLen)
{
nTmp = nPcmBufLen;
}
else
{
nTmp = nTotal;
}
memcpy(dst, pPcmBuffer, nTmp);
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
int64_t src_ch_layout = av_get_default_channel_layout(2), dst_ch_layout = AV_CH_LAYOUT_STEREO;
int src_rate = 48000, dst_rate = 44100;
uint8_t **src_data = NULL, **dst_data = NULL;
int src_nb_channels = 0, dst_nb_channels = 0;
int src_linesize, dst_linesize;
int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_FLT, dst_sample_fmt = AV_SAMPLE_FMT_S16;
const char * pszDstFileName = "D:\\test44100.pcm";
FILE * fDstFile = NULL;
int nDstBufSize = 0;
const char * strFmt = NULL;
struct SwrContext * swr_ctx = NULL;
int nRet = 0;
CAudioCapT ac;
CoInitialize(NULL);
av_register_all();
avcodec_register_all();
fDstFile = fopen(pszDstFileName, "wb");
if (!fDstFile) {
printf("open file failed.\n");
return -1;
}
//创建重采样上下文
swr_ctx = swr_alloc();
if (!swr_ctx)
{
printf("swr_alloc failed.\n");
goto end;
}
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
if ((nRet = swr_init(swr_ctx)) < 0)
{
printf("Failed to initialize the resampling context\n");
goto end;
}
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
nRet = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels,
src_nb_samples, src_sample_fmt, 0);
if (nRet < 0)
{
printf("Could not allocate source samples\n");
goto end;
}
max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
nRet = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 0);
if (nRet < 0)
{
printf("Could not allocate destination samples\n");
goto end;
}
int nReadSize = src_nb_samples * src_nb_channels * 4;
char * pPcmBuffer = new char[nReadSize];
if (!pPcmBuffer)
{
printf("Pcm Buffer failed.\n");
goto end;
}
ZeroMemory(pPcmBuffer, nReadSize);
ac.SetDeiveType(CAudioCapT::MICPHONE);
ac.Init();
ac.Start();
Audio_Data * pAudio = NULL;
int nAudioLeftLen = 0;
int nPcmBufferLen = 0;
int nLen = 0;
bool bFirst = true;
while (1)
{
if (_kbhit())
{
ac.Stop();
break;
}
//缓冲区是否已经满了
while (nPcmBufferLen != nReadSize)
{
if (pAudio == NULL)
{
pAudio = ac.GetAudio();
if (pAudio)
nAudioLeftLen = pAudio->iDataLen;
continue;
}
else
{
nLen = nReadSize - nPcmBufferLen;
if (nLen >= nAudioLeftLen)
{
memcpy(pPcmBuffer + nPcmBufferLen, pAudio->pData + (pAudio->iDataLen - nAudioLeftLen), nAudioLeftLen);
nPcmBufferLen += nAudioLeftLen;
nAudioLeftLen -= nAudioLeftLen;
delete [] pAudio->pData;
pAudio->pData = NULL;
delete pAudio;
pAudio = NULL;
continue;
}
else
{
memcpy(pPcmBuffer + nPcmBufferLen, pAudio->pData + (pAudio->iDataLen - nAudioLeftLen), nLen);
nPcmBufferLen += nLen;
nAudioLeftLen -= nLen;
}
}
}
FillFltpSample((double *)src_data[0], src_nb_samples, src_nb_channels, pPcmBuffer, nPcmBufferLen);
dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples)
{
av_freep(&dst_data[0]);
nRet = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 1);
if (nRet < 0)
break;
max_dst_nb_samples = dst_nb_samples;
}
nRet = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
if (nRet < 0)
{
printf("Error while converting\n");
goto end;
}
nDstBufSize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, nRet, dst_sample_fmt, 1);
if (nDstBufSize < 0)
{
printf("Could not get sample buffer size\n");
goto end;
}
//printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
fwrite(dst_data[0], 1, nDstBufSize, fDstFile);
printf("+");
nPcmBufferLen = 0;
}
end:
if (pPcmBuffer)
{
delete[] pPcmBuffer;
pPcmBuffer = NULL;
}
if (fDstFile)
{
fclose(fDstFile);
fDstFile = NULL;
}
if (src_data)
av_freep(&src_data[0]);
av_freep(&src_data);
if (dst_data)
av_freep(&dst_data[0]);
av_freep(&dst_data);
swr_free(&swr_ctx);
::CoUninitialize();
printf("\n\n");
printf("program exit!\n");
return 0;
}
需要的小伙伴可以从下面下载:
https://download.csdn.net/download/u011711997/10539607