音频编码流程 ----- PCM编码为AAC格式

1.音频编码流程

在这里插入图片描述

2.编码函数API含义解释

av_frame_make_writable 确保帧数据可写,尽可能避免数据复制.如果帧可写,则不执行任何操作,如果不可写,则分配新缓冲区并复制数据.返回: 成功时为 0,错误时为负 AVERROR.

av_samples_fill_arrays 这个函数就是将你输入的一帧数据写入AVFrame格式输出,便于后面编码send,recvice使用

3.音频编码实战Demo PCM转AAC格式

编码注意点:

  1. 编码器相关配置得设置正确,比如码率,采样率,声道,采样格式等
  2. 也要设置AVFrame的格式,主要是采样率,声道,采样格式
  3. 如果数据不是FLTP格式的花,需要转化为FLTP格式.
  4. PCM编码后的数据想要编码为AAC格式,得在前面加上adtsheader.
#ifndef MAINBACK_C
#define MAINBACK_C
#endif // MAINBACK_C
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
void f32le_convert_to_fltp(float *f32le, float *fltp, int nb_samples) {
    float *fltp_l = fltp;   // 左通道
    float *fltp_r = fltp + nb_samples;   // 右通道
    for(int i = 0; i < nb_samples; i++) {
        fltp_l[i] = f32le[i*2];     // 0 1   - 2 3
        fltp_r[i] = f32le[i*2+1];   // 可以尝试注释左声道或者右声道听听声音
    }
}
static void get_adts_header(AVCodecContext *ctx, uint8_t *adts_header, int aac_length)
{
    uint8_t freq_idx = 0;    //0: 96000 Hz  3: 48000 Hz 4: 44100 Hz
    switch (ctx->sample_rate) {
        case 96000: freq_idx = 0; break;
        case 88200: freq_idx = 1; break;
        case 64000: freq_idx = 2; break;
        case 48000: freq_idx = 3; break;
        case 44100: freq_idx = 4; break;
        case 32000: freq_idx = 5; break;
        case 24000: freq_idx = 6; break;
        case 22050: freq_idx = 7; break;
        case 16000: freq_idx = 8; break;
        case 12000: freq_idx = 9; break;
        case 11025: freq_idx = 10; break;
        case 8000: freq_idx = 11; break;
        case 7350: freq_idx = 12; break;
        default: freq_idx = 4; break;
    }
    uint8_t chanCfg = ctx->channels;
    uint32_t frame_length = aac_length + 7;
    adts_header[0] = 0xFF;
    adts_header[1] = 0xF1;
    adts_header[2] = ((ctx->profile) << 6) + (freq_idx << 2) + (chanCfg >> 2);
    adts_header[3] = (((chanCfg & 3) << 6) + (frame_length  >> 11));
    adts_header[4] = ((frame_length & 0x7FF) >> 3);
    adts_header[5] = (((frame_length & 7) << 5) + 0x1F);
    adts_header[6] = 0xFC;
}
int encode(AVCodecContext* codec_ctx,AVFrame* frame,AVPacket* pkt,FILE* out)
{
    int ret=0;
    ret = avcodec_send_frame(codec_ctx,frame);
    if(ret<0){
        printf("avcodec_send_frame failed\n");
        return ret;
    }

    while(1)
    {
        ret=avcodec_receive_packet(codec_ctx,pkt);
        if(ret==AVERROR(EAGAIN)||ret==AVERROR(AVERROR_EOF))
            break;
        if(ret<0)return ret;
        if(codec_ctx->flags&AV_CODEC_FLAG_GLOBAL_HEADER)
        {
            char header[7]={0};
            get_adts_header(codec_ctx,header,pkt->size);
            int size=fwrite(header,1,7,out);
            if(size!=7)
            {
                printf("fwrite error\n");
                return 0;
            }
        }

        fwrite(pkt->data,1,pkt->size,out);
    }

}
//编码流程  先初始化编码器,读取原始文件,send,recvice,写入
int main(int argc,char* argv[])
{
    if(argv<3)
    {
        printf("argv<3\n");
        return -1;
    }
    char* pcm_path=argv[1];
    char* out_path=argv[2];
    FILE* pcm_file=fopen(pcm_path,"rb");
    FILE* out_file=fopen(out_path,"wb");
    AVCodec* codec=avcodec_find_encoder(AV_CODEC_ID_AAC);
    AVCodecContext* codec_ctx=avcodec_alloc_context3(codec);

    codec_ctx->bit_rate=100000;
    codec_ctx->channel_layout=AV_CH_LAYOUT_STEREO;
    codec_ctx->channels=av_get_channel_layout_nb_channels(codec_ctx->channel_layout);
    codec_ctx->sample_fmt=AV_SAMPLE_FMT_FLTP;
//    codec_ctx->codec_id=AV_CODEC_ID_AAC;
//    codec_ctx->codec_type=AVMEDIA_TYPE_AUDIO;
    codec_ctx->sample_rate=48000;
    codec_ctx->profile=FF_PROFILE_AAC_LOW;
    codec_ctx->flags|=AV_CODEC_FLAG_GLOBAL_HEADER;
    avcodec_open2(codec_ctx,codec,NULL);

    AVFrame* frame=av_frame_alloc();
    AVPacket* pkt=av_packet_alloc();
//    frame->channel_layout=codec_ctx->channel_layout;
    frame->channels=codec_ctx->channels;
//    frame->sample_rate=codec_ctx->sample_rate;
    frame->format=codec_ctx->sample_fmt;
    frame->nb_samples=codec_ctx->frame_size;
    av_frame_get_buffer(frame,0);//分配frame的buff
    int frame_bytes=av_get_bytes_per_sample(frame->format)*frame->channels*frame->nb_samples;
    uint8_t* pcm_buff=av_malloc(frame_bytes);
    memset(pcm_buff,0,frame_bytes);
    uint8_t *pcm_temp_buf = (uint8_t *)malloc(frame_bytes);
    memset(pcm_temp_buf,0,frame_bytes);
    int pts=0;
    int ret=0;
    while(1)
    {
        int rsize=fread(pcm_buff,1,frame_bytes,pcm_file);
        ret = av_frame_make_writable(frame);
        if(ret != 0)
            printf("av_frame_make_writable failed, ret = %d\n", ret);
        f32le_convert_to_fltp(pcm_buff,pcm_temp_buf,frame->nb_samples);
        int need_size=av_samples_fill_arrays(frame->data,frame->linesize,pcm_temp_buf,frame->channels,frame->nb_samples,frame->format,0);
        if(rsize!=need_size)break;
        frame->pts=pts;
        pts+=1;
        printf("frame pts:%d\n",pts);
        encode(codec_ctx,frame,pkt,out_file);
    }
    encode(codec_ctx,NULL,pkt,out_file);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: fdk-aac是一款开源的音频编码器,可以将PCM(Pulse Code Modulation)格式音频数据进行压缩编码PCM是一种无损的音频存储格式,它将模拟音频信号换成数字信号,每个样本使用定点或浮点数表示音频波形。然而,PCM格式音频文件通常会占据较大的存储空间,不便于传输和存储。 使用fdk-aac编码PCM音频文件可以有效地压缩文件大小,减少存储空间的占用。编码过程中,fdk-aac会根据PCM音频数据的特性和人耳感知的特点,使用先进的压缩算法对音频进行分析和处理。它会利用人耳对不同频率和声道的灵敏度不同的特点,对音频数据进行采样和量化,并且使用不同的编码器和参数对不同部分的音频信号进行编码。 通过fdk-aac编码器,PCM音频文件可以换为高效的AAC(Advanced Audio Coding)格式AAC是一种被广泛应用于数字音频音视频传输领域的音频编码标准,它具有更好的压缩效率和音频质量,相对于其他编码格式如MP3,AAC格式音频文件更小,但音质更好。 因此,通过fdk-aac编码器,将PCM格式音频文件换为AAC格式,可以在保持音质的同时减少文件的大小,方便音频的传输和存储。这对于音频文件的压缩和网络传输等应用场景具有重要意义。 ### 回答2: fdk-aac是一种高效的音频编码器,用于将原始的PCM音频数据换为AAC格式PCM,也称为脉冲编码调制,是一种未经压缩的音频数据格式,具有较大的文件大小和较低的编码效率。而AAC是一种先进的音频编码格式,通过压缩音频数据可以获得较小的文件大小和较高的音质。fdk-aac编码器可以使用PCM作为输入,对音频数据进行压缩和编码,并生成AAC文件。 使用fdk-aac编码PCM的过程如下: 1. 准备PCM音频数据,PCM是一种无损音频格式,通常采样位数为16位,采样频率可以是44.1kHz或48kHz。 2. 将PCM音频数据输入到fdk-aac编码器中。编码器会对音频数据进行分析和处理,并根据一些音频压缩算法将其换为AAC格式。 3. 设置编码参数,例如压缩比特率、编码质量等。参数的设置可以影响到最终编码后的音质和文件大小。 4. 运行编码器,等待编码过程完成。编码器会根据设置的参数和音频数据的特性,对PCM音频数据进行压缩编码。 5. 检查编码结果,确保生成的AAC文件符合预期。检查可以包括文件大小、音频质量等方面的评估。 6. 存储或传输编码后的AAC文件。编码后的文件可以被用于存储、传输和播放等用途。 通过使用fdk-aac编码器,可以将较大的PCM音频数据压缩为较小的AAC文件,从而节省存储空间和传输带宽,并且能够保持较高的音频质量。 ### 回答3: fdk-aac是一种高度效率的音频编码器,它可以将原始的PCM音频信号换为AAC格式音频文件。PCM是一种未经压缩的音频数据格式,其采样率和位深度保持不变,需要较大的存储空间。而AAC是一种压缩的音频格式,可以以更小的文件大小提供高质量的音频。 使用fdk-aac编码pcm音频的步骤如下: 首先,我们需要准备一个PCM音频文件作为输入。这个PCM文件可以是从麦克风、音乐播放器或其他设备中捕获的音频信号。 然后,我们需要使用fdk-aac编码器对PCM文件进行编码编码过程中,fdk-aac会分析音频信号的特征并进行压缩,以减小文件大小同时保持音质。 编码完成后,我们可以得到一个AAC格式音频文件。这个文件具有较小的文件大小,适合在网络传输或存储中使用。 最后,我们可以使用支持AAC格式的播放器或设备来播放这个编码后的音频文件。 总结起来,fdk-aac编码器可以将PCM音频信号换为AAC格式音频文件,实现高质量音频的压缩和存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

相知-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值