音视频基础(四)音频重采样
音频重采样
重采样代码
点击查看代码
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libswresample/swresample.h"
// 初始化采样上下文
SwrContext* init_swr(){
SwrContext *swr_ctx = NULL;
//channel, number/
swr_ctx = swr_alloc_set_opts(NULL, //ctx
AV_CH_LAYOUT_STEREO, //输出channel布局
AV_SAMPLE_FMT_S16, //输出的采样格式
48000, //采样率
AV_CH_LAYOUT_STEREO, //输入channel布局
AV_SAMPLE_FMT_FLT, //输入的采样格式
48000, //输入的采样率
0, NULL);
if(!swr_ctx){
}
if(swr_init(swr_ctx) < 0){
}
return swr_ctx;
}
int main() {
// 打开设备状态码,0-成功,否则失败
int ret = 0;
char errors[1024] = {0, };
//重采样缓冲区
uint8_t **src_data = NULL;
int src_linesize = 0;
uint8_t **dst_data = NULL;
int dst_linesize = 0;
// 上下文相关
AVFormatContext *fmt_ctx = NULL;
AVDictionary *options = NULL;
// 包相关
int count = 0;
AVPacket pkt;
// 设置日志级别
av_log_set_level(AV_LOG_DEBUG);
// 先传入视频设备编号,再传入音频设备编号
// [[video device]:[audit device]]
char *devicename = ":0";
// 注册音频设备
avdevice_register_all();
// 获取输入数据格式
AVInputFormat *iformat = av_find_input_format("avfoundation");
if((ret = avformat_open_input(&fmt_ctx, devicename, iformat, &options)) < 0){
av_strerror(ret, errors, 1024);
printf(stderr, "Failed to open audio device, [%d]%s\n", ret, errors);
return 1;
}
av_init_packet(&pkt);
// 定义录制文件保存路径
char *out_path = "/Users/apple/tempPath/audio.pcm";
// 打开文件
FILE *out_file = fopen(out_path, "wb+");
SwrContext* swr_ctx = init_swr();
//2048/4=512/2=256
//创建输入缓冲区
av_samples_alloc_array_and_samples(&src_data, //输出缓冲区地址
&src_linesize, //缓冲区的大小
1, //通道个数
512, //单通道采样个数
AV_SAMPLE_FMT_FLT, //采样格式
0);
//创建输出缓冲区
av_samples_alloc_array_and_samples(&dst_data, //输出缓冲区地址
&dst_linesize, //缓冲区的大小
1, //通道个数
512, //单通道采样个数
AV_SAMPLE_FMT_S16, //采样格式
0);
while(count < 500){
ret = av_read_frame(fmt_ctx, &pkt);
if(ret == 1 || ret == -35) {
usleep(10000);
continue;
}
if(ret < 0){
break;
}
av_log(NULL, AV_LOG_INFO, "pkt size is %d(%p), count is %d \n",
pkt.size, pkt.data, count);
//进行内存拷贝,按字节拷贝的
memcpy((void*)src_data[0], (void*)pkt.data, pkt.size);
//重采样
swr_convert(swr_ctx, //重采样的上下文
dst_data, //输出结果缓冲区
512, //每个通道的采样数
(const uint8_t **)src_data, //输入缓冲区
512); //输入单个通道的采样数
//write file
//fwrite(pkt.data, 1, pkt.size, outfile);
fwrite(dst_data[0], 1, dst_linesize, out_file);
// 将数据以二进制形式写入文件
//fwrite(pkt.data, pkt.size, 1, out_file);
// 从缓冲区写入文件
fflush(out_file);
// 释放pkg指针
av_packet_unref(&pkt);
count ++;
}
// 关闭文件
fclose(out_file);
//释放输入输出缓冲区
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);
// 关闭设备,释放上下文指针
avformat_close_input(&fmt_ctx);
av_log(NULL, AV_LOG_DEBUG, "finish wangjiangjiang\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)