超级搬砖工 2020-11-04 11:03 采纳率: 71.4%
浏览 173

windows下faad2解码aac音频文件噪音比较严重,要怎么解决

音频源:16KHZ,单声道,16bit位宽的 PCM 编码的AAC
解码成:双通道,16kHZ,16bit位宽 的 PCM,录制解码后的PCM数据帧
播放器如下:

图片说明

关键源码如下:

long AudioDecode_AAC::AudioDecode_AAC_Init(
    unsigned char *frame,
    unsigned long size,
    unsigned long *samplerate,
    unsigned char *channels)
{
    if (!decoder)
    {

        //open decoder
        decoder = NeAACDecOpen();
        NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);

        conf->defObjectType = LC;
        conf->defSampleRate = 16000;//8000; //real samplerate/2
        conf->outputFormat = FAAD_FMT_16BIT; //
        conf->downMatrix = 0; //不进行自动扩展到双通道 ???
        conf->useOldADTSFormat = 0; //ADTS长度为0:56bit(1代表是58bit)
        conf->dontUpSampleImplicitSBR = 1;

        NeAACDecSetConfiguration(decoder, conf);


        //initialize decoder
        return NeAACDecInit(decoder, frame,size, samplerate, channels);
    }
    else
    {
        ERROR_LOG("AAC decoder already inited!\n");
        return -1;
    }

}

//成功:返回解码得到的PCM数据指针 ; 失败 :NULL
//frame_info:返回帧信息参数
 void* AudioDecode_AAC::AudioDecode_AAC_Decode(
    NeAACDecFrameInfo *frame_info,
    unsigned char *frame,
    unsigned long size)
{
#if 1
    static char frame_mono[2048] = { 0 };
    memset(&frame_mono,0,sizeof(frame_mono));
#endif 

    check_ADTS_len(frame,size);

    /*----进行解码操作----------------------------------------*/
    //解析下一帧数据长度

    void*pcm_data = NeAACDecDecode(decoder, frame_info, frame, size);
    printf(" frame_info->samples = %d frame_info->channels = %d\n", frame_info->samples,frame_info->channels);//初始化中dontUpSampleImplicitSBR = 1时返回2048;dontUpSampleImplicitSBR=0时返回4096
    if (size != frame_info->bytesconsumed)//每次传入一帧数据,这两个值每次都相等
    {
        printf("error!$$$$$$$$$$$$$$$$$$$$$$$$$size(%d) frame_info->bytesconsumed(%d)\n", size, frame_info->bytesconsumed);
    }

    if (frame_info->error > 0)
    {
        printf("error!$$$$$$$$$ %s\n", NeAACDecGetErrorMessage(frame_info->error));
    }
    else if (pcm_data && frame_info->samples > 0)
    {
#if 0   //转换成单通道数据,faad解码总是强制性变成双通道输出

        if (frame_info->channels == 2) //双通道数据转换成单通道
        {
            //从双声道的数据中提取单通道 
            int i, j;
            for (i = 0, j = 0; i < 4096 && j < 2048; i += 4, j += 2)
            {
                //每次拷贝2字节数据到frame_mono(16bit位宽,即每个通道数据一个采样2字节)
                frame_mono[j] = ((char*)pcm_data)[i]; 
                frame_mono[j + 1] = ((char*)pcm_data)[i + 1];
            }
            frame_info->samples = 1024; //只留下单通道数据
            frame_info->channels = 1;
        }
        return (void*)&frame_mono;
#else   //直接返回双通道数据
        return pcm_data;
#endif



    }

    return NULL;
}

保存数据部分如下:
图片说明

源文件如下:
链接:https://pan.baidu.com/s/1VGXIfD-X74XCDG3-O17dHg
提取码:wbzn

展开全部

  • 写回答

1条回答 默认 最新

  • 码农阿豪@新空间 Java领域优质创作者 2024-07-24 14:00
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    问题分析及解答如下:
    1. 问题描述:请求对音频源进行解码,从16KHZ、单声道、16bit位宽的PCM编码的AAC格式解码为双通道、16kHZ、16bit位宽的PCM,并记录解码后的PCM数据帧。

    2. 解决思路:根据提供的播放器代码和保存数据部分,通过编写音频解码器的初始化和解码函数,在解码过程中将双通道数据转换为单通道数据(如果需要),最后保存解码后的PCM数据帧。

    3. 解决步骤:
    4. 初始化AAC解码器:根据提供的源码,可以使用AudioDecode_AAC_Init函数进行AAC解码器的初始化,设置解码参数,并返回初始化是否成功。
    5. 解码AAC数据:利用AudioDecode_AAC_Decode函数对AAC数据进行解码,获取解码后的PCM数据指针,同时记录解码后的帧信息。
    6. 转换单通道数据(可选):如果需要将双通道数据转换为单通道数据,可以在解码过程中使用提供的转换代码部分。
    7. 保存PCM数据帧:在解码后的PCM数据帧获取到后,可以将其保存到指定的位置,以供后续处理或播放。
    8. 示例代码:
    // 初始化AAC解码器
    unsigned char frame[AAC_FRAME_SIZE]; // 定义AAC帧数据
    unsigned long samplerate;
    unsigned char channels;
    long ret = AudioDecode_AAC_Init(frame, AAC_FRAME_SIZE, &samplerate, &channels);
    if (ret < 0) {
        // 初始化失败处理逻辑
    }
    // 解码AAC数据
    NeAACDecFrameInfo frame_info;
    unsigned char aac_frame[AAC_FRAME_SIZE]; // AAC音频数据帧
    void* pcm_data = AudioDecode_AAC_Decode(&frame_info, aac_frame, AAC_FRAME_SIZE);
    if (pcm_data) {
        // 解码成功处理逻辑
        // 转换双通道数据为单通道数据
        if (frame_info.channels == 2) {
            // 进行单通道数据转换的处理
        }
        // 保存PCM数据帧到文件或内存中
        // 示例代码如下用于保存PCM数据到文件
        FILE* pcm_file = fopen("output.pcm", "wb");
        if (pcm_file) {
            fwrite(pcm_data, 1, frame_info.samples * frame_info.channels * sizeof(short), pcm_file);
            fclose(pcm_file);
        }
    }
    

    以上示例代码展示了初始化AAC解码器、解码AAC数据、转换单通道数据和保存PCM数据帧的基本过程,具体实现需要根据实际情况进行调整。希望这个回答对您有所帮助。

    展开全部

    评论
    编辑
    预览

    报告相同问题?

    手机看
    程序员都在用的中文IT技术交流社区

    程序员都在用的中文IT技术交流社区

    专业的中文 IT 技术社区,与千万技术人共成长

    专业的中文 IT 技术社区,与千万技术人共成长

    关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

    关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

    客服 返回
    顶部