请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

重采样声音变快

问题描述:
重采样之后播放, 能听清但是声音变的很快

我的播放命令:
ffplay -ar 44100 -ac 2 -f s16le ./audio.pcm

我的其他尝试:

  1. 使用命令ffplay -ar 44100 -ac 2 -f f32le ./audio.pcm
    播放速度很快,听不清
  2. 将单通道采样数改为 512. 使用上面两个命令播放,也完全听不清.

我的后台输出:

packet size is 2048(0x15e808a00)
packet size is 2048(0x15e808a00)
packet size is 2048(0x168008200)
packet size is 2048(0x15c820000)
packet size is 2048(0x15c820000)
packet size is 2048(0x15c820000)
packet size is 2048(0x15f008200)

我的代码:
由于我的pkg.size为 2048 , 所以我将单通道采样个数改为256. 其他都是老师的代码.

//
//  testc.c
//  myapp
//
//  Created by lichao on 2020/1/30.
//  Copyright © 2020年 lichao. All rights reserved.
//

#include "testc.h"
#include <string.h>

static int rec_status = 0;

void set_status(int status) {
    rec_status = status;
}

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,   //输出的采样格式
                                 44100,               //采样率
                                 AV_CH_LAYOUT_STEREO, //输入channel布局
                                 AV_SAMPLE_FMT_FLT,   //输入的采样格式
                                 44100,               //输入的采样率
                                 0, NULL);

    if (!swr_ctx) {

    }

    if (swr_init(swr_ctx) < 0) {

    }

    return swr_ctx;
}

void rec_audio() {

    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;

    //ctx
    AVFormatContext *fmt_ctx = NULL;
    AVDictionary *options = NULL;

    //pakcet
    AVPacket pkt;

    //[[video device]:[audio device]]
    char *devicename = ":2";

    //set log level
    av_log_set_level(AV_LOG_DEBUG);

    //start record
    rec_status = 1;

    //register audio device
    avdevice_register_all();

    //get format
    AVInputFormat *iformat = av_find_input_format("avfoundation");

    //open device
    if ((ret = avformat_open_input(&fmt_ctx, devicename, iformat, &options)) < 0) {
        av_strerror(ret, errors, 1024);
        fprintf(stderr, "Failed to open audio device, [%d]%s\n", ret, errors);
        return;
    }

    //create file
    char *out = "/Users/tianzc/audio.pcm";
    FILE *outfile = fopen(out, "wb+");

    SwrContext *swr_ctx = init_swr();

    //4096/4=1024/2=512
    //创建输入缓冲区
    av_samples_alloc_array_and_samples(&src_data,         //输出缓冲区地址
                                       &src_linesize,     //缓冲区的大小
                                       2,                 //通道个数
                                       256,               //单通道采样个数
                                       AV_SAMPLE_FMT_FLT, //采样格式
                                       0);

    //创建输出缓冲区/
    av_samples_alloc_array_and_samples(&dst_data,         //输出缓冲区地址
                                       &dst_linesize,     //缓冲区的大小
                                       2,                 //通道个数
                                       256,               //单通道采样个数
                                       AV_SAMPLE_FMT_S16, //采样格式
                                       0);
    //read data from device
    ret = av_read_frame(fmt_ctx, &pkt);
    av_log(NULL, AV_LOG_INFO,
           "ret  is %d   %d\n",
           ret, rec_status );
    while (ret == 0 &&
           rec_status) {

        av_log(NULL, AV_LOG_INFO,
               "packet size is %d(%p)\n",
               pkt.size, pkt.data);

        //进行内存拷贝,按字节拷贝的
        memcpy((void *) src_data[0], (void *) pkt.data, pkt.size);

        //重采样
        swr_convert(swr_ctx,                    //重采样的上下文
                    dst_data,                   //输出结果缓冲区
                    256,                        //每个通道的采样数
                    (const uint8_t **) src_data, //输入缓冲区
                    256);                       //输入单个通道的采样数

        //write file
        //fwrite(pkt.data, 1, pkt.size, outfile);
        fwrite(dst_data[0], 1, dst_linesize, outfile);
        fflush(outfile);
        av_packet_unref(&pkt); //release pkt
        ret = av_read_frame(fmt_ctx, &pkt);
    }

    //close file
    fclose(outfile);

    //释放输入输出缓冲区
    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);

    //close device and release ctx
    avformat_close_input(&fmt_ctx);

    av_log(NULL, AV_LOG_DEBUG, "finish!\n");

    return;
}

