使用ffmpeg保存PCM文件
  NYfg2BRCcXho 2023年11月02日 93 0


说明

  1. PCM是音频解码后的文件。或者说经过音频经过采样后形成的二进制文件。
  2. 对人来说,能听到的是20HZ-20KHZ,这也是次声波和超声波的分界线。
  3. 根据采样定理,2倍最高频率就可以还原,加速滤波器带来的畸变,44.1KHZ采样已经可以了。48KHZ以上的采样率,人已经无法分辨差异了。
  4. 保存PCM文件时使用的是采用有符号16位保存,而源音频不一定是,所以需要转换。

ffmpeg中的音频相关内容

概述

ffmpeg中AVPacket中可能会含有多个音频帧(AVFrame),一个音频帧含有多个采样,采样率决定了1s有多少个采样(或者说一个音频帧可以播放多久)。对于aac,一帧有1024个采样,mp3一帧则固定为1152个字节。

参数

AVPacket:音频或视频包,由成员stream_index区分。
AVFrame: 存储音频帧解码后的数据。
AVCodecContext->sample_fmt:采样格式,也就是数据存储格式:有无符号、位数等。
AVCodecContext->sample_rate:采样率
AVCodecContext->channel_layout:声道布局,也就是单声道,双声道,立体声。
AVFrame->nb_samples:这个音频帧含有多少个采样。

音频帧占用内存计算:

根据声道数、采样个数、采样格式可以计算出音频帧占用内存大小。

av_samples_get_buffer_size(NULL, 声道数,采样个数,采样格式, 1);

ffmpeg转换PCM格式步骤

  1. 设置转换参数SwrContext,包括声道数、采样率、采样格式 。
  2. 解码音频帧数据。
  3. 计算转换后内存占用大小并分配buf 。
  4. 使用swr_convert转换帧数据。
  5. 将数据写入文件。

示例代码

转换设置

SwrContext *swrCtx = swr_alloc();                               //音频重采样上下文

enum AVSampleFormat in_sample_fmt = pACodecCtx->sample_fmt; //输入的采样格式
int in_sample_rate = pACodecCtx->sample_rate; //输入的采样率
uint64_t in_ch_layout = pACodecCtx->channel_layout; //输入的声道布局

enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16; //输出的采样格式 16bit PCM
int out_sample_rate = 44100; //输出的采样率
uint64_t out_ch_layout = AV_CH_LAYOUT_MONO; //输出的声道布局
int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout); //输出的声道个数

swr_alloc_set_opts(swrCtx, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout, in_sample_fmt, in_sample_rate, 0, NULL);
swr_init(swrCtx);

转码与存储

if (avPacket.stream_index == AUDIO_INDEX) {
AVPacket->AVFrameret = avcodec_decode_audio4(pACodecCtx, avFrame, &got_frame, &avPacket);if (ret < 0) { printf("%s", "解码完成");}

//获取对应参数的采样需要占用的内存大小
int out_buffer_size = av_samples_get_buffer_size(NULL, out_channel_nb, avFrame->nb_samples, out_sample_fmt, 1);

//存储pcm数据
uint8_t *out_buffer = (uint8_t *)av_malloc(out_buffer_size);

if (got_frame) {
swr_convert(swrCtx, &out_buffer, out_buffer_size, (const uint8_t **)avFrame->data, avFrame->nb_samples);
//写入文件进行测试
fwrite(out_buffer, 1, out_buffer_size, pFile);}
av_free(out_buffer);
}

播放

ffplay -f s16le -ar 44100 -ac 1  test.pcm

参考资料

​​音频帧概念详解​​


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
NYfg2BRCcXho