音视频基础(四)音频重采样

音频重采样

image

image

image

重采样代码

点击查看代码
#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;
}

posted @   金元宝骑骑  阅读(209)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示