欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac

 更新時(shí)間:2023年11月08日 14:24:50   作者:CodeOfCC  
mp4的音頻流通常是aac編碼,我們做音視頻采集的時(shí)候就需要將,采集的音頻PCM編碼成aac,本文就來為大家介紹一下C++如何使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac吧

前言

mp4的音頻流通常是aac編碼,我們做音視頻采集的時(shí)候就需要將,采集的音頻PCM編碼成aac,然后再打包進(jìn)mp4,而aac編解碼庫中fdk-aac是性能較好的,使用方式也比較簡單。在C++項(xiàng)目中使用,通常再做一層封裝,提高模塊的復(fù)用性和替換性。本文將展示C++將fdk-aac封裝成一個(gè)編碼對象,以及使用示例。

一、接口設(shè)計(jì)

由于我前面的文章已經(jīng)給出了fdk-aac的使用示例:《Windows上使用vs編譯fdk-aac》,所以在這里直接設(shè)計(jì)對象的接口。

/// <summary>
/// aac編碼對象
/// 所有方法采用異常處理進(jìn)行錯(cuò)誤提示,使用時(shí)注意使用try-catch,拋出對象為std::exception。
/// 構(gòu)造方法參數(shù)的聲道數(shù)是最大緩存數(shù)量,并非實(shí)際聲道數(shù),實(shí)際聲道數(shù)由SetChannelMode方法確定,本版本需要確保SetChannelMode的聲道數(shù)與構(gòu)造方法參數(shù)的聲道數(shù)一致。
/// </summary>
class FdkaacEncoder {
public:
    /// <summary>
    /// 編碼數(shù)據(jù)到達(dá)事件參數(shù)
    /// </summary>
    class EncodedDataArrivedEventArgs 
    {
    public:
        /// <summary>
        /// 音頻幀
        /// </summary>
        AudioCodingFrame Frame;
    };
    /// <summary>
    /// 編碼數(shù)據(jù)到達(dá)事件
    /// </summary>
    std::function<void(void*,EncodedDataArrivedEventArgs*)> EncodedDataArrived;
    /// <summary>
    /// 構(gòu)造方法
    /// </summary>
    /// <param name="">編碼參數(shù)</param>
    FdkaacEncoder(SoundFormat format);
    /// <summary>
    /// 析構(gòu)方法
    /// </summary>
    ~FdkaacEncoder();
    /// <summary>
    /// 獲取聲音格式
    /// </summary>
    /// <returns>聲音格式</returns>
    SoundFormat GetSoundFormat();
    /// <summary>
    /// 設(shè)置比特率
    /// </summary>
    /// <param name="value">比特率,單位byte</param>
    void SetBitrate(int value);
    /// <summary>
    /// 獲取比特率
    /// </summary>
    /// <returns>比特率,單位byte</returns>
    int GetBitrate();
    /// <summary>
    /// 設(shè)置封裝類型
    /// </summary>
    /// <param name="value">封裝類型</param>
    void SetTransportType(TransportType value);
    /// <summary>
    /// 獲取封裝類型
    /// </summary>
    /// <returns>封裝類型</returns>
    TransportType GetTransportType();
    /// <summary>
    /// 設(shè)置比特率模式(CBR、VBR)
    /// </summary>
    /// <param name="value">比特率模式</param>
    void SetBitrateMode(BitrateModde value);
    /// <summary>
    /// 獲取比特率模式(CBR、VBR)
    /// </summary>
    /// <returns>比特率模式</returns>
    BitrateModde GetBitrateMode();
    /// <summary>
    /// 設(shè)置聲道順序
    /// </summary>
    /// <param name="value">聲道順序</param>
    void SetChannelOrder(ChannelOrder value);
    /// <summary>
    /// 獲取聲道順序
    /// </summary>
    /// <returns>聲道順序</returns>
    ChannelOrder GetChannelOrder();
    /// <summary>
    /// 設(shè)置聲道模式,聲道數(shù)需要小于等于構(gòu)造方法設(shè)置的聲道數(shù)。
    /// </summary>
    /// <param name="value">聲道模式</param>
    void SetChannelMode(ChannelMode value);
    /// <summary>
    /// 獲取聲道模式
    /// </summary>
    /// <returns></returns>
    ChannelMode GetChannelMode();
    /// <summary>
    /// 設(shè)置頻段復(fù)制模式
    /// </summary>
    /// <param name="value">頻段復(fù)制模式</param>
    void SetSbrMode(SbrMode value);
    /// <summary>
    /// 獲取頻段復(fù)制模式
    /// </summary>
    /// <returns>頻段復(fù)制模式</returns>
    SbrMode GetSbrMode();
    /// <summary>
    /// 設(shè)置AOT
    /// </summary>
    /// <param name="">AOT</param>
    void SetAudioObjectType(AudioObjectType);
    /// <summary>
    /// 獲取AOT
    /// </summary>
    /// <returns>AOT</returns>
    AudioObjectType GetAudioObjectType();
    /// <summary>
    /// 寫入音頻數(shù)據(jù)
    /// 注意數(shù)據(jù)長度不能過大,否則導(dǎo)致音頻不正常,建議2048。
    /// </summary>
    /// <param name="data">音頻數(shù)據(jù)</param>
    /// <param name="dataLength">數(shù)據(jù)長度</param>
    void Write(unsigned char* data, int dataLength);
}

