⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 foo_faac.cpp

📁 dsp上用c语言实现的aac音频算法的编解码器代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// FAAC encoder for foobar2000 diskwriter// Copyright (C) 2003 Janne Hyv鋜inen//// Changes://  0.4.2 (2003-12-14): Changed the gapless method again//  0.4.1 (2003-12-13): Added ctts field writing for MP4 mode//  0.4   (2003-12-11): Added support for average bitrate controlling//  0.3.5 (2003-10-17): Changed way gapless encoding is handled (iTunes is buggy...)//  0.3.4 (2003-10-14): Fixed AAC object type selecting//  0.3.3 (2003-10-02): Removed gapless support for raw AAC files, it was hacky and recent libfaad changes broke it//  0.3.2 (2003-09-17): Last fix wasn't perfect and very small input chunks wouldn't have been encoded//  0.3.1 (2003-09-14): Fixed possible memory access problems//  0.3   (2003-08-17): Even more corrections to MP4 writing, now encoder delay is taken into account and first MP4 sample is given length 0//                      writes 'TOOL' metadata tag with libfaac version string//  0.2.9 (2003-08-16): Fixes in MP4 writing//  0.2.8 (2003-08-16): Added silence padding at the end, new libfaac doesn't do it itself//  0.2.7 (2003-08-16): MP4 fixes, now MP4 header stores correct length//  0.2.6 (2003-08-16): MP4 writing uses correct length for last frame//  0.2.5 (2003-08-15): "libfaac flushing" added for 0.2.2 removed, foo_mp4 was cutting the end away incorrectly//  0.2.4 (2003-08-09): Added direct M4A writing and one new mode to bandwidth list//                      uses LFE mode with 6 channels//  0.2.3 (2003-08-08): Doesn't write tech info to APEv2 tags anymore//                      stores original file length now also for AAC//                      no longer limited to 32bit storage for length//                      changes to config//  0.2.2 (2003-08-07): Flushes libfaac now properly to get gapless playback//                      fixed bandwidth selecting issues in config//  0.2.1 (2003-08-07): Fixed MP4 writing//  0.2   (2003-08-07): Added MP4 creation and tagging, reorganized config//                      reports libfaac version in component info string//  0.1   (2003-08-06): First public version#include <mp4.h>#include "../SDK/foobar2000.h"#include "resource.h"#include <commctrl.h>#include <faac.h>#include <version.h>#define FOO_FAAC_VERSION     "0.4.2"#define FF_AAC  0#define FF_MP4  1#define FF_M4A  2#define FF_DEFAULT_OBJECTTYPE   LOW#define FF_DEFAULT_MIDSIDE      1#define FF_DEFAULT_TNS          0#define FF_DEFAULT_QUANTQUAL    100#define FF_DEFAULT_AVGBRATE     64#define FF_DEFAULT_CUTOFF       -1#define FF_DEFAULT_MP4CONTAINER FF_MP4#define FF_DEFAULT_USE_QQ       1#define FF_DEFAULT_USE_AB       0static cfg_int cfg_objecttype ( "objecttype", FF_DEFAULT_OBJECTTYPE );static cfg_int cfg_midside ( "midside", FF_DEFAULT_MIDSIDE );static cfg_int cfg_tns ( "tns", FF_DEFAULT_TNS );static cfg_int cfg_quantqual ( "quantqual", FF_DEFAULT_QUANTQUAL );static cfg_int cfg_avgbrate ( "avgbrate", FF_DEFAULT_AVGBRATE );static cfg_int cfg_cutoff ( "cutoff", FF_DEFAULT_CUTOFF );static cfg_int cfg_mp4container ( "mp4container", FF_DEFAULT_MP4CONTAINER );static cfg_int cfg_use_qq ( "use_qq", FF_DEFAULT_USE_QQ );static cfg_int cfg_use_ab ( "use_ab", FF_DEFAULT_USE_AB );DECLARE_COMPONENT_VERSION ( "FAAC encoder", FOO_FAAC_VERSION, "Uses libfaac version " FAAC_VERSION );class diskwriter_faac : public diskwriter {private:    // mp4    MP4FileHandle MP4hFile;    MP4TrackId MP4track;    // faac    faacEncHandle hEncoder;    faacEncConfigurationPtr myFormat;    unsigned int objectType;    unsigned int useMidSide;    unsigned int useTns;    int cutOff;    int bitRate;    unsigned long quantqual;    int use_qq, use_ab;    int create_mp4;    reader *m_reader;    mem_block_t<unsigned char> bitbuf;    mem_block_t<float> floatbuf;    unsigned long samplesInput, maxBytesOutput;    int *chanmap;    unsigned int bufferedSamples;    unsigned int frameSize;    string8 path;    file_info_i_full info;    unsigned int srate, nch, bps;    __int64 total_samples, encoded_samples, delay_samples;    bool encode_error;public:    diskwriter_faac()    {        objectType = cfg_objecttype;        useMidSide = cfg_midside;        useTns = cfg_tns;        cutOff = cfg_cutoff;        bitRate = cfg_avgbrate * 1000;        quantqual = cfg_quantqual;        use_qq = cfg_use_qq;        use_ab = cfg_use_ab;        hEncoder = 0;        myFormat = 0;        MP4hFile = 0;        MP4track = 0;        create_mp4 = cfg_mp4container;        m_reader = 0;    }    ~diskwriter_faac()    {        if ( m_reader ) m_reader->reader_release();    }    virtual const char *get_name() { return "AAC"; }    virtual const char *get_extension()    {        switch ( create_mp4 ) {        case FF_MP4:        default:            return "mp4";        case FF_M4A:            return "m4a";        case FF_AAC:            return "aac";        }    }            virtual int open ( const char *filename, metadb_handle *src_file )    {        if ( m_reader ) return 0;        encode_error = false;        path = filename;        if ( src_file ) src_file->handle_query ( &info ); else info.reset();        console::info ( "AAC encoding with FAAC version " FAAC_VERSION );        console::info ( string_printf ("Source file: %s", (const char *)info.get_file_path()) );        console::info ( string_printf ("Destination file: %s", (const char *)path) );        if ( path.is_empty() ) {            console::error ( "No destination name" );            return 0;        }        m_reader = file::g_open ( path, reader::MODE_WRITE_NEW );        if ( !m_reader ) {            console::error ( "Can't write to destination" );            return 0;        }        return 1;    }                    virtual int process_samples ( const audio_chunk *src )    {        if ( encode_error ) return 0;        if ( !hEncoder ) {            encode_error = true;            nch = src->get_channels();            srate = src->get_srate();            // get faac version            hEncoder = faacEncOpen ( 44100, 2, &samplesInput, &maxBytesOutput );            myFormat = faacEncGetCurrentConfiguration ( hEncoder );            if ( myFormat->version == FAAC_CFG_VERSION ) {                //console::info ( string_printf ("libfaac version %s", (const char *)myFormat->name) );                faacEncClose ( hEncoder );            } else {                console::error ( "Wrong libfaac version" );                faacEncClose ( hEncoder );                hEncoder = 0;                return 0;            }            // open the encoder library            hEncoder = faacEncOpen ( srate, nch, &samplesInput, &maxBytesOutput );            bufferedSamples = 0;            frameSize = samplesInput / nch;            total_samples = 0;            encoded_samples = 0;            delay_samples = frameSize;            bitbuf.check_size ( maxBytesOutput );            floatbuf.check_size ( samplesInput );            chanmap = mkChanMap ( nch, 3/*chanC*/, 4/*chanLF*/ );            if ( cutOff <= 0 ) {                if ( cutOff < 0 ) {                    cutOff = 0;                } else {                    cutOff = srate / 2;                }            }            if ( (unsigned)cutOff > (srate / 2) ) cutOff = srate / 2;            // put the options in the configuration struct            myFormat = faacEncGetCurrentConfiguration ( hEncoder );            myFormat->aacObjectType = objectType;            myFormat->mpegVersion = (create_mp4 || objectType == LTP) ? MPEG4 : MPEG2;            myFormat->useLfe = (nch == 6) ? 1 : 0;            myFormat->useTns = useTns;            myFormat->allowMidside = useMidSide;            if ( use_ab ) myFormat->bitRate = bitRate;            myFormat->bandWidth = cutOff;            if ( use_qq ) myFormat->quantqual = quantqual;            myFormat->outputFormat = create_mp4 ? 0 : 1;            myFormat->inputFormat = FAAC_INPUT_FLOAT;            if ( !faacEncSetConfiguration (hEncoder, myFormat) ) {                console::error ( "Unsupported output format" );                return 0;            }            // initialize MP4 creation            if ( create_mp4 ) {                MP4hFile = MP4CreateCb ( 0, 0, 0, open_cb, close_cb, read_cb, write_cb, setpos_cb, getpos_cb, filesize_cb, (void *)m_reader );                if ( MP4hFile == MP4_INVALID_FILE_HANDLE ) {                    console::error ( "MP4Create() failed" );                    return 0;                }                MP4SetTimeScale ( MP4hFile, 90000 );                MP4track = MP4AddAudioTrack ( MP4hFile, srate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE );                MP4SetAudioProfileLevel ( MP4hFile, 0x0F );                unsigned char *ASC = 0;                unsigned long ASCLength = 0;                faacEncGetDecoderSpecificInfo(hEncoder, &ASC, &ASCLength);                MP4SetTrackESConfiguration ( MP4hFile, MP4track, (u_int8_t *)ASC, ASCLength );            }            cutOff = myFormat->bandWidth;            quantqual = myFormat->quantqual;            bitRate = myFormat->bitRate;            if ( bitRate > 0 ) {                console::info ( string_printf ("Using quantizer quality %i and average bitrate of %i kbps per channel", quantqual, bitRate/1000) );            } else {                console::info ( string_printf ("Using quantizer quality %i and no average bitrate control", quantqual, bitRate) );            }            encode_error = false;        }        if ( srate != src->get_srate() || nch != src->get_channels() ) return 0;        {            unsigned int samples = src->get_sample_count() * nch;            const audio_sample *s = src->get_data();            do {                unsigned int num = (samples+bufferedSamples < samplesInput) ? samples+bufferedSamples : samplesInput;                if ( num == 0 ) break;                float *d = (float *)floatbuf.get_ptr() + bufferedSamples;                for ( unsigned int i = bufferedSamples; i < num; i++ ) {                    *d++ = (float)((*s++) * 32768.);                    bufferedSamples++;                    samples--;                }                if ( bufferedSamples == samplesInput ) {                    if ( nch >= 3 && chanmap ) {                        chan_remap ( (int *)floatbuf.get_ptr(), nch, frameSize, chanmap );                    }                    // call the actual encoding routine                    int bytesWritten = faacEncEncode ( hEncoder, (int32_t *)floatbuf.get_ptr(), samplesInput, bitbuf.get_ptr(), maxBytesOutput );                    bufferedSamples = 0;                    if ( bytesWritten < 0 ) {                        console::error ( "faacEncEncode() failed" );                        return 0;                    }                    if ( bytesWritten > 0 ) {                        MP4Duration dur = frameSize;                        MP4Duration ofs = 0;                        if ( delay_samples > 0 ) {                            dur = 0;                            ofs = delay_samples;                            delay_samples -= frameSize;                        }                        if ( create_mp4 ) {                            MP4WriteSample ( MP4hFile, MP4track, (const unsigned __int8 *)bitbuf.get_ptr(), bytesWritten, frameSize, ofs );                        } else {                            m_reader->write ( bitbuf.get_ptr(), bytesWritten );                        }                        encoded_samples += dur;                    }                }            } while ( bufferedSamples == 0 );        }        total_samples += src->get_sample_count();        return 1;    }    virtual void flush()    {        if ( hEncoder ) {            if ( nch >= 3 && chanmap ) {                chan_remap ( (int *)floatbuf.get_ptr(), nch, bufferedSamples/nch, chanmap );            }            __int64 samples_left = total_samples - encoded_samples;            while ( samples_left > 0 ) {                if ( !bufferedSamples ) {                    bufferedSamples = samplesInput;                    memset ( floatbuf.get_ptr(), 0, samplesInput * sizeof(float) );                }                int bytesWritten = faacEncEncode ( hEncoder, (int32_t *)floatbuf.get_ptr(), bufferedSamples, bitbuf.get_ptr(), maxBytesOutput );                bufferedSamples = 0;                if ( bytesWritten < 0 ) {                    console::error ( "faacEncEncode() failed" );                    break;                }                else if ( bytesWritten > 0 ) {                    MP4Duration dur = samples_left > frameSize ? frameSize : samples_left;                    if ( create_mp4 ) {                        MP4WriteSample ( MP4hFile, MP4track, (const unsigned __int8 *)bitbuf.get_ptr(), bytesWritten, dur );                    } else {                        m_reader->write ( bitbuf.get_ptr(), bytesWritten );                    }                    samples_left -= frameSize;                }            }            faacEncClose ( hEncoder );            hEncoder = 0;        }        if ( m_reader ) {            bool success = !encode_error && (m_reader->get_length() > 0);            if ( success ) {                write_tag();                console::info ( "Encoding finished successfully" );            }            if ( create_mp4 ) {                MP4Close ( MP4hFile );                MP4hFile = 0;            }            m_reader->reader_release();            m_reader = 0;            if ( !success ) {                console::info ( "Encoding failed" );                file::g_remove ( path );            }        }    }    virtual const char *get_config_page_name() { return "FAAC encoder"; }private:    int write_tag()    {        info.info_remove_all();        if ( !create_mp4 ) {            return tag_writer::g_run ( m_reader, &info, "ape" );        } else {            MP4SetMetadataTool ( MP4hFile, "libfaac version " FAAC_VERSION );            for ( int i = 0; i < info.meta_get_count(); i++ ) {                char *pName = (char *)info.meta_enum_name ( i );                const char *val = info.meta_enum_value ( i );                if ( !val || (val && !(*val)) ) continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -