ffmpeg重采样

server/2024/9/24 5:22:14/

ffmpeg重采样指的是可以将一个固定频率的音频转换为任意格式的音频,比如改变音频的采样率或者声道,这种操作简称为重采样。但是在重采样的过程中也会有一些数据丢失的过程,主要原因是在采样会会进行向上对齐,所以会出现转换后大小不一致的情况

在重采样的过程中,主要通过两个容器来互相交换数据来达到数据转换的效果,其中创建容器的方法为:

//返回值小于0代表创建失败
int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,int nb_samples, enum AVSampleFormat sample_fmt, int align);

在进行重采样操作时,另开一个线程来完成此工作

void Audiothread::run()
{ResampleAudioSpec in,out;//44100-s16le-2in.FileName = "D:/ffmpeg/ffm07_31_21_57_24.pcm";out.FileName = "D:/ffmpeg/4800_f32le_1.pcm";//初始化重采样上下文int ret = 0;//输入参数in.SamPleFmt = AV_SAMPLE_FMT_S16;//f32lein.SampleRate = 44100;in.ChLayout = AV_CH_LAYOUT_STEREO;//2声道//输出参数out.SamPleFmt = AV_SAMPLE_FMT_FLT;out.SampleRate = 48000;out.ChLayout = AV_CH_LAYOUT_MONO;//1声道ffmpegs::resampleAudio(in,out);
}
#include "ffmpegs.h"
#include <QDebug>
#include <QFile>
extern "C" {
//
#include <libswresample/swresample.h>
// 工具相关API(比如错误处理)
#include <libavutil/avutil.h>
}#define ERROR_BUF(ret) \char errbuf[1024]; \av_strerror(ret,errbuf,sizeof(errbuf));
ffmpegs::ffmpegs()
{}void ffmpegs::resampleAudio(ResampleAudioSpec& in, ResampleAudioSpec& out)
{resampleAudio(in.FileName,in.SampleRate,in.SamPleFmt,in.ChLayout,out.FileName,out.SampleRate,out.SamPleFmt,out.ChLayout);
}void ffmpegs::resampleAudio(const char *inFilename,int inSamplesRate,AVSampleFormat inSamplesFmt,int inChLayout,const char *outFilename,int outSampleRate,AVSampleFormat outSampleFmt1,int outChLayout)
{//44100-s16le-2QFile inFile(inFilename);QFile outFile(outFilename);//创建输入缓冲区//指向缓冲区的指针uint8_t **inData = nullptr;//缓冲区大小int inLinesize = 0;//声道数int inChs = av_get_channel_layout_nb_channels(inChLayout);//一个样本大小int inBytesPerSample = inChs * av_get_bytes_per_sample(inSamplesFmt);//缓冲区的样本数量int inSamples = 1024;//读取文件的数据大小int len = 0;//创建输出缓冲区//指向缓冲区的指针uint8_t **outData = nullptr;//缓冲区大小int outLinesize = 0;//声道数int outChs = av_get_channel_layout_nb_channels(inChLayout);//一个样本大小int outBytesPerSample = outChs * av_get_bytes_per_sample(outSampleFmt1);//缓冲区的样本数量int outSample = av_rescale_rnd(outSampleRate,inSamples,inSamplesRate,AV_ROUND_UP);//outSample = outSampleRate * inSamples / inSamplesRate//例如b[i] = av_rescale_rnd(a[i], 2, 1, AV_ROUND_NEAR_INF); // 缩放因子为2:1,所以b[i] = 2 * a[i]/*inSamplesRate    inSampless------------ =  ---------outSampleRate   outSamples*///返回结果int ret = 0;int isSamples = 0;//创建重采样上下文SwrContext *ctx = swr_alloc_set_opts(nullptr,//输出参数outChLayout,outSampleFmt1,outSampleRate,//输入参数inChLayout,inSamplesFmt,inSamplesRate,0,nullptr);if(!ctx){qDebug() << "swr_alloc_set_opts----error";return;}//初始化重采样上下文ret = swr_init(ctx);if(ret < 0){ERROR_BUF(ret);qDebug() << "swr_init" << errbuf;goto end;return;}//创建输出缓冲区//ret = 返回几个字节ret = av_samples_alloc_array_and_samples(&outData,&outLinesize,outChs,outSample,outSampleFmt1,1);if(ret < 0){ERROR_BUF(ret);qDebug() << "av_samples_alloc_array_and_samples error: " << errbuf;goto end;}//创建输入缓冲区//ret = 返回几个字节ret = av_samples_alloc_array_and_samples(&inData,&inLinesize,inChs,inSamples,inSamplesFmt,1);if(ret < 0){ERROR_BUF(ret);qDebug() << "av_samples_alloc_array_and_samples error: " << errbuf;goto end;}//打开文件if(!inFile.open(QFile::ReadOnly)){qDebug() << "打开文件失败:" << inFilename;goto end;}if(!outFile.open(QFile::WriteOnly)){qDebug() << "打开文件失败:" << outFilename;goto end;}//读取文件数据while((len = inFile.read((char*) inData[0],inLinesize)) > 0){//读取的样本数量isSamples = len / inBytesPerSample;//重采样(返回值转换后的样本数量)ret = swr_convert(ctx,outData,outSample,(const uint8_t **)inData,isSamples);if(ret < 0){ERROR_BUF(ret);qDebug() << "swr_convert error" << errbuf;goto end;}int size = av_samples_get_buffer_size(nullptr,outChs,ret,outSampleFmt1,1);//size == ret * outBytesPerSample//将转换后的数据写入输出文件中//outFile.write((char*) outData[0],ret * outBytesPerSample);outFile.write((char*) outData[0],size);}//检查一下输出缓冲区是否还有残留的样本(已经重采样过的,转换过的)while((ret = swr_convert(ctx,outData,outSample,nullptr,0)) > 0){//将转换后的数据写入输出文件中outFile.write((char*) outData[0],ret * outBytesPerSample);}
end://释放资源//关闭文件inFile.close();outFile.close();//释放重采样上下文swr_free(&ctx);//释放输出缓冲区av_free(&outData[0]);//释放输入缓冲区av_free(&inData[0]);return;//释放资源//释放重采样上下文swr_free(&ctx);
}

http://www.ppmy.cn/server/99774.html

相关文章

k8s分布式存储-ceph

文章目录 Cephdeploy-ceph部署1.系统环境初始化1.1 修改主机名&#xff0c;DNS解析1.2 时间同步1.3 配置apt基础源与ceph源1.4关闭selinux与防火墙1.5 **创建** ceph **集群部署用户** cephadmin1.6分发密钥 2. ceph部署2.1 **安装** ceph 部署工具2.2 **初始化** mon **节点**…

string的模拟实现

1.string.h代码 #pragma once #include<assert.h> namespace myh {class string{friend ostream& operator<<(ostream& _cout, const myh::string& s);friend istream& operator>>(istream& _cin, myh::string& s);public:typedef …

apache几个重要概念和处理应对状态码的一些方法

一、apache几个重要概念 Apache 是一款开源 Web 服务器软件&#xff0c;在Web服务器&#xff08;如Apache HTTP Server&#xff09;和软件开发中&#xff0c;高度模块化、DSO&#xff08;Dynamic Shared Object&#xff09;和MPM&#xff08;Multi-Processing Module&#xff…

数据库逻辑删除时查询为什么不可用用like来进行查询?它们之间有什么转换吗?

1.首先可以查询我们的数据库字段&#xff0c;我们这里使用的是< bit(1) > 即只能存储一位&#xff0c;也只能是0或者1 2.在数据库操作中也被是涉及到逻辑删除时&#xff08;即使用某个字段来标识记录是否被删除&#xff0c;而不是从数据库中移除记录&#xff09;&#x…

【数据结构】五、树:6.平衡二叉树AVL

2.平衡二叉树AVL 文章目录 2.平衡二叉树AVL2.1定义2.2存储结构2.3查找2.4插入&#xff08;保持平衡&#xff09;2.4.1 LL平衡旋转(右单旋转)2.4.2 RR平衡旋转(左单旋转)2.4.3 LR平衡旋转(先左后右双旋转)2.4.4 RL平衡旋转(先右后左双旋转)2.4.5题解 2.5性能分析2.6删除 2.1定义…

http的发展历史,各版本的差异点,以及和https的区别

### HTTP的发展历史及各版本的差异点 HTTP/0.9 - **发布时间**&#xff1a;1991年 - **特点**&#xff1a; - 最初的HTTP协议版本&#xff0c;非常简单。 - 只支持GET方法&#xff0c;不支持请求头和响应头。 - 响应仅为纯文本&#xff0c;无法传输图片、音频等多媒体资…

llama factory 训练 TensorBoard 可视化

首先需要在 yaml 里设置两个参数&#xff1a; output_dir: /home/wangguisen/projects/LLaMA-Factory/weights/tensbox_demoreport_to: tensorboard logging_dir: /home/wangguisen/projects/LLaMA-Factory/weights/tensbox_demo/runs然后开始训练&#xff0c;在你的输出目录下…

LCM红外小目标检测

根据站内的matlab代码修改成python版本。 import numpy as np import matplotlib.pyplot as plt import cv2 from pylab import mpl# 设置中文显示字体 mpl.rcParams["font.sans-serif"] ["SimHei"]def LCM_computation(patch_LCM_in):row, col patch_L…