二、使用示例

將wav文件編碼成acc文件。其中WavFileReader對象參考:《C++ 讀取wav文件中的PCM數(shù)據(jù)

1.雙聲道

#include<stdio.h>
#include<exception>
#include"WavFileReader.h"
#include"FdkaacEncoder.h"
void main(int argc, char* argv[])
{
    FILE* f=nullptr;
    try {        
        //wav文件讀取對象
        AC::WavFileReader wr;
        //aac編碼對象
        //其中參數(shù)的聲道數(shù)是最大緩存數(shù)量,并非實(shí)際聲道數(shù),實(shí)際聲道數(shù)由SetChannelMode方法確定,本版本需要確保SetChannelMode的聲道數(shù)與構(gòu)造方法參數(shù)的聲道數(shù)一致。
        AC::FdkaacEncoder fe({ 2 ,44100 ,16 });
        unsigned char buf[2048];
        //設(shè)置參數(shù)
        fe.SetSbrMode(AC::SbrMode_Disable);
        fe.SetAudioObjectType(AC::AudioObjectType::AUDIOOBJECTTYPE_AAC_LC);
        fe.SetBitrate(128 * 1024);
        fe.SetChannelMode(AC::ChannelMode::CHANNELMODE_2);
        fe.SetChannelOrder(AC::CHANNELORDER_WAV);
        fe.SetBitrateMode(AC::BitrateModde::BITRATEMODDE_CBR);
        fe.SetTransportType(AC::TRANSPORTTYPE_MP4_ADTS);
        //注冊編碼數(shù)據(jù)到達(dá)事件
        fe.EncodedDataArrived = [&](auto s, auto e) {
            //將得到的編碼數(shù)據(jù)寫入文件
            fwrite(e->Frame.Data, 1, e->Frame.DataLength, f);
        };
        //創(chuàng)建aac文件
        f = fopen("test_music.aac", "wb+");
        if (!f)
        {
            throw std::exception("create aac file fail,create name:test_music.aac");
        }
        //打開wav文件
        if (!wr.OpenWavFile("test_music.wav"))
        {
            throw std::exception("open wav file fail,filename:test_music.wav");
        }    
        while (1)
        {   //讀取wav中的pcm數(shù)據(jù)
            int size = wr.ReadData(buf, 2048);
            if (size < 1)
                break;
            //將pcm數(shù)據(jù)寫入編碼器
            fe.Write(buf, size);
        }    
        printf("encode completed\n");
    }
    catch(std::exception e){
        printf("%s\n",e.what());
    }
    catch (...) {
        printf("unknown errror\n");
    }
    if(f)
    fclose(f);
}

2.單聲道

#include<stdio.h>
#include<exception>
#include"WavFileReader.h"
#include"FdkaacEncoder.h"
void main(int argc, char* argv[])
{
    FILE* f = nullptr;
    try {
        //wav文件讀取對象
        AC::WavFileReader wr;
        //aac編碼對象
        //其中參數(shù)的聲道數(shù)是最大緩存數(shù)量,并非實(shí)際聲道數(shù),實(shí)際聲道數(shù)由SetChannelMode方法確定,本版本需要確保SetChannelMode的聲道數(shù)與構(gòu)造方法參數(shù)的聲道數(shù)一致。
        AC::FdkaacEncoder fe({ 1 ,44100 ,16 });
        unsigned char buf[2048];
        //設(shè)置參數(shù)
        fe.SetSbrMode(AC::SbrMode_Disable);
        fe.SetAudioObjectType(AC::AudioObjectType::AUDIOOBJECTTYPE_AAC_LC);
        fe.SetBitrate(128 * 1024);
        fe.SetChannelMode(AC::ChannelMode::CHANNELMODE_1);
        fe.SetChannelOrder(AC::CHANNELORDER_WAV);
        fe.SetBitrateMode(AC::BitrateModde::BITRATEMODDE_CBR);
        fe.SetTransportType(AC::TRANSPORTTYPE_MP4_ADTS);
        //注冊編碼數(shù)據(jù)到達(dá)事件
        fe.EncodedDataArrived = [&](auto s, auto e) {
            //將得到的編碼數(shù)據(jù)寫入文件
            fwrite(e->Frame.Data, 1, e->Frame.DataLength, f);
        };
        //創(chuàng)建aac文件
        f = fopen("test_music_1ch441s16b.aac", "wb+");
        if (!f)
        {
            throw std::exception("create aac file fail,create name:test_music_1ch441s16b.aac");
        }
        //打開wav文件
        if (!wr.OpenWavFile("test_music_1ch441s16b.wav"))
        {
            throw std::exception("open wav file fail,filename:test_music_1ch441s16b.wav");
        }
        while (1)
        {   //讀取wav中的pcm數(shù)據(jù)
            int size = wr.ReadData(buf, 2048);
            if (size < 1)
                break;
            //將pcm數(shù)據(jù)寫入編碼器
            fe.Write(buf, size);
        }
        printf("encode completed\n");
    }
    catch (std::exception e) {
        printf("%s\n", e.what());
    }
    catch (...) {
        printf("unknown errror\n");
    }
    if (f)
        fclose(f);
}