//#if 0
int main(int argc, char *argv[]) {
    rec_audio();
    return 0;
}
//#endif

正在回答 回答被采纳积分+3

1回答

李超 2022-06-23 14:51:08

用ffmpeg 命令查看你的设备参数了吗?进入课程QQ群,看里边的公告,就可以找到具体的命令了

1 回复 有任何疑惑可以回复我~
  • 提问者 weixin_慕沐9189930 #1
    我的设备参数
    ```
    (base) ~ ᐅ ffmpeg -f avfoundation -i :2
    ffmpeg version 5.0 Copyright (c) 2000-2022 the FFmpeg developers
      built with Apple clang version 13.0.0 (clang-1300.0.29.30)
      configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/5.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --
    ...
    Input #0, avfoundation, from ':2':
      Duration: N/A, start: 52250.434833, bitrate: 1536 kb/s
      Stream #0:0: Audio: pcm_f32le, 48000 Hz, mono, flt, 1536 kb/s
    ```
    
    我的尝试:
    1. 代码里面的44100 改为 48000 ,然后,使用命令`ffplay -ar 48000 -ac 2 -f s16le ./audio.pcm`, 发现声音还能听清,但是还是很快
    2. 代码里面的44100 改为 48000 ,然后,使用命令`ffplay -ar 48000 -ac 2 -f f32le ./audio.pcm`,全是噪音
    
    我选择输入设备为':2' 的原因在于: :2为我的mac麦克风
    回复 有任何疑惑可以回复我~ 2022-06-23 15:11:19
  • 李超 回复 提问者 weixin_慕沐9189930 #2
    你在进行冲采样之前,有没有测试一下录制的原始数据播放是否正常?
    回复 有任何疑惑可以回复我~ 2022-06-24 07:48:31
  • 提问者 weixin_慕沐9189930 回复 李超 #3
    已经解决, 解决思路如下。
    1. 按照老师说的,测试录制原始数据播放是否正常:经过测试是不正常的。
    
    2. 猜测:我的电脑设备数据和老师的设备数据不一致导致的。
    
    3. 验证:首先查看电脑可用的设备:ffmpeg -f avfoundation -list_devices true -i ''
        结果:[AVFoundation indev @ 0x14c004440] AVFoundation video devices:
    [AVFoundation indev @ 0x14c004440] [0] FaceTime HD Camera
    [AVFoundation indev @ 0x14c004440] [1] Capture screen 0
    [AVFoundation indev @ 0x14c004440] AVFoundation audio devices:
    [AVFoundation indev @ 0x14c004440] [0] MacBook Air麦克风
    [AVFoundation indev @ 0x14c004440] [1] Filmage 聚集设备
    [AVFoundation indev @ 0x14c004440] [2] FreeBuds 3
    [AVFoundation indev @ 0x14c004440] [3] BlackHole 16ch
    
    4. 选择设备0, 用默认的ffmpeg录制命令录制:ffmpeg -f avfoundation -i :0 out.wav
    
    5. 播放该录音: ffplay ./out.wav
      Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 1 channels, s16, 768 kb/s
       5.92 M-A:  0.000 fd=   0 aq=  104KB vq=    0KB sq=    0B f=0/0
    
    6. 发现采样率, 通道数, 数据格式和老师告诉我们的都不一样
    
    7. 一个一个尝试, 我的设备将采样率设置为48000, 通道数设置为1, 数据格式设置为f32le 就播放正常
    
    8. 猜测 mac的麦克风只有一个,所以默认是单通道。
    回复 有任何疑惑可以回复我~ 2022-06-25 10:49:21
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信