總結(jié)

以上就是今天要講的內(nèi)容,將編碼器設(shè)計(jì)成對象可以靈活的使用在項(xiàng)目中,尤其需要使用設(shè)計(jì)模式,比如原型模式:一個(gè)aac編碼器接口可以有不同的實(shí)現(xiàn)fdk-aac只是其中一種實(shí)現(xiàn),寫好的代碼可以隨意切換編碼器對象。或者策略模式,設(shè)計(jì)一個(gè)編碼器接口,調(diào)用時(shí)根據(jù)編碼格式選擇合適的編碼器。總的來說,這個(gè)對象的設(shè)計(jì)和實(shí)現(xiàn)不算特別難,就是在細(xì)節(jié)的地方需要注意,比如錯(cuò)誤提示,邊界值處理等。

以上就是C++使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac的詳細(xì)內(nèi)容,更多關(guān)于C++音頻編碼的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié)

    C語言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié)

    這篇文章主要介紹了C語言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié),分別介紹了rand()函數(shù)和srand()函數(shù)以及封裝出的arc4random()函數(shù),需要的朋友可以參考下
    2016-05-05
  • C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件算法操作總結(jié)

    C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件算法操作總結(jié)

    C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件提供了大量有用的算法,主要用于操作容器(如 vector, list, array 等),這些算法通常通過迭代器來操作容器元素,本文給大家介紹C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件算法總結(jié),感興趣的朋友一起看看吧
    2025-04-04
  • 《C++ primer plus》讀書筆記(三)

    《C++ primer plus》讀書筆記(三)

    本文是C++讀書筆記系列的第三篇,是讀完《C++ primer plus》一書第九、十兩章記錄下來的筆記,學(xué)習(xí)C++的同學(xué)可以看看參考下。
    2014-10-10
  • C++實(shí)現(xiàn)圖的遍歷算法(DFS,BFS)的示例代碼

    C++實(shí)現(xiàn)圖的遍歷算法(DFS,BFS)的示例代碼

    本文給大家?guī)淼氖菆D遍歷的算法,DFS(深度優(yōu)先遍歷),BFS(廣度優(yōu)先遍歷)。這兩個(gè)算法是比較重要和常用的算法,但是在圖中的實(shí)現(xiàn)只是最基本的操作,快跟隨小編一起學(xué)習(xí)一下吧
    2022-07-07
  • 詳解C語言的void*空指針

    詳解C語言的void*空指針

    這篇文章主要為大家詳細(xì)介紹了C語言的void*空指針,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 詳解C語言中結(jié)構(gòu)體(struct)的用法

    詳解C語言中結(jié)構(gòu)體(struct)的用法

    這篇文章主要為大家詳細(xì)介紹了C語言中結(jié)構(gòu)體(struct)的用法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2022-08-08
  • 基于Qt OpenCV的圖像灰度化像素操作詳解

    基于Qt OpenCV的圖像灰度化像素操作詳解

    這篇文章主要為大家詳細(xì)介紹了基于Qt+OpenCV的圖像灰度化像素操作:最大值法、平均法、加權(quán)平均值法,感興趣的小伙伴可以了解一下
    2022-07-07
  • 隨機(jī)數(shù)字去掉重復(fù)和排序的方法

    隨機(jī)數(shù)字去掉重復(fù)和排序的方法

    用計(jì)算機(jī)隨機(jī)生成了N個(gè)0到1000000000(包含0和1000000000)之間的隨機(jī)整數(shù)(N≤5000000),對于其中重復(fù)的數(shù)字,只保留一個(gè),把其余相同的數(shù)去掉。然后再把這些數(shù)從小到大排序。
    2013-03-03
  • C/C++?QT實(shí)現(xiàn)解析JSON文件的示例代碼

    C/C++?QT實(shí)現(xiàn)解析JSON文件的示例代碼

    JSON是一種輕量級(jí)的數(shù)據(jù)交換格式,它是基于ECMAScript的一個(gè)子集,使用完全獨(dú)立于編程語言的文本格式來存儲(chǔ)和表示數(shù)據(jù)。這篇文章主要介紹了QT實(shí)現(xiàn)解析JSON文件的示例代碼,需要的可以參考一下
    2022-01-01
  • 解決C++中事件不響應(yīng)的方法詳解

    解決C++中事件不響應(yīng)的方法詳解

    本篇文章是對C++事件不響應(yīng)的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評論