diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index b2a6e12..312a6aa 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -26,4 +26,5 @@ add_subdirectory(libhv/libhv-1.3.2) add_subdirectory(ffmpeg) add_subdirectory(fdk-aac) # ================= ffmpeg related end ================= # -add_subdirectory(libconfig) \ No newline at end of file +add_subdirectory(libconfig) +add_subdirectory(libfaac) \ No newline at end of file diff --git a/external/libfaac/CMakeLists.txt b/external/libfaac/CMakeLists.txt new file mode 100755 index 0000000..76de15b --- /dev/null +++ b/external/libfaac/CMakeLists.txt @@ -0,0 +1,12 @@ +include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${EXTERNAL_LIBS_OUTPUT_PATH}) +INCLUDE_DIRECTORIES(libfaac) +INCLUDE_DIRECTORIES(./) + +AUX_SOURCE_DIRECTORY(. MODULE_SRC) +AUX_SOURCE_DIRECTORY(libfaac MODULE_SRC) + +ADD_LIBRARY(faac STATIC ${MODULE_SRC}) + + diff --git a/external/libfaac/G711AToPcm.cpp b/external/libfaac/G711AToPcm.cpp new file mode 100644 index 0000000..92815ab --- /dev/null +++ b/external/libfaac/G711AToPcm.cpp @@ -0,0 +1,31 @@ + +#include "G711AToPcm.h" + +#include "g711.h" + + +G711AToPcm::G711AToPcm(void) +{ +} + + +G711AToPcm::~G711AToPcm(void) +{ +} +unsigned short G711AToPcm::DecodeOneChar(unsigned char data) +{ + return (int16_t)alaw2linear(data); +} +//------------------------------------------- +G711UToPcm::G711UToPcm(void) +{ +} + + +G711UToPcm::~G711UToPcm(void) +{ +} +unsigned short G711UToPcm::DecodeOneChar(unsigned char data) +{ + return (int16_t)ulaw2linear(data); +} diff --git a/external/libfaac/G711AToPcm.h b/external/libfaac/G711AToPcm.h new file mode 100644 index 0000000..d975667 --- /dev/null +++ b/external/libfaac/G711AToPcm.h @@ -0,0 +1,24 @@ + +#pragma once +#include "IDecodeToPcm.h" + +class G711AToPcm : + public DecodeToPcmBase +{ +public: + G711AToPcm(void); + virtual ~G711AToPcm(void); +public: + virtual unsigned short DecodeOneChar(unsigned char data); +}; + + +class G711UToPcm : + public DecodeToPcmBase +{ +public: + G711UToPcm(void); + virtual ~G711UToPcm(void); +public: + virtual unsigned short DecodeOneChar(unsigned char data); +}; diff --git a/external/libfaac/IDecodeToPcm.cpp b/external/libfaac/IDecodeToPcm.cpp new file mode 100644 index 0000000..2dbeedc --- /dev/null +++ b/external/libfaac/IDecodeToPcm.cpp @@ -0,0 +1,90 @@ + +#include "IDecodeToPcm.h" +#include "audio_buffer.h" +#include +#include +#include +#include + + +IDecodeToPcm::IDecodeToPcm(void) +{ +} + + +IDecodeToPcm::~IDecodeToPcm(void) +{ + +} +//------------------------------------------------------------------------------------------------------------------------ +InAudioInfo::InAudioInfo() +{ + InitParam& initParam = m_initparam; + initParam.u32AudioSamplerate=8000; + initParam.ucAudioChannel=1; + initParam.u32PCMBitSize=16; + initParam.ucAudioCodec = Law_ALaw; +} +InAudioInfo::InAudioInfo(InitParam param):m_initparam(param) +{ + +} +//------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------- +DecodeToPcmBase::DecodeToPcmBase(void) +{ + +} + + +DecodeToPcmBase::~DecodeToPcmBase(void) +{ + +} + +int DecodeToPcmBase::Init(InAudioInfo info) +{ + m_g7FrameSize = G711_ONE_LEN; + return 0; +} +int DecodeToPcmBase::PCMSize() +{ + return CON_PCM_SIZE; +} +int DecodeToPcmBase::G7FrameSize() +{ + return m_g7FrameSize; +} +int DecodeToPcmBase::Decode(unsigned char* pout_buf, unsigned int* pout_len , unsigned char* pin_buf, unsigned int in_len) +{ + int16_t *dst = (int16_t *) pout_buf; + uint8_t *src = (uint8_t *) pin_buf; + uint32_t i = 0; + int Ret = 0; + + if ((NULL == pout_buf) || \ + (NULL == pout_len) || \ + (NULL == pin_buf) || \ + (0 == in_len)) + { + return -1; + } + + if (*pout_len < 2 * in_len) + { + return -2; + } + //---{{{ + + for (i = 0; i < in_len; i++) + { + *(dst++) = (int16_t)DecodeOneChar(*(src++)); + } + + //---}}} + *pout_len = 2 * in_len; + + Ret = 2 * in_len; + return Ret; + return 0; +} diff --git a/external/libfaac/IDecodeToPcm.h b/external/libfaac/IDecodeToPcm.h new file mode 100644 index 0000000..a10462c --- /dev/null +++ b/external/libfaac/IDecodeToPcm.h @@ -0,0 +1,100 @@ + +#pragma once + +#ifndef _IDECODETOPCM_H +#define _IDECODETOPCM_H + +#include "MtAACEncoderAPI.h" + +#define USE_SHOUT_G711PACK 1 + +#if USE_SHOUT_G711PACK +#define G711_ONE_LEN 160 +#define G711_ONE_OFFSET 0 + +#else +#define G711_ONE_LEN 164 +#define G711_ONE_OFFSET 4 +#endif + +const int CON_PCM_SIZE = 320; + +class audio_buffer; + +class InAudioInfo +{ +public: + InAudioInfo(); + InAudioInfo(InitParam param); + ~InAudioInfo(){;} + + unsigned int CodecType() + { + return m_initparam.ucAudioCodec; + //return m_u32AudioCodec; + } + unsigned int Samplerate() + { + return m_initparam.u32AudioSamplerate; + //return m_u32AudioSamplerate; + } + unsigned int Channel() + { + return m_initparam.ucAudioChannel; + //return m_u32AudioChannel; + } + unsigned int PCMBitSize() + { + return m_initparam.u32PCMBitSize; + //return m_nPCMBitSize; + } + unsigned char G726RateBits() + { + return m_initparam.g726param.ucRateBits; + } +private: + unsigned int m_u32AudioCodec; + unsigned int m_u32AudioSamplerate; + unsigned int m_u32AudioChannel; + + unsigned int m_nPCMBitSize; + + InitParam m_initparam; +}; +//---------------------------------------------------------- +class IDecodeToPcm +{ +public: + IDecodeToPcm(void); + virtual ~IDecodeToPcm(void); + +public: + virtual int Init(InAudioInfo info)=0; + virtual int Decode( unsigned char* outbuf, unsigned int* outlen , unsigned char* inbuf, unsigned int inlen)=0; + virtual int PCMSize()=0; + virtual int G7FrameSize()=0; +}; +//---------------------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------------------------- +class DecodeToPcmBase:public IDecodeToPcm +{ +public: + DecodeToPcmBase(); + virtual ~DecodeToPcmBase(); + + int Init(InAudioInfo info); + +public: + virtual int Decode(unsigned char* outbuf, unsigned int* outlen , unsigned char* inbuf, unsigned int inlen); + virtual int PCMSize(); + virtual int G7FrameSize(); + + virtual unsigned short DecodeOneChar(unsigned char data)=0; + +private: + int m_g7FrameSize; +}; + +#endif + diff --git a/external/libfaac/MtAACEncoder.cpp b/external/libfaac/MtAACEncoder.cpp new file mode 100644 index 0000000..30e9bb7 --- /dev/null +++ b/external/libfaac/MtAACEncoder.cpp @@ -0,0 +1,190 @@ + +#include +#include +#include +#include + +#include "MtAACEncoder.h" +#include "MtAACEncoderAPI.h" +#include "outDebug.h" +#include "G711AToPcm.h" +#include "condef.h" + +G7ToAac::G7ToAac() +{ + m_pbPCMBuffer = NULL; + m_pbAACBuffer = NULL; + m_pbG7FrameBuffer = NULL; + m_pbPCMTmpBuffer = NULL; + m_audio_buffer_ = NULL; + m_pDecodeToPcm = NULL; + m_pPCMToAAC = NULL; +} + +G7ToAac::~G7ToAac() +{ + /*free the source of malloc*/ + SAFE_FREE_BUF(m_pbPCMBuffer); + SAFE_FREE_BUF(m_pbAACBuffer); + SAFE_FREE_BUF(m_pbG7FrameBuffer); + SAFE_FREE_BUF(m_pbPCMTmpBuffer); + + SAFE_DELETE_OBJ(m_audio_buffer_); + SAFE_DELETE_OBJ(m_pDecodeToPcm); + SAFE_DELETE_OBJ(m_pPCMToAAC); +} +bool G7ToAac::init() +{ + nRet = 0; + nTmp = 0; + nCount = 0; + nStatus = 0; + nPCMRead = 0; + + CreateBuffer(); + return true; +} + +bool G7ToAac::init(InAudioInfo info) +{ + m_inAudioInfo = info; + + bool ret=false; + ret = CreateDecodePcm(); + + ret = CreateEncodeAac(); + if (!ret) + { + return false; + } + return init(); +} +bool G7ToAac::CreateDecodePcm() +{ + if ( Law_ALaw == m_inAudioInfo.CodecType()) + { + m_pDecodeToPcm = new G711AToPcm(); + }else if ( Law_ULaw == m_inAudioInfo.CodecType() ) + { + m_pDecodeToPcm = new G711UToPcm(); + } + else + { + m_pDecodeToPcm = new G711AToPcm(); + } + m_pDecodeToPcm->Init(m_inAudioInfo); + + return true; +} +bool G7ToAac::CreateEncodeAac() +{ + m_pPCMToAAC = new PcmToAac(); + bool ret = m_pPCMToAAC->Init(&m_inAudioInfo); + + return ret; +} +bool G7ToAac::CreateBuffer() +{ + m_nPCMBufferSize = m_pPCMToAAC->GetPCMBufferSize(); + m_pbPCMBuffer = (unsigned char*) malloc(m_nPCMBufferSize * sizeof (unsigned char)); + memset(m_pbPCMBuffer, 0, m_nPCMBufferSize); + + m_nMaxOutputBytes = m_pPCMToAAC->GetMaxOutputBytes(); + m_pbAACBuffer = (unsigned char*) malloc(m_nMaxOutputBytes * sizeof (unsigned char)); + memset(m_pbAACBuffer, 0, m_nMaxOutputBytes); + + m_nG7FrameBufferSize = m_pDecodeToPcm->G7FrameSize(); + m_pbG7FrameBuffer = (unsigned char *) malloc(m_nG7FrameBufferSize * sizeof (unsigned char)); + memset(m_pbG7FrameBuffer, 0, m_nG7FrameBufferSize); + + m_nPCMSize = m_pDecodeToPcm->PCMSize(); + m_pbPCMTmpBuffer = (unsigned char *) malloc(m_nPCMSize * sizeof (unsigned char)); + memset(m_pbPCMTmpBuffer, 0, m_nPCMSize); + + m_audio_buffer_ = new audio_buffer(); + + return true; +} +int G7ToAac::aac_encode(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen) +{ + int encodeLen = 0; + + if (NULL != m_pDecodeToPcm) + { + encodeLen = aac_encode_obj(inbuf , inlen , outbuf , outlen); + } + + return encodeLen; +} + +int G7ToAac::aac_encode_obj(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen ) +{ + m_audio_buffer_->write_data(inbuf, inlen); + int buffer_len = 0; + *outlen = 0; + int nPCMSize = 0; + //while ((buffer_len = audio_buffer_->get_data(pbG711ABuffer, /*164*/G711_ONE_LEN)) > 0) + while ((buffer_len = m_audio_buffer_->get_data(m_pbG7FrameBuffer, m_nG7FrameBufferSize)) > 0) + { + if (buffer_len <= 0) + { + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM no G711 data !\n", __FUNCTION__, __LINE__); + //Sleep(100); + return -1; + } + + nStatus = 0; + memset(m_pbPCMTmpBuffer, 0, m_nPCMSize); + nPCMSize = m_nPCMSize; + //if ((nPCMRead = m_pDecodeToPcm->Decode(pbPCMTmpBuffer, (unsigned int*)&PCMSize, pbG711ABuffer+/*4*/G711_ONE_OFFSET, buffer_len-/*4*/G711_ONE_OFFSET )) < 0) // TODO: skip 4 byte? + if ((nPCMRead = m_pDecodeToPcm->Decode(m_pbPCMTmpBuffer, (unsigned int*)&nPCMSize, m_pbG7FrameBuffer, buffer_len )) < 0) // TODO: skip 4 byte? + { + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM failed buffer_len = %d !\n", __FUNCTION__, __LINE__, buffer_len); + return -1; + } + //if(AAC_DEBUG) printf("nPCMRead = %d, PCMSize = %d\n", nPCMRead, PCMSize); + + if ((m_nPCMBufferSize - nCount) < nPCMRead) + { + //if(AAC_DEBUG) printf("nPCMBufferSize = %d, nCount = %d, nPCMRead = %d\n", nPCMBufferSize, nCount, nPCMRead); + nStatus = 1; + memset(m_pbAACBuffer, 0, m_nMaxOutputBytes); + memcpy(m_pbPCMBuffer + nCount, m_pbPCMTmpBuffer, (m_nPCMBufferSize - nCount)); + + nRet = m_pPCMToAAC->Encode( (int32_t*)m_pbPCMBuffer , m_nPCMBufferSize , m_pbAACBuffer, m_nMaxOutputBytes); + + + memcpy(outbuf + *outlen, m_pbAACBuffer, nRet); + *outlen += nRet; + + nTmp = nPCMRead - (m_nPCMBufferSize - nCount); + memset(m_pbPCMBuffer, 0, m_nPCMBufferSize); + memcpy(m_pbPCMBuffer, m_pbPCMTmpBuffer + (m_nPCMBufferSize - nCount), nTmp); + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM (nPCMBufferSize - nCount) < nPCMRead\n", __FUNCTION__, __LINE__); + nCount = 0; + nCount += nTmp; + } + + if (nStatus == 0) + { + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM nStatus = 0...\n", __FUNCTION__, __LINE__); + memcpy(m_pbPCMBuffer + nCount, m_pbPCMTmpBuffer, nPCMRead); + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM nStatus = 0\n", __FUNCTION__, __LINE__); + nCount += nPCMRead; + } + + if (nPCMRead < /*320*/CON_PCM_SIZE) + { + if(AAC_DEBUG) printf("nPCMRead = %d\n", nPCMRead); + + nRet = m_pPCMToAAC->Encode((int*) m_pbPCMBuffer, nCount , m_pbAACBuffer, m_nMaxOutputBytes); + + + memcpy(outbuf + *outlen, m_pbAACBuffer, nRet); + *outlen += nRet; + + INFO_D(AAC_DEBUG , "G711A -> PCM nPCMRead < 320"); + } + } + return *outlen; +} diff --git a/external/libfaac/MtAACEncoder.h b/external/libfaac/MtAACEncoder.h new file mode 100644 index 0000000..23d53a2 --- /dev/null +++ b/external/libfaac/MtAACEncoder.h @@ -0,0 +1,55 @@ +#ifndef MtAACEncoder_H +#define MtAACEncoder_H + +#include "audio_buffer.h" +#include "IDecodeToPcm.h" +#include "PcmToAac.h" + +class G7ToAac +{ +public: + G7ToAac(); + virtual ~G7ToAac(); + + bool init(); + bool init(InAudioInfo info); + + int aac_encode(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen); + +private: + int aac_encode_obj(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen ); + + bool CreateDecodePcm(); + bool CreateEncodeAac(); + bool CreateBuffer(); +private: + int nRet; + int nTmp; + int nCount; + int nStatus; + int nPCMRead; + + + + int m_nPCMBufferSize; + unsigned char *m_pbPCMBuffer; + + unsigned long m_nMaxOutputBytes; + unsigned char *m_pbAACBuffer; + + int m_nPCMSize; + unsigned char *m_pbPCMTmpBuffer; + + unsigned char *m_pbG7FrameBuffer; + unsigned long m_nG7FrameBufferSize; + + audio_buffer *m_audio_buffer_; + //------ + InAudioInfo m_inAudioInfo; + + IDecodeToPcm* m_pDecodeToPcm; + PcmToAac* m_pPCMToAAC; +}; + +#endif /* MtAACEncoder_H */ + diff --git a/external/libfaac/MtAACEncoderAPI.cpp b/external/libfaac/MtAACEncoderAPI.cpp new file mode 100644 index 0000000..fe44dfe --- /dev/null +++ b/external/libfaac/MtAACEncoderAPI.cpp @@ -0,0 +1,34 @@ +#include "MtAACEncoderAPI.h" +#include "MtAACEncoder.h" +#include "condef.h" + +Mt_API MtAACEncoder_Handle Mt_APICALL Mt_AACEncoder_Init(InitParam initPar) +{ + G7ToAac *encoder = new G7ToAac(); + InAudioInfo info(initPar ); + bool ret = encoder->init(info); + if (!ret) + { + SAFE_DELETE_OBJ(encoder); + } + return encoder; +} + +Mt_API int Mt_APICALL Mt_AACEncoder_Encode(MtAACEncoder_Handle handle, unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen) +{ + if(handle == NULL) + { + return -1; + } + return ((G7ToAac*)handle)->aac_encode(inbuf, inlen, outbuf, outlen); +} + +Mt_API void Mt_APICALL Mt_AACEncoder_Release(MtAACEncoder_Handle handle) +{ + if(handle != NULL) + { + delete ((G7ToAac*)handle); + } +} + + diff --git a/external/libfaac/MtAACEncoderAPI.h b/external/libfaac/MtAACEncoderAPI.h new file mode 100644 index 0000000..95c5060 --- /dev/null +++ b/external/libfaac/MtAACEncoderAPI.h @@ -0,0 +1,75 @@ + +#ifndef MtAACEncoder_API_H +#define MtAACEncoder_API_H + +#ifdef _WIN32 +#define Mt_API __declspec(dllexport) +#define Mt_APICALL __stdcall +#else +#define Mt_API +#define Mt_APICALL +#endif + +#define Mt_Handle void* +#define MtAACEncoder_Handle void* + +///* Audio Codec */ +enum Law +{ + Law_ULaw = 0, /**< U law */ + Law_ALaw = 1, /**< A law */ + Law_PCM16 = 2, /**< 16 bit uniform PCM values. 原始 pcm 数据 */ + Law_G726 = 3 /**< G726 */ +}; + +///* Rate Bits */ +enum Rate +{ + Rate16kBits=2, /**< 16k bits per second (2 bits per ADPCM sample) */ + Rate24kBits=3, /**< 24k bits per second (3 bits per ADPCM sample) */ + Rate32kBits=4, /**< 32k bits per second (4 bits per ADPCM sample) */ + Rate40kBits=5 /**< 40k bits per second (5 bits per ADPCM sample) */ +}; + +typedef struct _g711param +{ + ; +}G711Param; + +typedef struct _g726param +{ + unsigned char ucRateBits;//Rate16kBits Rate24kBits Rate32kBits Rate40kBits +}G726Param; + +typedef struct _initParam +{ + unsigned char ucAudioCodec; // Law_uLaw Law_ALaw Law_PCM16 Law_G726 + unsigned char ucAudioChannel; //1 + unsigned int u32AudioSamplerate; //8000 + unsigned int u32PCMBitSize; //16 + union + { + G711Param g711param; + G726Param g726param; + }; + +}InitParam; + +#ifdef __cplusplus +extern "C" +{ +#endif + /* 创建AAC Encoder 返回为句柄值 */ + Mt_API MtAACEncoder_Handle Mt_APICALL Mt_AACEncoder_Init(InitParam initPar); + + /* 输入编码数据,返回编码后数据 */ + Mt_API int Mt_APICALL Mt_AACEncoder_Encode(MtAACEncoder_Handle handle, unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen); + + /* 释放AAC Encoder */ + Mt_API void Mt_APICALL Mt_AACEncoder_Release(MtAACEncoder_Handle handle); + +#ifdef __cplusplus +} +#endif + +#endif /* MtAACEncoder_API_H */ diff --git a/external/libfaac/MtDSSBuffers.cpp b/external/libfaac/MtDSSBuffers.cpp new file mode 100644 index 0000000..a219106 --- /dev/null +++ b/external/libfaac/MtDSSBuffers.cpp @@ -0,0 +1,106 @@ +#include "MtDSSBuffers.h" + +int init_buffers(buffers_t * bufs, int bufsize, int bufnum) +{ + int i; + bufs->rear = 0; + bufs->front = 0; + if(bufnum > MAX_BUF_NUM) + { + bufs->bufnum = MAX_BUF_NUM; + } + else + { + bufs->bufnum = bufnum; + } + for(i = 0; i < bufs->bufnum; i++) + { + bufs->buf[i].length = 0; + bufs->buf[i].start = (char *) calloc(1, bufsize); + bufs->buf[i].frame_type = -1; + bufs->buf[i].channel = -1; + bufs->buf[i].frame_index = 0; + if(bufs->buf[i].start == NULL) + return -1; + } +#ifdef WIN32 + InitializeCriticalSection(&(bufs->cs)); +#else + InitializeCriticalSection(&(bufs->cs), NULL); +#endif + return 0; +} + +int free_buffers(buffers_t* bufs) +{ + for(int i = 0; i < bufs->bufnum; i++) + { + if(bufs->buf[i].start != NULL) + free(bufs->buf[i].start); + } + bufs->pOnVideoData = NULL; + DeleteCriticalSection(&(bufs->cs)); + return 0; +} + +int buffers_get_data(void *data, unsigned int *length, buffers_t * bufs, int *type, + int *channel, int *frame_index) +{ + int res = -1; + EnterCriticalSection(&(bufs->cs)); + if(bufs->front != bufs->rear) + { + res = *length = bufs->buf[bufs->front].length; + memcpy(data, bufs->buf[bufs->front].start, *length); + *type = bufs->buf[bufs->front].frame_type; + *channel = bufs->buf[bufs->front].channel; + *frame_index = bufs->buf[bufs->front].frame_index; + bufs->front = (bufs->front + 1) % bufs->bufnum; + //res = 1; + } + LeaveCriticalSection(&(bufs->cs)); + return res; +} + +int buffers_put_data(void *data, unsigned int length, buffers_t * bufs, int type, + int channel, int frame_index) +{ + int res = 0; + EnterCriticalSection(&(bufs->cs)); + + if(((bufs->rear + 1) % bufs->bufnum) == bufs->front) + { + res = -1; + } + else + { + bufs->buf[bufs->rear].length = length; + bufs->buf[bufs->rear].frame_type = type; + bufs->buf[bufs->rear].channel = channel; + bufs->buf[bufs->rear].frame_index = frame_index; + if(length < iBufLen) + { + memcpy(bufs->buf[bufs->rear].start, data, length); + } + else + { + //WriteSystemLog("DataRecv.log", "Frame is too large"); + printf("Frame is too large, length=%d\r\n", length); + } + bufs->rear = (bufs->rear + 1) % bufs->bufnum; + res = 1; + } + + LeaveCriticalSection(&(bufs->cs)); + return res; +} + +void buffers_clear_data(buffers_t * bufs) +{ + EnterCriticalSection(&(bufs->cs)); + bufs->rear = 0; + bufs->front = 0; + LeaveCriticalSection(&(bufs->cs)); +} + + diff --git a/external/libfaac/MtDSSBuffers.h b/external/libfaac/MtDSSBuffers.h new file mode 100644 index 0000000..e1cbcdd --- /dev/null +++ b/external/libfaac/MtDSSBuffers.h @@ -0,0 +1,170 @@ + +#ifndef _EasyDSSBuffers_H_ +#define _EasyDSSBuffers_H_ + +#define _CRT_SECURE_NO_WARNINGS + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif +#include +#include +#include +#include + +#include +#if (defined(_WIN32)) //windows +//#define WIN32 +#ifndef DLL_EXPORT +#define JD_API extern "C"__declspec(dllimport) +#else +#define JD_API extern "C"__declspec(dllexport) +#endif +#elif defined(__linux__) //linux +#define __stdcall +#define CALLBACK +#define JD_API extern "C" +#define WINAPI +typedef int HANDLE; +typedef int HWND; +#endif + +#ifdef _WIN32 +#include +#endif +#include +#include +#include + +using namespace std; + +#define PFRAME 0x00 +#define IFRAME 0x01 + +const int iBufLen = 1024 * 128; +const int iRecvBufLen = iBufLen * 2; +const int iMaxParamterNum = 128; +const int iBufNum = 10; +const int MAX_BUF_NUM = 50; +const int iCharBufLen = 64; +const char BoundTag[] = "\r\n"; //甯ч棿闅旀爣璇 +const int BoundTagLen = sizeof (BoundTag) - 1; //甯ч棿闅旀爣璇嗛暱搴 +//const char IFrameTag[] = "HISI264I";//褰曞儚I甯ф爣蹇 +//const char PFrameTag[] = "HISI264P";//褰曞儚P甯ф爣蹇 +//const int FrameTagLen = sizeof(IFrameTag) - 1;// 褰曞儚甯ф爣蹇楅暱搴 + +const int MaxWaitTime = 3000; //瓒呮椂鏃堕棿 +const int MaxCameraNum = 24; //鏈澶ф憚鍍忔満鏁伴噺 + +const int AUDIO_BUFFER_SIZE = 960; //瀹氫箟鎾斁鐨勬瘡涓鐗囩紦鍐查兘鏄800涓瓧鑺 +const int MAX_AUDIO_BUF = 4; //鎾斁缂撳啿鐨勯氱煡绱㈠紩 +const int BUFFERNOTIFYSIZE = AUDIO_BUFFER_SIZE;/*8192*//*192000*/ //缂撳啿閫氱煡浣嶇疆鐨勫ぇ灏忥紝璇峰弬瑙丏irectSound搴旂敤绋嬪簭寮鍙戝揩閫熷叆闂 +const int SAMPLE_RATE = 8000;/*44100*/ //pcm 鐨勯噰鏍风巼 8k +const int N_CHANNEL = 1;/*2*/ //PCM 澹伴亾鏁 鍗曢氶亾 +const int BITS_PER_SAMPLE = 16; //姣忎釜閲囨牱鐐圭殑姣旂壒鏁 +const int CHANNEL = 1; +const int SAMPLES_PER_SECOND = 8000; +const int SIZE_AUDIO_FRAME = 960; + +#ifdef WIN32 +const GUID GUID_YUY2 = {0xc68e1552, 0x4a3f, 0x4706, + {0xb2, 0xd4, 0x83, 0x41, 0x4f, 0x15, 0xdc, 0xcc}}; +//typedef char int8_t; +//typedef unsigned char uint8_t; +//typedef short int16_t; +//typedef unsigned short uint16_t; +//typedef int int32_t; +//typedef unsigned int uint32_t; +//typedef __int64 int64_t; +//typedef unsigned __int64 uint64_t; +#else +typedef pthread_mutex_t CRITICAL_SECTION; +#define InitializeCriticalSection pthread_mutex_init +#define DeleteCriticalSection pthread_mutex_destroy +#define EnterCriticalSection pthread_mutex_lock +#define LeaveCriticalSection pthread_mutex_unlock +//typedef void* LPVOID; +//typedef unsigned long DWORD; +//#define CloseHandle close +#define Sleep(x) usleep(x*1000) +//#define closesocket close +//#define TRUE true +//#define FALSE false +//typedef bool BOOL; + +typedef struct +{ + pthread_mutex_t mtx; + pthread_cond_t cond; + bool manual_reset; + bool signaled; +} THANDLE, *PHANDLE; + +#define INFINITE 0xFFFFFFFF +#define WAIT_TIMEOUT 0x00000102L +#define WAIT_OBJECT_0 0 +#endif + +#ifndef TRACE +#define TRACE printf +#endif + +/*! + \brief H264鐮佹祦鍥炶皟鍑芥暟鎸囬拡 + \param iPlayHandle 鎾斁鍙ユ焺 + \param sData 鏁版嵁缂撳啿鍖 + \param iLen 鏁版嵁闀垮害 + \param iDataType 鏁版嵁绫诲瀷 0 - 瀹炴椂鏁版嵁娴, 1 - 褰曞儚鏁版嵁娴, 2 - 鏈湴閲囬泦鐨勯煶棰戞祦, 3 - 璁惧鍙戣繃鏉ョ殑闊抽娴 +*/ +typedef void(CALLBACK* fVideoDataCallBack)(int iPlayHandle, char* sData, int iLen, int iDataType, void* pUserData); + +/*! + \brief 鍛婅淇℃伅鍥炶皟鍑芥暟鎸囬拡 + \param pAlarmInfo 鍛婅淇℃伅T_JD_AlarmInfo缁撴瀯浣撴寚閽 + \param pUserData 鐢ㄦ埛鏁版嵁 +*/ +typedef void(CALLBACK* fMessageCallBack)(void* pAlarmInfo, void* pUserData); + +typedef struct +{ + char *start; + size_t length; + int frame_type; + int frame_index; + int channel; +} buffer_t; + +typedef struct _buffers_t +{ + int rear; + int front; + int bufnum; + int fps; + CRITICAL_SECTION cs; + buffer_t buf[MAX_BUF_NUM]; + fVideoDataCallBack pOnVideoData; // 鏁版嵁鍥炶皟鍑芥暟鎸囬拡 + void* pUserData; //鍥炶皟鍑芥暟鐢ㄦ埛鏁版嵁 + + _buffers_t() + { + pOnVideoData = NULL; + pUserData = NULL; + } + +} buffers_t; + +int init_buffers(buffers_t * bufs, int bufsize, int bufnum); + +int free_buffers(buffers_t *bufs); + +int buffers_get_data(void *data, unsigned int *length, buffers_t * bufs, int *type, int *channel, int *frame_index); + +int buffers_put_data(void *data, unsigned int length, buffers_t * bufs, int type, int channel, int frame_index); + +void buffers_clear_data(buffers_t * bufs); + +#endif diff --git a/external/libfaac/PcmToAac.cpp b/external/libfaac/PcmToAac.cpp new file mode 100644 index 0000000..a77d822 --- /dev/null +++ b/external/libfaac/PcmToAac.cpp @@ -0,0 +1,78 @@ + +#include "PcmToAac.h" + +#include "outDebug.h" + +PcmToAac::PcmToAac(void) +{ + m_nInputSamples=0; + m_nMaxOutputBytes=0; + m_nPCMBitSize = 16; +} + + +PcmToAac::~PcmToAac(void) +{ + if (NULL != hEncoder) + { + /*Close FAAC engine*/ + faacEncClose(hEncoder); + } + +} + +bool PcmToAac::Init(InAudioInfo* info) +{ + unsigned int objectType = LOW; + unsigned int mpegVersion = MPEG2; + static unsigned int useTns = 0; //#define DEFAULT_TNS 0 + + //TODO: config this + unsigned int nChannels = /*1*/info->Channel(); + + m_nPCMBitSize = /*16*/ info->PCMBitSize(); + unsigned long nInputSamples = 0; + unsigned long nSampleRate = /*8000*/info->Samplerate(); + unsigned long nMaxOutputBytes = 0; + + + /*open FAAC engine*/ + hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes); + if (hEncoder == NULL) + { + if(AAC_DEBUG) printf("%s:[%d] failed to call faacEncOpen !\n", __FUNCTION__, __LINE__); + //return -1; + return false; + } + m_nInputSamples = nInputSamples; + m_nMaxOutputBytes = nMaxOutputBytes; + + + /*get current encoding configuration*/ + pConfiguration = faacEncGetCurrentConfiguration(hEncoder); + pConfiguration->inputFormat = FAAC_INPUT_16BIT; + + /*0 - raw; 1 - ADTS*/ + pConfiguration->outputFormat = 1; + pConfiguration->useTns = useTns; + pConfiguration->aacObjectType = objectType; + pConfiguration->mpegVersion = mpegVersion; + + /*set encoding configuretion*/ + faacEncSetConfiguration(hEncoder, pConfiguration); + + return true; +} + +int PcmToAac::Encode(int32_t * pbPCMBuffer, unsigned int nPCMBufferSize, unsigned char * pbAACBuffer, unsigned int nMaxOutputBytes) +{ + unsigned int nPCMBitSize = GetPCMBitSize(); + + + unsigned int nInputSamples = (nPCMBufferSize / (nPCMBitSize / 8)); + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM faacEncEncode....\n", __FUNCTION__, __LINE__); + int nRet = faacEncEncode(hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes); + if(AAC_DEBUG) printf("%s:[%d] G711A -> PCM faacEncEncode\n", __FUNCTION__, __LINE__); + + return nRet; +} diff --git a/external/libfaac/PcmToAac.h b/external/libfaac/PcmToAac.h new file mode 100644 index 0000000..9295cc0 --- /dev/null +++ b/external/libfaac/PcmToAac.h @@ -0,0 +1,51 @@ + +#pragma once + +#include +#include +#include +#include "IDecodeToPcm.h" + +extern "C" +{ +#include +} + +class PcmToAac +{ +public: + PcmToAac(void); + ~PcmToAac(void); +public: + bool Init(InAudioInfo* info); + int Encode(int32_t * inputBuffer, unsigned int samplesInput, unsigned char *outputBuffer, unsigned int bufferSize); +public: + unsigned int GetPCMBitSize() + { + return m_nPCMBitSize; + } + unsigned int GetInputSamples() + { + return m_nInputSamples; + } + unsigned int GetMaxOutputBytes() + { + return m_nMaxOutputBytes; + } + unsigned int GetPCMBufferSize() + { + return (m_nInputSamples * (m_nPCMBitSize / 8)); + } + + +private: + faacEncHandle hEncoder; + faacEncConfigurationPtr pConfiguration; + + unsigned int m_nPCMBitSize /*= 16*/; + + unsigned long m_nInputSamples /*= 0*/; + + unsigned long m_nMaxOutputBytes /*= 0*/; +}; + diff --git a/external/libfaac/audio_buffer.cpp b/external/libfaac/audio_buffer.cpp new file mode 100644 index 0000000..66be603 --- /dev/null +++ b/external/libfaac/audio_buffer.cpp @@ -0,0 +1,56 @@ +#include "audio_buffer.h" +#include "MtDSSBuffers.h" +#include "outDebug.h" + + +audio_buffer::audio_buffer() +{ + data_ = new unsigned char[iBufLen]; + len_ = 0; +} + +audio_buffer::~audio_buffer() +{ + delete []data_; +} + +int audio_buffer::write_data(void* data, int len) +{ + if (iBufLen - len_ < len) + { + if(AAC_DEBUG) printf("audio_buffer full\n"); + return -1; + } + if (len > 0) + { + memcpy(data_ + len_, data, len); + len_ += len; + return len; + } + return 0; +} + +int audio_buffer::get_data(unsigned char* dest, int how_you_want) +{ + if (len_ == 0 || len_ < how_you_want) + { + return 0; + } + else + { + memcpy(dest, data_, how_you_want); + memmove(data_, data_ + how_you_want, len_ - how_you_want); + len_ -= how_you_want; + return how_you_want; + } +} + +unsigned char* audio_buffer::get_writable_ptr() +{ + return data_ + len_; +} + +void audio_buffer::update_data_len(int len) +{ + len_ += len; +} diff --git a/external/libfaac/audio_buffer.h b/external/libfaac/audio_buffer.h new file mode 100644 index 0000000..2a6246b --- /dev/null +++ b/external/libfaac/audio_buffer.h @@ -0,0 +1,21 @@ +#pragma once + +class audio_buffer +{ +public: + audio_buffer(void); + ~audio_buffer(void); + + int write_data(void *data, int len); + + int get_data(unsigned char *dest, int how_you_want); + + void update_data_len(int len); + + unsigned char *get_writable_ptr(); + +private: + unsigned char *data_; + int len_; +}; + diff --git a/external/libfaac/condef.h b/external/libfaac/condef.h new file mode 100644 index 0000000..d2fd5ca --- /dev/null +++ b/external/libfaac/condef.h @@ -0,0 +1,11 @@ +#ifndef _CONDEF_H +#define _CONDEF_H +#include +#include +#include +#include + +#define SAFE_DELETE_OBJ(OBJ) {if(NULL!=OBJ){delete OBJ;OBJ=NULL;}} +#define SAFE_FREE_BUF(OBJ) {if(NULL!=OBJ){free(OBJ);OBJ=NULL;}} + +#endif \ No newline at end of file diff --git a/external/libfaac/faac.h b/external/libfaac/faac.h new file mode 100644 index 0000000..57b2674 --- /dev/null +++ b/external/libfaac/faac.h @@ -0,0 +1,99 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: faac.h,v 1.36 2009/01/25 18:50:32 menno Exp $ + */ + +#ifndef _FAAC_H_ +#define _FAAC_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(_WIN32) && !defined(__MINGW32__) +# ifndef FAACAPI +# define FAACAPI __stdcall +# endif +#else +# ifndef FAACAPI +# define FAACAPI +# endif +#endif + +#pragma pack(push, 1) + +typedef struct { + void *ptr; + char *name; +} +psymodellist_t; + +#include "faaccfg.h" + + +typedef void *faacEncHandle; + +#ifndef HAVE_INT32_T +typedef signed int int32_t; +#endif + +/* + Allows an application to get FAAC version info. This is intended + purely for informative purposes. + + Returns FAAC_CFG_VERSION. +*/ +int FAACAPI faacEncGetVersion(char **faac_id_string, + char **faac_copyright_string); + + +faacEncConfigurationPtr FAACAPI + faacEncGetCurrentConfiguration(faacEncHandle hEncoder); + + +int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder, + faacEncConfigurationPtr config); + + +faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, + unsigned int numChannels, + unsigned long *inputSamples, + unsigned long *maxOutputBytes); + + +int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, unsigned char **ppBuffer, + unsigned long *pSizeOfDecoderSpecificInfo); + + +int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput, + unsigned char *outputBuffer, + unsigned int bufferSize); + + +int FAACAPI faacEncClose(faacEncHandle hEncoder); + + + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _FAAC_H_ */ diff --git a/external/libfaac/faaccfg.h b/external/libfaac/faaccfg.h new file mode 100644 index 0000000..278f60d --- /dev/null +++ b/external/libfaac/faaccfg.h @@ -0,0 +1,122 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: faaccfg.h,v 1.3 2004/07/04 12:12:05 corrados Exp $ + */ + +#ifndef _FAACCFG_H_ +#define _FAACCFG_H_ + +#define FAAC_CFG_VERSION 104 + +/* MPEG ID's */ +#define MPEG2 1 +#define MPEG4 0 + +/* AAC object types */ +#define MAIN 1 +#define LOW 2 +#define SSR 3 +#define LTP 4 + +/* Input Formats */ +#define FAAC_INPUT_NULL 0 +#define FAAC_INPUT_16BIT 1 +#define FAAC_INPUT_24BIT 2 +#define FAAC_INPUT_32BIT 3 +#define FAAC_INPUT_FLOAT 4 + +#define SHORTCTL_NORMAL 0 +#define SHORTCTL_NOSHORT 1 +#define SHORTCTL_NOLONG 2 + +#pragma pack(push, 1) +typedef struct faacEncConfiguration +{ + /* config version */ + int version; + + /* library version */ + char *name; + + /* copyright string */ + char *copyright; + + /* MPEG version, 2 or 4 */ + unsigned int mpegVersion; + + /* AAC object type */ + unsigned int aacObjectType; + + /* Allow mid/side coding */ + unsigned int allowMidside; + + /* Use one of the channels as LFE channel */ + unsigned int useLfe; + + /* Use Temporal Noise Shaping */ + unsigned int useTns; + + /* bitrate / channel of AAC file */ + unsigned long bitRate; + + /* AAC file frequency bandwidth */ + unsigned int bandWidth; + + /* Quantizer quality */ + unsigned long quantqual; + + /* Bitstream output format (0 = Raw; 1 = ADTS) */ + unsigned int outputFormat; + + /* psychoacoustic model list */ + psymodellist_t *psymodellist; + + /* selected index in psymodellist */ + unsigned int psymodelidx; + + /* + PCM Sample Input Format + 0 FAAC_INPUT_NULL invalid, signifies a misconfigured config + 1 FAAC_INPUT_16BIT native endian 16bit + 2 FAAC_INPUT_24BIT native endian 24bit in 24 bits (not implemented) + 3 FAAC_INPUT_32BIT native endian 24bit in 32 bits (DEFAULT) + 4 FAAC_INPUT_FLOAT 32bit floating point + */ + unsigned int inputFormat; + + /* block type enforcing (SHORTCTL_NORMAL/SHORTCTL_NOSHORT/SHORTCTL_NOLONG) */ + int shortctl; + + /* + Channel Remapping + + Default 0, 1, 2, 3 ... 63 (64 is MAX_CHANNELS in coder.h) + + WAVE 4.0 2, 0, 1, 3 + WAVE 5.0 2, 0, 1, 3, 4 + WAVE 5.1 2, 0, 1, 4, 5, 3 + AIFF 5.1 2, 0, 3, 1, 4, 5 + */ + int channel_map[64]; + +} faacEncConfiguration, *faacEncConfigurationPtr; + +#pragma pack(pop) + +#endif /* _FAACCFG_H_ */ diff --git a/external/libfaac/g711.cpp b/external/libfaac/g711.cpp new file mode 100644 index 0000000..102ef1c --- /dev/null +++ b/external/libfaac/g711.cpp @@ -0,0 +1,306 @@ +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ + +//#include "stdafx.h" +#include +#include +#include "g711.h" + +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; + +/* copy from CCITT G.711 specifications */ +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +static int +search( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} + +/* + * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law + * + * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2alaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char aval; + + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 8; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + aval = seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 4) & QUANT_MASK; + else + aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; + return (aval ^ mask); + } +} + +/* + * alaw2linear() - Convert an A-law value to 16-bit linear PCM + * + */ +int +alaw2linear( + unsigned char a_val) +{ + int t; + int seg; + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} + +#define BIAS (0x84) /* Bias for linear code. */ + +/* + * linear2ulaw() - Convert a linear PCM value to u-law + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2ulaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char uval; + + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = BIAS - pcm_val; + mask = 0x7F; + } else { + pcm_val += BIAS; + mask = 0xFF; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); + return (uval ^ mask); + } + +} + +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +int +ulaw2linear( + unsigned char u_val) +{ + int t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} + +/* A-law to u-law conversion */ +unsigned char +alaw2ulaw( + unsigned char aval) +{ + aval &= 0xff; + return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +unsigned char +ulaw2alaw( + unsigned char uval) +{ + uval &= 0xff; + return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} + +int g711_decode(void *pout_buf, int *pout_len, const void *pin_buf, const int in_len , int type) +{ + int16_t *dst = (int16_t *) pout_buf; + uint8_t *src = (uint8_t *) pin_buf; + uint32_t i = 0; + int Ret = 0; + + if ((NULL == pout_buf) || \ + (NULL == pout_len) || \ + (NULL == pin_buf) || \ + (0 == in_len)) + { + return -1; + } + + if (*pout_len < 2 * in_len) + { + return -2; + } + //---{{{ + if (TP_ALAW == type) + { + for (i = 0; i < in_len; i++) + { + //*(dst++) = alawtos16[*(src++)]; + *(dst++) = (int16_t)alaw2linear(*(src++)); + } + }else + { + for (i = 0; i < in_len; i++) + { + //*(dst++) = alawtos16[*(src++)]; + *(dst++) = (int16_t)ulaw2linear(*(src++)); + } + } + + //---}}} + *pout_len = 2 * in_len; + + Ret = 2 * in_len; + return Ret; +} \ No newline at end of file diff --git a/external/libfaac/g711.h b/external/libfaac/g711.h new file mode 100644 index 0000000..5bbe962 --- /dev/null +++ b/external/libfaac/g711.h @@ -0,0 +1,24 @@ + +#ifndef __G_711_H_ +#define __G_711_H_ + +#include + +enum _e_g711_tp +{ + TP_ALAW, //G711A + TP_ULAW //G711U +}; + +unsigned char linear2alaw(int pcm_val); /* 2's complement (16-bit range) */ +int alaw2linear(unsigned char a_val); + +unsigned char linear2ulaw(int pcm_val); /* 2's complement (16-bit range) */ +int ulaw2linear(unsigned char u_val); + +unsigned char alaw2ulaw(unsigned char aval); +unsigned char ulaw2alaw(unsigned char uval); + +int g711_decode(void *pout_buf, int *pout_len, const void *pin_buf, const int in_len , int type); + +#endif diff --git a/external/libfaac/libfaac/aacquant.c b/external/libfaac/libfaac/aacquant.c new file mode 100644 index 0000000..20a9ab7 --- /dev/null +++ b/external/libfaac/libfaac/aacquant.c @@ -0,0 +1,708 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * Copyright (C) 2002, 2003 Krzysztof Nikiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: aacquant.c,v 1.32 2008/03/23 23:00:25 menno Exp $ + */ + +#include +#include + +#include "frame.h" +#include "aacquant.h" +#include "coder.h" +#include "huffman.h" +#include "psych.h" +#include "util.h" + +#define TAKEHIRO_IEEE754_HACK 1 + +#define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#define QUANTFAC(rx) adj43[rx] +#define ROUNDFAC 0.4054 + +static int FixNoise(CoderInfo *coderInfo, + const double *xr, + double *xr_pow, + int *xi, + double *xmin, + double *pow43, + double *adj43); + +static void CalcAllowedDist(CoderInfo *coderInfo, PsyInfo *psyInfo, + double *xr, double *xmin, int quality); + + +void AACQuantizeInit(CoderInfo *coderInfo, unsigned int numChannels, + AACQuantCfg *aacquantCfg) +{ + unsigned int channel, i; + + aacquantCfg->pow43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double)); + aacquantCfg->adj43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double)); + + aacquantCfg->pow43[0] = 0.0; + for(i=1;ipow43[i] = pow((double)i, 4.0/3.0); + +#if TAKEHIRO_IEEE754_HACK + aacquantCfg->adj43[0] = 0.0; + for (i = 1; i < PRECALC_SIZE; i++) + aacquantCfg->adj43[i] = i - 0.5 - pow(0.5 * (aacquantCfg->pow43[i - 1] + aacquantCfg->pow43[i]),0.75); +#else // !TAKEHIRO_IEEE754_HACK + for (i = 0; i < PRECALC_SIZE-1; i++) + aacquantCfg->adj43[i] = (i + 1) - pow(0.5 * (aacquantCfg->pow43[i] + aacquantCfg->pow43[i + 1]), 0.75); + aacquantCfg->adj43[i] = 0.5; +#endif + + for (channel = 0; channel < numChannels; channel++) { + coderInfo[channel].requantFreq = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double)); + } +} + +void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels, + AACQuantCfg *aacquantCfg) +{ + unsigned int channel; + + if (aacquantCfg->pow43) + { + FreeMemory(aacquantCfg->pow43); + aacquantCfg->pow43 = NULL; + } + if (aacquantCfg->adj43) + { + FreeMemory(aacquantCfg->adj43); + aacquantCfg->adj43 = NULL; + } + + for (channel = 0; channel < numChannels; channel++) { + if (coderInfo[channel].requantFreq) FreeMemory(coderInfo[channel].requantFreq); + } +} + +static void BalanceEnergy(CoderInfo *coderInfo, + const double *xr, const int *xi, + double *pow43) +{ + const double ifqstep = pow(2.0, 0.25); + const double logstep_1 = 1.0 / log(ifqstep); + int sb; + int nsfb = coderInfo->nr_of_sfb; + int start, end; + int l; + double en0, enq; + int shift; + + for (sb = 0; sb < nsfb; sb++) + { + double qfac_1; + + start = coderInfo->sfb_offset[sb]; + end = coderInfo->sfb_offset[sb+1]; + + qfac_1 = pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain)); + + en0 = 0.0; + enq = 0.0; + for (l = start; l < end; l++) + { + double xq; + + if (!sb && !xi[l]) + continue; + + xq = pow43[xi[l]]; + + en0 += xr[l] * xr[l]; + enq += xq * xq; + } + + if (enq == 0.0) + continue; + + enq *= qfac_1 * qfac_1; + + shift = (int)(log(sqrt(enq / en0)) * logstep_1 + 1000.5); + shift -= 1000; + + shift += coderInfo->scale_factor[sb]; + coderInfo->scale_factor[sb] = shift; + } +} + +static void UpdateRequant(CoderInfo *coderInfo, int *xi, + double *pow43) +{ + double *requant_xr = coderInfo->requantFreq; + int sb; + int i; + + for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) + { + double invQuantFac = + pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain)); + int start = coderInfo->sfb_offset[sb]; + int end = coderInfo->sfb_offset[sb + 1]; + + for (i = start; i < end; i++) + requant_xr[i] = pow43[xi[i]] * invQuantFac; + } +} + +int AACQuantize(CoderInfo *coderInfo, + PsyInfo *psyInfo, + ChannelInfo *channelInfo, + int *cb_width, + int num_cb, + double *xr, + AACQuantCfg *aacquantCfg) +{ + int sb, i, do_q = 0; + int bits = 0, sign; + double xr_pow[FRAME_LEN]; + double xmin[MAX_SCFAC_BANDS]; + int xi[FRAME_LEN]; + + /* Use local copy's */ + int *scale_factor = coderInfo->scale_factor; + + /* Set all scalefactors to 0 */ + coderInfo->global_gain = 0; + for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) + scale_factor[sb] = 0; + + /* Compute xr_pow */ + for (i = 0; i < FRAME_LEN; i++) { + double temp = fabs(xr[i]); + xr_pow[i] = sqrt(temp * sqrt(temp)); + do_q += (temp > 1E-20); + } + + if (do_q) { + CalcAllowedDist(coderInfo, psyInfo, xr, xmin, aacquantCfg->quality); + coderInfo->global_gain = 0; + FixNoise(coderInfo, xr, xr_pow, xi, xmin, + aacquantCfg->pow43, aacquantCfg->adj43); + BalanceEnergy(coderInfo, xr, xi, aacquantCfg->pow43); + UpdateRequant(coderInfo, xi, aacquantCfg->pow43); + + for ( i = 0; i < FRAME_LEN; i++ ) { + sign = (xr[i] < 0) ? -1 : 1; + xi[i] *= sign; + coderInfo->requantFreq[i] *= sign; + } + } else { + coderInfo->global_gain = 0; + SetMemory(xi, 0, FRAME_LEN*sizeof(int)); + } + + BitSearch(coderInfo, xi); + + /* offset the difference of common_scalefac and scalefactors by SF_OFFSET */ + for (i = 0; i < coderInfo->nr_of_sfb; i++) { + if ((coderInfo->book_vector[i]!=INTENSITY_HCB)&&(coderInfo->book_vector[i]!=INTENSITY_HCB2)) { + scale_factor[i] = coderInfo->global_gain - scale_factor[i] + SF_OFFSET; + } + } + coderInfo->global_gain = scale_factor[0]; +#if 0 + printf("global gain: %d\n", coderInfo->global_gain); + for (i = 0; i < coderInfo->nr_of_sfb; i++) + printf("sf %d: %d\n", i, coderInfo->scale_factor[i]); +#endif + // clamp to valid diff range + { + int previous_scale_factor = coderInfo->global_gain; + int previous_is_factor = 0; + for (i = 0; i < coderInfo->nr_of_sfb; i++) { + if ((coderInfo->book_vector[i]==INTENSITY_HCB) || + (coderInfo->book_vector[i]==INTENSITY_HCB2)) { + const int diff = scale_factor[i] - previous_is_factor; + if (diff < -60) scale_factor[i] = previous_is_factor - 60; + else if (diff > 59) scale_factor[i] = previous_is_factor + 59; + previous_is_factor = scale_factor[i]; +// printf("sf %d: %d diff=%d **\n", i, coderInfo->scale_factor[i], diff); + } else if (coderInfo->book_vector[i]) { + const int diff = scale_factor[i] - previous_scale_factor; + if (diff < -60) scale_factor[i] = previous_scale_factor - 60; + else if (diff > 59) scale_factor[i] = previous_scale_factor + 59; + previous_scale_factor = scale_factor[i]; +// printf("sf %d: %d diff=%d\n", i, coderInfo->scale_factor[i], diff); + } + } + } + + /* place the codewords and their respective lengths in arrays data[] and len[] respectively */ + /* there are 'counter' elements in each array, and these are variable length arrays depending on the input */ +#ifdef DRM + coderInfo->iLenReordSpData = 0; /* init length of reordered spectral data */ + coderInfo->iLenLongestCW = 0; /* init length of longest codeword */ + coderInfo->cur_cw = 0; /* init codeword counter */ +#endif + coderInfo->spectral_count = 0; + sb = 0; + for(i = 0; i < coderInfo->nr_of_sfb; i++) { + OutputBits( + coderInfo, +#ifdef DRM + &coderInfo->book_vector[i], /* needed for VCB11 */ +#else + coderInfo->book_vector[i], +#endif + xi, + coderInfo->sfb_offset[i], + coderInfo->sfb_offset[i+1]-coderInfo->sfb_offset[i]); + + if (coderInfo->book_vector[i]) + sb = i; + } + + // FIXME: Check those max_sfb/nr_of_sfb. Isn't it the same? + coderInfo->max_sfb = coderInfo->nr_of_sfb = sb + 1; + + return bits; +} + + +#if TAKEHIRO_IEEE754_HACK + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + +#if 0 +static void Quantize(const double *xp, int *pi, double istep) +{ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j = FRAME_LEN/4 - 1; j >= 0; --j) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + double x2 = istep * xp[2]; + double x3 = istep * xp[3]; + + x0 += MAGIC_FLOAT; fi[0].f = x0; + x1 += MAGIC_FLOAT; fi[1].f = x1; + x2 += MAGIC_FLOAT; fi[2].f = x2; + x3 += MAGIC_FLOAT; fi[3].f = x3; + + fi[0].f = x0 + (adj43asm - MAGIC_INT)[fi[0].i]; + fi[1].f = x1 + (adj43asm - MAGIC_INT)[fi[1].i]; + fi[2].f = x2 + (adj43asm - MAGIC_INT)[fi[2].i]; + fi[3].f = x3 + (adj43asm - MAGIC_INT)[fi[3].i]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi += 4; + xp += 4; + } +} +#endif +static void QuantizeBand(const double *xp, int *pi, double istep, + int offset, int end, double *adj43) +{ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j = offset; j < end; j++) + { + double x0 = istep * xp[j]; + + x0 += MAGIC_FLOAT; fi[j].f = (float)x0; + fi[j].f = x0 + (adj43 - MAGIC_INT)[fi[j].i]; + fi[j].i -= MAGIC_INT; + } +} +#else +#if 0 +static void Quantize(const double *xr, int *ix, double istep) +{ + int j; + + for (j = FRAME_LEN/8; j > 0; --j) { + double x1, x2, x3, x4, x5, x6, x7, x8; + int rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8; + + x1 = *xr++ * istep; + x2 = *xr++ * istep; + XRPOW_FTOI(x1, rx1); + x3 = *xr++ * istep; + XRPOW_FTOI(x2, rx2); + x4 = *xr++ * istep; + XRPOW_FTOI(x3, rx3); + x5 = *xr++ * istep; + XRPOW_FTOI(x4, rx4); + x6 = *xr++ * istep; + XRPOW_FTOI(x5, rx5); + x7 = *xr++ * istep; + XRPOW_FTOI(x6, rx6); + x8 = *xr++ * istep; + XRPOW_FTOI(x7, rx7); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x8, rx8); + x2 += QUANTFAC(rx2); + XRPOW_FTOI(x1,*ix++); + x3 += QUANTFAC(rx3); + XRPOW_FTOI(x2,*ix++); + x4 += QUANTFAC(rx4); + XRPOW_FTOI(x3,*ix++); + x5 += QUANTFAC(rx5); + XRPOW_FTOI(x4,*ix++); + x6 += QUANTFAC(rx6); + XRPOW_FTOI(x5,*ix++); + x7 += QUANTFAC(rx7); + XRPOW_FTOI(x6,*ix++); + x8 += QUANTFAC(rx8); + XRPOW_FTOI(x7,*ix++); + XRPOW_FTOI(x8,*ix++); + } +} +#endif +static void QuantizeBand(const double *xp, int *ix, double istep, + int offset, int end, double *adj43) +{ + int j; + + for (j = offset; j < end; j++) + { + double x0 = istep * xp[j]; + x0 += adj43[(int)x0]; + ix[j] = (int)x0; + } +} +#endif + +static void CalcAllowedDist(CoderInfo *coderInfo, PsyInfo *psyInfo, + double *xr, double *xmin, int quality) +{ + int sfb, start, end, l; + const double globalthr = 132.0 / (double)quality; + int last = coderInfo->lastx; + int lastsb = 0; + int *cb_offset = coderInfo->sfb_offset; + int num_cb = coderInfo->nr_of_sfb; + double avgenrg = coderInfo->avgenrg; + + for (sfb = 0; sfb < num_cb; sfb++) + { + if (last > cb_offset[sfb]) + lastsb = sfb; + } + + for (sfb = 0; sfb < num_cb; sfb++) + { + double thr, tmp; + double enrg = 0.0; + + start = cb_offset[sfb]; + end = cb_offset[sfb + 1]; + + if (sfb > lastsb) + { + xmin[sfb] = 0; + continue; + } + + if (coderInfo->block_type != ONLY_SHORT_WINDOW) + { + double enmax = -1.0; + double lmax; + + lmax = start; + for (l = start; l < end; l++) + { + if (enmax < (xr[l] * xr[l])) + { + enmax = xr[l] * xr[l]; + lmax = l; + } + } + + start = lmax - 2; + end = lmax + 3; + if (start < 0) + start = 0; + if (end > last) + end = last; + } + + for (l = start; l < end; l++) + { + enrg += xr[l]*xr[l]; + } + + thr = enrg/((double)(end-start)*avgenrg); + thr = pow(thr, 0.1*(lastsb-sfb)/lastsb + 0.3); + + tmp = 1.0 - ((double)start / (double)last); + tmp = tmp * tmp * tmp + 0.075; + + thr = 1.0 / (1.4*thr + tmp); + + xmin[sfb] = ((coderInfo->block_type == ONLY_SHORT_WINDOW) ? 0.65 : 1.12) + * globalthr * thr; + } +} + +static int FixNoise(CoderInfo *coderInfo, + const double *xr, + double *xr_pow, + int *xi, + double *xmin, + double *pow43, + double *adj43) +{ + int i, sb; + int start, end; + double diffvol; + double tmp; + const double ifqstep = pow(2.0, 0.1875); + const double log_ifqstep = 1.0 / log(ifqstep); + const double maxstep = 0.05; + + for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) + { + double sfacfix; + double fixstep = 0.25; + int sfac; + double fac; + int dist; + double sfacfix0 = 1.0, dist0 = 1e50; + double maxx; + + start = coderInfo->sfb_offset[sb]; + end = coderInfo->sfb_offset[sb+1]; + + if (!xmin[sb]) + goto nullsfb; + + maxx = 0.0; + for (i = start; i < end; i++) + { + if (xr_pow[i] > maxx) + maxx = xr_pow[i]; + } + + //printf("band %d: maxx: %f\n", sb, maxx); + if (maxx < 10.0) + { + nullsfb: + for (i = start; i < end; i++) + xi[i] = 0; + coderInfo->scale_factor[sb] = 10; + continue; + } + + sfacfix = 1.0 / maxx; + sfac = (int)(log(sfacfix) * log_ifqstep - 0.5); + for (i = start; i < end; i++) + xr_pow[i] *= sfacfix; + maxx *= sfacfix; + coderInfo->scale_factor[sb] = sfac; + QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end, + adj43); + //printf("\tsfac: %d\n", sfac); + + calcdist: + diffvol = 0.0; + for (i = start; i < end; i++) + { + tmp = xi[i]; + diffvol += tmp * tmp; // ~x^(3/2) + } + + if (diffvol < 1e-6) + diffvol = 1e-6; + tmp = pow(diffvol / (double)(end - start), -0.666); + + if (fabs(fixstep) > maxstep) + { + double dd = 0.5*(tmp / xmin[sb] - 1.0); + + if (fabs(dd) < fabs(fixstep)) + { + fixstep = dd; + + if (fabs(fixstep) < maxstep) + fixstep = maxstep * ((fixstep > 0) ? 1 : -1); + } + } + + if (fixstep > 0) + { + if (tmp < dist0) + { + dist0 = tmp; + sfacfix0 = sfacfix; + } + else + { + if (fixstep > .1) + fixstep = .1; + } + } + else + { + dist0 = tmp; + sfacfix0 = sfacfix; + } + + dist = (tmp > xmin[sb]); + fac = 0.0; + if (fabs(fixstep) >= maxstep) + { + if ((dist && (fixstep < 0)) + || (!dist && (fixstep > 0))) + { + fixstep = -0.5 * fixstep; + } + + fac = 1.0 + fixstep; + } + else if (dist) + { + fac = 1.0 + fabs(fixstep); + } + + if (fac != 0.0) + { + if (maxx * fac >= IXMAX_VAL) + { + // restore best noise + fac = sfacfix0 / sfacfix; + for (i = start; i < end; i++) + xr_pow[i] *= fac; + maxx *= fac; + sfacfix *= fac; + coderInfo->scale_factor[sb] = log(sfacfix) * log_ifqstep - 0.5; + QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end, + adj43); + continue; + } + + if (coderInfo->scale_factor[sb] < -10) + { + for (i = start; i < end; i++) + xr_pow[i] *= fac; + maxx *= fac; + sfacfix *= fac; + coderInfo->scale_factor[sb] = log(sfacfix) * log_ifqstep - 0.5; + QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end, + adj43); + goto calcdist; + } + } + } + return 0; +} + +int SortForGrouping(CoderInfo* coderInfo, + PsyInfo *psyInfo, + ChannelInfo *channelInfo, + int *sfb_width_table, + double *xr) +{ + int i,j,ii; + int index = 0; + double xr_tmp[FRAME_LEN]; + int group_offset=0; + int k=0; + int windowOffset = 0; + + + /* set up local variables for used quantInfo elements */ + int* sfb_offset = coderInfo->sfb_offset; + int* nr_of_sfb = &(coderInfo->nr_of_sfb); + int* window_group_length; + int num_window_groups; + *nr_of_sfb = coderInfo->max_sfb; /* Init to max_sfb */ + window_group_length = coderInfo->window_group_length; + num_window_groups = coderInfo->num_window_groups; + + /* calc org sfb_offset just for shortblock */ + sfb_offset[k]=0; + for (k=1 ; k <*nr_of_sfb+1; k++) { + sfb_offset[k] = sfb_offset[k-1] + sfb_width_table[k-1]; + } + + /* sort the input spectral coefficients */ + index = 0; + group_offset=0; + for (i=0; i< num_window_groups; i++) { + for (k=0; k<*nr_of_sfb; k++) { + for (j=0; j < window_group_length[i]; j++) { + for (ii=0;ii< sfb_width_table[k];ii++) + xr_tmp[index++] = xr[ii+ sfb_offset[k] + BLOCK_LEN_SHORT*j +group_offset]; + } + } + group_offset += BLOCK_LEN_SHORT*window_group_length[i]; + } + + for (k=0; ksfb_offset[coderInfo->nr_of_sfb]; + for (l = 0; l < end; l++) + { + if (xr[l]) + { + last = l; + totenrg += xr[l] * xr[l]; + } + } + last++; + + coderInfo->lastx = last; + coderInfo->avgenrg = totenrg / last; +} diff --git a/external/libfaac/libfaac/aacquant.h b/external/libfaac/libfaac/aacquant.h new file mode 100644 index 0000000..400901f --- /dev/null +++ b/external/libfaac/libfaac/aacquant.h @@ -0,0 +1,74 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: aacquant.h,v 1.9 2003/10/12 16:43:39 knik Exp $ + */ + +#ifndef AACQUANT_H +#define AACQUANT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "coder.h" +#include "psych.h" + +#define IXMAX_VAL 8191 +#define PRECALC_SIZE (IXMAX_VAL+2) +#define LARGE_BITS 100000 +#define SF_OFFSET 100 + +#define POW20(x) pow(2.0,((double)x)*.25) +#define IPOW20(x) pow(2.0,-((double)x)*.1875) + +#pragma pack(push, 1) +typedef struct + { + double *pow43; + double *adj43; + double quality; + } AACQuantCfg; +#pragma pack(pop) + +void AACQuantizeInit(CoderInfo *coderInfo, unsigned int numChannels, + AACQuantCfg *aacquantCfg); +void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels, + AACQuantCfg *aacquantCfg); + +int AACQuantize(CoderInfo *coderInfo, + PsyInfo *psyInfo, + ChannelInfo *channelInfo, + int *cb_width, + int num_cb, + double *xr, + AACQuantCfg *aacquantcfg); + +int SortForGrouping(CoderInfo* coderInfo, + PsyInfo *psyInfo, + ChannelInfo *channelInfo, + int *sfb_width_table, + double *xr); +void CalcAvgEnrg(CoderInfo *coderInfo, + const double *xr); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* AACQUANT_H */ diff --git a/external/libfaac/libfaac/backpred.c b/external/libfaac/libfaac/backpred.c new file mode 100644 index 0000000..e57a02f --- /dev/null +++ b/external/libfaac/libfaac/backpred.c @@ -0,0 +1,381 @@ +/********************************************************************** + +This software module was originally developed by +and edited by Nokia in the course of +development of the MPEG-2 NBC/MPEG-4 Audio standard +ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an +implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools +as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives +users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this +software module or modifications thereof for use in hardware or +software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio +standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing +patents. The original developer of this software module and his/her +company, the subsequent editors and their companies, and ISO/IEC have +no liability for use of this software module or modifications thereof +in an implementation. Copyright is not released for non MPEG-2 +NBC/MPEG-4 Audio conforming products. The original developer retains +full right to use the code for his/her own purpose, assign or donate +the code to a third party and to inhibit third party from using the +code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This +copyright notice must be included in all copies or derivative works. + +Copyright (c) 1997. +**********************************************************************/ +/* + * $Id: backpred.c,v 1.5 2001/09/04 18:39:35 menno Exp $ + */ + +#include +#include "frame.h" +#include "coder.h" +#include "channels.h" +#include "backpred.h" + + +void PredInit(faacEncHandle hEncoder) +{ + unsigned int channel; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + BwpInfo *bwpInfo = &(hEncoder->coderInfo[channel].bwpInfo); + + bwpInfo->psy_init_mc = 0; + bwpInfo->reset_count_mc = 0; + } +} + +void PredCalcPrediction(double *act_spec, double *last_spec, int btype, + int nsfb, + int *isfb_width, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + int chanNum) +{ + int i, k, j, cb_long; + int leftChanNum; + int isRightWithCommonWindow; + double num_bit, snr[SBMAX_L]; + double energy[BLOCK_LEN_LONG], snr_p[BLOCK_LEN_LONG], temp1, temp2; + ChannelInfo *thisChannel; + + /* Set pointers for specified channel number */ + /* int psy_init; */ + int *psy_init; + double (*dr)[BLOCK_LEN_LONG],(*e)[BLOCK_LEN_LONG]; + double (*K)[BLOCK_LEN_LONG], (*R)[BLOCK_LEN_LONG]; + double (*VAR)[BLOCK_LEN_LONG], (*KOR)[BLOCK_LEN_LONG]; + double *sb_samples_pred; + int *thisLineNeedsResetting; + /* int reset_count; */ + int *reset_count; + int *pred_global_flag; + int *pred_sfb_flag; + int *reset_group; + + /* Set pointers for this chanNum */ + pred_global_flag = &(coderInfo[chanNum].pred_global_flag); + pred_sfb_flag = coderInfo[chanNum].pred_sfb_flag; + reset_group = &(coderInfo[chanNum].reset_group_number); + psy_init = &coderInfo[chanNum].bwpInfo.psy_init_mc; + dr = &coderInfo[chanNum].bwpInfo.dr_mc[0]; + e = &coderInfo[chanNum].bwpInfo.e_mc[0]; + K = &coderInfo[chanNum].bwpInfo.K_mc[0]; + R = &coderInfo[chanNum].bwpInfo.R_mc[0]; + VAR = &coderInfo[chanNum].bwpInfo.VAR_mc[0]; + KOR = &coderInfo[chanNum].bwpInfo.KOR_mc[0]; + sb_samples_pred = &coderInfo[chanNum].bwpInfo.sb_samples_pred_mc[0]; + thisLineNeedsResetting = &coderInfo[chanNum].bwpInfo.thisLineNeedsResetting_mc[0]; + reset_count = &coderInfo[chanNum].bwpInfo.reset_count_mc; + + thisChannel = &(channelInfo[chanNum]); + *psy_init = (*psy_init && (btype!=2)); + + if((*psy_init) == 0) { + for (j=0; jch_is_left) { + (*reset_count)++; + if (*reset_count >= 31 * RESET_FRAME) + *reset_count = RESET_FRAME; + } + return; + } + + + /**************************************************/ + /* Compute state using last_spec */ + /**************************************************/ + for (i=0;i=1;j--) + R[j][i] = A*(R[j-1][i]-dr[j][i]); + R[0][i] = A*e[0][i]; + } + + + /**************************************************/ + /* Reset state here if resets were sent */ + /**************************************************/ + for (i=0;iMINVAR) + K[j][i] = KOR[j][i]/VAR[j][i]*B; + else + K[j][i] = 0; + } + } + + + for (k=0; kcpe)&&( !(thisChannel->ch_is_left))) { + leftChanNum = thisChannel->paired_ch; + if (channelInfo[leftChanNum].common_window) { + isRightWithCommonWindow = 1; + } + } + + if (isRightWithCommonWindow) { + + /**************************************************/ + /* Use predictor data from the left channel. */ + /**************************************************/ + CopyPredInfo(&(coderInfo[chanNum]),&(coderInfo[leftChanNum])); + + /* Make sure to turn off bands with intensity stereo */ +#if 0 + if (thisChannel->is_info.is_present) { + for (i=0; iis_info.is_used[i]) { + pred_sfb_flag[i] = 0; + } + } + } +#endif + + cb_long=0; + for (i=0; i0.0) + num_bit+=snr[i]/6.*isfb_width[i]; + + /* Determine global enable, if not enabled predicted samples are zeroed */ + pred_global_flag[0]=1; + if(num_bit<50) { + pred_global_flag[0]=0; num_bit=0.0; + for (j=0; jcpe)&&( !(thisChannel->ch_is_left))) { + /* if (!thisChannel->ch_is_left) {*/ + /**********************************************************/ + /* Using predictor reset data from the left channel. */ + /**********************************************************/ + reset_count = &coderInfo[leftChanNum].bwpInfo.reset_count_mc; + /* Reset the frame counter */ + for (i=0;i= 31 * RESET_FRAME) + *reset_count = RESET_FRAME; + if (*reset_count % RESET_FRAME == 0) + { /* Send a reset in this frame */ + *reset_group = *reset_count / 8; + for (i = *reset_group - 1; i < BLOCK_LEN_LONG; i += 30) + { + thisLineNeedsResetting[i]=1; + } + } + else + *reset_group = -1; + } + + + /* Ensure that prediction data is sent when there is a prediction + * reset. + */ + if (*reset_group != -1 && pred_global_flag[0] == 0) + { + pred_global_flag[0] = 1; + for (i = 0; i < nsfb; i++) + pred_sfb_flag[i] = 0; + } +} + + +void CopyPredInfo(CoderInfo *right, CoderInfo *left) +{ + int band; + + right->pred_global_flag = left->pred_global_flag; + right->reset_group_number = left->reset_group_number; + + for (band = 0; bandpred_sfb_flag[band] = left->pred_sfb_flag[band]; + } +} + + + + diff --git a/external/libfaac/libfaac/backpred.h b/external/libfaac/libfaac/backpred.h new file mode 100644 index 0000000..db5680d --- /dev/null +++ b/external/libfaac/libfaac/backpred.h @@ -0,0 +1,51 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: backpred.h,v 1.5 2001/06/08 18:01:09 menno Exp $ + */ + +#ifndef _AAC_BACK_H_INCLUDED +#define _AAC_BACK_H_INCLUDED + +#define PRED_ALPHA 0.90625 +#define PRED_A 0.953125 +#define PRED_B 0.953125 + +#define ALPHA PRED_ALPHA +#define A PRED_A +#define B PRED_B +#define MINVAR 1.e-10 + +/* Reset every RESET_FRAME frames. */ +#define RESET_FRAME 8 + +void PredCalcPrediction(double *act_spec, + double *last_spec, + int btype, + int nsfb, + int *isfb_width, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + int chanNum); + +void PredInit(faacEncHandle hEncoder); + +void CopyPredInfo(CoderInfo *right, CoderInfo *left); + + +#endif diff --git a/external/libfaac/libfaac/bitstream.c b/external/libfaac/libfaac/bitstream.c new file mode 100644 index 0000000..fb3f005 --- /dev/null +++ b/external/libfaac/libfaac/bitstream.c @@ -0,0 +1,1496 @@ +/********************************************************************** + +This software module was originally developed by +and edited by Texas Instruments in the course of +development of the MPEG-2 NBC/MPEG-4 Audio standard +ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an +implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools +as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives +users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this +software module or modifications thereof for use in hardware or +software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio +standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing +patents. The original developer of this software module and his/her +company, the subsequent editors and their companies, and ISO/IEC have +no liability for use of this software module or modifications thereof +in an implementation. Copyright is not released for non MPEG-2 +NBC/MPEG-4 Audio conforming products. The original developer retains +full right to use the code for his/her own purpose, assign or donate +the code to a third party and to inhibit third party from using the +code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This +copyright notice must be included in all copies or derivative works. + +Copyright (c) 1997. +**********************************************************************/ +/* + * $Id: bitstream.c,v 1.34 2007/06/05 18:59:47 menno Exp $ + */ + +#include +#include + +#include "coder.h" +#include "channels.h" +#include "huffman.h" +#include "bitstream.h" +#include "ltp.h" +#include "util.h" + +static int CountBitstream(faacEncHandle hEncoder, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int numChannels); +static int WriteADTSHeader(faacEncHandle hEncoder, + BitStream *bitStream, + int writeFlag); +static int WriteCPE(CoderInfo *coderInfoL, + CoderInfo *coderInfoR, + ChannelInfo *channelInfo, + BitStream* bitStream, + int objectType, + int writeFlag); +static int WriteSCE(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int objectType, + int writeFlag); +static int WriteLFE(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int objectType, + int writeFlag); +static int WriteICSInfo(CoderInfo *coderInfo, + BitStream *bitStream, + int objectType, + int common_window, + int writeFlag); +static int WriteICS(CoderInfo *coderInfo, + BitStream *bitStream, + int commonWindow, + int objectType, + int writeFlag); +static int WriteLTPPredictorData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WritePredictorData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WritePulseData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WriteTNSData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WriteGainControlData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WriteSpectralData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static int WriteAACFillBits(BitStream* bitStream, + int numBits, + int writeFlag); +static int FindGroupingBits(CoderInfo *coderInfo); +static long BufferNumBit(BitStream *bitStream); +static int WriteByte(BitStream *bitStream, + unsigned long data, + int numBit); +static int ByteAlign(BitStream* bitStream, + int writeFlag, int bitsSoFar); +#ifdef DRM +static int PutBitHcr(BitStream *bitStream, + unsigned long curpos, + unsigned long data, + int numBit); +static int rewind_word(int W, int len); +static int WriteReorderedSpectralData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); +static void calc_CRC(BitStream *bitStream, int len); +#endif + + +static int WriteFAACStr(BitStream *bitStream, char *version, int write) +{ + int i; + char str[200]; + int len, padbits, count; + int bitcnt; + + sprintf(str, "libfaac %s", version); + + len = strlen(str) + 1; + padbits = (8 - ((bitStream->numBit + 7) % 8)) % 8; + count = len + 3; + + bitcnt = LEN_SE_ID + 4 + ((count < 15) ? 0 : 8) + count * 8; + if (!write) + return bitcnt; + + PutBit(bitStream, ID_FIL, LEN_SE_ID); + if (count < 15) + { + PutBit(bitStream, count, 4); + } + else + { + PutBit(bitStream, 15, 4); + PutBit(bitStream, count - 14, 8); + } + + PutBit(bitStream, 0, padbits); + PutBit(bitStream, 0, 8); + PutBit(bitStream, 0, 8); // just in case + for (i = 0; i < len; i++) + PutBit(bitStream, str[i], 8); + + PutBit(bitStream, 0, 8 - padbits); + + return bitcnt; +} + + +int WriteBitstream(faacEncHandle hEncoder, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int numChannel) +{ + int channel; + int bits = 0; + int bitsLeftAfterFill, numFillBits; + + CountBitstream(hEncoder, coderInfo, channelInfo, bitStream, numChannel); + + if(hEncoder->config.outputFormat == 1){ + bits += WriteADTSHeader(hEncoder, bitStream, 1); + }else{ + bits = 0; // compilier will remove it, byt anyone will see that current size of bitstream is 0 + } + +/* sur: faad2 complains about scalefactor error if we are writing FAAC String */ +#ifndef DRM + if (hEncoder->frameNum == 4) + WriteFAACStr(bitStream, hEncoder->config.name, 1); +#endif + + for (channel = 0; channel < numChannel; channel++) { + + if (channelInfo[channel].present) { + + /* Write out a single_channel_element */ + if (!channelInfo[channel].cpe) { + + if (channelInfo[channel].lfe) { + /* Write out lfe */ + bits += WriteLFE(&coderInfo[channel], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 1); + } else { + /* Write out sce */ + bits += WriteSCE(&coderInfo[channel], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 1); + } + + } else { + + if (channelInfo[channel].ch_is_left) { + /* Write out cpe */ + bits += WriteCPE(&coderInfo[channel], + &coderInfo[channelInfo[channel].paired_ch], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 1); + } + } + } + } + + /* Compute how many fill bits are needed to avoid overflowing bit reservoir */ + /* Save room for ID_END terminator */ + if (bits < (8 - LEN_SE_ID) ) { + numFillBits = 8 - LEN_SE_ID - bits; + } else { + numFillBits = 0; + } + + /* Write AAC fill_elements, smallest fill element is 7 bits. */ + /* Function may leave up to 6 bits left after fill, so tell it to fill a few extra */ + numFillBits += 6; + bitsLeftAfterFill = WriteAACFillBits(bitStream, numFillBits, 1); + bits += (numFillBits - bitsLeftAfterFill); + + /* Write ID_END terminator */ + bits += LEN_SE_ID; + PutBit(bitStream, ID_END, LEN_SE_ID); + + /* Now byte align the bitstream */ + /* + * This byte_alignment() is correct for both MPEG2 and MPEG4, although + * in MPEG4 the byte_alignment() is officially done before the new frame + * instead of at the end. But this is basically the same. + */ + bits += ByteAlign(bitStream, 1, bits); + + return bits; +} + +static int CountBitstream(faacEncHandle hEncoder, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int numChannel) +{ + int channel; + int bits = 0; + int bitsLeftAfterFill, numFillBits; + + + if(hEncoder->config.outputFormat == 1){ + bits += WriteADTSHeader(hEncoder, bitStream, 0); + }else{ + bits = 0; // compilier will remove it, byt anyone will see that current size of bitstream is 0 + } + +/* sur: faad2 complains about scalefactor error if we are writing FAAC String */ +#ifndef DRM + if (hEncoder->frameNum == 4) + bits += WriteFAACStr(bitStream, hEncoder->config.name, 0); +#endif + + for (channel = 0; channel < numChannel; channel++) { + + if (channelInfo[channel].present) { + + /* Write out a single_channel_element */ + if (!channelInfo[channel].cpe) { + + if (channelInfo[channel].lfe) { + /* Write out lfe */ + bits += WriteLFE(&coderInfo[channel], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 0); + } else { + /* Write out sce */ + bits += WriteSCE(&coderInfo[channel], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 0); + } + + } else { + + if (channelInfo[channel].ch_is_left) { + /* Write out cpe */ + bits += WriteCPE(&coderInfo[channel], + &coderInfo[channelInfo[channel].paired_ch], + &channelInfo[channel], + bitStream, + hEncoder->config.aacObjectType, + 0); + } + } + } + } + + /* Compute how many fill bits are needed to avoid overflowing bit reservoir */ + /* Save room for ID_END terminator */ + if (bits < (8 - LEN_SE_ID) ) { + numFillBits = 8 - LEN_SE_ID - bits; + } else { + numFillBits = 0; + } + + /* Write AAC fill_elements, smallest fill element is 7 bits. */ + /* Function may leave up to 6 bits left after fill, so tell it to fill a few extra */ + numFillBits += 6; + bitsLeftAfterFill = WriteAACFillBits(bitStream, numFillBits, 0); + bits += (numFillBits - bitsLeftAfterFill); + + /* Write ID_END terminator */ + bits += LEN_SE_ID; + + /* Now byte align the bitstream */ + bits += ByteAlign(bitStream, 0, bits); + + hEncoder->usedBytes = bit2byte(bits); + + return bits; +} + +static int WriteADTSHeader(faacEncHandle hEncoder, + BitStream *bitStream, + int writeFlag) +{ + int bits = 56; + + if (writeFlag) { + /* Fixed ADTS header */ + PutBit(bitStream, 0xFFFF, 12); /* 12 bit Syncword */ + PutBit(bitStream, hEncoder->config.mpegVersion, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */ + PutBit(bitStream, 0, 2); /* layer == 0 */ + PutBit(bitStream, 1, 1); /* protection absent */ + PutBit(bitStream, hEncoder->config.aacObjectType - 1, 2); /* profile */ + PutBit(bitStream, hEncoder->sampleRateIdx, 4); /* sampling rate */ + PutBit(bitStream, 0, 1); /* private bit */ + PutBit(bitStream, hEncoder->numChannels, 3); /* ch. config (must be > 0) */ + /* simply using numChannels only works for + 6 channels or less, else a channel + configuration should be written */ + PutBit(bitStream, 0, 1); /* original/copy */ + PutBit(bitStream, 0, 1); /* home */ + +#if 0 // Removed in corrigendum 14496-3:2002 + if (hEncoder->config.mpegVersion == 0) + PutBit(bitStream, 0, 2); /* emphasis */ +#endif + + /* Variable ADTS header */ + PutBit(bitStream, 0, 1); /* copyr. id. bit */ + PutBit(bitStream, 0, 1); /* copyr. id. start */ + PutBit(bitStream, hEncoder->usedBytes, 13); + PutBit(bitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */ + PutBit(bitStream, 0, 2); /* raw data blocks (0+1=1) */ + + } + + /* + * MPEG2 says byte_aligment() here, but ADTS always is multiple of 8 bits + * MPEG4 has no byte_alignment() here + */ + /* + if (hEncoder->config.mpegVersion == 1) + bits += ByteAlign(bitStream, writeFlag); + */ + +#if 0 // Removed in corrigendum 14496-3:2002 + if (hEncoder->config.mpegVersion == 0) + bits += 2; /* emphasis */ +#endif + + return bits; +} + +static int WriteCPE(CoderInfo *coderInfoL, + CoderInfo *coderInfoR, + ChannelInfo *channelInfo, + BitStream* bitStream, + int objectType, + int writeFlag) +{ + int bits = 0; + +#ifndef DRM + if (writeFlag) { + /* write ID_CPE, single_element_channel() identifier */ + PutBit(bitStream, ID_CPE, LEN_SE_ID); + + /* write the element_identifier_tag */ + PutBit(bitStream, channelInfo->tag, LEN_TAG); + + /* common_window? */ + PutBit(bitStream, channelInfo->common_window, LEN_COM_WIN); + } + + bits += LEN_SE_ID; + bits += LEN_TAG; + bits += LEN_COM_WIN; +#endif + + /* if common_window, write ics_info */ + if (channelInfo->common_window) { + int numWindows, maxSfb; + + bits += WriteICSInfo(coderInfoL, bitStream, objectType, channelInfo->common_window, writeFlag); + numWindows = coderInfoL->num_window_groups; + maxSfb = coderInfoL->max_sfb; + + if (writeFlag) { + PutBit(bitStream, channelInfo->msInfo.is_present, LEN_MASK_PRES); + if (channelInfo->msInfo.is_present == 1) { + int g; + int b; + for (g=0;gmsInfo.ms_used[g*maxSfb+b], LEN_MASK); + } + } + } + } + bits += LEN_MASK_PRES; + if (channelInfo->msInfo.is_present == 1) + bits += (numWindows*maxSfb*LEN_MASK); + } + + /* Write individual_channel_stream elements */ + bits += WriteICS(coderInfoL, bitStream, channelInfo->common_window, objectType, writeFlag); + bits += WriteICS(coderInfoR, bitStream, channelInfo->common_window, objectType, writeFlag); + + return bits; +} + +static int WriteSCE(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int objectType, + int writeFlag) +{ + int bits = 0; + +#ifndef DRM + if (writeFlag) { + /* write Single Element Channel (SCE) identifier */ + PutBit(bitStream, ID_SCE, LEN_SE_ID); + + /* write the element identifier tag */ + PutBit(bitStream, channelInfo->tag, LEN_TAG); + } + + bits += LEN_SE_ID; + bits += LEN_TAG; +#endif + + /* Write an Individual Channel Stream element */ + bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag); + + return bits; +} + +static int WriteLFE(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int objectType, + int writeFlag) +{ + int bits = 0; + + if (writeFlag) { + /* write ID_LFE, lfe_element_channel() identifier */ + PutBit(bitStream, ID_LFE, LEN_SE_ID); + + /* write the element_identifier_tag */ + PutBit(bitStream, channelInfo->tag, LEN_TAG); + } + + bits += LEN_SE_ID; + bits += LEN_TAG; + + /* Write an individual_channel_stream element */ + bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag); + + return bits; +} + +static int WriteICSInfo(CoderInfo *coderInfo, + BitStream *bitStream, + int objectType, + int common_window, + int writeFlag) +{ + int grouping_bits; + int bits = 0; + + if (writeFlag) { + /* write out ics_info() information */ + PutBit(bitStream, 0, LEN_ICS_RESERV); /* reserved Bit*/ + + /* Write out window sequence */ + PutBit(bitStream, coderInfo->block_type, LEN_WIN_SEQ); /* block type */ + + /* Write out window shape */ + PutBit(bitStream, coderInfo->window_shape, LEN_WIN_SH); /* window shape */ + } + + bits += LEN_ICS_RESERV; + bits += LEN_WIN_SEQ; + bits += LEN_WIN_SH; + + /* For short windows, write out max_sfb and scale_factor_grouping */ + if (coderInfo->block_type == ONLY_SHORT_WINDOW){ + if (writeFlag) { + PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBS); + grouping_bits = FindGroupingBits(coderInfo); + PutBit(bitStream, grouping_bits, MAX_SHORT_WINDOWS - 1); /* the grouping bits */ + } + bits += LEN_MAX_SFBS; + bits += MAX_SHORT_WINDOWS - 1; + } else { /* Otherwise, write out max_sfb and predictor data */ + if (writeFlag) { + PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBL); + } + bits += LEN_MAX_SFBL; +#ifdef DRM + } + if (writeFlag) { + PutBit(bitStream,coderInfo->tnsInfo.tnsDataPresent,LEN_TNS_PRES); + } + bits += LEN_TNS_PRES; +#endif + if (objectType == LTP) + { + bits++; + if(writeFlag) + PutBit(bitStream, coderInfo->ltpInfo.global_pred_flag, 1); /* Prediction Global used */ + + bits += WriteLTPPredictorData(coderInfo, bitStream, writeFlag); + if (common_window) + bits += WriteLTPPredictorData(coderInfo, bitStream, writeFlag); + } else { + bits++; + if (writeFlag) + PutBit(bitStream, coderInfo->pred_global_flag, LEN_PRED_PRES); /* predictor_data_present */ + + bits += WritePredictorData(coderInfo, bitStream, writeFlag); + } +#ifndef DRM + } +#endif + + return bits; +} + +static int WriteICS(CoderInfo *coderInfo, + BitStream *bitStream, + int commonWindow, + int objectType, + int writeFlag) +{ + /* this function writes out an individual_channel_stream to the bitstream and */ + /* returns the number of bits written to the bitstream */ + int bits = 0; + +#ifndef DRM + /* Write the 8-bit global_gain */ + if (writeFlag) + PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN); + bits += LEN_GLOB_GAIN; +#endif + + /* Write ics information */ + if (!commonWindow) { + bits += WriteICSInfo(coderInfo, bitStream, objectType, commonWindow, writeFlag); + } + +#ifdef DRM + /* Write the 8-bit global_gain */ + if (writeFlag) + PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN); + bits += LEN_GLOB_GAIN; +#endif + + bits += SortBookNumbers(coderInfo, bitStream, writeFlag); + bits += WriteScalefactors(coderInfo, bitStream, writeFlag); +#ifdef DRM + if (writeFlag) { + /* length_of_reordered_spectral_data */ + PutBit(bitStream, coderInfo->iLenReordSpData, LEN_HCR_REORDSD); + + /* length_of_longest_codeword */ + PutBit(bitStream, coderInfo->iLenLongestCW, LEN_HCR_LONGCW); + } + bits += LEN_HCR_REORDSD + LEN_HCR_LONGCW; +#else + bits += WritePulseData(coderInfo, bitStream, writeFlag); +#endif + bits += WriteTNSData(coderInfo, bitStream, writeFlag); +#ifndef DRM + bits += WriteGainControlData(coderInfo, bitStream, writeFlag); +#endif + +#ifdef DRM + /* DRM CRC calculation */ + if (writeFlag) + calc_CRC(bitStream, bits); + + bits += WriteReorderedSpectralData(coderInfo, bitStream, writeFlag); +#else + bits += WriteSpectralData(coderInfo, bitStream, writeFlag); +#endif + + /* Return number of bits */ + return bits; +} + +static int WriteLTPPredictorData(CoderInfo *coderInfo, BitStream *bitStream, int writeFlag) +{ + int i, last_band; + int bits; + LtpInfo *ltpInfo = &coderInfo->ltpInfo; + + bits = 0; + + if (ltpInfo->global_pred_flag) + { + + if(writeFlag) + PutBit(bitStream, 1, 1); /* LTP used */ + bits++; + + switch(coderInfo->block_type) + { + case ONLY_LONG_WINDOW: + case LONG_SHORT_WINDOW: + case SHORT_LONG_WINDOW: + bits += LEN_LTP_LAG; + bits += LEN_LTP_COEF; + if(writeFlag) + { + PutBit(bitStream, ltpInfo->delay[0], LEN_LTP_LAG); + PutBit(bitStream, ltpInfo->weight_idx, LEN_LTP_COEF); + } + + last_band = ((coderInfo->nr_of_sfb < MAX_LT_PRED_LONG_SFB) ? + coderInfo->nr_of_sfb : MAX_LT_PRED_LONG_SFB); +// last_band = coderInfo->nr_of_sfb; + + bits += last_band; + if(writeFlag) + for (i = 0; i < last_band; i++) + PutBit(bitStream, ltpInfo->sfb_prediction_used[i], LEN_LTP_LONG_USED); + break; + + default: + break; + } + } + + return (bits); +} + +static int WritePredictorData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag) +{ + int bits = 0; + + /* Write global predictor data present */ + short predictorDataPresent = coderInfo->pred_global_flag; + int numBands = min(coderInfo->max_pred_sfb, coderInfo->nr_of_sfb); + + if (writeFlag) { + if (predictorDataPresent) { + int b; + if (coderInfo->reset_group_number == -1) { + PutBit(bitStream, 0, LEN_PRED_RST); /* No prediction reset */ + } else { + PutBit(bitStream, 1, LEN_PRED_RST); + PutBit(bitStream, (unsigned long)coderInfo->reset_group_number, + LEN_PRED_RSTGRP); + } + + for (b=0;bpred_sfb_flag[b], LEN_PRED_ENAB); + } + } + } + bits += (predictorDataPresent) ? + (LEN_PRED_RST + + ((coderInfo->reset_group_number)!=-1)*LEN_PRED_RSTGRP + + numBands*LEN_PRED_ENAB) : 0; + + return bits; +} + +static int WritePulseData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag) +{ + int bits = 0; + + if (writeFlag) { + PutBit(bitStream, 0, LEN_PULSE_PRES); /* no pulse_data_present */ + } + + bits += LEN_PULSE_PRES; + + return bits; +} + +static int WriteTNSData(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag) +{ + int bits = 0; + int numWindows; + int len_tns_nfilt; + int len_tns_length; + int len_tns_order; + int filtNumber; + int resInBits; + int bitsToTransmit; + unsigned long unsignedIndex; + int w; + + TnsInfo* tnsInfoPtr = &coderInfo->tnsInfo; + +#ifndef DRM + if (writeFlag) { + PutBit(bitStream,tnsInfoPtr->tnsDataPresent,LEN_TNS_PRES); + } + bits += LEN_TNS_PRES; +#endif + + /* If TNS is not present, bail */ + if (!tnsInfoPtr->tnsDataPresent) { + return bits; + } + + /* Set window-dependent TNS parameters */ + if (coderInfo->block_type == ONLY_SHORT_WINDOW) { + numWindows = MAX_SHORT_WINDOWS; + len_tns_nfilt = LEN_TNS_NFILTS; + len_tns_length = LEN_TNS_LENGTHS; + len_tns_order = LEN_TNS_ORDERS; + } + else { + numWindows = 1; + len_tns_nfilt = LEN_TNS_NFILTL; + len_tns_length = LEN_TNS_LENGTHL; + len_tns_order = LEN_TNS_ORDERL; + } + + /* Write TNS data */ + bits += (numWindows * len_tns_nfilt); + for (w=0;wwindowData[w]; + int numFilters = windowDataPtr->numFilters; + if (writeFlag) { + PutBit(bitStream,numFilters,len_tns_nfilt); /* n_filt[] = 0 */ + } + if (numFilters) { + bits += LEN_TNS_COEFF_RES; + resInBits = windowDataPtr->coefResolution; + if (writeFlag) { + PutBit(bitStream,resInBits-DEF_TNS_RES_OFFSET,LEN_TNS_COEFF_RES); + } + bits += numFilters * (len_tns_length+len_tns_order); + for (filtNumber=0;filtNumbertnsFilter[filtNumber]; + int order = tnsFilterPtr->order; + if (writeFlag) { + PutBit(bitStream,tnsFilterPtr->length,len_tns_length); + PutBit(bitStream,order,len_tns_order); + } + if (order) { + bits += (LEN_TNS_DIRECTION + LEN_TNS_COMPRESS); + if (writeFlag) { + PutBit(bitStream,tnsFilterPtr->direction,LEN_TNS_DIRECTION); + PutBit(bitStream,tnsFilterPtr->coefCompress,LEN_TNS_COMPRESS); + } + bitsToTransmit = resInBits - tnsFilterPtr->coefCompress; + bits += order * bitsToTransmit; + if (writeFlag) { + int i; + for (i=1;i<=order;i++) { + unsignedIndex = (unsigned long) (tnsFilterPtr->index[i])&(~(~0<data; + int* len = coderInfo->len; + + if (writeFlag) { + for(i = 0; i < coderInfo->spectral_count; i++) { + if (len[i] > 0) { /* only send out non-zero codebook data */ + PutBit(bitStream, data[i], len[i]); /* write data */ + bits += len[i]; + } + } + } else { + for(i = 0; i < coderInfo->spectral_count; i++) { + bits += len[i]; + } + } + + return bits; +} + +static int WriteAACFillBits(BitStream* bitStream, + int numBits, + int writeFlag) +{ + int numberOfBitsLeft = numBits; + + /* Need at least (LEN_SE_ID + LEN_F_CNT) bits for a fill_element */ + int minNumberOfBits = LEN_SE_ID + LEN_F_CNT; + + while (numberOfBitsLeft >= minNumberOfBits) + { + int numberOfBytes; + int maxCount; + + if (writeFlag) { + PutBit(bitStream, ID_FIL, LEN_SE_ID); /* Write fill_element ID */ + } + numberOfBitsLeft -= minNumberOfBits; /* Subtract for ID,count */ + + numberOfBytes = (int)(numberOfBitsLeft/LEN_BYTE); + maxCount = (1< maxNumberOfBytes ) ? (maxNumberOfBytes) : (numberOfBytes); + escCount = numberOfBytes - maxCount; + if (writeFlag) { + PutBit(bitStream, escCount, LEN_BYTE); + for (i = 0; i < numberOfBytes-1; i++) { + PutBit(bitStream, 0, LEN_BYTE); + } + } + } + numberOfBitsLeft -= LEN_BYTE*numberOfBytes; + } + + return numberOfBitsLeft; +} + +static int FindGroupingBits(CoderInfo *coderInfo) +{ + /* This function inputs the grouping information and outputs the seven bit + 'grouping_bits' field that the AAC decoder expects. */ + + int grouping_bits = 0; + int tmp[8]; + int i, j; + int index = 0; + + for(i = 0; i < coderInfo->num_window_groups; i++){ + for (j = 0; j < coderInfo->window_group_length[i]; j++){ + tmp[index++] = i; + } + } + + for(i = 1; i < 8; i++){ + grouping_bits = grouping_bits << 1; + if(tmp[i] == tmp[i-1]) { + grouping_bits++; + } + } + + return grouping_bits; +} + +/* size in bytes! */ +BitStream *OpenBitStream(int size, unsigned char *buffer) +{ + BitStream *bitStream; + + bitStream = AllocMemory(sizeof(BitStream)); + bitStream->size = size; +#ifdef DRM + /* skip first byte for CRC */ + bitStream->numBit = 8; + bitStream->currentBit = 8; +#else + bitStream->numBit = 0; + bitStream->currentBit = 0; +#endif + bitStream->data = buffer; + SetMemory(bitStream->data, 0, size); + + return bitStream; +} + +int CloseBitStream(BitStream *bitStream) +{ + int bytes = bit2byte(bitStream->numBit); + + FreeMemory(bitStream); + + return bytes; +} + +static long BufferNumBit(BitStream *bitStream) +{ + return bitStream->numBit; +} + +static int WriteByte(BitStream *bitStream, + unsigned long data, + int numBit) +{ + long numUsed,idx; + + idx = (bitStream->currentBit / BYTE_NUMBIT) % bitStream->size; + numUsed = bitStream->currentBit % BYTE_NUMBIT; +#ifndef DRM + if (numUsed == 0) + bitStream->data[idx] = 0; +#endif + bitStream->data[idx] |= (data & ((1<currentBit += numBit; + bitStream->numBit = bitStream->currentBit; + + return 0; +} + +int PutBit(BitStream *bitStream, + unsigned long data, + int numBit) +{ + int num,maxNum,curNum; + unsigned long bits; + + if (numBit == 0) + return 0; + + /* write bits in packets according to buffer byte boundaries */ + num = 0; + maxNum = BYTE_NUMBIT - bitStream->currentBit % BYTE_NUMBIT; + while (num < numBit) { + curNum = min(numBit-num,maxNum); + bits = data>>(numBit-num-curNum); + if (WriteByte(bitStream, bits, curNum)) { + return 1; + } + num += curNum; + maxNum = BYTE_NUMBIT; + } + + return 0; +} + +static int ByteAlign(BitStream *bitStream, int writeFlag, int bitsSoFar) +{ + int len, i,j; + + if (writeFlag) + { + len = BufferNumBit(bitStream); + } else { + len = bitsSoFar; + } + + j = (8 - (len%8))%8; + + if ((len % 8) == 0) j = 0; + if (writeFlag) { + for( i=0; icurrentBit = curpos; + return PutBit(bitStream, data, numBit); +} + +static int rewind_word(int W, int len) +{ /* rewind len (max. 32) bits so that the MSB becomes LSB */ + short i; + int tmp_W = 0; + + for (i = 0; i < len; i++) { + tmp_W <<= 1; + if (W & (1<window_group_length; + int* sfb_offset = coderInfo->sfb_offset; + + cw_info_t cw_info[FRAME_LEN]; + cw_info_t cw_info_preso[FRAME_LEN]; + + int num_cw = coderInfo->cur_cw; + int window_cw_cnt[MAX_SHORT_WINDOWS] = {0,0,0,0,0,0,0,0}; + + int presort, set, num_sets; + + unsigned short cur_cb, cw_cnt; + short is_backwards; + int diff, tmp_data, cw_part_cnt, cur_cw_part; + + int cur_cw_len, cur_data; + int sfb_cnt, win_cnt, acc_win_cnt, win_grp_cnt; + int coeff_cnt, last_sfb, cur_sfb_len; + + /* set up local pointers to data and len */ + /* data array contains data to be written */ + /* len array contains lengths of data words */ + int* data = coderInfo->data; + int* len = coderInfo->len; + int* num_data = coderInfo->num_data_cw; + + if (writeFlag) { + /* build offset table */ + cur_data = 0; + cw_info[0].cw_offset = 0; + for (i = 0; i < num_cw; i++) { + cur_cw_len = 0; + for (j = 0; j < num_data[i]; j++) { + cur_cw_len += len[cur_data++]; + } + + cw_info[i].num_data = num_data[i]; + cw_info[i].cw_len = cur_cw_len; + if (i > 0) /* calculate offset (codeword info parameter) */ + cw_info[i].cw_offset = cw_info[i - 1].cw_offset + num_data[i - 1]; + } + + /* presort codewords ------------------------------------------------ */ + /* classify codewords first */ + sfb_cnt = win_cnt = win_grp_cnt = coeff_cnt = last_sfb = acc_win_cnt = 0; + cur_sfb_len = sfb_offset[1] / window_group_length[0]; + cur_cb = coderInfo->book_vector[0]; + for (i = 0; i < num_cw; i++) { + /* Set codeword info parameters */ + cw_info[i].cb = cur_cb; + cw_info[i].num_sl_cw = (cur_cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN; + + cw_info[i].window = acc_win_cnt + win_cnt; + cw_info[i].cw_nr = window_cw_cnt[cw_info[i].window]; + window_cw_cnt[cw_info[i].window]++; + + coeff_cnt += cw_info[i].num_sl_cw; + if (coeff_cnt - last_sfb >= cur_sfb_len) { + last_sfb += cur_sfb_len; + + win_cnt++; /* next window */ + if (win_cnt == window_group_length[win_grp_cnt]) { + win_cnt = 0; + + sfb_cnt++; /* next sfb */ + if (sfb_cnt == coderInfo->all_sfb) { + sfb_cnt = 0; + + acc_win_cnt += window_group_length[win_grp_cnt]; + win_grp_cnt++; /* next window group */ + } + + /* new codebook and sfb length */ + cur_cb = coderInfo->book_vector[sfb_cnt]; + if (last_sfb < FRAME_LEN) { + cur_sfb_len = (sfb_offset[sfb_cnt + 1] - sfb_offset[sfb_cnt]) + / window_group_length[win_grp_cnt]; + } + } + } + } + + /* presorting (first presorting step) */ + /* only needed for short windows */ + +/* Somehow the second presorting step does not give expected results. Disabling the + following code surprisingly gives good results. TODO: find the bug */ + if (0) {//coderInfo->block_type == ONLY_SHORT_WINDOW) { + for (i = 0; i < MAX_SHORT_WINDOWS; i++) + window_cw_cnt[i] = 0; /* reset all counters */ + + win_cnt = 0; + cw_cnt = 0; + for (i = 0; i < num_cw; i++) { + for (j = 0; j < num_cw; j++) { + if (cw_info[j].window == win_cnt) { + if (cw_info[j].cw_nr == window_cw_cnt[win_cnt]) { + cw_info_preso[cw_cnt++] = cw_info[j]; + window_cw_cnt[win_cnt]++; + + /* check if two one-dimensional codewords */ + if (cw_info[j].num_sl_cw == PAIR_LEN) { + cw_info_preso[cw_cnt++] = cw_info[j + 1]; + window_cw_cnt[win_cnt]++; + } + + win_cnt++; /* next window */ + if (win_cnt == MAX_SHORT_WINDOWS) + win_cnt = 0; + } + } + } + } + } else { + for (i = 0; i < num_cw; i++) { + cw_info_preso[i] = cw_info[i]; /* just copy */ + } + } + + /* presorting (second presorting step) */ + cw_cnt = 0; + for (presort = 0; presort < LEN_PRESORT_CODEBOOK; presort++) { + /* next codebook that has to be processed according to presorting */ + unsigned short nextCB = PresortedCodebook_VCB11[presort]; + + for (i = 0; i < num_cw; i++) { + /* process only codewords that are due now */ + if ((cw_info_preso[i].cb == nextCB) || + ((nextCB < ESC_HCB) && (cw_info_preso[i].cb == nextCB + 1))) + { + cw_info[cw_cnt++] = cw_info_preso[i]; + } + } + } + + /* init segments */ + accsegmsize = 0; + for (i = 0; i < num_cw; i++) { + /* 8.5.3.3.3.2 Derivation of segment width */ + cursegmsize = min(maxCwLen[cw_info[i].cb], coderInfo->iLenLongestCW); + + if (accsegmsize + cursegmsize > coderInfo->iLenReordSpData) { + /* the last segment is extended until iLenReordSpData */ + segment[segmcnt - 1].right = coderInfo->iLenReordSpData - 1; + segment[segmcnt - 1].len = coderInfo->iLenReordSpData - segment[segmcnt - 1].left; + break; + } + + segment[segmcnt].left = accsegmsize; + segment[segmcnt].right = accsegmsize + cursegmsize - 1; + segment[segmcnt++].len = cursegmsize; + accsegmsize += cursegmsize; + } + + /* store current bit position */ + startbitpos = bitStream->currentBit; + + /* write write priority codewords (PCWs) and nonPCWs ---------------- */ + num_sets = num_cw / segmcnt; /* number of sets */ + + for (set = 0; set <= num_sets; set++) { + int trial; + + /* ever second set the bit order is reversed */ + is_backwards = set % 2; + + for (trial = 0; trial < segmcnt; trial++) { + int codewordBase; + int set_encoded = segmcnt; + + if (set == num_sets) + set_encoded = num_cw - set * segmcnt; /* last set is shorter than the rest */ + + for (codewordBase = 0; codewordBase < segmcnt; codewordBase++) { + int segment_index = (trial + codewordBase) % segmcnt; + int codeword_index = codewordBase + set * segmcnt; + + if (codeword_index >= num_cw) + break; + + if ((cw_info[codeword_index].cw_len > 0) && (segment[segment_index].len > 0)) { + /* codeword is not yet written (completely) */ + /* space left in this segment */ + short tmplen; + + /* how many bits can be written? */ + if (segment[segment_index].len >= cw_info[codeword_index].cw_len) { + tmplen = cw_info[codeword_index].cw_len; + set_encoded--; /* CW fits into segment */ + } else { + tmplen = segment[segment_index].len; + } + + /* Adjust lengths */ + cw_info[codeword_index].cw_len -= tmplen; + segment[segment_index].len -= tmplen; + + /* write codewords to bitstream */ + for (cw_part_cnt = 0; cw_part_cnt < cw_info[codeword_index].num_data; cw_part_cnt++) { + cur_cw_part = cw_info[codeword_index].cw_offset + cw_part_cnt; + + if (len[cur_cw_part] <= tmplen) { + /* write complete data, no partitioning */ + if (is_backwards) { + /* write data in reversed bit-order */ + PutBitHcr(bitStream, startbitpos + segment[segment_index].right - len[cur_cw_part] + 1, + rewind_word(data[cur_cw_part], len[cur_cw_part]), len[cur_cw_part]); + + segment[segment_index].right -= len[cur_cw_part]; + } else { + PutBitHcr(bitStream, startbitpos + segment[segment_index].left, + data[cur_cw_part], len[cur_cw_part]); + + segment[segment_index].left += len[cur_cw_part]; + } + + tmplen -= len[cur_cw_part]; + len[cur_cw_part] = 0; + } else { + /* codeword part must be partitioned */ + /* data must be taken from the left side */ + tmp_data = data[cur_cw_part]; + + diff = len[cur_cw_part] - tmplen; + tmp_data >>= diff; + + /* remove bits which are already used */ + data[cur_cw_part] &= (1 << diff) - 1 /* diff number of ones */; + len[cur_cw_part] = diff; + + if (is_backwards) { + /* write data in reversed bit-order */ + PutBitHcr(bitStream, startbitpos + segment[segment_index].right - tmplen + 1, + rewind_word(tmp_data, tmplen), tmplen); + + segment[segment_index].right -= tmplen; + } else { + PutBitHcr(bitStream, startbitpos + segment[segment_index].left, + tmp_data, tmplen); + + segment[segment_index].left += tmplen; + } + + tmplen = 0; + } + + if (tmplen == 0) + break; /* all data written for this segment trial */ + } + } + } /* of codewordBase */ + + if (set_encoded == 0) + break; /* no unencoded codewords left in this set */ + } /* of trial */ + } + + /* set parameter for bit stream to current correct position */ + bitStream->currentBit = startbitpos + coderInfo->iLenReordSpData; + bitStream->numBit = bitStream->currentBit; + } + + return coderInfo->iLenReordSpData; +} + +/* + CRC8 x^8 + x^4 + x^3 + x^2 + 1 +*/ +static const unsigned char _crctable[256] = +{ + 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, + 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, + 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, + 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, + 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, + 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, + 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, + 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, + 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, + 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, + 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, + 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, + 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, + 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F, + 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, + 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, + 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, + 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, + 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, + 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, + 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, + 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, + 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, + 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, + 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, + 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, + 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, + 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, + 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, + 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4 +}; + +static void calc_CRC(BitStream *bitStream, int len) +{ + //int i; + //unsigned char r = ~0; /* Initialize to all ones */ + unsigned char crc = ~0; /* Initialize to all ones */ + + /* CRC polynome used x^8 + x^4 + x^3 + x^2 +1 */ + + unsigned int cb = len / 8; + unsigned int taillen = len & 0x7; + unsigned char* pb = &bitStream->data[1]; + //compatible, but slower unsigned char b = ( bitStream->data[cb + 1] ) >> ( 8 - taillen ); + unsigned char b = bitStream->data[cb + 1]; + +//#define GPOLY 0435 +// +// for (i = 8; i < len + 8; i++) { +// r = ( (r << 1) ^ (( ( +// ( bitStream->data[i / 8] >> (7 - (i % 8)) ) +// & 1) ^ ((r >> 7) & 1)) * GPOLY )) & 0xFF; +// } + +#define GP 0x1d + +//fprintf( stderr, "\nfaac:" ); + + while ( cb-- ) + { +//fprintf( stderr, " %02X", *pb ); + crc = _crctable[ crc ^ *pb++ ]; + } + + //compatible, but slower switch ( taillen ) + //{ + //case 7: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 6 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 6: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 5 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 5: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 4 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 4: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 3 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 3: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 2 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 2: + // crc = ( ( crc << 1 ) ^ ( ( ( ( b >> 1 ) & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // // goto next case + //case 1: + // crc = ( ( crc << 1 ) ^ ( ( ( b & 1 ) ^ ( ( crc >> 7 ) & 1 ) ) * GP ) ) & 0xFF; + // break; + //} +//fprintf( stderr, " %02X", ( b >> ( 8 - taillen ) ) << 7 ); + switch ( taillen ) + { + case 7: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 6: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 5: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 4: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 3: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 2: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + b <<= 1; + // goto next case + case 1: + crc = ( ( crc << 1 ) ^ ( ( (signed char)( b ^ crc ) >> 7 ) & GP ) ) & 0xFF; + break; + } + + //if ( crc != r ) + //{ + // fprintf( stderr, "%08X != %08X\n", crc, r ); + //} +//fprintf( stderr, " (%5d bits), CRC is %02X\n", len, ~crc & 0xFF ); + + /* CRC is stored inverted, per definition at first byte in stream */ + bitStream->data[0] = ~crc; +} +#endif diff --git a/external/libfaac/libfaac/bitstream.h b/external/libfaac/libfaac/bitstream.h new file mode 100644 index 0000000..b56e1a5 --- /dev/null +++ b/external/libfaac/libfaac/bitstream.h @@ -0,0 +1,172 @@ +/********************************************************************** +MPEG-4 Audio VM +Bit stream module + + + +This software module was originally developed by + +Heiko Purnhagen (University of Hannover) + +and edited by + +in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard +ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an +implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools +as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives +users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this +software module or modifications thereof for use in hardware or +software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio +standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing +patents. The original developer of this software module and his/her +company, the subsequent editors and their companies, and ISO/IEC have +no liability for use of this software module or modifications thereof +in an implementation. Copyright is not released for non MPEG-2 +NBC/MPEG-4 Audio conforming products. The original developer retains +full right to use the code for his/her own purpose, assign or donate +the code to a third party and to inhibit third party from using the +code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This +copyright notice must be included in all copies or derivative works. + +Copyright (c) 1996. +**********************************************************************/ +/* + * $Id: bitstream.h,v 1.14 2004/07/04 12:10:52 corrados Exp $ + */ + +#ifndef BITSTREAM_H +#define BITSTREAM_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "frame.h" +#include "coder.h" +#include "channels.h" + +/* + * Raw bitstream constants + */ +#define LEN_SE_ID 3 +#define LEN_TAG 4 +#define LEN_GLOB_GAIN 8 +#define LEN_COM_WIN 1 +#define LEN_ICS_RESERV 1 +#define LEN_WIN_SEQ 2 +#define LEN_WIN_SH 1 +#define LEN_MAX_SFBL 6 +#define LEN_MAX_SFBS 4 +#define LEN_CB 4 +#define LEN_SCL_PCM 8 +#define LEN_PRED_PRES 1 +#define LEN_PRED_RST 1 +#define LEN_PRED_RSTGRP 5 +#define LEN_PRED_ENAB 1 +#define LEN_MASK_PRES 2 +#define LEN_MASK 1 +#define LEN_PULSE_PRES 1 + +#define LEN_TNS_PRES 1 +#define LEN_TNS_NFILTL 2 +#define LEN_TNS_NFILTS 1 +#define LEN_TNS_COEFF_RES 1 +#define LEN_TNS_LENGTHL 6 +#define LEN_TNS_LENGTHS 4 +#define LEN_TNS_ORDERL 5 +#define LEN_TNS_ORDERS 3 +#define LEN_TNS_DIRECTION 1 +#define LEN_TNS_COMPRESS 1 +#define LEN_GAIN_PRES 1 + +#define LEN_NEC_NPULSE 2 +#define LEN_NEC_ST_SFB 6 +#define LEN_NEC_POFF 5 +#define LEN_NEC_PAMP 4 +#define NUM_NEC_LINES 4 +#define NEC_OFFSET_AMP 4 + +#define LEN_NCC 3 +#define LEN_IS_CPE 1 +#define LEN_CC_LR 1 +#define LEN_CC_DOM 1 +#define LEN_CC_SGN 1 +#define LEN_CCH_GES 2 +#define LEN_CCH_CGP 1 +#define LEN_D_CNT 4 +#define LEN_D_ESC 12 +#define LEN_F_CNT 4 +#define LEN_F_ESC 8 +#define LEN_BYTE 8 +#define LEN_PAD_DATA 8 + +#define LEN_PC_COMM 8 + +#ifdef DRM +# define LEN_HCR_REORDSD 14 +# define LEN_HCR_LONGCW 6 +# define FIRST_PAIR_HCB 5 +# define QUAD_LEN 4 +# define PAIR_LEN 2 +# define ESC_HCB 11 +#endif + +#define ID_SCE 0 +#define ID_CPE 1 +#define ID_CCE 2 +#define ID_LFE 3 +#define ID_DSE 4 +#define ID_PCE 5 +#define ID_FIL 6 +#define ID_END 7 + + +/* MPEG ID's */ +#define MPEG2 1 +#define MPEG4 0 + +/* AAC object types */ +#define MAIN 1 +#define LOW 2 +#define SSR 3 +#define LTP 4 + + +#define BYTE_NUMBIT 8 /* bits in byte (char) */ +#define LONG_NUMBIT 32 /* bits in unsigned long */ +#define bit2byte(a) (((a)+BYTE_NUMBIT-1)/BYTE_NUMBIT) + + +typedef struct +{ + unsigned char *data; /* data bits */ + long numBit; /* number of bits in buffer */ + long size; /* buffer size in bytes */ + long currentBit; /* current bit position in bit stream */ + long numByte; /* number of bytes read/written (only file) */ +} BitStream; + + + +int WriteBitstream(faacEncHandle hEncoder, + CoderInfo *coderInfo, + ChannelInfo *channelInfo, + BitStream *bitStream, + int numChannels); + + +BitStream *OpenBitStream(int size, unsigned char *buffer); + +int CloseBitStream(BitStream *bitStream); + +int PutBit(BitStream *bitStream, + unsigned long data, + int numBit); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* BITSTREAM_H */ + diff --git a/external/libfaac/libfaac/channels.c b/external/libfaac/libfaac/channels.c new file mode 100644 index 0000000..c205b02 --- /dev/null +++ b/external/libfaac/libfaac/channels.c @@ -0,0 +1,110 @@ +/************************* MPEG-2 NBC Audio Decoder ************************** + * * +"This software module was originally developed in the course of +development of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, +14496-1,2 and 3. This software module is an implementation of a part of one or more +MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 +Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio +standards free license to this software module or modifications thereof for use in +hardware or software products claiming conformance to the MPEG-2 NBC/MPEG-4 +Audio standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing patents. +The original developer of this software module and his/her company, the subsequent +editors and their companies, and ISO/IEC have no liability for use of this software +module or modifications thereof in an implementation. Copyright is not released for +non MPEG-2 NBC/MPEG-4 Audio conforming products.The original developer +retains full right to use the code for his/her own purpose, assign or donate the +code to a third party and to inhibit third party from using the code for non +MPEG-2 NBC/MPEG-4 Audio conforming products. This copyright notice must +be included in all copies or derivative works." +Copyright(c)1996. + * * + ****************************************************************************/ +/* + * $Id: channels.c,v 1.5 2001/09/04 18:39:35 menno Exp $ + */ + +#include "channels.h" +#include "coder.h" +#include "util.h" + +/* If LFE present */ +/* Num channels # of SCE's # of CPE's #of LFE's */ +/* ============ ========== ========== ========= */ +/* 1 1 0 0 */ +/* 2 0 1 0 */ +/* 3 1 1 0 */ +/* 4 1 1 1 */ +/* 5 1 2 0 */ +/* For more than 5 channels, use the following elements: */ +/* 2*N 1 2*(N-1) 1 */ +/* 2*N+1 1 2*N 0 */ +/* */ +/* Else: */ +/* */ +/* Num channels # of SCE's # of CPE's #of LFE's */ +/* ============ ========== ========== ========= */ +/* 1 1 0 0 */ +/* 2 0 1 0 */ +/* 3 1 1 0 */ +/* 4 2 1 0 */ +/* 5 1 2 0 */ +/* For more than 5 channels, use the following elements: */ +/* 2*N 2 2*(N-1) 0 */ +/* 2*N+1 1 2*N 0 */ + +void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe) +{ + int sceTag = 0; + int lfeTag = 0; + int cpeTag = 0; + int numChannelsLeft = numChannels; + + + /* First element is sce, except for 2 channel case */ + if (numChannelsLeft != 2) { + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].tag = sceTag++; + channelInfo[numChannels-numChannelsLeft].cpe = 0; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + numChannelsLeft--; + } + + /* Next elements are cpe's */ + while (numChannelsLeft > 1) { + /* Left channel info */ + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].tag = cpeTag++; + channelInfo[numChannels-numChannelsLeft].cpe = 1; + channelInfo[numChannels-numChannelsLeft].common_window = 0; + channelInfo[numChannels-numChannelsLeft].ch_is_left = 1; + channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft+1; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + numChannelsLeft--; + + /* Right channel info */ + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].cpe = 1; + channelInfo[numChannels-numChannelsLeft].common_window = 0; + channelInfo[numChannels-numChannelsLeft].ch_is_left = 0; + channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft-1; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + numChannelsLeft--; + } + + /* Is there another channel left ? */ + if (numChannelsLeft) { + if (useLfe) { + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].tag = lfeTag++; + channelInfo[numChannels-numChannelsLeft].cpe = 0; + channelInfo[numChannels-numChannelsLeft].lfe = 1; + } else { + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].tag = sceTag++; + channelInfo[numChannels-numChannelsLeft].cpe = 0; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + } + numChannelsLeft--; + } +} diff --git a/external/libfaac/libfaac/channels.h b/external/libfaac/libfaac/channels.h new file mode 100644 index 0000000..acb8a9d --- /dev/null +++ b/external/libfaac/libfaac/channels.h @@ -0,0 +1,54 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: channels.h,v 1.7 2003/06/26 19:19:41 knik Exp $ + */ + +#ifndef CHANNEL_H +#define CHANNEL_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "coder.h" + +typedef struct { + int is_present; + int ms_used[MAX_SCFAC_BANDS]; +} MSInfo; + +typedef struct { + int tag; + int present; + int ch_is_left; + int paired_ch; + int common_window; + int cpe; + int sce; + int lfe; + MSInfo msInfo; +} ChannelInfo; + +void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CHANNEL_H */ diff --git a/external/libfaac/libfaac/coder.h b/external/libfaac/libfaac/coder.h new file mode 100644 index 0000000..b80ec32 --- /dev/null +++ b/external/libfaac/libfaac/coder.h @@ -0,0 +1,210 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: coder.h,v 1.13 2005/02/02 07:49:10 sur Exp $ + */ + +#ifndef CODER_H +#define CODER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Allow encoding of Digital Radio Mondiale (DRM) */ +//#define DRM + +/* Allow encoding of Digital Radio Mondiale (DRM) with transform length 1024 */ +//#define DRM_1024 + +#define MAX_CHANNELS 64 + +#ifdef DRM +#ifdef DRM_1024 +# define FRAME_LEN 1024 +# define BLOCK_LEN_LONG 1024 +# define BLOCK_LEN_SHORT 128 +#else +# define FRAME_LEN 960 +# define BLOCK_LEN_LONG 960 +# define BLOCK_LEN_SHORT 120 +#endif /* DRM_1024 */ +#else +# define FRAME_LEN 1024 +# define BLOCK_LEN_LONG 1024 +# define BLOCK_LEN_SHORT 128 +#endif + +#define NSFB_LONG 51 +#define NSFB_SHORT 15 +#define MAX_SHORT_WINDOWS 8 +#define MAX_SCFAC_BANDS ((NSFB_SHORT+1)*MAX_SHORT_WINDOWS) + +enum WINDOW_TYPE { + ONLY_LONG_WINDOW, + LONG_SHORT_WINDOW, + ONLY_SHORT_WINDOW, + SHORT_LONG_WINDOW +}; + +#define TNS_MAX_ORDER 20 +#define DEF_TNS_GAIN_THRESH 1.4 +#define DEF_TNS_COEFF_THRESH 0.1 +#define DEF_TNS_COEFF_RES 4 +#define DEF_TNS_RES_OFFSET 3 +#define LEN_TNS_NFILTL 2 +#define LEN_TNS_NFILTS 1 + +#define DELAY 2048 +#define LEN_LTP_DATA_PRESENT 1 +#define LEN_LTP_LAG 11 +#define LEN_LTP_COEF 3 +#define LEN_LTP_SHORT_USED 1 +#define LEN_LTP_SHORT_LAG_PRESENT 1 +#define LEN_LTP_SHORT_LAG 5 +#define LTP_LAG_OFFSET 16 +#define LEN_LTP_LONG_USED 1 +#define MAX_LT_PRED_LONG_SFB 40 +#define MAX_LT_PRED_SHORT_SFB 13 +#define SHORT_SQ_OFFSET (BLOCK_LEN_LONG-(BLOCK_LEN_SHORT*4+BLOCK_LEN_SHORT/2)) +#define CODESIZE 8 +#define NOK_LT_BLEN (3 * BLOCK_LEN_LONG) + +#define SBMAX_L 49 +#define LPC 2 + +typedef struct { + int order; /* Filter order */ + int direction; /* Filtering direction */ + int coefCompress; /* Are coeffs compressed? */ + int length; /* Length, in bands */ + double aCoeffs[TNS_MAX_ORDER+1]; /* AR Coefficients */ + double kCoeffs[TNS_MAX_ORDER+1]; /* Reflection Coefficients */ + int index[TNS_MAX_ORDER+1]; /* Coefficient indices */ +} TnsFilterData; + +typedef struct { + int numFilters; /* Number of filters */ + int coefResolution; /* Coefficient resolution */ + TnsFilterData tnsFilter[1< +#include +#include + +#include "fft.h" +#include "util.h" + +#define MAXLOGM 9 +#define MAXLOGR 8 + +#if defined DRM && !defined DRM_1024 + +#include "kiss_fft/kiss_fft.h" +#include "kiss_fft/kiss_fftr.h" + +static const int logm_to_nfft[] = +{ +/* 0 1 2 3 */ + 0, 0, 0, 0, +/* 4 5 6 7 */ + 0, 0, 60, 0, +/* 8 9 */ + 240, 480 +}; + +void fft_initialize( FFT_Tables *fft_tables ) +{ + memset( fft_tables->cfg, 0, sizeof( fft_tables->cfg ) ); +} +void fft_terminate( FFT_Tables *fft_tables ) +{ + unsigned int i; + for ( i = 0; i < sizeof( fft_tables->cfg ) / sizeof( fft_tables->cfg[0] ); i++ ) + { + if ( fft_tables->cfg[i][0] ) + { + free( fft_tables->cfg[i][0] ); + fft_tables->cfg[i][0] = NULL; + } + if ( fft_tables->cfg[i][1] ) + { + free( fft_tables->cfg[i][1] ); + fft_tables->cfg[i][1] = NULL; + } + } +} + +void rfft( FFT_Tables *fft_tables, double *x, int logm ) +{ +#if 0 +/* sur: do not use real-only optimized FFT */ + double xi[1 << MAXLOGR]; + + int nfft; + + if ( logm > MAXLOGR ) + { + fprintf(stderr, "rfft size too big\n"); + exit(1); + } + + nfft = logm_to_nfft[logm]; + + if ( nfft ) + { + //unsigned int i; + //for ( i = 0; i < nfft; i++ ) + //{ + // xi[i] = 0.0; + //} + memset( xi, 0, nfft * sizeof( xi[0] ) ); + + fft( fft_tables, x, xi, logm ); + + memcpy( x + nfft / 2, xi, ( nfft / 2 ) * sizeof(x[0]) ); + } + else + { + fprintf( stderr, "bad config for logm = %d\n", logm); + exit( 1 ); + } + +#else +/* sur: use real-only optimized FFT */ + + int nfft = 0; + + kiss_fft_scalar fin[1 << MAXLOGR]; + kiss_fft_cpx fout[1 << MAXLOGR]; + + if ( logm > MAXLOGR ) + { + fprintf(stderr, "fft size too big\n"); + exit(1); + } + + nfft = logm_to_nfft[logm]; + + if ( fft_tables->cfg[logm][0] == NULL ) + { + if ( nfft ) + { + fft_tables->cfg[logm][0] = kiss_fftr_alloc( nfft, 0, NULL, NULL ); + } + else + { + fprintf(stderr, "bad logm = %d\n", logm); + exit( 1 ); + } + } + + if ( fft_tables->cfg[logm][0] ) + { + unsigned int i; + + for ( i = 0; i < nfft; i++ ) + { + fin[i] = x[i]; + } + + kiss_fftr( (kiss_fftr_cfg)fft_tables->cfg[logm][0], fin, fout ); + + for ( i = 0; i < nfft / 2; i++ ) + { + x[i] = fout[i].r; + x[i + nfft / 2] = fout[i].i; + } + } + else + { + fprintf( stderr, "bad config for logm = %d\n", logm); + exit( 1 ); + } +#endif +} + +void fft( FFT_Tables *fft_tables, double *xr, double *xi, int logm ) +{ + int nfft = 0; + + kiss_fft_cpx fin[1 << MAXLOGM]; + kiss_fft_cpx fout[1 << MAXLOGM]; + + if ( logm > MAXLOGM ) + { + fprintf(stderr, "fft size too big\n"); + exit(1); + } + + nfft = logm_to_nfft[logm]; + + if ( fft_tables->cfg[logm][0] == NULL ) + { + if ( nfft ) + { + fft_tables->cfg[logm][0] = kiss_fft_alloc( nfft, 0, NULL, NULL ); + } + else + { + fprintf(stderr, "bad logm = %d\n", logm); + exit( 1 ); + } + } + + if ( fft_tables->cfg[logm][0] ) + { + unsigned int i; + + for ( i = 0; i < nfft; i++ ) + { + fin[i].r = xr[i]; + fin[i].i = xi[i]; + } + + kiss_fft( (kiss_fft_cfg)fft_tables->cfg[logm][0], fin, fout ); + + for ( i = 0; i < nfft; i++ ) + { + xr[i] = fout[i].r; + xi[i] = fout[i].i; + } + } + else + { + fprintf( stderr, "bad config for logm = %d\n", logm); + exit( 1 ); + } +} + +void ffti( FFT_Tables *fft_tables, double *xr, double *xi, int logm ) +{ + int nfft = 0; + + kiss_fft_cpx fin[1 << MAXLOGM]; + kiss_fft_cpx fout[1 << MAXLOGM]; + + if ( logm > MAXLOGM ) + { + fprintf(stderr, "fft size too big\n"); + exit(1); + } + + nfft = logm_to_nfft[logm]; + + if ( fft_tables->cfg[logm][1] == NULL ) + { + if ( nfft ) + { + fft_tables->cfg[logm][1] = kiss_fft_alloc( nfft, 1, NULL, NULL ); + } + else + { + fprintf(stderr, "bad logm = %d\n", logm); + exit( 1 ); + } + } + + if ( fft_tables->cfg[logm][1] ) + { + unsigned int i; + double fac = 1.0 / (double)nfft; + + for ( i = 0; i < nfft; i++ ) + { + fin[i].r = xr[i]; + fin[i].i = xi[i]; + } + + kiss_fft( (kiss_fft_cfg)fft_tables->cfg[logm][1], fin, fout ); + + for ( i = 0; i < nfft; i++ ) + { + xr[i] = fout[i].r * fac; + xi[i] = fout[i].i * fac; + } + } + else + { + fprintf( stderr, "bad config for logm = %d\n", logm); + exit( 1 ); + } +} + +/* sur: Trying to use cfft from libfaad2 -- it does not work 'from scratch' */ +// +//#include "cfft/common.h" +// +//void fft_initialize( FFT_Tables *fft_tables ) +//{ +// memset( fft_tables->cfft, 0, sizeof( fft_tables->cfft ) ); +//} +//void fft_terminate( FFT_Tables *fft_tables ) +//{ +// unsigned int i; +// for ( i = 0; i < sizeof( fft_tables->cfft ) / sizeof( fft_tables->cfft[0] ); i++ ) +// { +// if ( fft_tables->cfft[i] ) +// { +// cfftu( fft_tables->cfft[i] ); +// fft_tables->cfft[i] = NULL; +// } +// } +//} +// +//void rfft( FFT_Tables *fft_tables, double *x, int logm ) +//{ +// double xi[1 << MAXLOGR]; +// +// int nfft; +// +// if ( logm > MAXLOGR ) +// { +// fprintf(stderr, "rfft size too big\n"); +// exit(1); +// } +// +// nfft = logm_to_nfft[logm]; +// +// if ( nfft ) +// { +// unsigned int i; +// +// for ( i = 0; i < nfft; i++ ) +// { +// xi[i] = 0.0; +// } +// //memset( xi, 0, nfft * sizeof( xi[0] ) ); +// +// fft( fft_tables, x, xi, logm ); +// +// memcpy( x + nfft / 2, xi, ( nfft / 2 ) * sizeof(x[0]) ); +// +//#ifdef SUR_DEBUG_FFT +// { +// FILE* f = fopen( "fft.log", "at" ); +// +// fprintf( f, "RFFT(%d)\n", nfft ); +// +// for ( i = 0; i < nfft; i++ ) +// { +// fprintf( f, ";%d;%g;%g\n", i, x[i], xi[i] ); +// } +// +// fclose( f ); +// } +//#endif +// } +// else +// { +// fprintf( stderr, "bad config for logm = %d\n", logm); +// exit( 1 ); +// } +//} +// +//void fft( FFT_Tables *fft_tables, double *xr, double *xi, int logm ) +//{ +// int nfft; +// +// complex_t c[1 << MAXLOGM]; +// +// if ( logm > MAXLOGM ) +// { +// fprintf(stderr, "fft size too big\n"); +// exit(1); +// } +// +// nfft = logm_to_nfft[logm]; +// +// if ( fft_tables->cfft[logm] == NULL ) +// { +// if ( nfft ) +// { +// fft_tables->cfft[logm] = cffti( nfft ); +// } +// else +// { +// fprintf(stderr, "bad logm = %d\n", logm); +// exit( 1 ); +// } +// } +// +// if ( fft_tables->cfft[logm] ) +// { +// unsigned int i; +// +// for ( i = 0; i < nfft; i++ ) +// { +// RE( c[i] ) = xr[i]; +// IM( c[i] ) = xi[i]; +// } +// +// cfftf( fft_tables->cfft[logm], c ); +// +// for ( i = 0; i < nfft; i++ ) +// { +// xr[i] = RE( c[i] ); +// xi[i] = IM( c[i] ); +// } +// +//#ifdef SUR_DEBUG_FFT +// { +// FILE* f = fopen( "fft.log", "at" ); +// +// fprintf( f, "FFT(%d)\n", nfft ); +// +// for ( i = 0; i < nfft; i++ ) +// { +// fprintf( f, ";%d;%g;%g\n", i, xr[i], xi[i] ); +// } +// +// fclose( f ); +// } +//#endif +// } +// else +// { +// fprintf( stderr, "bad config for logm = %d\n", logm); +// exit( 1 ); +// } +//} +// +//void ffti( FFT_Tables *fft_tables, double *xr, double *xi, int logm ) +//{ +// int nfft; +// +// complex_t c[1 << MAXLOGM]; +// +// if ( logm > MAXLOGM ) +// { +// fprintf(stderr, "fft size too big\n"); +// exit(1); +// } +// +// nfft = logm_to_nfft[logm]; +// +// if ( fft_tables->cfft[logm] == NULL ) +// { +// if ( nfft ) +// { +// fft_tables->cfft[logm] = cffti( nfft ); +// } +// else +// { +// fprintf(stderr, "bad logm = %d\n", logm); +// exit( 1 ); +// } +// } +// +// if ( fft_tables->cfft[logm] ) +// { +// unsigned int i; +// +// for ( i = 0; i < nfft; i++ ) +// { +// RE( c[i] ) = xr[i]; +// IM( c[i] ) = xi[i]; +// } +// +// cfftb( fft_tables->cfft[logm], c ); +// +// for ( i = 0; i < nfft; i++ ) +// { +// xr[i] = RE( c[i] ); +// xi[i] = IM( c[i] ); +// } +// +//#ifdef SUR_DEBUG_FFT +// { +// FILE* f = fopen( "fft.log", "at" ); +// +// fprintf( f, "FFTI(%d)\n", nfft ); +// +// for ( i = 0; i < nfft; i++ ) +// { +// fprintf( f, ";%d;%g;%g\n", i, xr[i], xi[i] ); +// } +// +// fclose( f ); +// } +//#endif +// } +// else +// { +// fprintf( stderr, "bad config for logm = %d\n", logm); +// exit( 1 ); +// } +//} + +#else /* !defined DRM || defined DRM_1024 */ + +void fft_initialize( FFT_Tables *fft_tables ) +{ + int i; + fft_tables->costbl = AllocMemory( (MAXLOGM+1) * sizeof( fft_tables->costbl[0] ) ); + fft_tables->negsintbl = AllocMemory( (MAXLOGM+1) * sizeof( fft_tables->negsintbl[0] ) ); + fft_tables->reordertbl = AllocMemory( (MAXLOGM+1) * sizeof( fft_tables->reordertbl[0] ) ); + + for( i = 0; i< MAXLOGM+1; i++ ) + { + fft_tables->costbl[i] = NULL; + fft_tables->negsintbl[i] = NULL; + fft_tables->reordertbl[i] = NULL; + } +} + +void fft_terminate( FFT_Tables *fft_tables ) +{ + int i; + + for( i = 0; i< MAXLOGM+1; i++ ) + { + if( fft_tables->costbl[i] != NULL ) + FreeMemory( fft_tables->costbl[i] ); + + if( fft_tables->negsintbl[i] != NULL ) + FreeMemory( fft_tables->negsintbl[i] ); + + if( fft_tables->reordertbl[i] != NULL ) + FreeMemory( fft_tables->reordertbl[i] ); + } + + FreeMemory( fft_tables->costbl ); + FreeMemory( fft_tables->negsintbl ); + FreeMemory( fft_tables->reordertbl ); + + fft_tables->costbl = NULL; + fft_tables->negsintbl = NULL; + fft_tables->reordertbl = NULL; +} + +static void reorder( FFT_Tables *fft_tables, double *x, int logm) +{ + int i; + int size = 1 << logm; + unsigned short *r; //size + + + if ( fft_tables->reordertbl[logm] == NULL ) // create bit reversing table + { + fft_tables->reordertbl[logm] = AllocMemory(size * sizeof(*(fft_tables->reordertbl[0]))); + + for (i = 0; i < size; i++) + { + int reversed = 0; + int b0; + int tmp = i; + + for (b0 = 0; b0 < logm; b0++) + { + reversed = (reversed << 1) | (tmp & 1); + tmp >>= 1; + } + fft_tables->reordertbl[logm][i] = reversed; + } + } + + r = fft_tables->reordertbl[logm]; + + for (i = 0; i < size; i++) + { + int j = r[i]; + double tmp; + + if (j <= i) + continue; + + tmp = x[i]; + x[i] = x[j]; + x[j] = tmp; + } +} + +static void fft_proc( + double *xr, + double *xi, + fftfloat *refac, + fftfloat *imfac, + int size) +{ + int step, shift, pos; + int exp, estep; + + estep = size; + for (step = 1; step < size; step *= 2) + { + int x1; + int x2 = 0; + estep >>= 1; + for (pos = 0; pos < size; pos += (2 * step)) + { + x1 = x2; + x2 += step; + exp = 0; + for (shift = 0; shift < step; shift++) + { + double v2r, v2i; + + v2r = xr[x2] * refac[exp] - xi[x2] * imfac[exp]; + v2i = xr[x2] * imfac[exp] + xi[x2] * refac[exp]; + + xr[x2] = xr[x1] - v2r; + xr[x1] += v2r; + + xi[x2] = xi[x1] - v2i; + + xi[x1] += v2i; + + exp += estep; + + x1++; + x2++; + } + } + } +} + +static void check_tables( FFT_Tables *fft_tables, int logm) +{ + if( fft_tables->costbl[logm] == NULL ) + { + int i; + int size = 1 << logm; + + if( fft_tables->negsintbl[logm] != NULL ) + FreeMemory( fft_tables->negsintbl[logm] ); + + fft_tables->costbl[logm] = AllocMemory((size / 2) * sizeof(*(fft_tables->costbl[0]))); + fft_tables->negsintbl[logm] = AllocMemory((size / 2) * sizeof(*(fft_tables->negsintbl[0]))); + + for (i = 0; i < (size >> 1); i++) + { + double theta = 2.0 * M_PI * ((double) i) / (double) size; + fft_tables->costbl[logm][i] = cos(theta); + fft_tables->negsintbl[logm][i] = -sin(theta); + } + } +} + +void fft( FFT_Tables *fft_tables, double *xr, double *xi, int logm) +{ + if (logm > MAXLOGM) + { + fprintf(stderr, "fft size too big\n"); + exit(1); + } + + if (logm < 1) + { + //printf("logm < 1\n"); + return; + } + + check_tables( fft_tables, logm); + + reorder( fft_tables, xr, logm); + reorder( fft_tables, xi, logm); + + fft_proc( xr, xi, fft_tables->costbl[logm], fft_tables->negsintbl[logm], 1 << logm ); +} + +void rfft( FFT_Tables *fft_tables, double *x, int logm) +{ + double xi[1 << MAXLOGR]; + + if (logm > MAXLOGR) + { + fprintf(stderr, "rfft size too big\n"); + exit(1); + } + + memset(xi, 0, (1 << logm) * sizeof(xi[0])); + + fft( fft_tables, x, xi, logm); + + memcpy(x + (1 << (logm - 1)), xi, (1 << (logm - 1)) * sizeof(*x)); +} + +void ffti( FFT_Tables *fft_tables, double *xr, double *xi, int logm) +{ + int i, size; + double fac; + double *xrp, *xip; + + fft( fft_tables, xi, xr, logm); + + size = 1 << logm; + fac = 1.0 / size; + xrp = xr; + xip = xi; + + for (i = 0; i < size; i++) + { + *xrp++ *= fac; + *xip++ *= fac; + } +} + +#endif /* defined DRM && !defined DRM_1024 */ + +/* +$Log: fft.c,v $ +Revision 1.12 2005/02/02 07:49:55 sur +Added interface to kiss_fft library to implement FFT for 960 transform length. + +Revision 1.11 2004/04/02 14:56:17 danchr +fix name clash w/ libavcodec: fft_init -> fft_initialize +bump version number to 1.24 beta + +Revision 1.10 2003/11/16 05:02:51 stux +moved global tables from fft.c into hEncoder FFT_Tables. Add fft_init and fft_terminate, flowed through all necessary changes. This should remove at least one instance of a memory leak, and fix some thread-safety problems. Version update to 1.23.3 + +Revision 1.9 2003/09/07 16:48:01 knik +reduced arrays size + +Revision 1.8 2002/11/23 17:32:54 knik +rfft: made xi a local variable + +Revision 1.7 2002/08/21 16:52:25 knik +new simplier and faster fft routine and correct real fft +new real fft is just a complex fft wrapper so it is slower than optimal but +by surprise it seems to be at least as fast as the old buggy function + +*/ diff --git a/external/libfaac/libfaac/fft.h b/external/libfaac/libfaac/fft.h new file mode 100644 index 0000000..322db00 --- /dev/null +++ b/external/libfaac/libfaac/fft.h @@ -0,0 +1,55 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * $Id: fft.h,v 1.6 2005/02/02 07:50:35 sur Exp $ + * Copyright (C) 2002 Krzysztof Nikiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _FFT_H_ +#define _FFT_H_ + +typedef float fftfloat; + +#if defined DRM && !defined DRM_1024 + +#define MAX_FFT 10 + +typedef struct +{ + /* cfg[Max FFT][FFT and inverse FFT] */ + void* cfg[MAX_FFT][2]; +} FFT_Tables; + +#else /* use own FFT */ + +typedef struct +{ + fftfloat **costbl; + fftfloat **negsintbl; + unsigned short **reordertbl; +} FFT_Tables; + +#endif /* defined DRM && !defined DRM_1024 */ + +void fft_initialize ( FFT_Tables *fft_tables ); +void fft_terminate ( FFT_Tables *fft_tables ); + +void rfft ( FFT_Tables *fft_tables, double *x, int logm ); +void fft ( FFT_Tables *fft_tables, double *xr, double *xi, int logm ); +void ffti ( FFT_Tables *fft_tables, double *xr, double *xi, int logm ); + +#endif diff --git a/external/libfaac/libfaac/filtbank.c b/external/libfaac/libfaac/filtbank.c new file mode 100644 index 0000000..0a24cce --- /dev/null +++ b/external/libfaac/libfaac/filtbank.c @@ -0,0 +1,578 @@ +/************************* MPEG-2 NBC Audio Decoder ************************** + * * +"This software module was originally developed by +AT&T, Dolby Laboratories, Fraunhofer Gesellschaft IIS in the course of +development of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, +14496-1,2 and 3. This software module is an implementation of a part of one or more +MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 +Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio +standards free license to this software module or modifications thereof for use in +hardware or software products claiming conformance to the MPEG-2 NBC/MPEG-4 +Audio standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing patents. +The original developer of this software module and his/her company, the subsequent +editors and their companies, and ISO/IEC have no liability for use of this software +module or modifications thereof in an implementation. Copyright is not released for +non MPEG-2 NBC/MPEG-4 Audio conforming products.The original developer +retains full right to use the code for his/her own purpose, assign or donate the +code to a third party and to inhibit third party from using the code for non +MPEG-2 NBC/MPEG-4 Audio conforming products. This copyright notice must +be included in all copies or derivative works." +Copyright(c)1996. + * * + ****************************************************************************/ +/* + * $Id: filtbank.c,v 1.13 2005/02/02 07:51:12 sur Exp $ + */ + +/* + * CHANGES: + * 2001/01/17: menno: Added frequency cut off filter. + * + */ + +#include +#include +#include + +#include "coder.h" +#include "filtbank.h" +#include "frame.h" +#include "fft.h" +#include "util.h" + +#define TWOPI 2*M_PI + + +static void CalculateKBDWindow ( double* win, double alpha, int length ); +static double Izero ( double x); +static void MDCT ( FFT_Tables *fft_tables, double *data, int N ); +static void IMDCT ( FFT_Tables *fft_tables, double *data, int N ); + + + +void FilterBankInit(faacEncHandle hEncoder) +{ + unsigned int i, channel; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + hEncoder->freqBuff[channel] = (double*)AllocMemory(2*FRAME_LEN*sizeof(double)); + hEncoder->overlapBuff[channel] = (double*)AllocMemory(FRAME_LEN*sizeof(double)); + SetMemory(hEncoder->overlapBuff[channel], 0, FRAME_LEN*sizeof(double)); + } + + hEncoder->sin_window_long = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double)); + hEncoder->sin_window_short = (double*)AllocMemory(BLOCK_LEN_SHORT*sizeof(double)); + hEncoder->kbd_window_long = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double)); + hEncoder->kbd_window_short = (double*)AllocMemory(BLOCK_LEN_SHORT*sizeof(double)); + + for( i=0; isin_window_long[i] = sin((M_PI/(2*BLOCK_LEN_LONG)) * (i + 0.5)); + for( i=0; isin_window_short[i] = sin((M_PI/(2*BLOCK_LEN_SHORT)) * (i + 0.5)); + + CalculateKBDWindow(hEncoder->kbd_window_long, 4, BLOCK_LEN_LONG*2); + CalculateKBDWindow(hEncoder->kbd_window_short, 6, BLOCK_LEN_SHORT*2); +} + +void FilterBankEnd(faacEncHandle hEncoder) +{ + unsigned int channel; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + if (hEncoder->freqBuff[channel]) FreeMemory(hEncoder->freqBuff[channel]); + if (hEncoder->overlapBuff[channel]) FreeMemory(hEncoder->overlapBuff[channel]); + } + + if (hEncoder->sin_window_long) FreeMemory(hEncoder->sin_window_long); + if (hEncoder->sin_window_short) FreeMemory(hEncoder->sin_window_short); + if (hEncoder->kbd_window_long) FreeMemory(hEncoder->kbd_window_long); + if (hEncoder->kbd_window_short) FreeMemory(hEncoder->kbd_window_short); +} + +void FilterBank(faacEncHandle hEncoder, + CoderInfo *coderInfo, + double *p_in_data, + double *p_out_mdct, + double *p_overlap, + int overlap_select) +{ + double *p_o_buf, *first_window, *second_window; + double *transf_buf; + int k, i; + int block_type = coderInfo->block_type; + + transf_buf = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + + /* create / shift old values */ + /* We use p_overlap here as buffer holding the last frame time signal*/ + if(overlap_select != MNON_OVERLAPPED) { + memcpy(transf_buf, p_overlap, FRAME_LEN*sizeof(double)); + memcpy(transf_buf+BLOCK_LEN_LONG, p_in_data, FRAME_LEN*sizeof(double)); + memcpy(p_overlap, p_in_data, FRAME_LEN*sizeof(double)); + } else { + memcpy(transf_buf, p_in_data, 2*FRAME_LEN*sizeof(double)); + } + + /* Window shape processing */ + if(overlap_select != MNON_OVERLAPPED) { + switch (coderInfo->prev_window_shape) { + case SINE_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW)) + first_window = hEncoder->sin_window_long; + else + first_window = hEncoder->sin_window_short; + break; + case KBD_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW)) + first_window = hEncoder->kbd_window_long; + else + first_window = hEncoder->kbd_window_short; + break; + } + + switch (coderInfo->window_shape){ + case SINE_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW)) + second_window = hEncoder->sin_window_long; + else + second_window = hEncoder->sin_window_short; + break; + case KBD_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW)) + second_window = hEncoder->kbd_window_long; + else + second_window = hEncoder->kbd_window_short; + break; + } + } else { + /* Always long block and sine window for LTP */ + first_window = hEncoder->sin_window_long; + second_window = hEncoder->sin_window_long; + } + + /* Set ptr to transf-Buffer */ + p_o_buf = transf_buf; + + /* Separate action for each Block Type */ + switch (block_type) { + case ONLY_LONG_WINDOW : + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++){ + p_out_mdct[i] = p_o_buf[i] * first_window[i]; + p_out_mdct[i+BLOCK_LEN_LONG] = p_o_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1]; + } + MDCT( &hEncoder->fft_tables, p_out_mdct, 2*BLOCK_LEN_LONG ); + break; + + case LONG_SHORT_WINDOW : + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + p_out_mdct[i] = p_o_buf[i] * first_window[i]; + memcpy(p_out_mdct+BLOCK_LEN_LONG,p_o_buf+BLOCK_LEN_LONG,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++) + p_out_mdct[i+BLOCK_LEN_LONG+NFLAT_LS] = p_o_buf[i+BLOCK_LEN_LONG+NFLAT_LS] * second_window[BLOCK_LEN_SHORT-i-1]; + SetMemory(p_out_mdct+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double)); + MDCT( &hEncoder->fft_tables, p_out_mdct, 2*BLOCK_LEN_LONG ); + break; + + case SHORT_LONG_WINDOW : + SetMemory(p_out_mdct,0,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++) + p_out_mdct[i+NFLAT_LS] = p_o_buf[i+NFLAT_LS] * first_window[i]; + memcpy(p_out_mdct+NFLAT_LS+BLOCK_LEN_SHORT,p_o_buf+NFLAT_LS+BLOCK_LEN_SHORT,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + p_out_mdct[i+BLOCK_LEN_LONG] = p_o_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1]; + MDCT( &hEncoder->fft_tables, p_out_mdct, 2*BLOCK_LEN_LONG ); + break; + + case ONLY_SHORT_WINDOW : + p_o_buf += NFLAT_LS; + for ( k=0; k < MAX_SHORT_WINDOWS; k++ ) { + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++ ){ + p_out_mdct[i] = p_o_buf[i] * first_window[i]; + p_out_mdct[i+BLOCK_LEN_SHORT] = p_o_buf[i+BLOCK_LEN_SHORT] * second_window[BLOCK_LEN_SHORT-i-1]; + } + MDCT( &hEncoder->fft_tables, p_out_mdct, 2*BLOCK_LEN_SHORT ); + p_out_mdct += BLOCK_LEN_SHORT; + p_o_buf += BLOCK_LEN_SHORT; + first_window = second_window; + } + break; + } + + if (transf_buf) FreeMemory(transf_buf); +} + +void IFilterBank(faacEncHandle hEncoder, + CoderInfo *coderInfo, + double *p_in_data, + double *p_out_data, + double *p_overlap, + int overlap_select) +{ + double *o_buf, *transf_buf, *overlap_buf; + double *first_window, *second_window; + + double *fp; + int k, i; + int block_type = coderInfo->block_type; + + transf_buf = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + overlap_buf = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + + /* Window shape processing */ + if (overlap_select != MNON_OVERLAPPED) { +// switch (coderInfo->prev_window_shape){ +// case SINE_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW)) + first_window = hEncoder->sin_window_long; + else + first_window = hEncoder->sin_window_short; +// break; +// case KBD_WINDOW: +// if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW)) +// first_window = hEncoder->kbd_window_long; +// else +// first_window = hEncoder->kbd_window_short; +// break; +// } + +// switch (coderInfo->window_shape){ +// case SINE_WINDOW: + if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW)) + second_window = hEncoder->sin_window_long; + else + second_window = hEncoder->sin_window_short; +// break; +// case KBD_WINDOW: +// if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW)) +// second_window = hEncoder->kbd_window_long; +// else +// second_window = hEncoder->kbd_window_short; +// break; +// } + } else { + /* Always long block and sine window for LTP */ + first_window = hEncoder->sin_window_long; + second_window = hEncoder->sin_window_long; + } + + /* Assemble overlap buffer */ + memcpy(overlap_buf,p_overlap,BLOCK_LEN_LONG*sizeof(double)); + o_buf = overlap_buf; + + /* Separate action for each Block Type */ + switch( block_type ) { + case ONLY_LONG_WINDOW : + memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double)); + IMDCT( &hEncoder->fft_tables, transf_buf, 2*BLOCK_LEN_LONG ); + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + transf_buf[i] *= first_window[i]; + if (overlap_select != MNON_OVERLAPPED) { + for ( i = 0 ; i < BLOCK_LEN_LONG; i++ ){ + o_buf[i] += transf_buf[i]; + o_buf[i+BLOCK_LEN_LONG] = transf_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1]; + } + } else { /* overlap_select == NON_OVERLAPPED */ + for ( i = 0 ; i < BLOCK_LEN_LONG; i++ ) + transf_buf[i+BLOCK_LEN_LONG] *= second_window[BLOCK_LEN_LONG-i-1]; + } + break; + + case LONG_SHORT_WINDOW : + memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double)); + IMDCT( &hEncoder->fft_tables, transf_buf, 2*BLOCK_LEN_LONG ); + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + transf_buf[i] *= first_window[i]; + if (overlap_select != MNON_OVERLAPPED) { + for ( i = 0 ; i < BLOCK_LEN_LONG; i++ ) + o_buf[i] += transf_buf[i]; + memcpy(o_buf+BLOCK_LEN_LONG,transf_buf+BLOCK_LEN_LONG,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++) + o_buf[i+BLOCK_LEN_LONG+NFLAT_LS] = transf_buf[i+BLOCK_LEN_LONG+NFLAT_LS] * second_window[BLOCK_LEN_SHORT-i-1]; + SetMemory(o_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double)); + } else { /* overlap_select == NON_OVERLAPPED */ + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++) + transf_buf[i+BLOCK_LEN_LONG+NFLAT_LS] *= second_window[BLOCK_LEN_SHORT-i-1]; + SetMemory(transf_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double)); + } + break; + + case SHORT_LONG_WINDOW : + memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double)); + IMDCT( &hEncoder->fft_tables, transf_buf, 2*BLOCK_LEN_LONG ); + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++) + transf_buf[i+NFLAT_LS] *= first_window[i]; + if (overlap_select != MNON_OVERLAPPED) { + for ( i = 0 ; i < BLOCK_LEN_SHORT; i++ ) + o_buf[i+NFLAT_LS] += transf_buf[i+NFLAT_LS]; + memcpy(o_buf+BLOCK_LEN_SHORT+NFLAT_LS,transf_buf+BLOCK_LEN_SHORT+NFLAT_LS,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + o_buf[i+BLOCK_LEN_LONG] = transf_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1]; + } else { /* overlap_select == NON_OVERLAPPED */ + SetMemory(transf_buf,0,NFLAT_LS*sizeof(double)); + for ( i = 0 ; i < BLOCK_LEN_LONG ; i++) + transf_buf[i+BLOCK_LEN_LONG] *= second_window[BLOCK_LEN_LONG-i-1]; + } + break; + + case ONLY_SHORT_WINDOW : + if (overlap_select != MNON_OVERLAPPED) { + fp = o_buf + NFLAT_LS; + } else { /* overlap_select == NON_OVERLAPPED */ + fp = transf_buf; + } + for ( k=0; k < MAX_SHORT_WINDOWS; k++ ) { + memcpy(transf_buf,p_in_data,BLOCK_LEN_SHORT*sizeof(double)); + IMDCT( &hEncoder->fft_tables, transf_buf, 2*BLOCK_LEN_SHORT ); + p_in_data += BLOCK_LEN_SHORT; + if (overlap_select != MNON_OVERLAPPED) { + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++){ + transf_buf[i] *= first_window[i]; + fp[i] += transf_buf[i]; + fp[i+BLOCK_LEN_SHORT] = transf_buf[i+BLOCK_LEN_SHORT] * second_window[BLOCK_LEN_SHORT-i-1]; + } + fp += BLOCK_LEN_SHORT; + } else { /* overlap_select == NON_OVERLAPPED */ + for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++){ + fp[i] *= first_window[i]; + fp[i+BLOCK_LEN_SHORT] *= second_window[BLOCK_LEN_SHORT-i-1]; + } + fp += 2*BLOCK_LEN_SHORT; + } + first_window = second_window; + } + SetMemory(o_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double)); + break; + } + + if (overlap_select != MNON_OVERLAPPED) + memcpy(p_out_data,o_buf,BLOCK_LEN_LONG*sizeof(double)); + else /* overlap_select == NON_OVERLAPPED */ + memcpy(p_out_data,transf_buf,2*BLOCK_LEN_LONG*sizeof(double)); + + /* save unused output data */ + memcpy(p_overlap,o_buf+BLOCK_LEN_LONG,BLOCK_LEN_LONG*sizeof(double)); + + if (overlap_buf) FreeMemory(overlap_buf); + if (transf_buf) FreeMemory(transf_buf); +} + +void specFilter(double *freqBuff, + int sampleRate, + int lowpassFreq, + int specLen + ) +{ + int lowpass,xlowpass; + + /* calculate the last line which is not zero */ + lowpass = (lowpassFreq * specLen) / (sampleRate>>1) + 1; + xlowpass = (lowpass < specLen) ? lowpass : specLen ; + + SetMemory(freqBuff+xlowpass,0,(specLen-xlowpass)*sizeof(double)); +} + +static double Izero(double x) +{ + const double IzeroEPSILON = 1E-41; /* Max error acceptable in Izero */ + double sum, u, halfx, temp; + int n; + + sum = u = n = 1; + halfx = x/2.0; + do { + temp = halfx/(double)n; + n += 1; + temp *= temp; + u *= temp; + sum += u; + } while (u >= IzeroEPSILON*sum); + + return(sum); +} + +static void CalculateKBDWindow(double* win, double alpha, int length) +{ + int i; + double IBeta; + double tmp; + double sum = 0.0; + + alpha *= M_PI; + IBeta = 1.0/Izero(alpha); + + /* calculate lower half of Kaiser Bessel window */ + for(i=0; i<(length>>1); i++) { + tmp = 4.0*(double)i/(double)length - 1.0; + win[i] = Izero(alpha*sqrt(1.0-tmp*tmp))*IBeta; + sum += win[i]; + } + + sum = 1.0/sum; + tmp = 0.0; + + /* calculate lower half of window */ + for(i=0; i<(length>>1); i++) { + tmp += win[i]; + win[i] = sqrt(tmp*sum); + } +} + +static void MDCT( FFT_Tables *fft_tables, double *data, int N ) +{ + double *xi, *xr; + double tempr, tempi, c, s, cold, cfreq, sfreq; /* temps for pre and post twiddle */ + double freq = TWOPI / N; + double cosfreq8, sinfreq8; + int i, n; + + xi = (double*)AllocMemory((N >> 2)*sizeof(double)); + xr = (double*)AllocMemory((N >> 2)*sizeof(double)); + + /* prepare for recurrence relation in pre-twiddle */ + cfreq = cos (freq); + sfreq = sin (freq); + cosfreq8 = cos (freq * 0.125); + sinfreq8 = sin (freq * 0.125); + c = cosfreq8; + s = sinfreq8; + + for (i = 0; i < (N >> 2); i++) { + /* calculate real and imaginary parts of g(n) or G(p) */ + n = (N >> 1) - 1 - 2 * i; + + if (i < (N >> 3)) + tempr = data [(N >> 2) + n] + data [N + (N >> 2) - 1 - n]; /* use second form of e(n) for n = N / 2 - 1 - 2i */ + else + tempr = data [(N >> 2) + n] - data [(N >> 2) - 1 - n]; /* use first form of e(n) for n = N / 2 - 1 - 2i */ + + n = 2 * i; + if (i < (N >> 3)) + tempi = data [(N >> 2) + n] - data [(N >> 2) - 1 - n]; /* use first form of e(n) for n=2i */ + else + tempi = data [(N >> 2) + n] + data [N + (N >> 2) - 1 - n]; /* use second form of e(n) for n=2i*/ + + /* calculate pre-twiddled FFT input */ + xr[i] = tempr * c + tempi * s; + xi[i] = tempi * c - tempr * s; + + /* use recurrence to prepare cosine and sine for next value of i */ + cold = c; + c = c * cfreq - s * sfreq; + s = s * cfreq + cold * sfreq; + } + + /* Perform in-place complex FFT of length N/4 */ + switch (N) { + case BLOCK_LEN_SHORT * 2: + fft( fft_tables, xr, xi, 6); + break; + case BLOCK_LEN_LONG * 2: + fft( fft_tables, xr, xi, 9); + } + + /* prepare for recurrence relations in post-twiddle */ + c = cosfreq8; + s = sinfreq8; + + /* post-twiddle FFT output and then get output data */ + for (i = 0; i < (N >> 2); i++) { + /* get post-twiddled FFT output */ + tempr = 2. * (xr[i] * c + xi[i] * s); + tempi = 2. * (xi[i] * c - xr[i] * s); + + /* fill in output values */ + data [2 * i] = -tempr; /* first half even */ + data [(N >> 1) - 1 - 2 * i] = tempi; /* first half odd */ + data [(N >> 1) + 2 * i] = -tempi; /* second half even */ + data [N - 1 - 2 * i] = tempr; /* second half odd */ + + /* use recurrence to prepare cosine and sine for next value of i */ + cold = c; + c = c * cfreq - s * sfreq; + s = s * cfreq + cold * sfreq; + } + + if (xr) FreeMemory(xr); + if (xi) FreeMemory(xi); +} + +static void IMDCT( FFT_Tables *fft_tables, double *data, int N) +{ + double *xi, *xr; + double tempr, tempi, c, s, cold, cfreq, sfreq; /* temps for pre and post twiddle */ + double freq = 2.0 * M_PI / N; + double fac, cosfreq8, sinfreq8; + int i; + + xi = (double*)AllocMemory((N >> 2)*sizeof(double)); + xr = (double*)AllocMemory((N >> 2)*sizeof(double)); + + /* Choosing to allocate 2/N factor to Inverse Xform! */ + fac = 2. / N; /* remaining 2/N from 4/N IFFT factor */ + + /* prepare for recurrence relation in pre-twiddle */ + cfreq = cos (freq); + sfreq = sin (freq); + cosfreq8 = cos (freq * 0.125); + sinfreq8 = sin (freq * 0.125); + c = cosfreq8; + s = sinfreq8; + + for (i = 0; i < (N >> 2); i++) { + /* calculate real and imaginary parts of g(n) or G(p) */ + tempr = -data[2 * i]; + tempi = data[(N >> 1) - 1 - 2 * i]; + + /* calculate pre-twiddled FFT input */ + xr[i] = tempr * c - tempi * s; + xi[i] = tempi * c + tempr * s; + + /* use recurrence to prepare cosine and sine for next value of i */ + cold = c; + c = c * cfreq - s * sfreq; + s = s * cfreq + cold * sfreq; + } + + /* Perform in-place complex IFFT of length N/4 */ + switch (N) { + case BLOCK_LEN_SHORT * 2: + ffti( fft_tables, xr, xi, 6); + break; + case BLOCK_LEN_LONG * 2: + ffti( fft_tables, xr, xi, 9); + } + + /* prepare for recurrence relations in post-twiddle */ + c = cosfreq8; + s = sinfreq8; + + /* post-twiddle FFT output and then get output data */ + for (i = 0; i < (N >> 2); i++) { + + /* get post-twiddled FFT output */ + tempr = fac * (xr[i] * c - xi[i] * s); + tempi = fac * (xi[i] * c + xr[i] * s); + + /* fill in output values */ + data [(N >> 1) + (N >> 2) - 1 - 2 * i] = tempr; + if (i < (N >> 3)) + data [(N >> 1) + (N >> 2) + 2 * i] = tempr; + else + data [2 * i - (N >> 2)] = -tempr; + + data [(N >> 2) + 2 * i] = tempi; + if (i < (N >> 3)) + data [(N >> 2) - 1 - 2 * i] = -tempi; + else + data [(N >> 2) + N - 1 - 2*i] = tempi; + + /* use recurrence to prepare cosine and sine for next value of i */ + cold = c; + c = c * cfreq - s * sfreq; + s = s * cfreq + cold * sfreq; + } + + if (xr) FreeMemory(xr); + if (xi) FreeMemory(xi); +} diff --git a/external/libfaac/libfaac/filtbank.h b/external/libfaac/libfaac/filtbank.h new file mode 100644 index 0000000..4a869e9 --- /dev/null +++ b/external/libfaac/libfaac/filtbank.h @@ -0,0 +1,71 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: filtbank.h,v 1.11 2005/02/02 07:51:49 sur Exp $ + */ + +#ifndef FILTBANK_H +#define FILTBANK_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "frame.h" + +#ifdef DRM +#define NFLAT_LS (( BLOCK_LEN_LONG - BLOCK_LEN_SHORT ) / 2) +#else +#define NFLAT_LS 448 +#endif + +#define MOVERLAPPED 0 +#define MNON_OVERLAPPED 1 + + +#define SINE_WINDOW 0 +#define KBD_WINDOW 1 + +void FilterBankInit ( faacEncHandle hEncoder ); + +void FilterBankEnd ( faacEncHandle hEncoder ); + +void FilterBank( faacEncHandle hEncoder, + CoderInfo *coderInfo, + double *p_in_data, + double *p_out_mdct, + double *p_overlap, + int overlap_select ); + +void IFilterBank( faacEncHandle hEncoder, + CoderInfo *coderInfo, + double *p_in_data, + double *p_out_mdct, + double *p_overlap, + int overlap_select ); + +void specFilter( double *freqBuff, + int sampleRate, + int lowpassFreq, + int specLen ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* FILTBANK_H */ diff --git a/external/libfaac/libfaac/frame.c b/external/libfaac/libfaac/frame.c new file mode 100644 index 0000000..c66325e --- /dev/null +++ b/external/libfaac/libfaac/frame.c @@ -0,0 +1,1252 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: frame.c,v 1.67 2004/11/17 14:26:06 menno Exp $ + */ + +/* + * CHANGES: + * 2001/01/17: menno: Added frequency cut off filter. + * 2001/02/28: menno: Added Temporal Noise Shaping. + * 2001/03/05: menno: Added Long Term Prediction. + * 2001/05/01: menno: Added backward prediction. + * + */ + +#include +#include +#include +#include + +#include "frame.h" +#include "coder.h" +#include "midside.h" +#include "channels.h" +#include "bitstream.h" +#include "filtbank.h" +#include "aacquant.h" +#include "util.h" +#include "huffman.h" +#include "psych.h" +#include "tns.h" +#include "ltp.h" +#include "backpred.h" +#include "version.h" + +#if FAAC_RELEASE +static char *libfaacName = FAAC_VERSION; +#else +static char *libfaacName = FAAC_VERSION ".1 (" __DATE__ ") UNSTABLE"; +#endif +static char *libCopyright = + "FAAC - Freeware Advanced Audio Coder (http://www.audiocoding.com/)\n" + " Copyright (C) 1999,2000,2001 Menno Bakker\n" + " Copyright (C) 2002,2003 Krzysztof Nikiel\n" + "This software is based on the ISO MPEG-4 reference source code.\n"; + +static const psymodellist_t psymodellist[] = { + {&psymodel2, "knipsycho psychoacoustic"}, + {NULL} +}; + +static SR_INFO srInfo[12+1]; + +// base bandwidth for q=100 +static const int bwbase = 16000; +// bandwidth multiplier (for quantiser) +static const int bwmult = 120; +// max bandwidth/samplerate ratio +static const double bwfac = 0.45; + + +int FAACAPI faacEncGetVersion( char **faac_id_string, + char **faac_copyright_string) +{ + if (faac_id_string) + *faac_id_string = libfaacName; + + if (faac_copyright_string) + *faac_copyright_string = libCopyright; + + return FAAC_CFG_VERSION; +} + + +int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder,unsigned char** ppBuffer,unsigned long* pSizeOfDecoderSpecificInfo) +{ + BitStream* pBitStream = NULL; + + if((hEncoder == NULL) || (ppBuffer == NULL) || (pSizeOfDecoderSpecificInfo == NULL)) { + return -1; + } + + if(hEncoder->config.mpegVersion == MPEG2){ + return -2; /* not supported */ + } + + *pSizeOfDecoderSpecificInfo = 2; + *ppBuffer = malloc(2); + + if(*ppBuffer != NULL){ + + memset(*ppBuffer,0,*pSizeOfDecoderSpecificInfo); + pBitStream = OpenBitStream(*pSizeOfDecoderSpecificInfo, *ppBuffer); + PutBit(pBitStream, hEncoder->config.aacObjectType, 5); + PutBit(pBitStream, hEncoder->sampleRateIdx, 4); + PutBit(pBitStream, hEncoder->numChannels, 4); + CloseBitStream(pBitStream); + + return 0; + } else { + return -3; + } +} + + +faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder) +{ + faacEncConfigurationPtr config = &(hEncoder->config); + + return config; +} + +int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder, + faacEncConfigurationPtr config) +{ + int i; + + hEncoder->config.allowMidside = config->allowMidside; + hEncoder->config.useLfe = config->useLfe; + hEncoder->config.useTns = config->useTns; + hEncoder->config.aacObjectType = config->aacObjectType; + hEncoder->config.mpegVersion = config->mpegVersion; + hEncoder->config.outputFormat = config->outputFormat; + hEncoder->config.inputFormat = config->inputFormat; + hEncoder->config.shortctl = config->shortctl; + + assert((hEncoder->config.outputFormat == 0) || (hEncoder->config.outputFormat == 1)); + + switch( hEncoder->config.inputFormat ) + { + case FAAC_INPUT_16BIT: + //case FAAC_INPUT_24BIT: + case FAAC_INPUT_32BIT: + case FAAC_INPUT_FLOAT: + break; + + default: + return 0; + break; + } + + /* No SSR supported for now */ + if (hEncoder->config.aacObjectType == SSR) + return 0; + + /* LTP only with MPEG4 */ + if ((hEncoder->config.aacObjectType == LTP) && (hEncoder->config.mpegVersion != MPEG4)) + return 0; + + /* Re-init TNS for new profile */ + TnsInit(hEncoder); + + /* Check for correct bitrate */ + if (config->bitRate > MaxBitrate(hEncoder->sampleRate)) + return 0; +#if 0 + if (config->bitRate < MinBitrate()) + return 0; +#endif + + if (config->bitRate && !config->bandWidth) + { + static struct { + int rate; // per channel at 44100 sampling frequency + int cutoff; + } rates[] = { +#ifdef DRM + /* DRM uses low bit-rates. We've chosen higher bandwidth values and + decrease the quantizer quality at the same time to preserve the + low bit-rate */ + {4500, 1200}, + {9180, 2500}, + {11640, 3000}, + {14500, 4000}, + {17460, 5500}, + {20960, 6250}, + {40000, 12000}, +#else + {29500, 5000}, + {37500, 7000}, + {47000, 10000}, + {64000, 16000}, + {76000, 20000}, +#endif + {0, 0} + }; + + int f0, f1; + int r0, r1; + +#ifdef DRM + double tmpbitRate = (double)config->bitRate; +#else + double tmpbitRate = (double)config->bitRate * 44100 / hEncoder->sampleRate; +#endif + + config->quantqual = 100; + + f0 = f1 = rates[0].cutoff; + r0 = r1 = rates[0].rate; + + for (i = 0; rates[i].rate; i++) + { + f0 = f1; + f1 = rates[i].cutoff; + r0 = r1; + r1 = rates[i].rate; + if (rates[i].rate >= tmpbitRate) + break; + } + + if (tmpbitRate > r1) + tmpbitRate = r1; + if (tmpbitRate < r0) + tmpbitRate = r0; + + if (f1 > f0) + config->bandWidth = + pow((double)tmpbitRate / r1, + log((double)f1 / f0) / log ((double)r1 / r0)) * (double)f1; + else + config->bandWidth = f1; + +#ifndef DRM + config->bandWidth = + (double)config->bandWidth * hEncoder->sampleRate / 44100; + config->bitRate = tmpbitRate * hEncoder->sampleRate / 44100; +#endif + + if (config->bandWidth > bwbase) + config->bandWidth = bwbase; + } + + hEncoder->config.bitRate = config->bitRate; + + if (!config->bandWidth) + { + config->bandWidth = (config->quantqual - 100) * bwmult + bwbase; + } + + hEncoder->config.bandWidth = config->bandWidth; + + // check bandwidth + if (hEncoder->config.bandWidth < 100) + hEncoder->config.bandWidth = 100; + if (hEncoder->config.bandWidth > (hEncoder->sampleRate / 2)) + hEncoder->config.bandWidth = hEncoder->sampleRate / 2; + + if (config->quantqual > 500) + config->quantqual = 500; + if (config->quantqual < 10) + config->quantqual = 10; + + hEncoder->config.quantqual = config->quantqual; + + /* set quantization quality */ + hEncoder->aacquantCfg.quality = config->quantqual; + + // reset psymodel + hEncoder->psymodel->PsyEnd(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels); + if (config->psymodelidx >= (sizeof(psymodellist) / sizeof(psymodellist[0]) - 1)) + config->psymodelidx = (sizeof(psymodellist) / sizeof(psymodellist[0])) - 2; + + hEncoder->config.psymodelidx = config->psymodelidx; + hEncoder->psymodel = psymodellist[hEncoder->config.psymodelidx].model; + hEncoder->psymodel->PsyInit(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels, + hEncoder->sampleRate, hEncoder->srInfo->cb_width_long, + hEncoder->srInfo->num_cb_long, hEncoder->srInfo->cb_width_short, + hEncoder->srInfo->num_cb_short); + + /* load channel_map */ + for( i = 0; i < 64; i++ ) + hEncoder->config.channel_map[i] = config->channel_map[i]; + + /* OK */ + return 1; +} + +faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, + unsigned int numChannels, + unsigned long *inputSamples, + unsigned long *maxOutputBytes) +{ + unsigned int channel; + faacEncHandle hEncoder; + + *inputSamples = FRAME_LEN*numChannels; + *maxOutputBytes = (6144/8)*numChannels; + +#ifdef DRM + *maxOutputBytes += 1; /* for CRC */ +#endif + + hEncoder = (faacEncStruct*)AllocMemory(sizeof(faacEncStruct)); + SetMemory(hEncoder, 0, sizeof(faacEncStruct)); + + hEncoder->numChannels = numChannels; + hEncoder->sampleRate = sampleRate; + hEncoder->sampleRateIdx = GetSRIndex(sampleRate); + + /* Initialize variables to default values */ + hEncoder->frameNum = 0; + hEncoder->flushFrame = 0; + + /* Default configuration */ + hEncoder->config.version = FAAC_CFG_VERSION; + hEncoder->config.name = libfaacName; + hEncoder->config.copyright = libCopyright; + hEncoder->config.mpegVersion = MPEG4; + hEncoder->config.aacObjectType = LTP; + hEncoder->config.allowMidside = 1; + hEncoder->config.useLfe = 1; + hEncoder->config.useTns = 0; + hEncoder->config.bitRate = 0; /* default bitrate / channel */ + hEncoder->config.bandWidth = bwfac * hEncoder->sampleRate; + if (hEncoder->config.bandWidth > bwbase) + hEncoder->config.bandWidth = bwbase; + hEncoder->config.quantqual = 100; + hEncoder->config.psymodellist = (psymodellist_t *)psymodellist; + hEncoder->config.psymodelidx = 0; + hEncoder->psymodel = + hEncoder->config.psymodellist[hEncoder->config.psymodelidx].model; + hEncoder->config.shortctl = SHORTCTL_NORMAL; + + /* default channel map is straight-through */ + for( channel = 0; channel < 64; channel++ ) + hEncoder->config.channel_map[channel] = channel; + + /* + by default we have to be compatible with all previous software + which assumes that we will generate ADTS + /AV + */ + hEncoder->config.outputFormat = 1; + + /* + be compatible with software which assumes 24bit in 32bit PCM + */ + hEncoder->config.inputFormat = FAAC_INPUT_32BIT; + + /* find correct sampling rate depending parameters */ + hEncoder->srInfo = &srInfo[hEncoder->sampleRateIdx]; + + for (channel = 0; channel < numChannels; channel++) + { + hEncoder->coderInfo[channel].prev_window_shape = SINE_WINDOW; + hEncoder->coderInfo[channel].window_shape = SINE_WINDOW; + hEncoder->coderInfo[channel].block_type = ONLY_LONG_WINDOW; + hEncoder->coderInfo[channel].num_window_groups = 1; + hEncoder->coderInfo[channel].window_group_length[0] = 1; + + /* FIXME: Use sr_idx here */ + hEncoder->coderInfo[channel].max_pred_sfb = GetMaxPredSfb(hEncoder->sampleRateIdx); + + hEncoder->sampleBuff[channel] = NULL; + hEncoder->nextSampleBuff[channel] = NULL; + hEncoder->next2SampleBuff[channel] = NULL; + hEncoder->ltpTimeBuff[channel] = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + SetMemory(hEncoder->ltpTimeBuff[channel], 0, 2*BLOCK_LEN_LONG*sizeof(double)); + } + + /* Initialize coder functions */ + fft_initialize( &hEncoder->fft_tables ); + + hEncoder->psymodel->PsyInit(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels, + hEncoder->sampleRate, hEncoder->srInfo->cb_width_long, + hEncoder->srInfo->num_cb_long, hEncoder->srInfo->cb_width_short, + hEncoder->srInfo->num_cb_short); + + FilterBankInit(hEncoder); + + TnsInit(hEncoder); + + LtpInit(hEncoder); + + PredInit(hEncoder); + + AACQuantizeInit(hEncoder->coderInfo, hEncoder->numChannels, + &(hEncoder->aacquantCfg)); + + + + HuffmanInit(hEncoder->coderInfo, hEncoder->numChannels); + + /* Return handle */ + return hEncoder; +} + +int FAACAPI faacEncClose(faacEncHandle hEncoder) +{ + unsigned int channel; + + /* Deinitialize coder functions */ + hEncoder->psymodel->PsyEnd(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels); + + FilterBankEnd(hEncoder); + + LtpEnd(hEncoder); + + AACQuantizeEnd(hEncoder->coderInfo, hEncoder->numChannels, + &(hEncoder->aacquantCfg)); + + HuffmanEnd(hEncoder->coderInfo, hEncoder->numChannels); + + fft_terminate( &hEncoder->fft_tables ); + + /* Free remaining buffer memory */ + for (channel = 0; channel < hEncoder->numChannels; channel++) + { + if (hEncoder->ltpTimeBuff[channel]) + FreeMemory(hEncoder->ltpTimeBuff[channel]); + if (hEncoder->sampleBuff[channel]) + FreeMemory(hEncoder->sampleBuff[channel]); + if (hEncoder->nextSampleBuff[channel]) + FreeMemory(hEncoder->nextSampleBuff[channel]); + if (hEncoder->next2SampleBuff[channel]) + FreeMemory (hEncoder->next2SampleBuff[channel]); + if (hEncoder->next3SampleBuff[channel]) + FreeMemory (hEncoder->next3SampleBuff[channel]); + } + + /* Free handle */ + if (hEncoder) + FreeMemory(hEncoder); + + return 0; +} + +int FAACAPI faacEncEncode(faacEncHandle hEncoder, + int32_t *inputBuffer, + unsigned int samplesInput, + unsigned char *outputBuffer, + unsigned int bufferSize + ) +{ + unsigned int channel, i; + int sb, frameBytes; + unsigned int offset; + BitStream *bitStream; /* bitstream used for writing the frame to */ + TnsInfo *tnsInfo_for_LTP; + TnsInfo *tnsDecInfo; +#ifdef DRM + int desbits, diff; + double fix; +#endif + + /* local copy's of parameters */ + ChannelInfo *channelInfo = hEncoder->channelInfo; + CoderInfo *coderInfo = hEncoder->coderInfo; + unsigned int numChannels = hEncoder->numChannels; + unsigned int sampleRate = hEncoder->sampleRate; + unsigned int aacObjectType = hEncoder->config.aacObjectType; + unsigned int mpegVersion = hEncoder->config.mpegVersion; + unsigned int useLfe = hEncoder->config.useLfe; + unsigned int useTns = hEncoder->config.useTns; + unsigned int allowMidside = hEncoder->config.allowMidside; + unsigned int bandWidth = hEncoder->config.bandWidth; + unsigned int shortctl = hEncoder->config.shortctl; + + /* Increase frame number */ + hEncoder->frameNum++; + + if (samplesInput == 0) + hEncoder->flushFrame++; + + /* After 4 flush frames all samples have been encoded, + return 0 bytes written */ + if (hEncoder->flushFrame > 4) + return 0; + + /* Determine the channel configuration */ + GetChannelInfo(channelInfo, numChannels, useLfe); + + /* Update current sample buffers */ + for (channel = 0; channel < numChannels; channel++) + { + double *tmp; + + if (hEncoder->sampleBuff[channel]) { + for(i = 0; i < FRAME_LEN; i++) { + hEncoder->ltpTimeBuff[channel][i] = hEncoder->sampleBuff[channel][i]; + } + } + if (hEncoder->nextSampleBuff[channel]) { + for(i = 0; i < FRAME_LEN; i++) { + hEncoder->ltpTimeBuff[channel][FRAME_LEN + i] = + hEncoder->nextSampleBuff[channel][i]; + } + } + + if (!hEncoder->sampleBuff[channel]) + hEncoder->sampleBuff[channel] = (double*)AllocMemory(FRAME_LEN*sizeof(double)); + + tmp = hEncoder->sampleBuff[channel]; + + hEncoder->sampleBuff[channel] = hEncoder->nextSampleBuff[channel]; + hEncoder->nextSampleBuff[channel] = hEncoder->next2SampleBuff[channel]; + hEncoder->next2SampleBuff[channel] = hEncoder->next3SampleBuff[channel]; + hEncoder->next3SampleBuff[channel] = tmp; + + if (samplesInput == 0) + { + /* start flushing*/ + for (i = 0; i < FRAME_LEN; i++) + hEncoder->next3SampleBuff[channel][i] = 0.0; + } + else + { + int samples_per_channel = samplesInput/numChannels; + + /* handle the various input formats and channel remapping */ + switch( hEncoder->config.inputFormat ) + { + case FAAC_INPUT_16BIT: + { + short *input_channel = (short*)inputBuffer + hEncoder->config.channel_map[channel]; + + for (i = 0; i < samples_per_channel; i++) + { + hEncoder->next3SampleBuff[channel][i] = (double)*input_channel; + input_channel += numChannels; + } + } + break; + + case FAAC_INPUT_32BIT: + { + int32_t *input_channel = (int32_t*)inputBuffer + hEncoder->config.channel_map[channel]; + + for (i = 0; i < samples_per_channel; i++) + { + hEncoder->next3SampleBuff[channel][i] = (1.0/256) * (double)*input_channel; + input_channel += numChannels; + } + } + break; + + case FAAC_INPUT_FLOAT: + { + float *input_channel = (float*)inputBuffer + hEncoder->config.channel_map[channel]; + + for (i = 0; i < samples_per_channel; i++) + { + hEncoder->next3SampleBuff[channel][i] = (double)*input_channel; + input_channel += numChannels; + } + } + break; + + default: + return -1; /* invalid input format */ + break; + } + + for (i = (int)(samplesInput/numChannels); i < FRAME_LEN; i++) + hEncoder->next3SampleBuff[channel][i] = 0.0; + } + + /* Psychoacoustics */ + /* Update buffers and run FFT on new samples */ + /* LFE psychoacoustic can run without it */ + if (!channelInfo[channel].lfe || channelInfo[channel].cpe) + { + hEncoder->psymodel->PsyBufferUpdate( + &hEncoder->fft_tables, + &hEncoder->gpsyInfo, + &hEncoder->psyInfo[channel], + hEncoder->next3SampleBuff[channel], + bandWidth, + hEncoder->srInfo->cb_width_short, + hEncoder->srInfo->num_cb_short); + } + } + + if (hEncoder->frameNum <= 3) /* Still filling up the buffers */ + return 0; + + /* Psychoacoustics */ + hEncoder->psymodel->PsyCalculate(channelInfo, &hEncoder->gpsyInfo, hEncoder->psyInfo, + hEncoder->srInfo->cb_width_long, hEncoder->srInfo->num_cb_long, + hEncoder->srInfo->cb_width_short, + hEncoder->srInfo->num_cb_short, numChannels); + + hEncoder->psymodel->BlockSwitch(coderInfo, hEncoder->psyInfo, numChannels); + + /* force block type */ + if (shortctl == SHORTCTL_NOSHORT) + { + for (channel = 0; channel < numChannels; channel++) + { + coderInfo[channel].block_type = ONLY_LONG_WINDOW; + } + } + if (shortctl == SHORTCTL_NOLONG) + { + for (channel = 0; channel < numChannels; channel++) + { + coderInfo[channel].block_type = ONLY_SHORT_WINDOW; + } + } + + /* AAC Filterbank, MDCT with overlap and add */ + for (channel = 0; channel < numChannels; channel++) { + int k; + + FilterBank(hEncoder, + &coderInfo[channel], + hEncoder->sampleBuff[channel], + hEncoder->freqBuff[channel], + hEncoder->overlapBuff[channel], + MOVERLAPPED); + + if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) { + for (k = 0; k < 8; k++) { + specFilter(hEncoder->freqBuff[channel]+k*BLOCK_LEN_SHORT, + sampleRate, bandWidth, BLOCK_LEN_SHORT); + } + } else { + specFilter(hEncoder->freqBuff[channel], sampleRate, + bandWidth, BLOCK_LEN_LONG); + } + } + + /* TMP: Build sfb offset table and other stuff */ + for (channel = 0; channel < numChannels; channel++) { + channelInfo[channel].msInfo.is_present = 0; + + if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) { + coderInfo[channel].max_sfb = hEncoder->srInfo->num_cb_short; + coderInfo[channel].nr_of_sfb = hEncoder->srInfo->num_cb_short; + + coderInfo[channel].num_window_groups = 1; + coderInfo[channel].window_group_length[0] = 8; + coderInfo[channel].window_group_length[1] = 0; + coderInfo[channel].window_group_length[2] = 0; + coderInfo[channel].window_group_length[3] = 0; + coderInfo[channel].window_group_length[4] = 0; + coderInfo[channel].window_group_length[5] = 0; + coderInfo[channel].window_group_length[6] = 0; + coderInfo[channel].window_group_length[7] = 0; + + offset = 0; + for (sb = 0; sb < coderInfo[channel].nr_of_sfb; sb++) { + coderInfo[channel].sfb_offset[sb] = offset; + offset += hEncoder->srInfo->cb_width_short[sb]; + } + coderInfo[channel].sfb_offset[coderInfo[channel].nr_of_sfb] = offset; + } else { + coderInfo[channel].max_sfb = hEncoder->srInfo->num_cb_long; + coderInfo[channel].nr_of_sfb = hEncoder->srInfo->num_cb_long; + + coderInfo[channel].num_window_groups = 1; + coderInfo[channel].window_group_length[0] = 1; + + offset = 0; + for (sb = 0; sb < coderInfo[channel].nr_of_sfb; sb++) { + coderInfo[channel].sfb_offset[sb] = offset; + offset += hEncoder->srInfo->cb_width_long[sb]; + } + coderInfo[channel].sfb_offset[coderInfo[channel].nr_of_sfb] = offset; + } + } + + /* Perform TNS analysis and filtering */ + for (channel = 0; channel < numChannels; channel++) { + if ((!channelInfo[channel].lfe) && (useTns)) { + TnsEncode(&(coderInfo[channel].tnsInfo), + coderInfo[channel].max_sfb, + coderInfo[channel].max_sfb, + coderInfo[channel].block_type, + coderInfo[channel].sfb_offset, + hEncoder->freqBuff[channel]); + } else { + coderInfo[channel].tnsInfo.tnsDataPresent = 0; /* TNS not used for LFE */ + } + } + + for(channel = 0; channel < numChannels; channel++) + { + if((coderInfo[channel].tnsInfo.tnsDataPresent != 0) && (useTns)) + tnsInfo_for_LTP = &(coderInfo[channel].tnsInfo); + else + tnsInfo_for_LTP = NULL; + + if(channelInfo[channel].present && (!channelInfo[channel].lfe) && + (coderInfo[channel].block_type != ONLY_SHORT_WINDOW) && + (mpegVersion == MPEG4) && (aacObjectType == LTP)) + { + LtpEncode(hEncoder, + &coderInfo[channel], + &(coderInfo[channel].ltpInfo), + tnsInfo_for_LTP, + hEncoder->freqBuff[channel], + hEncoder->ltpTimeBuff[channel]); + } else { + coderInfo[channel].ltpInfo.global_pred_flag = 0; + } + } + + for(channel = 0; channel < numChannels; channel++) + { + if ((aacObjectType == MAIN) && (!channelInfo[channel].lfe)) { + int numPredBands = min(coderInfo[channel].max_pred_sfb, coderInfo[channel].nr_of_sfb); + PredCalcPrediction(hEncoder->freqBuff[channel], + coderInfo[channel].requantFreq, + coderInfo[channel].block_type, + numPredBands, + (coderInfo[channel].block_type==ONLY_SHORT_WINDOW)? + hEncoder->srInfo->cb_width_short:hEncoder->srInfo->cb_width_long, + coderInfo, + channelInfo, + channel); + } else { + coderInfo[channel].pred_global_flag = 0; + } + } + + for (channel = 0; channel < numChannels; channel++) { + if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) { + SortForGrouping(&coderInfo[channel], + &hEncoder->psyInfo[channel], + &channelInfo[channel], + hEncoder->srInfo->cb_width_short, + hEncoder->freqBuff[channel]); + } + CalcAvgEnrg(&coderInfo[channel], hEncoder->freqBuff[channel]); + + // reduce LFE bandwidth + if (!channelInfo[channel].cpe && channelInfo[channel].lfe) + { + coderInfo[channel].nr_of_sfb = coderInfo[channel].max_sfb = 3; + } + } + + MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels, allowMidside); + + for (channel = 0; channel < numChannels; channel++) + { + CalcAvgEnrg(&coderInfo[channel], hEncoder->freqBuff[channel]); + } + +#ifdef DRM + /* loop the quantization until the desired bit-rate is reached */ + diff = 1; /* to enter while loop */ + hEncoder->aacquantCfg.quality = 120; /* init quality setting */ + while (diff > 0) { /* if too many bits, do it again */ +#endif + /* Quantize and code the signal */ + for (channel = 0; channel < numChannels; channel++) { + if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) { + AACQuantize(&coderInfo[channel], &hEncoder->psyInfo[channel], + &channelInfo[channel], hEncoder->srInfo->cb_width_short, + hEncoder->srInfo->num_cb_short, hEncoder->freqBuff[channel], + &(hEncoder->aacquantCfg)); + } else { + AACQuantize(&coderInfo[channel], &hEncoder->psyInfo[channel], + &channelInfo[channel], hEncoder->srInfo->cb_width_long, + hEncoder->srInfo->num_cb_long, hEncoder->freqBuff[channel], + &(hEncoder->aacquantCfg)); + } + } + +#ifdef DRM + /* Write the AAC bitstream */ + bitStream = OpenBitStream(bufferSize, outputBuffer); + WriteBitstream(hEncoder, coderInfo, channelInfo, bitStream, numChannels); + + /* Close the bitstream and return the number of bytes written */ + frameBytes = CloseBitStream(bitStream); + + /* now calculate desired bits and compare with actual encoded bits */ + desbits = (int) ((double) numChannels * (hEncoder->config.bitRate * FRAME_LEN) + / hEncoder->sampleRate); + + diff = ((frameBytes - 1 /* CRC */) * 8) - desbits; + + /* do linear correction according to relative difference */ + fix = (double) desbits / ((frameBytes - 1 /* CRC */) * 8); + + /* speed up convergence. A value of 0.92 gives approx up to 10 iterations */ + if (fix > 0.92) + fix = 0.92; + + hEncoder->aacquantCfg.quality *= fix; + + /* quality should not go lower than 1, set diff to exit loop */ + if (hEncoder->aacquantCfg.quality <= 1) + diff = -1; + } +#endif + + // fix max_sfb in CPE mode + for (channel = 0; channel < numChannels; channel++) + { + if (channelInfo[channel].present + && (channelInfo[channel].cpe) + && (channelInfo[channel].ch_is_left)) + { + CoderInfo *cil, *cir; + + cil = &coderInfo[channel]; + cir = &coderInfo[channelInfo[channel].paired_ch]; + + cil->max_sfb = cir->max_sfb = max(cil->max_sfb, cir->max_sfb); + cil->nr_of_sfb = cir->nr_of_sfb = cil->max_sfb; + } + } + + MSReconstruct(coderInfo, channelInfo, numChannels); + + for (channel = 0; channel < numChannels; channel++) + { + /* If short window, reconstruction not needed for prediction */ + if ((coderInfo[channel].block_type == ONLY_SHORT_WINDOW)) { + int sind; + for (sind = 0; sind < BLOCK_LEN_LONG; sind++) { + coderInfo[channel].requantFreq[sind] = 0.0; + } + } else { + + if((coderInfo[channel].tnsInfo.tnsDataPresent != 0) && (useTns)) + tnsDecInfo = &(coderInfo[channel].tnsInfo); + else + tnsDecInfo = NULL; + + if ((!channelInfo[channel].lfe) && (aacObjectType == LTP)) { /* no reconstruction needed for LFE channel*/ + + LtpReconstruct(&coderInfo[channel], &(coderInfo[channel].ltpInfo), + coderInfo[channel].requantFreq); + + if(tnsDecInfo != NULL) + TnsDecodeFilterOnly(&(coderInfo[channel].tnsInfo), coderInfo[channel].nr_of_sfb, + coderInfo[channel].max_sfb, coderInfo[channel].block_type, + coderInfo[channel].sfb_offset, coderInfo[channel].requantFreq); + + IFilterBank(hEncoder, &coderInfo[channel], + coderInfo[channel].requantFreq, + coderInfo[channel].ltpInfo.time_buffer, + coderInfo[channel].ltpInfo.ltp_overlap_buffer, + MOVERLAPPED); + + LtpUpdate(&(coderInfo[channel].ltpInfo), + coderInfo[channel].ltpInfo.time_buffer, + coderInfo[channel].ltpInfo.ltp_overlap_buffer, + BLOCK_LEN_LONG); + } + } + } + +#ifndef DRM + /* Write the AAC bitstream */ + bitStream = OpenBitStream(bufferSize, outputBuffer); + + WriteBitstream(hEncoder, coderInfo, channelInfo, bitStream, numChannels); + + /* Close the bitstream and return the number of bytes written */ + frameBytes = CloseBitStream(bitStream); + + /* Adjust quality to get correct average bitrate */ + if (hEncoder->config.bitRate) + { + double fix; + int desbits = numChannels * (hEncoder->config.bitRate * FRAME_LEN) + / hEncoder->sampleRate; + int diff = (frameBytes * 8) - desbits; + + hEncoder->bitDiff += diff; + fix = (double)hEncoder->bitDiff / desbits; + fix *= 0.01; + fix = max(fix, -0.2); + fix = min(fix, 0.2); + + if (((diff > 0) && (fix > 0.0)) || ((diff < 0) && (fix < 0.0))) + { + hEncoder->aacquantCfg.quality *= (1.0 - fix); + if (hEncoder->aacquantCfg.quality > 300) + hEncoder->aacquantCfg.quality = 300; + if (hEncoder->aacquantCfg.quality < 50) + hEncoder->aacquantCfg.quality = 50; + } + } +#endif + + return frameBytes; +} + + +#ifdef DRM +/* Scalefactorband data table for 960 transform length */ +/* all parameters which are different from the 1024 transform length table are + marked with an "x" */ +static SR_INFO srInfo[12+1] = +{ + { 96000, 40/*x*/, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0/*x*/ + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28/*x*/ + } + }, { 88200, 40/*x*/, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0/*x*/ + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28/*x*/ + } + }, { 64000, 45/*x*/, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, + 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 16/*x*/, 0/*x*/ + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28/*x*/ + } + }, { 48000, 49, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32/*x*/ + }, { + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8/*x*/ + } + }, { 44100, 49, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32/*x*/ + }, { + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8/*x*/ + } + }, { 32000, 49/*x*/, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0/*x*/, 0/*x*/ + },{ + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 + } + }, { 24000, 46/*x*/, 15, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, + 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 0/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12/*x*/ + } + }, { 22050, 46/*x*/, 15, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, + 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 0/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12/*x*/ + } + }, { 16000, 42/*x*/, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 0/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12/*x*/ + } + }, { 12000, 42/*x*/, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 0/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12/*x*/ + } + }, { 11025, 42/*x*/, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 0/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12/*x*/ + } + }, { 8000, 40, 15, + { + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 16/*x*/ + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 12/*x*/ + } + }, + { -1 } +}; +#else +/* Scalefactorband data table for 1024 transform length */ +static SR_INFO srInfo[12+1] = +{ + { 96000, 41, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 + } + }, { 88200, 41, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 + } + }, { 64000, 47, 12, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, + 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40 + },{ + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 32 + } + }, { 48000, 49, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96 + }, { + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 + } + }, { 44100, 49, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96 + }, { + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 + } + }, { 32000, 51, 14, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 + },{ + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 + } + }, { 24000, 47, 15, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, + 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64 + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20 + } + }, { 22050, 47, 15, + { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, + 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64 + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20 + } + }, { 16000, 43, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 + } + }, { 12000, 43, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 + } + }, { 11025, 43, 15, + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 + }, { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 + } + }, { 8000, 40, 15, + { + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80 + }, { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20 + } + }, + { -1 } +}; +#endif + +/* +$Log: frame.c,v $ +Revision 1.67 2004/11/17 14:26:06 menno +Infinite loop fix +dunno if this is good, encoder might be tuned to use energies from before MS encoding. But since the MS encoded samples are used in quantisation this might actually be better. Please test. + +Revision 1.66 2004/11/04 12:51:09 aforanna +version number updated to 1.24.1 due to changes in Winamp and CoolEdit plugins + +Revision 1.65 2004/07/18 09:34:24 corrados +New bandwidth settings for DRM, improved quantization quality adaptation (almost constant bit-rate now) + +Revision 1.64 2004/07/13 17:56:37 corrados +bug fix with new object type definitions + +Revision 1.63 2004/07/08 14:01:25 corrados +New scalefactorband table for 960 transform length, bug fix in HCR + +Revision 1.62 2004/07/04 12:10:52 corrados +made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set) +implemented HCR tool, VCB11, CRC, scalable bitstream order +note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32 +960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts + +Revision 1.61 2004/05/03 11:37:16 danchr +bump version to unstable 1.24+ + +Revision 1.60 2004/04/13 13:47:33 danchr +clarify release <> unstable status + +Revision 1.59 2004/04/02 14:56:17 danchr +fix name clash w/ libavcodec: fft_init -> fft_initialize +bump version number to 1.24 beta + +Revision 1.58 2004/03/17 13:34:20 danchr +Automatic, untuned setting of lowpass for VBR. + +Revision 1.57 2004/03/15 20:16:42 knik +fixed copyright notice + +Revision 1.56 2004/01/23 10:22:26 stux +*** empty log message *** + +Revision 1.55 2003/12/17 20:59:55 knik +changed default cutoff to 16k + +Revision 1.54 2003/11/24 18:09:12 knik +A safe version of faacEncGetVersion() without string length problem. +Removed Stux from copyright notice. I don't think he contributed something very +substantial to faac and this is not the right place to list all contributors. + +Revision 1.53 2003/11/16 05:02:52 stux +moved global tables from fft.c into hEncoder FFT_Tables. Add fft_init and fft_terminate, flowed through all necessary changes. This should remove at least one instance of a memory leak, and fix some thread-safety problems. Version update to 1.23.3 + +Revision 1.52 2003/11/15 08:13:42 stux +added FaacEncGetVersion(), version 1.23.2, added myself to faacCopyright :-P, does vanity know no bound ;) + +Revision 1.51 2003/11/10 17:48:00 knik +Allowed independent bitRate and bandWidth setting. +Small fixes. + +Revision 1.50 2003/10/29 10:31:25 stux +Added channel_map to FaacEncHandle, facilitates free generalised channel remapping in the faac core. Default is straight-through, should be *zero* performance hit... and even probably an immeasurable performance gain, updated FAAC_CFG_VERSION to 104 and FAAC_VERSION to 1.22.0 + +Revision 1.49 2003/10/12 16:43:39 knik +average bitrate control made more stable + +Revision 1.48 2003/10/12 14:29:53 knik +more accurate average bitrate control + +Revision 1.47 2003/09/24 16:26:54 knik +faacEncStruct: quantizer specific data enclosed in AACQuantCfg structure. +Added config option to enforce block type. + +Revision 1.46 2003/09/07 16:48:31 knik +Updated psymodel call. Updated bitrate/cutoff mapping table. + +Revision 1.45 2003/08/23 15:02:13 knik +last frame moved back to the library + +Revision 1.44 2003/08/15 11:42:08 knik +removed single silent flush frame + +Revision 1.43 2003/08/11 09:43:47 menno +thread safety, some tables added to the encoder context + +Revision 1.42 2003/08/09 11:39:30 knik +LFE support enabled by default + +Revision 1.41 2003/08/08 10:02:09 menno +Small fix + +Revision 1.40 2003/08/07 08:17:00 knik +Better LFE support (reduced bandwidth) + +Revision 1.39 2003/08/02 11:32:10 stux +added config.inputFormat, and associated defines and code, faac now handles native endian 16bit, 24bit and float input. Added faacEncGetDecoderSpecificInfo to the dll exports, needed for MP4. Updated DLL .dsp to compile without error. Updated CFG_VERSION to 102. Version number might need to be updated as the API has technically changed. Did not update libfaac.pdf + +Revision 1.38 2003/07/10 19:17:01 knik +24-bit input + +Revision 1.37 2003/06/26 19:20:09 knik +Mid/Side support. +Copyright info moved from frontend. +Fixed memory leak. + +Revision 1.36 2003/05/12 17:53:16 knik +updated ABR table + +Revision 1.35 2003/05/10 09:39:55 knik +added approximate ABR setting +modified default cutoff + +Revision 1.34 2003/05/01 09:31:39 knik +removed ISO psyodel +disabled m/s coding +fixed default bandwidth +reduced max_sfb check + +Revision 1.33 2003/04/13 08:37:23 knik +version number moved to version.h + +Revision 1.32 2003/03/27 17:08:23 knik +added quantizer quality and bandwidth setting + +Revision 1.31 2002/10/11 18:00:15 menno +small bugfix + +Revision 1.30 2002/10/08 18:53:01 menno +Fixed some memory leakage + +Revision 1.29 2002/08/19 16:34:43 knik +added one additional flush frame +fixed sample buffer memory allocation + +*/ diff --git a/external/libfaac/libfaac/frame.h b/external/libfaac/libfaac/frame.h new file mode 100644 index 0000000..a31efe6 --- /dev/null +++ b/external/libfaac/libfaac/frame.h @@ -0,0 +1,160 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: frame.h,v 1.30 2009/01/25 18:50:32 menno Exp $ + */ + +#ifndef FRAME_H +#define FRAME_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif + +#ifndef HAVE_INT32_T +typedef signed int int32_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "coder.h" +#include "channels.h" +#include "psych.h" +#include "aacquant.h" +#include "fft.h" + +#if defined(_WIN32) && !defined(__MINGW32__) + #ifndef FAACAPI + #define FAACAPI __stdcall + #endif +#else + #ifndef FAACAPI + #define FAACAPI + #endif +#endif + +#pragma pack(push, 1) + +typedef struct { + psymodel_t *model; + char *name; +} psymodellist_t; + +#include + +typedef struct { + /* number of channels in AAC file */ + unsigned int numChannels; + + /* samplerate of AAC file */ + unsigned long sampleRate; + unsigned int sampleRateIdx; + + unsigned int usedBytes; + + /* frame number */ + unsigned int frameNum; + unsigned int flushFrame; + + /* Scalefactorband data */ + SR_INFO *srInfo; + + /* sample buffers of current next and next next frame*/ + double *sampleBuff[MAX_CHANNELS]; + double *nextSampleBuff[MAX_CHANNELS]; + double *next2SampleBuff[MAX_CHANNELS]; + double *next3SampleBuff[MAX_CHANNELS]; + double *ltpTimeBuff[MAX_CHANNELS]; + + /* Filterbank buffers */ + double *sin_window_long; + double *sin_window_short; + double *kbd_window_long; + double *kbd_window_short; + double *freqBuff[MAX_CHANNELS]; + double *overlapBuff[MAX_CHANNELS]; + + double *msSpectrum[MAX_CHANNELS]; + + /* Channel and Coder data for all channels */ + CoderInfo coderInfo[MAX_CHANNELS]; + ChannelInfo channelInfo[MAX_CHANNELS]; + + /* Psychoacoustics data */ + PsyInfo psyInfo[MAX_CHANNELS]; + GlobalPsyInfo gpsyInfo; + + /* Configuration data */ + faacEncConfiguration config; + + psymodel_t *psymodel; + + /* quantizer specific config */ + AACQuantCfg aacquantCfg; + + /* FFT Tables */ + FFT_Tables fft_tables; + + /* output bits difference in average bitrate mode */ + int bitDiff; +} faacEncStruct, *faacEncHandle; + +int FAACAPI faacEncGetVersion(char **faac_id_string, + char **faac_copyright_string); + +int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, + unsigned char** ppBuffer, + unsigned long* pSizeOfDecoderSpecificInfo); + +faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder); +int FAACAPI faacEncSetConfiguration (faacEncHandle hEncoder, faacEncConfigurationPtr config); + +faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, + unsigned int numChannels, + unsigned long *inputSamples, + unsigned long *maxOutputBytes); + +int FAACAPI faacEncEncode(faacEncHandle hEncoder, + int32_t *inputBuffer, + unsigned int samplesInput, + unsigned char *outputBuffer, + unsigned int bufferSize + ); + +int FAACAPI faacEncClose(faacEncHandle hEncoder); + + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* FRAME_H */ diff --git a/external/libfaac/libfaac/huffman.c b/external/libfaac/libfaac/huffman.c new file mode 100644 index 0000000..968d2c6 --- /dev/null +++ b/external/libfaac/libfaac/huffman.c @@ -0,0 +1,1226 @@ +/*********** + +This software module was originally developed by Dolby +Laboratories and edited by Sony Corporation +in the course of development of the MPEG-2 NBC/MPEG-4 +Audio standard ISO/IEC13818-7, 14496-1, 2 and 3. This software module is an +implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools as +specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives users of the +MPEG-2NBC/MPEG-4 Audio standards free license to this software module +or modifications thereof for use in hardware or software products +claiming conformance to the MPEG-2 NBC/MPEG-4 Audio standards. Those +intending to use this software module in hardware or software products +are advised that this use may infringe existing patents. The original +developer of this software module, the subsequent +editors and their companies, and ISO/IEC have no liability for use of +this software module or modifications thereof in an +implementation. Copyright is not released for non MPEG-2 NBC/MPEG-4 +Audio conforming products. The original developer retains full right to +use the code for the developer's own purpose, assign or donate the code to a +third party and to inhibit third party from using the code for non +MPEG-2 NBC/MPEG-4 Audio conforming products. This copyright notice +must be included in all copies or derivative works. Copyright 1996. + +***********/ +/* + * $Id: huffman.c,v 1.11 2005/02/02 07:53:20 sur Exp $ + */ + +#include +#include + +#include "huffman.h" +#include "coder.h" +#include "bitstream.h" +#include "util.h" + +#include "hufftab.h" + +void HuffmanInit(CoderInfo *coderInfo, unsigned int numChannels) +{ + unsigned int channel; + + for (channel = 0; channel < numChannels; channel++) { + coderInfo[channel].data = (int*)AllocMemory(5*FRAME_LEN*sizeof(int)); + coderInfo[channel].len = (int*)AllocMemory(5*FRAME_LEN*sizeof(int)); + +#ifdef DRM + coderInfo[channel].num_data_cw = (int*)AllocMemory(FRAME_LEN*sizeof(int)); +#endif + } +} + +void HuffmanEnd(CoderInfo *coderInfo, unsigned int numChannels) +{ + unsigned int channel; + + for (channel = 0; channel < numChannels; channel++) { + if (coderInfo[channel].data) FreeMemory(coderInfo[channel].data); + if (coderInfo[channel].len) FreeMemory(coderInfo[channel].len); + +#ifdef DRM + if (coderInfo[channel].num_data_cw) FreeMemory(coderInfo[channel].num_data_cw); +#endif + } +} + +int BitSearch(CoderInfo *coderInfo, + int *quant) /* Quantized spectral values */ + /* + This function inputs a vector of quantized spectral data, quant[][], and returns a vector, + 'book_vector[]' that describes how to group together the scalefactor bands into a smaller + number of sections. There are MAX_SCFAC_BANDS elements in book_vector (equal to 49 in the + case of long blocks and 112 for short blocks), and each element has a huffman codebook + number assigned to it. + + For a quick and simple algorithm, this function performs a binary + search across the sfb's (scale factor bands). On the first approach, it calculates the + needed amount of bits if every sfb were its own section and transmitted its own huffman + codebook value side information (equal to 9 bits for a long block, 7 for a short). The + next iteration combines adjacent sfb's, and calculates the bit rate for length two sfb + sections. If any wider two-sfb section requires fewer bits than the sum of the two + single-sfb sections (below it in the binary tree), then the wider section will be chosen. + This process occurs until the sections are split into three uniform parts, each with an + equal amount of sfb's contained. + + The binary tree is stored as a two-dimensional array. Since this tree is not full, (there + are only 49 nodes, not 2^6 = 64), the numbering is a little complicated. If the tree were + full, the top node would be 1. It's children would be 2 and 3. But, since this tree + is not full, the top row of three nodes are numbered {4,5,6}. The row below it is + {8,9,10,11,12,13}, and so on. + + The binary tree is called bit_stats[112][3]. There are 112 total nodes (some are not + used since it's not full). bit_stats[x][0] holds the bit totals needed for the sfb sectioning + strategy represented by the node x in the tree. bit_stats[x][1] holds the optimal huffman + codebook table that minimizes the bit rate, given the sectioning boundaries dictated by node x. +*/ + +{ + int i,j,k; + int hop; + int min_book_choice[112][3]; + int bit_stats[240][3]; + int total_bit_count; + int levels; + int pow2levels; + int fracpow2lev; + + /* Set local pointer to coderInfo book_vector */ + int* book_vector = coderInfo -> book_vector; + + levels = (int) ((log((double)coderInfo->nr_of_sfb)/log((double)2.0))+1); + +/* #define SLOW */ + +#ifdef SLOW + for(i = 0; i < 5; i++) { +#else + i = 0; +#endif + hop = 1 << i; + + NoiselessBitCount(coderInfo, quant, hop, min_book_choice); + + /* load up the (not-full) binary search tree with the min_book_choice values */ + k=0; + total_bit_count = 0; + + pow2levels = 1 << (levels - i); + fracpow2lev = pow2levels + (coderInfo->nr_of_sfb >> i); + + for (j=pow2levels; j < fracpow2lev; j++) + { + bit_stats[j][0] = min_book_choice[k][0]; /* the minimum bit cost for this section */ + bit_stats[j][1] = min_book_choice[k][1]; /* used with this huffman book number */ + +#ifdef SLOW + if (i>0){ /* not on the lowest level, grouping more than one signle scalefactor band per section*/ + if (bit_stats[j][0] < bit_stats[2*j][0] + bit_stats[2*j+1][0]){ + + /* it is cheaper to combine surrounding sfb secionts into one larger huffman book section */ + for(n=k;nsfb_offset; + int nr_of_sfb = coderInfo->nr_of_sfb; + + /* each section is 'hop' scalefactor bands wide */ + for (i=0; i < nr_of_sfb; i=i+hop){ +#ifdef SLOW + if ((i+hop) > nr_of_sfb) + q = nr_of_sfb; + else +#endif + q = i+hop; + + { + + /* find the maximum absolute value in the current spectral section, to see what tables are available to use */ + max_sb_coeff = 0; + for (j=sfb_offset[i]; j max_sb_coeff) + max_sb_coeff = ABS(quant[j]); + } + + j = 0; + offset = sfb_offset[i]; +#ifdef SLOW + if ((i+hop) > nr_of_sfb){ + end = sfb_offset[nr_of_sfb]; + } else +#endif + end = sfb_offset[q]; + length = end - offset; + + /* all spectral coefficients in this section are zero */ + if (max_sb_coeff == 0) { + book_choice[j][0] = CalcBits(coderInfo,0,quant,offset,length); + book_choice[j++][1] = 0; + + } + else { /* if the section does have non-zero coefficients */ + if(max_sb_coeff < 2){ + book_choice[j][0] = CalcBits(coderInfo,1,quant,offset,length); + book_choice[j++][1] = 1; + book_choice[j][0] = CalcBits(coderInfo,2,quant,offset,length); + book_choice[j++][1] = 2; + book_choice[j][0] = CalcBits(coderInfo,3,quant,offset,length); + book_choice[j++][1] = 3; + } + else if (max_sb_coeff < 3){ + book_choice[j][0] = CalcBits(coderInfo,3,quant,offset,length); + book_choice[j++][1] = 3; + book_choice[j][0] = CalcBits(coderInfo,4,quant,offset,length); + book_choice[j++][1] = 4; + book_choice[j][0] = CalcBits(coderInfo,5,quant,offset,length); + book_choice[j++][1] = 5; + } + else if (max_sb_coeff < 5){ + book_choice[j][0] = CalcBits(coderInfo,5,quant,offset,length); + book_choice[j++][1] = 5; + book_choice[j][0] = CalcBits(coderInfo,6,quant,offset,length); + book_choice[j++][1] = 6; + book_choice[j][0] = CalcBits(coderInfo,7,quant,offset,length); + book_choice[j++][1] = 7; + } + else if (max_sb_coeff < 8){ + book_choice[j][0] = CalcBits(coderInfo,7,quant,offset,length); + book_choice[j++][1] = 7; + book_choice[j][0] = CalcBits(coderInfo,8,quant,offset,length); + book_choice[j++][1] = 8; + book_choice[j][0] = CalcBits(coderInfo,9,quant,offset,length); + book_choice[j++][1] = 9; + } + else if (max_sb_coeff < 13){ + book_choice[j][0] = CalcBits(coderInfo,9,quant,offset,length); + book_choice[j++][1] = 9; + book_choice[j][0] = CalcBits(coderInfo,10,quant,offset,length); + book_choice[j++][1] = 10; + } + /* (max_sb_coeff >= 13), choose table 11 */ + else { + book_choice[j][0] = CalcBits(coderInfo,11,quant,offset,length); + book_choice[j++][1] = 11; + } + } + + /* find the minimum bit cost and table number for huffman coding this scalefactor section */ + min_book_choice[i][1] = book_choice[0][1]; + min_book_choice[i][0] = book_choice[0][0]; + + for(k=1;k= 1) { + N++; + x = x/2; + } + + *len_esc_sequence = 2*N + 5; /* the length of the escape sequence in bits */ + + output = (int)((pow(2,N) - 1)*pow(2,N+5) + y - pow(2,N+4)); + return(output); +} + +int OutputBits(CoderInfo *coderInfo, +#ifdef DRM + int *book, /* we need to change book for VCB11 */ +#else + int book, +#endif + int *quant, + int offset, + int length) +{ + /* + This function inputs + - a specific codebook number, 'book' + - the quantized spectral data, 'quant[][]' + - the offset into the spectral data to begin scanning, 'offset' + - the 'length' of the segment to huffman code + -> therefore, the segment quant[offset] to quant[offset+length-1] + is huffman coded. + + This function outputs + - the number of bits required, 'bits' using the prescribed codebook, book applied to + the given segment of spectral data. + + There are three parameters that are passed back and forth into this function. data[] + and len[] are one-dimensional arrays that store the codebook values and their respective + bit lengths. These are used when packing the data for the bitstream in OutputBits(). The + index into these arrays is 'coderInfo->spectral_count''. It gets incremented internally in this + function as counter, then passed to the outside through outside_counter. The next time + OutputBits() is called, counter starts at the value it left off from the previous call. + + */ + int esc_sequence; + int len_esc; + int index; + int bits=0; + int tmp; + int codebook,i,j; + int counter; + + /* Set up local pointers to coderInfo elements data and len */ + int* data= coderInfo->data; + int* len= coderInfo->len; +#ifdef DRM + int* num_data = coderInfo->num_data_cw; + int cur_cw_len; + int max_esc_sequ = 0; +#endif + + counter = coderInfo->spectral_count; + +#ifdef DRM + switch (*book) { +#else + switch (book) { +#endif + case 0: + case INTENSITY_HCB2: + case INTENSITY_HCB: +#ifdef DRM + for(i=offset;idata[counter] = 0; + coderInfo->len[counter++] = 0; + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + +#ifdef DRM + num_data[coderInfo->cur_cw++] = 1; + } +#endif + return(bits); + case 1: + for(i=offset;icur_cw++] = 1; + coderInfo->iLenReordSpData += tmp; + if (tmp > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = tmp; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 2: + for(i=offset;icur_cw++] = 1; + coderInfo->iLenReordSpData += tmp; + if (tmp > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = tmp; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 3: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<4;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 4: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<4;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 5: + for(i=offset;icur_cw++] = 1; + coderInfo->iLenReordSpData += tmp; + if (tmp > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = tmp; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 6: + for(i=offset;icur_cw++] = 1; + coderInfo->iLenReordSpData += tmp; + if (tmp > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = tmp; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 7: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<2;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 8: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<2;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 9: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<2;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 10: + for(i=offset;icur_cw] = 1; + cur_cw_len = tmp; +#endif + for(j=0;j<2;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + return(bits); + case 11: + /* First, calculate the indecies into the huffman tables */ + for(i=offset;i= 16) && (ABS(quant[i+1]) >= 16)) { /* both codewords were above 16 */ + /* first, code the orignal pair, with the larger value saturated to +/- 16 */ + index = 17*16 + 16; + } + else if (ABS(quant[i]) >= 16) { /* the first codeword was above 16, not the second one */ + /* first, code the orignal pair, with the larger value saturated to +/- 16 */ + index = 17*16 + ABS(quant[i+1]); + } + else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */ + index = 17*ABS(quant[i]) + 16; + } + else { /* there were no values above 16, so no escape sequences */ + index = 17*ABS(quant[i]) + ABS(quant[i+1]); + } + + /* write out the codewords */ + tmp = huff11[index][FIRSTINTAB]; + codebook = huff11[index][LASTINTAB]; + bits += tmp; + data[counter] = codebook; + len[counter++] = tmp; +#ifdef DRM + num_data[coderInfo->cur_cw] = 1; + cur_cw_len = tmp; +#endif + + /* Take care of the sign bits */ + for(j=0;j<2;j++){ + if(quant[i+j] > 0) { /* send out '0' if a positive value */ + data[counter] = 0; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } else + if(quant[i+j] < 0) { /* send out '1' if a negative value */ + data[counter] = 1; + len[counter++] = 1; + bits += 1; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += 1; +#endif + } + } + + /* write out the escape sequences */ + if ((ABS(quant[i]) >= 16) && (ABS(quant[i+1]) >= 16)) { /* both codewords were above 16 */ + /* code and transmit the first escape_sequence */ + esc_sequence = CalculateEscSequence(quant[i],&len_esc); + bits += len_esc; + data[counter] = esc_sequence; + len[counter++] = len_esc; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += len_esc; + + if (esc_sequence > max_esc_sequ) + max_esc_sequ = esc_sequence; +#endif + + /* then code and transmit the second escape_sequence */ + esc_sequence = CalculateEscSequence(quant[i+1],&len_esc); + bits += len_esc; + data[counter] = esc_sequence; + len[counter++] = len_esc; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += len_esc; + + if (esc_sequence > max_esc_sequ) + max_esc_sequ = esc_sequence; +#endif + } + else if (ABS(quant[i]) >= 16) { /* the first codeword was above 16, not the second one */ + /* code and transmit the escape_sequence */ + esc_sequence = CalculateEscSequence(quant[i],&len_esc); + bits += len_esc; + data[counter] = esc_sequence; + len[counter++] = len_esc; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += len_esc; + + if (esc_sequence > max_esc_sequ) + max_esc_sequ = esc_sequence; +#endif + } + else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */ + /* code and transmit the escape_sequence */ + esc_sequence = CalculateEscSequence(quant[i+1],&len_esc); + bits += len_esc; + data[counter] = esc_sequence; + len[counter++] = len_esc; +#ifdef DRM + num_data[coderInfo->cur_cw]++; + cur_cw_len += len_esc; + + if (esc_sequence > max_esc_sequ) + max_esc_sequ = esc_sequence; +#endif + } +#ifdef DRM + coderInfo->iLenReordSpData += cur_cw_len; + if (cur_cw_len > coderInfo->iLenLongestCW) + coderInfo->iLenLongestCW = cur_cw_len; + + coderInfo->cur_cw++; +#endif + } + coderInfo->spectral_count = counter; /* send the current count back to the outside world */ + +#ifdef DRM + /* VCB11: check which codebook should be used using max escape sequence */ + /* 8.5.3.1.3, table 157 */ + if (max_esc_sequ <= 15) + *book = 16; + else if (max_esc_sequ <= 31) + *book = 17; + else if (max_esc_sequ <= 47) + *book = 18; + else if (max_esc_sequ <= 63) + *book = 19; + else if (max_esc_sequ <= 95) + *book = 20; + else if (max_esc_sequ <= 127) + *book = 21; + else if (max_esc_sequ <= 159) + *book = 22; + else if (max_esc_sequ <= 191) + *book = 23; + else if (max_esc_sequ <= 223) + *book = 24; + else if (max_esc_sequ <= 255) + *book = 25; + else if (max_esc_sequ <= 319) + *book = 26; + else if (max_esc_sequ <= 383) + *book = 27; + else if (max_esc_sequ <= 511) + *book = 28; + else if (max_esc_sequ <= 767) + *book = 29; + else if (max_esc_sequ <= 1023) + *book = 30; + else if (max_esc_sequ <= 2047) + *book = 31; + /* else: codebook 11 -> it is already 11 */ +#endif + + return(bits); + } + return 0; +} + +int CalcBits(CoderInfo *coderInfo, + int book, + int *quant, + int offset, + int length) +{ + /* + This function inputs + - a specific codebook number, 'book' + - the quantized spectral data, 'quant[]' + - the offset into the spectral data to begin scanning, 'offset' + - the 'length' of the segment to huffman code + -> therefore, the segment quant[offset] to quant[offset+length-1] + is huffman coded. + + This function outputs + - the number of bits required, 'bits' using the prescribed codebook, book applied to + the given segment of spectral data. + + */ + + int len_esc; + int index; + int bits = 0; + int i, j; + + switch (book) { + case 1: + for(i=offset;i= 16) && (ABS(quant[i+1]) >= 16)) { /* both codewords were above 16 */ + /* first, code the orignal pair, with the larger value saturated to +/- 16 */ + index = 17*16 + 16; + } else if (ABS(quant[i]) >= 16) { /* the first codeword was above 16, not the second one */ + /* first, code the orignal pair, with the larger value saturated to +/- 16 */ + index = 17*16 + ABS(quant[i+1]); + } else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */ + index = 17*ABS(quant[i]) + 16; + } else { /* there were no values above 16, so no escape sequences */ + index = 17*ABS(quant[i]) + ABS(quant[i+1]); + } + + /* write out the codewords */ + bits += huff11[index][FIRSTINTAB]; + + /* Take care of the sign bits */ + for(j=0;j<2;j++){ + if(quant[i+j] != 0) bits += 1; /* only for non-zero spectral coefficients */ + } + + /* write out the escape sequences */ + if ((ABS(quant[i]) >= 16) && (ABS(quant[i+1]) >= 16)) { /* both codewords were above 16 */ + /* code and transmit the first escape_sequence */ + CalculateEscSequence(quant[i],&len_esc); + bits += len_esc; + + /* then code and transmit the second escape_sequence */ + CalculateEscSequence(quant[i+1],&len_esc); + bits += len_esc; + } else if (ABS(quant[i]) >= 16) { /* the first codeword was above 16, not the second one */ + /* code and transmit the escape_sequence */ + CalculateEscSequence(quant[i],&len_esc); + bits += len_esc; + } else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */ + /* code and transmit the escape_sequence */ + CalculateEscSequence(quant[i+1],&len_esc); + bits += len_esc; + } + } + return (bits); + } + return 0; +} + +int SortBookNumbers(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag) +{ + /* + This function inputs the vector, 'book_vector[]', which is of length MAX_SCFAC_BANDS, + and contains the optimal huffman tables of each sfb. It returns the vector, 'output_book_vector[]', which + has it's elements formatted for the encoded bit stream. It's syntax is: + + {sect_cb[0], length_segment[0], ... ,sect_cb[num_of_sections], length_segment[num_of_sections]} + + The above syntax is true, unless there is an escape sequence. An + escape sequence occurs when a section is longer than 2 ^ (bit_len) + long in units of scalefactor bands. Also, the integer returned from + this function is the number of bits written in the bitstream, + 'bit_count'. + + This function supports both long and short blocks. + */ + + int i; + int repeat_counter; + int bit_count = 0; + int previous; + int max, bit_len/*,sfbs*/; + int max_sfb,g,band; + int sect_cb_bits = 4; + + /* Set local pointers to coderInfo elements */ + int* book_vector = coderInfo->book_vector; + +#ifdef DRM + sect_cb_bits = 5; /* 5 bits in case of VCB11 */ +#endif + + if (coderInfo->block_type == ONLY_SHORT_WINDOW){ + max = 7; + bit_len = 3; + } else { /* the block_type is a long,start, or stop window */ + max = 31; + bit_len = 5; + } + + /* Compute number of scalefactor bands */ + max_sfb = coderInfo->nr_of_sfb / coderInfo->num_window_groups; + + + for (g = 0; g < coderInfo->num_window_groups; g++) { + band=g*max_sfb; + + repeat_counter=1; + + previous = book_vector[band]; + if (writeFlag) { + PutBit(bitStream,book_vector[band],sect_cb_bits); + } + bit_count += sect_cb_bits; + + for (i=band+1;i= 16) && (previous <= 32))) + { + if (writeFlag) + PutBit(bitStream,book_vector[i],sect_cb_bits); + bit_count += sect_cb_bits; + previous = book_vector[i]; + repeat_counter=1; + + } else +#endif + if( (book_vector[i] != previous)) { + if (writeFlag) { + PutBit(bitStream,repeat_counter,bit_len); + } + bit_count += bit_len; + + if (repeat_counter == max){ /* in case you need to terminate an escape sequence */ + if (writeFlag) + PutBit(bitStream,0,bit_len); + bit_count += bit_len; + } + + if (writeFlag) + PutBit(bitStream,book_vector[i],sect_cb_bits); + bit_count += sect_cb_bits; + previous = book_vector[i]; + repeat_counter=1; + } + /* if the length of the section is longer than the amount of bits available in */ + /* the bitsream, "max", then start up an escape sequence */ + else if ((book_vector[i] == previous) && (repeat_counter == max)) { + if (writeFlag) { + PutBit(bitStream,repeat_counter,bit_len); + } + bit_count += bit_len; + repeat_counter = 1; + } + else { + repeat_counter++; + } + } + +#ifdef DRM + if (!((previous == 11) || ((previous >= 16) && (previous <= 32)))) +#endif + { + if (writeFlag) + PutBit(bitStream,repeat_counter,bit_len); + bit_count += bit_len; + + if (repeat_counter == max) { /* special case if the last section length is an */ + /* escape sequence */ + if (writeFlag) + PutBit(bitStream,0,bit_len); + bit_count += bit_len; + } + } + } /* Bottom of group iteration */ + + return bit_count; +} + +int WriteScalefactors(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag) + +{ + /* this function takes care of counting the number of bits necessary */ + /* to encode the scalefactors. In addition, if the writeFlag == 1, */ + /* then the scalefactors are written out the bitStream output bit */ + /* stream. it returns k, the number of bits written to the bitstream*/ + + int i,j,bit_count=0; + int diff,length,codeword; + int previous_scale_factor; + int previous_is_factor; /* Intensity stereo */ + int index = 0; + int nr_of_sfb_per_group; + + /* set local pointer to coderInfo elements */ + int* scale_factors = coderInfo->scale_factor; + + if (coderInfo->block_type == ONLY_SHORT_WINDOW) { /* short windows */ + nr_of_sfb_per_group = coderInfo->nr_of_sfb/coderInfo->num_window_groups; + } else { + nr_of_sfb_per_group = coderInfo->nr_of_sfb; + coderInfo->num_window_groups = 1; + coderInfo->window_group_length[0] = 1; + } + + previous_scale_factor = coderInfo->global_gain; + previous_is_factor = 0; + + for(j=0; jnum_window_groups; j++){ + for(i=0;ibook_vector[index]==INTENSITY_HCB) || + (coderInfo->book_vector[index]==INTENSITY_HCB2) ) { + /* only send scalefactors if using non-zero codebooks */ + diff = scale_factors[index] - previous_is_factor; + if ((diff < 60)&&(diff >= -60)) + length = huff12[diff+60][FIRSTINTAB]; + else length = 0; + bit_count+=length; + previous_is_factor = scale_factors[index]; + if (writeFlag == 1 ) { + codeword = huff12[diff+60][LASTINTAB]; + PutBit(bitStream,codeword,length); + } + } else if (coderInfo->book_vector[index]) { + /* only send scalefactors if using non-zero codebooks */ + diff = scale_factors[index] - previous_scale_factor; + if ((diff < 60)&&(diff >= -60)) + length = huff12[diff+60][FIRSTINTAB]; + else length = 0; + bit_count+=length; + previous_scale_factor = scale_factors[index]; + if (writeFlag == 1 ) { + codeword = huff12[diff+60][LASTINTAB]; + PutBit(bitStream,codeword,length); + } + } + index++; + } + } + return bit_count; +} + diff --git a/external/libfaac/libfaac/huffman.h b/external/libfaac/libfaac/huffman.h new file mode 100644 index 0000000..d3bd9c3 --- /dev/null +++ b/external/libfaac/libfaac/huffman.h @@ -0,0 +1,93 @@ +/*********** + +This software module was originally developed by Dolby +Laboratories in the course of development of the MPEG-2 AAC/MPEG-4 +Audio standard ISO/IEC13818-7, 14496-1, 2 and 3. This software module is an implementation of a part +of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the +MPEG-2 aac/MPEG-4 Audio standard. ISO/IEC gives users of the +MPEG-2aac/MPEG-4 Audio standards free license to this software module +or modifications thereof for use in hardware or software products +claiming conformance to the MPEG-2 aac/MPEG-4 Audio standards. Those +intending to use this software module in hardware or software products +are advised that this use may infringe existing patents. The original +developer of this software module, the subsequent +editors and their companies, and ISO/IEC have no liability for use of +this software module or modifications thereof in an +implementation. Copyright is not released for non MPEG-2 aac/MPEG-4 +Audio conforming products. The original developer retains full right to +use the code for the developer's own purpose, assign or donate the code to a +third party and to inhibit third party from using the code for non +MPEG-2 aac/MPEG-4 Audio conforming products. This copyright notice +must be included in all copies or derivative works. Copyright 1996. + +***********/ +/* + * $Id: huffman.h,v 1.6 2004/07/12 08:46:43 corrados Exp $ + */ + +#ifndef HUFFMAN_H +#define HUFFMAN_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "bitstream.h" +#include "coder.h" + +/* Huffman tables */ +#define MAXINDEX 289 +#define NUMINTAB 2 +#define FIRSTINTAB 0 +#define LASTINTAB 1 + +#define INTENSITY_HCB 15 +#define INTENSITY_HCB2 14 + + +#define ABS(A) ((A) < 0 ? (-A) : (A)) + +#include "frame.h" + +void HuffmanInit(CoderInfo *coderInfo, unsigned int numChannels); +void HuffmanEnd(CoderInfo *coderInfo, unsigned int numChannels); + +int BitSearch(CoderInfo *coderInfo, + int *quant); + +int NoiselessBitCount(CoderInfo *coderInfo, + int *quant, + int hop, + int min_book_choice[112][3]); + +static int CalculateEscSequence(int input, int *len_esc_sequence); + +int CalcBits(CoderInfo *coderInfo, + int book, + int *quant, + int offset, + int length); + +int OutputBits(CoderInfo *coderInfo, +#ifdef DRM + int *book, /* we need to change book for VCB11 */ +#else + int book, +#endif + int *quant, + int offset, + int length); + +int SortBookNumbers(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); + +int WriteScalefactors(CoderInfo *coderInfo, + BitStream *bitStream, + int writeFlag); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HUFFMAN_H */ diff --git a/external/libfaac/libfaac/hufftab.h b/external/libfaac/libfaac/hufftab.h new file mode 100644 index 0000000..5892679 --- /dev/null +++ b/external/libfaac/libfaac/hufftab.h @@ -0,0 +1,331 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: hufftab.h,v 1.3 2001/06/08 18:01:09 menno Exp $ + */ + +unsigned short huff1[][2] = { + { 11, 2040}, + { 9, 497},{ 11, 2045},{ 10, 1013},{ 7, 104},{ 10, 1008}, + { 11, 2039},{ 9, 492},{ 11, 2037},{ 10, 1009},{ 7, 114}, + { 10, 1012},{ 7, 116},{ 5, 17},{ 7, 118},{ 9, 491}, + { 7, 108},{ 10, 1014},{ 11, 2044},{ 9, 481},{ 11, 2033}, + { 9, 496},{ 7, 97},{ 9, 502},{ 11, 2034},{ 9, 490}, + { 11, 2043},{ 9, 498},{ 7, 105},{ 9, 493},{ 7, 119}, + { 5, 23},{ 7, 111},{ 9, 486},{ 7, 100},{ 9, 485}, + { 7, 103},{ 5, 21},{ 7, 98},{ 5, 18},{ 1, 0}, + { 5, 20},{ 7, 101},{ 5, 22},{ 7, 109},{ 9, 489}, + { 7, 99},{ 9, 484},{ 7, 107},{ 5, 19},{ 7, 113}, + { 9, 483},{ 7, 112},{ 9, 499},{ 11, 2046},{ 9, 487}, + { 11, 2035},{ 9, 495},{ 7, 96},{ 9, 494},{ 11, 2032}, + { 9, 482},{ 11, 2042},{ 10, 1011},{ 7, 106},{ 9, 488}, + { 7, 117},{ 5, 16},{ 7, 115},{ 9, 500},{ 7, 110}, + { 10, 1015},{ 11, 2038},{ 9, 480},{ 11, 2041},{ 10, 1010}, + { 7, 102},{ 9, 501},{ 11, 2047},{ 9, 503},{ 11, 2036} + }; +unsigned short huff2[][2] = { + { 9, 499}, + { 7, 111},{ 9, 509},{ 8, 235},{ 6, 35},{ 8, 234}, + { 9, 503},{ 8, 232},{ 9, 506},{ 8, 242},{ 6, 45}, + { 7, 112},{ 6, 32},{ 5, 6},{ 6, 43},{ 7, 110}, + { 6, 40},{ 8, 233},{ 9, 505},{ 7, 102},{ 8, 248}, + { 8, 231},{ 6, 27},{ 8, 241},{ 9, 500},{ 7, 107}, + { 9, 501},{ 8, 236},{ 6, 42},{ 7, 108},{ 6, 44}, + { 5, 10},{ 6, 39},{ 7, 103},{ 6, 26},{ 8, 245}, + { 6, 36},{ 5, 8},{ 6, 31},{ 5, 9},{ 3, 0}, + { 5, 7},{ 6, 29},{ 5, 11},{ 6, 48},{ 8, 239}, + { 6, 28},{ 7, 100},{ 6, 30},{ 5, 12},{ 6, 41}, + { 8, 243},{ 6, 47},{ 8, 240},{ 9, 508},{ 7, 113}, + { 9, 498},{ 8, 244},{ 6, 33},{ 8, 230},{ 8, 247}, + { 7, 104},{ 9, 504},{ 8, 238},{ 6, 34},{ 7, 101}, + { 6, 49},{ 4, 2},{ 6, 38},{ 8, 237},{ 6, 37}, + { 7, 106},{ 9, 507},{ 7, 114},{ 9, 510},{ 7, 105}, + { 6, 46},{ 8, 246},{ 9, 511},{ 7, 109},{ 9, 502} + }; +unsigned short huff3[][2] = { + { 1, 0}, + { 4, 9},{ 8, 239},{ 4, 11},{ 5, 25},{ 8, 240}, + { 9, 491},{ 9, 486},{ 10, 1010},{ 4, 10},{ 6, 53}, + { 9, 495},{ 6, 52},{ 6, 55},{ 9, 489},{ 9, 493}, + { 9, 487},{ 10, 1011},{ 9, 494},{ 10, 1005},{ 13, 8186}, + { 9, 492},{ 9, 498},{ 11, 2041},{ 11, 2040},{ 10, 1016}, + { 12, 4088},{ 4, 8},{ 6, 56},{ 10, 1014},{ 6, 54}, + { 7, 117},{ 10, 1009},{ 10, 1003},{ 10, 1004},{ 12, 4084}, + { 5, 24},{ 7, 118},{ 11, 2036},{ 6, 57},{ 7, 116}, + { 10, 1007},{ 9, 499},{ 9, 500},{ 11, 2038},{ 9, 488}, + { 10, 1002},{ 13, 8188},{ 8, 242},{ 9, 497},{ 12, 4091}, + { 10, 1013},{ 11, 2035},{ 12, 4092},{ 8, 238},{ 10, 1015}, + { 15, 32766},{ 9, 496},{ 11, 2037},{ 15, 32765},{ 13, 8187}, + { 14, 16378},{ 16, 65535},{ 8, 241},{ 10, 1008},{ 14, 16380}, + { 9, 490},{ 10, 1006},{ 14, 16379},{ 12, 4086},{ 12, 4090}, + { 15, 32764},{ 11, 2034},{ 12, 4085},{ 16, 65534},{ 10, 1012}, + { 11, 2039},{ 15, 32763},{ 12, 4087},{ 12, 4089},{ 15, 32762} + }; +unsigned short huff4[][2] = { + { 4, 7}, + { 5, 22},{ 8, 246},{ 5, 24},{ 4, 8},{ 8, 239}, + { 9, 495},{ 8, 243},{ 11, 2040},{ 5, 25},{ 5, 23}, + { 8, 237},{ 5, 21},{ 4, 1},{ 8, 226},{ 8, 240}, + { 7, 112},{ 10, 1008},{ 9, 494},{ 8, 241},{ 11, 2042}, + { 8, 238},{ 8, 228},{ 10, 1010},{ 11, 2038},{ 10, 1007}, + { 11, 2045},{ 4, 5},{ 5, 20},{ 8, 242},{ 4, 9}, + { 4, 4},{ 8, 229},{ 8, 244},{ 8, 232},{ 10, 1012}, + { 4, 6},{ 4, 2},{ 8, 231},{ 4, 3},{ 4, 0}, + { 7, 107},{ 8, 227},{ 7, 105},{ 9, 499},{ 8, 235}, + { 8, 230},{ 10, 1014},{ 7, 110},{ 7, 106},{ 9, 500}, + { 10, 1004},{ 9, 496},{ 10, 1017},{ 8, 245},{ 8, 236}, + { 11, 2043},{ 8, 234},{ 7, 111},{ 10, 1015},{ 11, 2041}, + { 10, 1011},{ 12, 4095},{ 8, 233},{ 7, 109},{ 10, 1016}, + { 7, 108},{ 7, 104},{ 9, 501},{ 10, 1006},{ 9, 498}, + { 11, 2036},{ 11, 2039},{ 10, 1009},{ 12, 4094},{ 10, 1005}, + { 9, 497},{ 11, 2037},{ 11, 2046},{ 10, 1013},{ 11, 2044} + }; +unsigned short huff5[][2] = { + { 13, 8191}, + { 12, 4087},{ 11, 2036},{ 11, 2024},{ 10, 1009},{ 11, 2030}, + { 11, 2041},{ 12, 4088},{ 13, 8189},{ 12, 4093},{ 11, 2033}, + { 10, 1000},{ 9, 488},{ 8, 240},{ 9, 492},{ 10, 1006}, + { 11, 2034},{ 12, 4090},{ 12, 4084},{ 10, 1007},{ 9, 498}, + { 8, 232},{ 7, 112},{ 8, 236},{ 9, 496},{ 10, 1002}, + { 11, 2035},{ 11, 2027},{ 9, 491},{ 8, 234},{ 5, 26}, + { 4, 8},{ 5, 25},{ 8, 238},{ 9, 495},{ 11, 2029}, + { 10, 1008},{ 8, 242},{ 7, 115},{ 4, 11},{ 1, 0}, + { 4, 10},{ 7, 113},{ 8, 243},{ 11, 2025},{ 11, 2031}, + { 9, 494},{ 8, 239},{ 5, 24},{ 4, 9},{ 5, 27}, + { 8, 235},{ 9, 489},{ 11, 2028},{ 11, 2038},{ 10, 1003}, + { 9, 499},{ 8, 237},{ 7, 114},{ 8, 233},{ 9, 497}, + { 10, 1005},{ 11, 2039},{ 12, 4086},{ 11, 2032},{ 10, 1001}, + { 9, 493},{ 8, 241},{ 9, 490},{ 10, 1004},{ 11, 2040}, + { 12, 4089},{ 13, 8188},{ 12, 4092},{ 12, 4085},{ 11, 2026}, + { 10, 1011},{ 10, 1010},{ 11, 2037},{ 12, 4091},{ 13, 8190} + }; +unsigned short huff6[][2] = { + { 11, 2046}, + { 10, 1021},{ 9, 497},{ 9, 491},{ 9, 500},{ 9, 490}, + { 9, 496},{ 10, 1020},{ 11, 2045},{ 10, 1014},{ 9, 485}, + { 8, 234},{ 7, 108},{ 7, 113},{ 7, 104},{ 8, 240}, + { 9, 486},{ 10, 1015},{ 9, 499},{ 8, 239},{ 6, 50}, + { 6, 39},{ 6, 40},{ 6, 38},{ 6, 49},{ 8, 235}, + { 9, 503},{ 9, 488},{ 7, 111},{ 6, 46},{ 4, 8}, + { 4, 4},{ 4, 6},{ 6, 41},{ 7, 107},{ 9, 494}, + { 9, 495},{ 7, 114},{ 6, 45},{ 4, 2},{ 4, 0}, + { 4, 3},{ 6, 47},{ 7, 115},{ 9, 506},{ 9, 487}, + { 7, 110},{ 6, 43},{ 4, 7},{ 4, 1},{ 4, 5}, + { 6, 44},{ 7, 109},{ 9, 492},{ 9, 505},{ 8, 238}, + { 6, 48},{ 6, 36},{ 6, 42},{ 6, 37},{ 6, 51}, + { 8, 236},{ 9, 498},{ 10, 1016},{ 9, 484},{ 8, 237}, + { 7, 106},{ 7, 112},{ 7, 105},{ 7, 116},{ 8, 241}, + { 10, 1018},{ 11, 2047},{ 10, 1017},{ 9, 502},{ 9, 493}, + { 9, 504},{ 9, 489},{ 9, 501},{ 10, 1019},{ 11, 2044} + }; +unsigned short huff7[][2] = { + { 1, 0}, + { 3, 5},{ 6, 55},{ 7, 116},{ 8, 242},{ 9, 491}, + { 10, 1005},{ 11, 2039},{ 3, 4},{ 4, 12},{ 6, 53}, + { 7, 113},{ 8, 236},{ 8, 238},{ 9, 494},{ 9, 501}, + { 6, 54},{ 6, 52},{ 7, 114},{ 8, 234},{ 8, 241}, + { 9, 489},{ 9, 499},{ 10, 1013},{ 7, 115},{ 7, 112}, + { 8, 235},{ 8, 240},{ 9, 497},{ 9, 496},{ 10, 1004}, + { 10, 1018},{ 8, 243},{ 8, 237},{ 9, 488},{ 9, 495}, + { 10, 1007},{ 10, 1009},{ 10, 1017},{ 11, 2043},{ 9, 493}, + { 8, 239},{ 9, 490},{ 9, 498},{ 10, 1011},{ 10, 1016}, + { 11, 2041},{ 11, 2044},{ 10, 1006},{ 9, 492},{ 9, 500}, + { 10, 1012},{ 10, 1015},{ 11, 2040},{ 12, 4093},{ 12, 4094}, + { 11, 2038},{ 10, 1008},{ 10, 1010},{ 10, 1014},{ 11, 2042}, + { 11, 2045},{ 12, 4092},{ 12, 4095} + }; +unsigned short huff8[][2] = { + { 5, 14}, + { 4, 5},{ 5, 16},{ 6, 48},{ 7, 111},{ 8, 241}, + { 9, 506},{ 10, 1022},{ 4, 3},{ 3, 0},{ 4, 4}, + { 5, 18},{ 6, 44},{ 7, 106},{ 7, 117},{ 8, 248}, + { 5, 15},{ 4, 2},{ 4, 6},{ 5, 20},{ 6, 46}, + { 7, 105},{ 7, 114},{ 8, 245},{ 6, 47},{ 5, 17}, + { 5, 19},{ 6, 42},{ 6, 50},{ 7, 108},{ 8, 236}, + { 8, 250},{ 7, 113},{ 6, 43},{ 6, 45},{ 6, 49}, + { 7, 109},{ 7, 112},{ 8, 242},{ 9, 505},{ 8, 239}, + { 7, 104},{ 6, 51},{ 7, 107},{ 7, 110},{ 8, 238}, + { 8, 249},{ 10, 1020},{ 9, 504},{ 7, 116},{ 7, 115}, + { 8, 237},{ 8, 240},{ 8, 246},{ 9, 502},{ 9, 509}, + { 10, 1021},{ 8, 243},{ 8, 244},{ 8, 247},{ 9, 503}, + { 9, 507},{ 9, 508},{ 10, 1023} + }; +unsigned short huff9[][2] = { + { 1, 0}, + { 3, 5},{ 6, 55},{ 8, 231},{ 9, 478},{ 10, 974}, + { 10, 985},{ 11, 1992},{ 11, 1997},{ 12, 4040},{ 12, 4061}, + { 13, 8164},{ 13, 8172},{ 3, 4},{ 4, 12},{ 6, 53}, + { 7, 114},{ 8, 234},{ 8, 237},{ 9, 482},{ 10, 977}, + { 10, 979},{ 10, 992},{ 11, 2008},{ 12, 4047},{ 12, 4053}, + { 6, 54},{ 6, 52},{ 7, 113},{ 8, 232},{ 8, 236}, + { 9, 481},{ 10, 975},{ 10, 989},{ 10, 987},{ 11, 2000}, + { 12, 4039},{ 12, 4052},{ 12, 4068},{ 8, 230},{ 7, 112}, + { 8, 233},{ 9, 477},{ 9, 483},{ 10, 978},{ 10, 988}, + { 11, 1996},{ 11, 1994},{ 11, 2014},{ 12, 4056},{ 12, 4074}, + { 13, 8155},{ 9, 479},{ 8, 235},{ 9, 476},{ 9, 486}, + { 10, 981},{ 10, 990},{ 11, 1995},{ 11, 2013},{ 11, 2012}, + { 12, 4045},{ 12, 4066},{ 12, 4071},{ 13, 8161},{ 10, 976}, + { 9, 480},{ 9, 484},{ 10, 982},{ 11, 1989},{ 11, 2001}, + { 11, 2011},{ 12, 4050},{ 11, 2016},{ 12, 4057},{ 12, 4075}, + { 13, 8163},{ 13, 8169},{ 11, 1988},{ 9, 485},{ 10, 983}, + { 11, 1990},{ 11, 1999},{ 11, 2010},{ 12, 4043},{ 12, 4058}, + { 12, 4067},{ 12, 4073},{ 13, 8166},{ 13, 8179},{ 13, 8183}, + { 11, 2003},{ 10, 984},{ 10, 993},{ 11, 2004},{ 11, 2009}, + { 12, 4051},{ 12, 4062},{ 13, 8157},{ 13, 8153},{ 13, 8162}, + { 13, 8170},{ 13, 8177},{ 13, 8182},{ 11, 2002},{ 10, 980}, + { 10, 986},{ 11, 1991},{ 11, 2007},{ 11, 2018},{ 12, 4046}, + { 12, 4059},{ 13, 8152},{ 13, 8174},{ 14, 16368},{ 13, 8180}, + { 14, 16370},{ 11, 2017},{ 10, 991},{ 11, 1993},{ 11, 2006}, + { 12, 4042},{ 12, 4048},{ 12, 4069},{ 12, 4070},{ 13, 8171}, + { 13, 8175},{ 14, 16371},{ 14, 16372},{ 14, 16373},{ 12, 4064}, + { 11, 1998},{ 11, 2005},{ 12, 4038},{ 12, 4049},{ 12, 4065}, + { 13, 8160},{ 13, 8168},{ 13, 8176},{ 14, 16369},{ 14, 16376}, + { 14, 16374},{ 15, 32764},{ 12, 4072},{ 11, 2015},{ 12, 4041}, + { 12, 4055},{ 12, 4060},{ 13, 8156},{ 13, 8159},{ 13, 8173}, + { 13, 8181},{ 14, 16377},{ 14, 16379},{ 15, 32765},{ 15, 32766}, + { 13, 8167},{ 12, 4044},{ 12, 4054},{ 12, 4063},{ 13, 8158}, + { 13, 8154},{ 13, 8165},{ 13, 8178},{ 14, 16378},{ 14, 16375}, + { 14, 16380},{ 14, 16381},{ 15, 32767} + }; +unsigned short huff10[][2] = { + { 6, 34}, + { 5, 8},{ 6, 29},{ 6, 38},{ 7, 95},{ 8, 211}, + { 9, 463},{ 10, 976},{ 10, 983},{ 10, 1005},{ 11, 2032}, + { 11, 2038},{ 12, 4093},{ 5, 7},{ 4, 0},{ 4, 1}, + { 5, 9},{ 6, 32},{ 7, 84},{ 7, 96},{ 8, 213}, + { 8, 220},{ 9, 468},{ 10, 973},{ 10, 990},{ 11, 2023}, + { 6, 28},{ 4, 2},{ 5, 6},{ 5, 12},{ 6, 30}, + { 6, 40},{ 7, 91},{ 8, 205},{ 8, 217},{ 9, 462}, + { 9, 476},{ 10, 985},{ 10, 1009},{ 6, 37},{ 5, 11}, + { 5, 10},{ 5, 13},{ 6, 36},{ 7, 87},{ 7, 97}, + { 8, 204},{ 8, 221},{ 9, 460},{ 9, 478},{ 10, 979}, + { 10, 999},{ 7, 93},{ 6, 33},{ 6, 31},{ 6, 35}, + { 6, 39},{ 7, 89},{ 7, 100},{ 8, 216},{ 8, 223}, + { 9, 466},{ 9, 482},{ 10, 989},{ 10, 1006},{ 8, 209}, + { 7, 85},{ 6, 41},{ 7, 86},{ 7, 88},{ 7, 98}, + { 8, 206},{ 8, 224},{ 8, 226},{ 9, 474},{ 10, 980}, + { 10, 995},{ 11, 2027},{ 9, 457},{ 7, 94},{ 7, 90}, + { 7, 92},{ 7, 99},{ 8, 202},{ 8, 218},{ 9, 455}, + { 9, 458},{ 9, 480},{ 10, 987},{ 10, 1000},{ 11, 2028}, + { 9, 483},{ 8, 210},{ 8, 203},{ 8, 208},{ 8, 215}, + { 8, 219},{ 9, 454},{ 9, 469},{ 9, 472},{ 10, 970}, + { 10, 986},{ 11, 2026},{ 11, 2033},{ 9, 481},{ 8, 212}, + { 8, 207},{ 8, 214},{ 8, 222},{ 8, 225},{ 9, 464}, + { 9, 470},{ 10, 977},{ 10, 981},{ 10, 1010},{ 11, 2030}, + { 11, 2043},{ 10, 1001},{ 9, 461},{ 9, 456},{ 9, 459}, + { 9, 465},{ 9, 471},{ 9, 479},{ 10, 975},{ 10, 992}, + { 10, 1007},{ 11, 2022},{ 11, 2040},{ 12, 4090},{ 10, 1003}, + { 9, 477},{ 9, 467},{ 9, 473},{ 9, 475},{ 10, 978}, + { 10, 972},{ 10, 988},{ 10, 1002},{ 11, 2029},{ 11, 2035}, + { 11, 2041},{ 12, 4089},{ 11, 2034},{ 10, 974},{ 9, 484}, + { 10, 971},{ 10, 984},{ 10, 982},{ 10, 994},{ 10, 997}, + { 11, 2024},{ 11, 2036},{ 11, 2037},{ 11, 2039},{ 12, 4091}, + { 11, 2042},{ 10, 1004},{ 10, 991},{ 10, 993},{ 10, 996}, + { 10, 998},{ 10, 1008},{ 11, 2025},{ 11, 2031},{ 12, 4088}, + { 12, 4094},{ 12, 4092},{ 12, 4095} + }; +unsigned short huff11[][2] = { + { 4, 0}, + { 5, 6},{ 6, 25},{ 7, 61},{ 8, 156},{ 8, 198}, + { 9, 423},{ 10, 912},{ 10, 962},{ 10, 991},{ 11, 2022}, + { 11, 2035},{ 12, 4091},{ 11, 2028},{ 12, 4090},{ 12, 4094}, + { 10, 910},{ 5, 5},{ 4, 1},{ 5, 8},{ 6, 20}, + { 7, 55},{ 7, 66},{ 8, 146},{ 8, 175},{ 9, 401}, + { 9, 421},{ 9, 437},{ 10, 926},{ 10, 960},{ 10, 930}, + { 10, 973},{ 11, 2006},{ 8, 174},{ 6, 23},{ 5, 7}, + { 5, 9},{ 6, 24},{ 7, 57},{ 7, 64},{ 8, 142}, + { 8, 163},{ 8, 184},{ 9, 409},{ 9, 428},{ 9, 449}, + { 10, 945},{ 10, 918},{ 10, 958},{ 10, 970},{ 8, 157}, + { 7, 60},{ 6, 21},{ 6, 22},{ 6, 26},{ 7, 59}, + { 7, 68},{ 8, 145},{ 8, 165},{ 8, 190},{ 9, 406}, + { 9, 430},{ 9, 441},{ 10, 929},{ 10, 913},{ 10, 933}, + { 10, 981},{ 8, 148},{ 8, 154},{ 7, 54},{ 7, 56}, + { 7, 58},{ 7, 65},{ 8, 140},{ 8, 155},{ 8, 176}, + { 8, 195},{ 9, 414},{ 9, 427},{ 9, 444},{ 10, 927}, + { 10, 911},{ 10, 937},{ 10, 975},{ 8, 147},{ 8, 191}, + { 7, 62},{ 7, 63},{ 7, 67},{ 7, 69},{ 8, 158}, + { 8, 167},{ 8, 185},{ 9, 404},{ 9, 418},{ 9, 442}, + { 9, 451},{ 10, 934},{ 10, 935},{ 10, 955},{ 10, 980}, + { 8, 159},{ 9, 416},{ 8, 143},{ 8, 141},{ 8, 144}, + { 8, 152},{ 8, 166},{ 8, 182},{ 8, 196},{ 9, 415}, + { 9, 431},{ 9, 447},{ 10, 921},{ 10, 959},{ 10, 948}, + { 10, 969},{ 10, 999},{ 8, 168},{ 9, 438},{ 8, 171}, + { 8, 164},{ 8, 170},{ 8, 178},{ 8, 194},{ 8, 197}, + { 9, 408},{ 9, 420},{ 9, 440},{ 10, 908},{ 10, 932}, + { 10, 964},{ 10, 966},{ 10, 989},{ 10, 1000},{ 8, 173}, + { 10, 943},{ 9, 402},{ 8, 189},{ 8, 188},{ 9, 398}, + { 9, 407},{ 9, 410},{ 9, 419},{ 9, 433},{ 10, 909}, + { 10, 920},{ 10, 951},{ 10, 979},{ 10, 977},{ 10, 987}, + { 11, 2013},{ 8, 180},{ 10, 990},{ 9, 425},{ 9, 411}, + { 9, 412},{ 9, 417},{ 9, 426},{ 9, 429},{ 9, 435}, + { 10, 907},{ 10, 946},{ 10, 952},{ 10, 974},{ 10, 993}, + { 10, 992},{ 11, 2002},{ 11, 2021},{ 8, 183},{ 11, 2019}, + { 9, 443},{ 9, 424},{ 9, 422},{ 9, 432},{ 9, 434}, + { 9, 439},{ 10, 923},{ 10, 922},{ 10, 954},{ 10, 949}, + { 10, 982},{ 11, 2007},{ 10, 996},{ 11, 2008},{ 11, 2026}, + { 8, 186},{ 11, 2024},{ 10, 928},{ 9, 445},{ 9, 436}, + { 10, 906},{ 9, 452},{ 10, 914},{ 10, 938},{ 10, 944}, + { 10, 956},{ 10, 983},{ 11, 2004},{ 11, 2012},{ 11, 2011}, + { 11, 2005},{ 11, 2032},{ 8, 193},{ 11, 2043},{ 10, 968}, + { 10, 931},{ 10, 917},{ 10, 925},{ 10, 940},{ 10, 942}, + { 10, 965},{ 10, 984},{ 10, 994},{ 10, 998},{ 11, 2020}, + { 11, 2023},{ 11, 2016},{ 11, 2025},{ 11, 2039},{ 9, 400}, + { 11, 2034},{ 10, 915},{ 9, 446},{ 9, 448},{ 10, 916}, + { 10, 919},{ 10, 941},{ 10, 963},{ 10, 961},{ 10, 978}, + { 11, 2010},{ 11, 2009},{ 11, 2015},{ 11, 2027},{ 11, 2036}, + { 11, 2042},{ 9, 405},{ 11, 2040},{ 10, 957},{ 10, 924}, + { 10, 939},{ 10, 936},{ 10, 947},{ 10, 953},{ 10, 976}, + { 10, 995},{ 10, 997},{ 11, 2018},{ 11, 2014},{ 11, 2029}, + { 11, 2033},{ 11, 2041},{ 11, 2044},{ 9, 403},{ 12, 4093}, + { 10, 988},{ 10, 950},{ 10, 967},{ 10, 972},{ 10, 971}, + { 10, 985},{ 10, 986},{ 11, 2003},{ 11, 2017},{ 11, 2030}, + { 11, 2031},{ 11, 2037},{ 11, 2038},{ 12, 4092},{ 12, 4095}, + { 9, 413},{ 9, 450},{ 8, 181},{ 8, 161},{ 8, 150}, + { 8, 151},{ 8, 149},{ 8, 153},{ 8, 160},{ 8, 162}, + { 8, 172},{ 8, 169},{ 8, 177},{ 8, 179},{ 8, 187}, + { 8, 192},{ 9, 399},{ 5, 4} + }; +unsigned int huff12[][2] = { + { 18, 262120}, + { 18, 262118},{ 18, 262119},{ 18, 262117},{ 19, 524277},{ 19, 524273}, + { 19, 524269},{ 19, 524278},{ 19, 524270},{ 19, 524271},{ 19, 524272}, + { 19, 524284},{ 19, 524285},{ 19, 524287},{ 19, 524286},{ 19, 524279}, + { 19, 524280},{ 19, 524283},{ 19, 524281},{ 18, 262116},{ 19, 524282}, + { 18, 262115},{ 17, 131055},{ 17, 131056},{ 16, 65525},{ 17, 131054}, + { 16, 65522},{ 16, 65523},{ 16, 65524},{ 16, 65521},{ 15, 32758}, + { 15, 32759},{ 14, 16377},{ 14, 16373},{ 14, 16375},{ 14, 16371}, + { 14, 16374},{ 14, 16370},{ 13, 8183},{ 13, 8181},{ 12, 4089}, + { 12, 4087},{ 12, 4086},{ 11, 2041},{ 12, 4084},{ 11, 2040}, + { 10, 1017},{ 10, 1015},{ 10, 1013},{ 9, 504},{ 9, 503}, + { 8, 250},{ 8, 248},{ 8, 246},{ 7, 121},{ 6, 58}, + { 6, 56},{ 5, 26},{ 4, 11},{ 3, 4},{ 1, 0}, + { 4, 10},{ 4, 12},{ 5, 27},{ 6, 57},{ 6, 59}, + { 7, 120},{ 7, 122},{ 8, 247},{ 8, 249},{ 9, 502}, + { 9, 505},{ 10, 1012},{ 10, 1014},{ 10, 1016},{ 11, 2037}, + { 11, 2036},{ 11, 2038},{ 11, 2039},{ 12, 4085},{ 12, 4088}, + { 13, 8180},{ 13, 8182},{ 13, 8184},{ 14, 16376},{ 14, 16372}, + { 16, 65520},{ 15, 32756},{ 16, 65526},{ 15, 32757},{ 18, 262114}, + { 19, 524249},{ 19, 524250},{ 19, 524251},{ 19, 524252},{ 19, 524253}, + { 19, 524254},{ 19, 524248},{ 19, 524242},{ 19, 524243},{ 19, 524244}, + { 19, 524245},{ 19, 524246},{ 19, 524274},{ 19, 524255},{ 19, 524263}, + { 19, 524264},{ 19, 524265},{ 19, 524266},{ 19, 524267},{ 19, 524262}, + { 19, 524256},{ 19, 524257},{ 19, 524258},{ 19, 524259},{ 19, 524260}, + { 19, 524261},{ 19, 524247},{ 19, 524268},{ 19, 524276},{ 19, 524275} + }; + + diff --git a/external/libfaac/libfaac/kiss_fft/CHANGELOG b/external/libfaac/libfaac/kiss_fft/CHANGELOG new file mode 100644 index 0000000..49446ff --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/CHANGELOG @@ -0,0 +1,58 @@ +1.2.1 (April 4, 2004) + compiles cleanly with just about every -W warning flag under the sun + + reorganized kiss_fft_state so it could be read-only/const. This may be useful for embedded systems + that are willing to predeclare twiddle factors, factorization. + + Fixed C_MUL,S_MUL on 16-bit platforms. + + tmpbuf will only be allocated if input & output buffers are same + scratchbuf will only be allocated for ffts that are not multiples of 2,3,5 + + NOTE: The tmpbuf,scratchbuf changes may require synchronization code for multi-threaded apps. + + +1.2 (Feb 23, 2004) + interface change -- cfg object is forward declaration of struct instead of void* + This maintains type saftey and lets the compiler warn/error about stupid mistakes. + (prompted by suggestion from Erik de Castro Lopo) + + small speed improvements + + added psdpng.c -- sample utility that will create png spectrum "waterfalls" from an input file + ( not terribly useful yet) + +1.1.1 (Feb 1, 2004 ) + minor bug fix -- only affects odd rank, in-place, multi-dimensional FFTs + +1.1 : (Jan 30,2004) + split sample_code/ into test/ and tools/ + + Removed 2-D fft and added N-D fft (arbitrary) + + modified fftutil.c to allow multi-d FFTs + + Modified core fft routine to allow an input stride via kiss_fft_stride() + (eased support of multi-D ffts) + + Added fast convolution filtering (FIR filtering using overlap-scrap method, with tail scrap) + + Add kfc.[ch]: the KISS FFT Cache. It takes care of allocs for you ( suggested by Oscar Lesta ). + +1.0.1 (Dec 15, 2003) + fixed bug that occurred when nfft==1 + +1.0 : (Dec 14, 2003) + changed kiss_fft function from using a single buffer, to two buffers. + If the same buffer pointer is supplied for both in and out, kiss will + manage the buffer copies. + + added kiss_fft2d and kiss_fftr as separate source files (declarations in kiss_fft.h ) + +0.4 :(Nov 4,2003) optimized for radix 2,3,4,5 + +0.3 :(Oct 28, 2003) woops, version 2 didn't actually factor out any radices other than 2 + +0.2 :(Oct 27, 2003) added mixed radix, only radix 2,4 optimized versions + +0.1 :(May 19 2003) initial release, radix 2 only diff --git a/external/libfaac/libfaac/kiss_fft/COPYING b/external/libfaac/libfaac/kiss_fft/COPYING new file mode 100644 index 0000000..472830e --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/COPYING @@ -0,0 +1,11 @@ +Copyright (c) 2003-2004 Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/libfaac/libfaac/kiss_fft/README b/external/libfaac/libfaac/kiss_fft/README new file mode 100644 index 0000000..f5ac197 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/README @@ -0,0 +1,109 @@ +KISS FFT - A mixed-radix Fast Fourier Transform based up on the principle, +"Keep It Simple, Stupid." + + There are many great fft libraries already around. Kiss FFT is not trying +to be better than any of them. It only attempts to be a reasonably efficient, +moderately useful FFT that can use fixed or floating data types and can be +incorporated into someone's C program in a few minutes with trivial licensing. + +USAGE: + + The basic usage for 1-d complex FFT is: + + #include "kiss_fft.h" + + kiss_fft_cfg cfg = kiss_fft_alloc( nfft ,inverse_fft ); + + while ... + + ... // put kth sample in cx_in[k].r and cx_in[k].i + + kiss_fft( cfg , cx_in , cx_out ); + + ... // transformed. DC is in cx_out[0].r and cx_out[0].i + + free(cfg); + + Note: frequency-domain data is stored from dc up to 2pi. + so cx_out[0] is the dc bin of the FFT + and cx_out[nfft/2] is the Nyquist bin (if exists) + + Declarations are in "kiss_fft.h", along with a brief description of the +functions you'll need to use. + +Code definitions for 1d complex FFTs are in kiss_fft.c. + +You can do other cool stuff with the extras you'll find in tools/ + + * arbitrary dimension complex FFTs + * 1-d real FFTs + * fast convolution FIR filtering + * spectrum image creation + +The core fft and most tools/ code can be compiled to use float, double +or Q15 short samples. The default is float. + + +BACKGROUND: + + I started coding this because I couldn't find a fixed point FFT that didn't +use assembly code. I started with floating point numbers so I could get the +theory straight before working on fixed point issues. In the end, I had a +little bit of code that could be recompiled easily to do ffts with short, float +or double (other types should be easy too). + + Once I got my FFT working, I was curious about the speed compared to +a well respected and highly optimized fft library. I don't want to criticize +this great library, so let's call it FFT_BRANDX. +During this process, I learned: + + 1. FFT_BRANDX has more than 100K lines of code. The core of kiss_fft is about 500 lines (cpx 1-d). + 2. It took me an embarrassingly long time to get FFT_BRANDX working. + 3. A simple program using FFT_BRANDX is 522KB. A similar program using kiss_fft is 18KB. + 4. FFT_BRANDX is roughly twice as fast as KISS FFT. + + It is wonderful that free, highly optimized libraries like FFT_BRANDX exist. +But such libraries carry a huge burden of complexity necessary to extract every +last bit of performance. + + Sometimes simpler is better, even if it's not better. + +PERFORMANCE: + (on Athlon XP 2100+, with gcc 2.96, float data type) + + Kiss performed 10000 1024-pt cpx ffts in .63 s of cpu time. + For comparison, it took md5sum twice as long to process the same amount of data. + + Transforming 5 minutes of CD quality audio takes less than a second (nfft=1024). + +DO NOT: + ... use Kiss if you need the Fastest Fourier Transform in the World + ... ask me to add features that will bloat the code + +UNDER THE HOOD: + + Kiss FFT uses a time decimation, mixed-radix, out-of-place FFT. +No scaling is done. Optimized butterflies are used for factors 2,3,4, and 5. + + The real optimization code only works for even length ffts. It does two half-length + FFTs in parallel (packed into real&imag), and then combines them via twiddling. + + The fast convolution filtering uses the overlap-scrap method, slightly + modified to put the scrap at the tail. + +LICENSE: + BSD, see COPYING for details. Basically, "free to use&change, give credit where due, no guarantees" + +TODO: + *) Add real optimization for odd length FFTs (DST?) + *) Add real optimization to the n-dimensional FFT + *) Add simple windowing function, e.g. Hamming : w(i)=.54-.46*cos(2pi*i/(n-1)) + *) Make the fixed point scaling and bit shifts more easily configurable. + *) Document/revisit the input/output fft scaling + *) See if the fixed point code can be optimized a little without adding complexity. + *) Make doc describing the overlap (tail) scrap fast convolution filtering in kiss_fastfir.c + *) Test all the ./tools/ code with fixed point (kiss_fastfir.c doesn't work, maybe others) + +AUTHOR: + Mark Borgerding + Mark@Borgerding.net diff --git a/external/libfaac/libfaac/kiss_fft/README.kiss_fft b/external/libfaac/libfaac/kiss_fft/README.kiss_fft new file mode 100644 index 0000000..4197ffb --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/README.kiss_fft @@ -0,0 +1,6 @@ +See README and COPYING files for author and copyright information. + +kiss_fft.c is modified in order to eliminate static variables. + +-- sur. + diff --git a/external/libfaac/libfaac/kiss_fft/TIPS b/external/libfaac/libfaac/kiss_fft/TIPS new file mode 100644 index 0000000..0709032 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/TIPS @@ -0,0 +1,23 @@ +Speed: + * experiment with compiler flags + Special thanks to Oscar Lesta. He suggested some compiler flags + for gcc that make a big difference. They shave 10-15% off + execution time on some systems. Try some combination of: + -march=pentiumpro + -ffast-math + -fomit-frame-pointer + + * If the input data has no imaginary component, use the kiss_fftr code under tools/. + Real ffts are roughly twice as fast as complex. + +Reducing code size: + * remove some of the butterflies. There are currently butterflies optimized for radices + 2,3,4,5. It is worth mentioning that you can still use FFT sizes that contain + these factors, they just won't be quite as fast. You can decide for yourself + whether to keep radix 2 or 4. If you do some work in this area, let me + know what you find. + + * For platforms where ROM/code space is more plentiful than RAM, + consider creating a hardcoded kiss_fft_state. In other words, decide which + FFT size(s) you want and make a structure with the correct factors and twiddles. + diff --git a/external/libfaac/libfaac/kiss_fft/_kiss_fft_guts.h b/external/libfaac/libfaac/kiss_fft/_kiss_fft_guts.h new file mode 100644 index 0000000..c572473 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/_kiss_fft_guts.h @@ -0,0 +1,97 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_scalar as either short or a float type + and defines + typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ +#include "kiss_fft.h" + + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#ifdef FIXED_POINT + +# define smul(a,b) ( (long)(a)*(b) ) +# define sround( x ) (short)( ( (x) + (1<<14) ) >>15 ) + +# define S_MUL(a,b) sround( smul(a,b) ) + +# define C_MUL(m,a,b) \ + do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ + (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) + +# define C_FIXDIV(c,div) \ + do{ (c).r /= div; (c).i /=div; }while(0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = sround( smul( (c).r , s ) ) ;\ + (c).i = sround( smul( (c).i , s ) ) ; }while(0) + +#else /* not FIXED_POINT*/ + +# define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) +# define C_FIXDIV(c,div) /* NOOP */ +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) +#endif + +#define C_ADD( res, a,b)\ + do { (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; }while(0) +#define C_SUB( res, a,b)\ + do { (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; }while(0) +#define C_ADDTO( res , a)\ + do { (res).r += (a).r; (res).i += (a).i; }while(0) +#define C_SUBFROM( res , a)\ + do { (res).r -= (a).r; (res).i -= (a).i; }while(0) + +static +void kf_cexp(kiss_fft_cpx * x,double phase) /* returns e ** (j*phase) */ +{ +#ifdef FIXED_POINT + x->r = (kiss_fft_scalar) (32767 * cos (phase)); + x->i = (kiss_fft_scalar) (32767 * sin (phase)); +#else + x->r = cos (phase); + x->i = sin (phase); +#endif +} + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/external/libfaac/libfaac/kiss_fft/kiss_fft.c b/external/libfaac/libfaac/kiss_fft/kiss_fft.c new file mode 100644 index 0000000..1634cd8 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/kiss_fft.c @@ -0,0 +1,362 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "_kiss_fft_guts.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static void kf_bfly2( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m + ) +{ + kiss_fft_cpx * Fout2; + kiss_fft_cpx * tw1 = st->twiddles; + kiss_fft_cpx t; + Fout2 = Fout + m; + do{ + C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2); + + C_MUL (t, *Fout2 , *tw1); + tw1 += fstride; + C_SUB( *Fout2 , *Fout , t ); + C_ADDTO( *Fout , t ); + ++Fout2; + ++Fout; + }while (--m); +} + +static void kf_bfly4( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + const size_t m + ) +{ + kiss_fft_cpx *tw1,*tw2,*tw3; + kiss_fft_cpx scratch[6]; + size_t k=m; + const size_t m2=2*m; + const size_t m3=3*m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4); + + C_MUL(scratch[0],Fout[m] , *tw1 ); + C_MUL(scratch[1],Fout[m2] , *tw2 ); + C_MUL(scratch[2],Fout[m3] , *tw3 ); + + C_SUB( scratch[5] , *Fout, scratch[1] ); + C_ADDTO(*Fout, scratch[1]); + C_ADD( scratch[3] , scratch[0] , scratch[2] ); + C_SUB( scratch[4] , scratch[0] , scratch[2] ); + C_SUB( Fout[m2], *Fout, scratch[3] ); + tw1 += fstride; + tw2 += fstride*2; + tw3 += fstride*3; + C_ADDTO( *Fout , scratch[3] ); + + if(st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + }else{ + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + }while(--k); +} + +static void kf_bfly3( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + size_t m + ) +{ + size_t k=m; + const size_t m2 = 2*m; + kiss_fft_cpx *tw1,*tw2; + kiss_fft_cpx scratch[5]; + kiss_fft_cpx epi3; + epi3 = st->twiddles[fstride*m]; + + tw1=tw2=st->twiddles; + + do{ + C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); + + C_MUL(scratch[1],Fout[m] , *tw1); + C_MUL(scratch[2],Fout[m2] , *tw2); + + C_ADD(scratch[3],scratch[1],scratch[2]); + C_SUB(scratch[0],scratch[1],scratch[2]); + tw1 += fstride; + tw2 += fstride*2; + + Fout[m].r = Fout->r - scratch[3].r/2; + Fout[m].i = Fout->i - scratch[3].i/2; + + C_MULBYSCALAR( scratch[0] , epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + }while(--k); +} + +static void kf_bfly5( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m + ) +{ + kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; + int u; + kiss_fft_cpx scratch[13]; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx *tw; + kiss_fft_cpx ya,yb; + ya = twiddles[fstride*m]; + yb = twiddles[fstride*2*m]; + + Fout0=Fout; + Fout1=Fout0+m; + Fout2=Fout0+2*m; + Fout3=Fout0+3*m; + Fout4=Fout0+4*m; + + tw=st->twiddles; + for ( u=0; ur += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); + + C_ADD(*Fout2,scratch[11],scratch[12]); + C_SUB(*Fout3,scratch[11],scratch[12]); + + ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void kf_bfly_generic( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m, + int p + ) +{ + int u,k,q1,q; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx t; + int Norig = st->nfft; + + kiss_fft_cpx *scratchbuf=(kiss_fft_cpx *)malloc( sizeof(kiss_fft_cpx) * p ); + + for ( u=0; u=Norig) twidx-=Norig; + C_MUL(t,scratchbuf[q] , twiddles[twidx] ); + C_ADDTO( Fout[ k ] ,t); + } + k += m; + } + } + + free( scratchbuf ); +} + +static +void kf_work( + kiss_fft_cpx * Fout, + const kiss_fft_cpx * f, + const size_t fstride, + int in_stride, + int * factors, + const kiss_fft_cfg st + ) +{ + kiss_fft_cpx * Fout_beg=Fout; + const int p=*factors++; /* the radix */ + const int m=*factors++; /* stage's fft length/p */ + const kiss_fft_cpx * Fout_end = Fout + p*m; + + if (m==1) { + do{ + *Fout = *f; + f += fstride*in_stride; + }while(++Fout != Fout_end ); + }else{ + do{ + kf_work( Fout , f, fstride*p, in_stride, factors,st); + f += fstride*in_stride; + }while( (Fout += m) != Fout_end ); + } + + Fout=Fout_beg; + + switch (p) { + case 2: kf_bfly2(Fout,fstride,st,m); break; + case 3: kf_bfly3(Fout,fstride,st,m); break; + case 4: kf_bfly4(Fout,fstride,st,m); break; + case 5: kf_bfly5(Fout,fstride,st,m); break; + default: kf_bfly_generic(Fout,fstride,st,m,p); break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static +void kf_factor(int n,int * facbuf) +{ + int p=4; + double floor_sqrt; + floor_sqrt = floor( sqrt((double)n) ); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: p = 2; break; + case 2: p = 3; break; + default: p += 2; break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) +{ + kiss_fft_cfg st=NULL; + size_t memneeded = sizeof(struct kiss_fft_state) + + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ + + if ( lenmem==NULL ) { + st = ( kiss_fft_cfg)malloc( memneeded ); + }else{ + if (*lenmem >= memneeded) + st = (kiss_fft_cfg)mem; + *lenmem = memneeded; + } + if (st) { + int i; + const double pi=3.14159265358979323846264338327; + const double phase0 = -2.0 * pi / (double)( nfft ); + + st->nfft=nfft; + st->inverse = inverse_fft; + + for (i=0;iinverse) + phase *= -1; + kf_cexp(st->twiddles+i, phase ); + } + + kf_factor(nfft,st->factors); + } + return st; +} + + + + +void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) +{ + if (fin == fout) { + kiss_fft_cpx *tmpbuf=(kiss_fft_cpx*)malloc( sizeof(kiss_fft_cpx) * st->nfft ); + kf_work(tmpbuf,fin,1,in_stride, st->factors,st); + memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); + free( tmpbuf ); + }else{ + kf_work( fout, fin, 1,in_stride, st->factors,st ); + } +} + +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) +{ + kiss_fft_stride(cfg,fin,fout,1); +} + diff --git a/external/libfaac/libfaac/kiss_fft/kiss_fft.h b/external/libfaac/libfaac/kiss_fft/kiss_fft.h new file mode 100644 index 0000000..146a45d --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/kiss_fft.h @@ -0,0 +1,94 @@ +/* + Copyright (c) 2013-2016 EasyDarwin.ORG. All rights reserved. + Github: https://github.com/EasyDarwin + WEChat: EasyDarwin + Website: http://www.easydarwin.org +*/ +#ifndef KISS_FFT_H +#define KISS_FFT_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + then see tools/ + */ + +#ifdef FIXED_POINT +# define kiss_fft_scalar short +#else +# ifndef kiss_fft_scalar +/* default is float */ +# define kiss_fft_scalar float +# endif +#endif + +typedef struct { + kiss_fft_scalar r; + kiss_fft_scalar i; +}kiss_fft_cpx; + +typedef struct kiss_fft_state* kiss_fft_cfg; + +/* + * kiss_fft_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); + +void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); + +/* If kiss_fft_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_free free + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/libfaac/libfaac/kiss_fft/kiss_fftr.c b/external/libfaac/libfaac/kiss_fft/kiss_fftr.c new file mode 100644 index 0000000..6baeb21 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/kiss_fftr.c @@ -0,0 +1,137 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "kiss_fftr.h" +#include "_kiss_fft_guts.h" + +struct kiss_fftr_state{ + kiss_fft_cfg substate; + kiss_fft_cpx * tmpbuf; + kiss_fft_cpx * super_twiddles; +}; + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) +{ + int i; + kiss_fftr_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + fprintf(stderr,"Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2); + + if (lenmem == NULL) { + st = (kiss_fftr_cfg) malloc (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ + st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) i / nfft + .5); + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles+i,phase); + } + return st; +} + +void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k,N; + + if ( st->substate->inverse) { + fprintf(stderr,"kiss fft usage error: improper alloc\n"); + exit(1); + } + + N = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); + + freqdata[0].r = st->tmpbuf[0].r + st->tmpbuf[0].i; + freqdata[0].i = 0; + C_FIXDIV(freqdata[0],2); + + for (k=1;k <= N/2 ; ++k ) { + kiss_fft_cpx fpnk,fpk,f1k,f2k,tw; + + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[N-k].r; + fpnk.i = -st->tmpbuf[N-k].i; + C_FIXDIV(fpk,2); + C_FIXDIV(fpnk,2); + + C_ADD( f1k, fpk , fpnk ); + C_SUB( f2k, fpk , fpnk ); + C_MUL( tw , f2k , st->super_twiddles[k]); + + C_ADD( freqdata[k] , f1k ,tw); + freqdata[k].r = (f1k.r + tw.r) / 2; + freqdata[k].i = (f1k.i + tw.i) / 2; + + freqdata[N-k].r = (f1k.r - tw.r)/2; + freqdata[N-k].i = - (f1k.i - tw.i)/2; + } + freqdata[N].r = st->tmpbuf[0].r - st->tmpbuf[0].i; + freqdata[N].i = 0; + C_FIXDIV(freqdata[N],2); +} + +void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, N; + + if (st->substate->inverse == 0) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + N = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[N].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[N].r; + + for (k = 1; k <= N / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmpbuf; + fk = freqdata[k]; + fnkc.r = freqdata[N - k].r; + fnkc.i = -freqdata[N - k].i; + + C_ADD (fek, fk, fnkc); + C_SUB (tmpbuf, fk, fnkc); + C_MUL (fok, tmpbuf, st->super_twiddles[k]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[N - k], fek, fok); + st->tmpbuf[N - k].i *= -1; + } + kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); +} diff --git a/external/libfaac/libfaac/kiss_fft/kiss_fftr.h b/external/libfaac/libfaac/kiss_fft/kiss_fftr.h new file mode 100644 index 0000000..38b77f5 --- /dev/null +++ b/external/libfaac/libfaac/kiss_fft/kiss_fftr.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2013-2016 EasyDarwin.ORG. All rights reserved. + Github: https://github.com/EasyDarwin + WEChat: EasyDarwin + Website: http://www.easydarwin.org +*/ +#ifndef KISS_FTR_H +#define KISS_FTR_H + +#include "kiss_fft.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_state *kiss_fftr_cfg; + + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/libfaac/libfaac/ltp.c b/external/libfaac/libfaac/ltp.c new file mode 100644 index 0000000..f3fa86d --- /dev/null +++ b/external/libfaac/libfaac/ltp.c @@ -0,0 +1,420 @@ +/************************************************************************** + +This software module was originally developed by +Nokia in the course of development of the MPEG-2 AAC/MPEG-4 +Audio standard ISO/IEC13818-7, 14496-1, 2 and 3. +This software module is an implementation of a part +of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the +MPEG-2 aac/MPEG-4 Audio standard. ISO/IEC gives users of the +MPEG-2aac/MPEG-4 Audio standards free license to this software module +or modifications thereof for use in hardware or software products +claiming conformance to the MPEG-2 aac/MPEG-4 Audio standards. Those +intending to use this software module in hardware or software products +are advised that this use may infringe existing patents. The original +developer of this software module, the subsequent +editors and their companies, and ISO/IEC have no liability for use of +this software module or modifications thereof in an +implementation. Copyright is not released for non MPEG-2 aac/MPEG-4 +Audio conforming products. The original developer retains full right to +use the code for the developer's own purpose, assign or donate the code to a +third party and to inhibit third party from using the code for non +MPEG-2 aac/MPEG-4 Audio conforming products. This copyright notice +must be included in all copies or derivative works. +Copyright (c)1997. + +***************************************************************************/ +/* + * $Id: ltp.c,v 1.9 2003/06/26 19:20:31 knik Exp $ + */ + +#include +#include + +#include "frame.h" +#include "coder.h" +#include "ltp.h" +#include "tns.h" +#include "filtbank.h" +#include "util.h" + + +/* short double_to_int(double sig_in); */ +#define double_to_int(sig_in) \ + ((sig_in) > 32767 ? 32767 : ( \ + (sig_in) < -32768 ? -32768 : (sig_in))) + +#define _MDCT_SCALE 512 + +/* Purpose: Codebook for LTP weight coefficients. */ +static double codebook[CODESIZE] = +{ + 0.570829, + 0.696616, + 0.813004, + 0.911304, + 0.984900, + 1.067894, + 1.194601, + 1.369533 +}; + + +static double snr_pred(double *mdct_in, double *mdct_pred, int *sfb_flag, int *sfb_offset, + int block_type, int side_info, int num_of_sfb) +{ + int i, j, flen; + double snr_limit; + double num_bit, snr[NSFB_LONG]; + double temp1, temp2; + double energy[BLOCK_LEN_LONG], snr_p[BLOCK_LEN_LONG]; + + if (block_type != ONLY_SHORT_WINDOW) + { + flen = BLOCK_LEN_LONG; + snr_limit = 1.e-30; + } else { + flen = BLOCK_LEN_SHORT; + snr_limit = 1.e-20; + } + + for (i = 0; i < flen; i++) + { + energy[i] = mdct_in[i] * mdct_in[i]; + snr_p[i] = (mdct_in[i] - mdct_pred[i]) * (mdct_in[i] - mdct_pred[i]); + } + + num_bit = 0.0; + + for (i = 0; i < num_of_sfb; i++) + { + temp1 = 0.0; + temp2 = 0.0; + for (j = sfb_offset[i]; j < sfb_offset[i + 1]; j++) + { + temp1 += energy[j]; + temp2 += snr_p[j]; + } + + if (temp2 < snr_limit) + temp2 = snr_limit; + + if (temp1 > 1.e-20) + snr[i] = -10. * log10 (temp2 / temp1); + else + snr[i] = 0.0; + + sfb_flag[i] = 1; + + if (block_type != ONLY_SHORT_WINDOW) + { + if (snr[i] <= 0.0) + { + sfb_flag[i] = 0; + for (j = sfb_offset[i]; j < sfb_offset[i + 1]; j++) + mdct_pred[j] = 0.0; + } else { + num_bit += snr[i] / 6. * (sfb_offset[i + 1] - sfb_offset[i]); + } + } + } + + if (num_bit < side_info) + { +// printf("LTP not used!, num_bit: %f ", num_bit); + num_bit = 0.0; + for (j = 0; j < flen; j++) + mdct_pred[j] = 0.0; + for (i = 0; i < num_of_sfb; i++) + sfb_flag[i] = 0; + } else { + num_bit -= side_info; +// printf("LTP used!, num_bit: %f ", num_bit); + } + + return (num_bit); +} + +static void prediction(double *buffer, double *predicted_samples, double *weight, int lag, + int flen) +{ + int i, offset; + int num_samples; + + offset = NOK_LT_BLEN - flen / 2 - lag; + + num_samples = flen; + if(NOK_LT_BLEN - offset < flen) + num_samples = NOK_LT_BLEN - offset; + + for(i = 0; i < num_samples; i++) + predicted_samples[i] = *weight * _MDCT_SCALE*buffer[offset++]; + for( ; i < flen; i++) + predicted_samples[i] = 0.0; + + +} + +static void w_quantize(double *freq, int *ltp_idx) +{ + int i; + double dist, low; + + low = 1.0e+10; + dist = 0.0; + for (i = 0; i < CODESIZE; i++) + { + dist = (*freq - codebook[i]) * (*freq - codebook[i]); + if (dist < low) + { + low = dist; + *ltp_idx = i; + } + } + + *freq = codebook[*ltp_idx]; +} + +static int pitch(double *sb_samples, double *x_buffer, int flen, int lag0, int lag1, + double *predicted_samples, double *gain, int *cb_idx) +{ + int i, j, delay; + double corr1, corr2, lag_corr; + double p_max, energy, lag_energy; + + /* + * Below is a figure illustrating how the lag and the + * samples in the buffer relate to each other. + * + * ------------------------------------------------------------------ + * | | | | | + * | slot 1 | 2 | 3 | 4 | + * | | | | | + * ------------------------------------------------------------------ + * + * lag = 0 refers to the end of slot 4 and lag = DELAY refers to the end + * of slot 2. The start of the predicted frame is then obtained by + * adding the length of the frame to the lag. Remember that slot 4 doesn't + * actually exist, since it is always filled with zeros. + * + * The above short explanation was for long blocks. For short blocks the + * zero lag doesn't refer to the end of slot 4 but to the start of slot + * 4 - the frame length of a short block. + * + * Some extra code is then needed to handle those lag values that refer + * to slot 4. + */ + + p_max = 0.0; + lag_corr = lag_energy = 0.0; + delay = lag0; + + + for (i = lag0; iblock_type, sfb_offset, + mdct_predicted); + + /* Get the prediction gain. */ + bit_gain = snr_pred(p_spectrum, mdct_predicted, sfb_prediction_used, + sfb_offset, side_info, last_band, coderInfo->nr_of_sfb); + + return (bit_gain); +} + +void LtpInit(faacEncHandle hEncoder) +{ + int i; + unsigned int channel; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + LtpInfo *ltpInfo = &(hEncoder->coderInfo[channel].ltpInfo); + + ltpInfo->buffer = AllocMemory(NOK_LT_BLEN * sizeof(double)); + ltpInfo->mdct_predicted = AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + ltpInfo->time_buffer = AllocMemory(BLOCK_LEN_LONG*sizeof(double)); + ltpInfo->ltp_overlap_buffer = AllocMemory(BLOCK_LEN_LONG*sizeof(double)); + + for (i = 0; i < NOK_LT_BLEN; i++) + ltpInfo->buffer[i] = 0; + + ltpInfo->weight_idx = 0; + for(i = 0; i < MAX_SHORT_WINDOWS; i++) + ltpInfo->sbk_prediction_used[i] = ltpInfo->delay[i] = 0; + + for(i = 0; i < MAX_SCFAC_BANDS; i++) + ltpInfo->sfb_prediction_used[i] = 0; + + ltpInfo->side_info = LEN_LTP_DATA_PRESENT; + + for(i = 0; i < 2 * BLOCK_LEN_LONG; i++) + ltpInfo->mdct_predicted[i] = 0.0; + + } +} + +void LtpEnd(faacEncHandle hEncoder) +{ + unsigned int channel; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + LtpInfo *ltpInfo = &(hEncoder->coderInfo[channel].ltpInfo); + + if (ltpInfo->buffer) + FreeMemory(ltpInfo->buffer); + if (ltpInfo->mdct_predicted) + FreeMemory(ltpInfo->mdct_predicted); + if (ltpInfo->time_buffer) + FreeMemory(ltpInfo->time_buffer); + if (ltpInfo->ltp_overlap_buffer) + FreeMemory(ltpInfo->ltp_overlap_buffer); + } +} + +int LtpEncode(faacEncHandle hEncoder, + CoderInfo *coderInfo, + LtpInfo *ltpInfo, + TnsInfo *tnsInfo, + double *p_spectrum, + double *p_time_signal) +{ + int i, last_band; + double num_bit[MAX_SHORT_WINDOWS]; + double *predicted_samples; + + ltpInfo->global_pred_flag = 0; + ltpInfo->side_info = 0; + + predicted_samples = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double)); + + switch(coderInfo->block_type) + { + case ONLY_LONG_WINDOW: + case LONG_SHORT_WINDOW: + case SHORT_LONG_WINDOW: + last_band = (coderInfo->nr_of_sfb < MAX_LT_PRED_LONG_SFB) ? coderInfo->nr_of_sfb : MAX_LT_PRED_LONG_SFB; + + ltpInfo->delay[0] = + pitch(p_time_signal, ltpInfo->buffer, 2 * BLOCK_LEN_LONG, + 0, 2 * BLOCK_LEN_LONG, predicted_samples, <pInfo->weight, + <pInfo->weight_idx); + + + num_bit[0] = + ltp_enc_tf(hEncoder, coderInfo, p_spectrum, predicted_samples, + ltpInfo->mdct_predicted, + coderInfo->sfb_offset, coderInfo->nr_of_sfb, + last_band, ltpInfo->side_info, ltpInfo->sfb_prediction_used, + tnsInfo); + + + ltpInfo->global_pred_flag = (num_bit[0] == 0.0) ? 0 : 1; + + if(ltpInfo->global_pred_flag) + for (i = 0; i < coderInfo->sfb_offset[last_band]; i++) + p_spectrum[i] -= ltpInfo->mdct_predicted[i]; + else + ltpInfo->side_info = 1; + + break; + + default: + break; + } + + if (predicted_samples) FreeMemory(predicted_samples); + + return (ltpInfo->global_pred_flag); +} + +void LtpReconstruct(CoderInfo *coderInfo, LtpInfo *ltpInfo, double *p_spectrum) +{ + int i, last_band; + + if(ltpInfo->global_pred_flag) + { + switch(coderInfo->block_type) + { + case ONLY_LONG_WINDOW: + case LONG_SHORT_WINDOW: + case SHORT_LONG_WINDOW: + last_band = (coderInfo->nr_of_sfb < MAX_LT_PRED_LONG_SFB) ? + coderInfo->nr_of_sfb : MAX_LT_PRED_LONG_SFB; + + for (i = 0; i < coderInfo->sfb_offset[last_band]; i++) + p_spectrum[i] += ltpInfo->mdct_predicted[i]; + break; + + default: + break; + } + } +} + +void LtpUpdate(LtpInfo *ltpInfo, double *time_signal, + double *overlap_signal, int block_size_long) +{ + int i; + + for(i = 0; i < NOK_LT_BLEN - 2 * block_size_long; i++) + ltpInfo->buffer[i] = ltpInfo->buffer[i + block_size_long]; + + for(i = 0; i < block_size_long; i++) + { + ltpInfo->buffer[NOK_LT_BLEN - 2 * block_size_long + i] = time_signal[i]; + ltpInfo->buffer[NOK_LT_BLEN - block_size_long + i] = overlap_signal[i]; + } +} diff --git a/external/libfaac/libfaac/ltp.h b/external/libfaac/libfaac/ltp.h new file mode 100644 index 0000000..31afd00 --- /dev/null +++ b/external/libfaac/libfaac/ltp.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2013-2016 EasyDarwin.ORG. All rights reserved. + Github: https://github.com/EasyDarwin + WEChat: EasyDarwin + Website: http://www.easydarwin.org +*/ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: ltp.h,v 1.3 2001/06/08 18:01:09 menno Exp $ + */ + +#ifndef LTP_H +#define LTP_H + +#include "coder.h" + + + +void LtpInit(faacEncHandle hEncoder); +void LtpEnd(faacEncHandle hEncoder); +int LtpEncode(faacEncHandle hEncoder, + CoderInfo *coderInfo, + LtpInfo *ltpInfo, + TnsInfo *tnsInfo, + double *p_spectrum, + double *p_time_signal); +void LtpReconstruct(CoderInfo *coderInfo, LtpInfo *ltpInfo, double *p_spectrum); +void LtpUpdate(LtpInfo *ltpInfo, double *time_signal, + double *overlap_signal, int block_size_long); + +#endif /* not defined LTP_H */ + diff --git a/external/libfaac/libfaac/midside.c b/external/libfaac/libfaac/midside.c new file mode 100644 index 0000000..fa6f611 --- /dev/null +++ b/external/libfaac/libfaac/midside.c @@ -0,0 +1,169 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2003 Krzysztof Nikiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: midside.c,v 1.1 2003/06/26 19:39:54 knik Exp $ + */ + +#include +#include "channels.h" +#include "util.h" + + +void MSEncode(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + double *spectrum[MAX_CHANNELS], + int maxchan, + int allowms) +{ + int chn; + + for (chn = 0; chn < maxchan; chn++) + { + if (channelInfo[chn].present) + { + if ((channelInfo[chn].cpe) && (channelInfo[chn].ch_is_left)) + { + int rch = channelInfo[chn].paired_ch; + + channelInfo[chn].msInfo.is_present = 0; + channelInfo[rch].msInfo.is_present = 0; + + /* Perform MS if block_types are the same */ + if ((coderInfo[chn].block_type == coderInfo[rch].block_type) + && allowms) + { + int nsfb = coderInfo[chn].nr_of_sfb; + MSInfo *msInfoL = &(channelInfo[chn].msInfo); + MSInfo *msInfoR = &(channelInfo[rch].msInfo); + int sfb; + + channelInfo[chn].common_window = 1; /* Use common window */ + channelInfo[chn].msInfo.is_present = 1; + channelInfo[rch].msInfo.is_present = 1; + + // make the same reference energy in both channels + coderInfo[chn].avgenrg = coderInfo[rch].avgenrg = + 0.5 * (coderInfo[chn].avgenrg + coderInfo[rch].avgenrg); + + for (sfb = 0; sfb < nsfb; sfb++) + { + int ms = 0; + int l, start, end; + double sum, diff; + double enrgs, enrgd, enrgl, enrgr; + double maxs, maxd, maxl, maxr; + + start = coderInfo[chn].sfb_offset[sfb]; + end = coderInfo[chn].sfb_offset[sfb + 1]; + + enrgs = enrgd = enrgl = enrgr = 0.0; + maxs = maxd = maxl = maxr = 0.0; + for (l = start; l < end; l++) + { + double lx = spectrum[chn][l]; + double rx = spectrum[rch][l]; + + sum = 0.5 * (lx + rx); + diff = 0.5 * (lx - rx); + + enrgs += sum * sum; + maxs = max(maxs, fabs(sum)); + + enrgd += diff * diff; + maxd = max(maxd, fabs(diff)); + + enrgl += lx * lx; + enrgr += rx * rx; + + maxl = max(maxl, fabs(lx)); + maxr = max(maxr, fabs(rx)); + } + +#if 1 + if ((min(enrgs, enrgd) < min(enrgl, enrgr)) + && (min(maxs, maxd) < min(maxl, maxr))) + ms = 1; +#else + if (min(enrgs, enrgd) < min(enrgl, enrgr)) + ms = 1; +#endif + + //printf("%d:%d\n", sfb, ms); + + msInfoR->ms_used[sfb] = msInfoL->ms_used[sfb] = ms; + + if (ms) + for (l = start; l < end; l++) + { + sum = spectrum[chn][l] + spectrum[rch][l]; + diff = spectrum[chn][l] - spectrum[rch][l]; + spectrum[chn][l] = 0.5 * sum; + spectrum[rch][l] = 0.5 * diff; + } + } + } + } + } + } +} + +void MSReconstruct(CoderInfo *coderInfo, + ChannelInfo *channelInfo, + int maxchan) +{ + int chn; + + for (chn = 0; chn < maxchan; chn++) + { + if (channelInfo[chn].present) + { + if (channelInfo[chn].cpe && channelInfo[chn].ch_is_left) + { + int rch = channelInfo[chn].paired_ch; + + MSInfo *msInfoL = &(channelInfo[chn].msInfo); + + if (msInfoL->is_present) { + int nsfb = coderInfo[chn].nr_of_sfb; + int sfb; + + for (sfb = 0; sfb < nsfb; sfb++) + { + int l, start, end; + + start = coderInfo[chn].sfb_offset[sfb]; + end = coderInfo[chn].sfb_offset[sfb + 1]; + + if (msInfoL->ms_used[sfb]) + { + for (l = start; l < end; l++) + { + double sum, diff; + + sum = coderInfo[chn].requantFreq[l]; + diff = coderInfo[rch].requantFreq[l]; + coderInfo[chn].requantFreq[l] = sum + diff; + coderInfo[rch].requantFreq[l] = sum - diff; + } + } + } + } + } + } + } +} diff --git a/external/libfaac/libfaac/midside.h b/external/libfaac/libfaac/midside.h new file mode 100644 index 0000000..a47660f --- /dev/null +++ b/external/libfaac/libfaac/midside.h @@ -0,0 +1,40 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2003 Krzysztof Nikiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: midside.h,v 1.1 2003/06/26 19:40:23 knik Exp $ + */ + +#ifndef _MIDSIDE_H +#define _MIDSIDE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "coder.h" + + +void MSEncode(CoderInfo *coderInfo, ChannelInfo *channelInfo, double *spectrum[MAX_CHANNELS], + unsigned int numberOfChannels, unsigned int msenable); +void MSReconstruct(CoderInfo *coderInfo, ChannelInfo *channelInfo, int numberOfChannels); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MIDSIDE_H */ diff --git a/external/libfaac/libfaac/psych.h b/external/libfaac/libfaac/psych.h new file mode 100644 index 0000000..00769c0 --- /dev/null +++ b/external/libfaac/libfaac/psych.h @@ -0,0 +1,85 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: psych.h,v 1.14 2005/04/24 19:16:14 rjamorim Exp $ + */ + +#ifndef PSYCH_H +#define PSYCH_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include "coder.h" +#include "channels.h" +#include "fft.h" + +typedef struct { + int size; + int sizeS; + + /* Previous input samples */ + double *prevSamples; + double *prevSamplesS; + + int block_type; + + void *data; +} PsyInfo; + +typedef struct { + double sampleRate; + + /* Hann window */ + double *hannWindow; + double *hannWindowS; + + void *data; +} GlobalPsyInfo; + +typedef struct +{ +void (*PsyInit) (GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, + unsigned int numChannels, unsigned int sampleRate, + int *cb_width_long, int num_cb_long, + int *cb_width_short, int num_cb_short); +void (*PsyEnd) (GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, + unsigned int numChannels); +void (*PsyCalculate) (ChannelInfo *channelInfo, GlobalPsyInfo *gpsyInfo, + PsyInfo *psyInfo, int *cb_width_long, int num_cb_long, + int *cb_width_short, int num_cb_short, + unsigned int numChannels); +void (*PsyBufferUpdate) ( FFT_Tables *fft_tables, GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, + double *newSamples, unsigned int bandwidth, + int *cb_width_short, int num_cb_short); +void (*BlockSwitch) (CoderInfo *coderInfo, PsyInfo *psyInfo, + unsigned int numChannels); +} psymodel_t; + +extern psymodel_t psymodel2; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PSYCH_H */ \ No newline at end of file diff --git a/external/libfaac/libfaac/psychkni.c b/external/libfaac/libfaac/psychkni.c new file mode 100644 index 0000000..1bf52ba --- /dev/null +++ b/external/libfaac/libfaac/psychkni.c @@ -0,0 +1,450 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2002 Krzysztof Nikiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: psychkni.c,v 1.17 2005/04/24 19:16:14 rjamorim Exp $ + */ +#include +#include +#include + +#include "psych.h" +#include "coder.h" +#include "fft.h" +#include "util.h" +#include "frame.h" + +typedef float psyfloat; + +typedef struct +{ + /* bandwidth */ + int bandS; + int lastband; + + /* SFB energy */ + psyfloat *fftEnrgS[8]; + psyfloat *fftEnrgNextS[8]; + psyfloat *fftEnrgNext2S[8]; + psyfloat *fftEnrgPrevS[8]; +} +psydata_t; + + +static void Hann(GlobalPsyInfo * gpsyInfo, double *inSamples, int size) +{ + int i; + + /* Applying Hann window */ + if (size == BLOCK_LEN_LONG * 2) + { + for (i = 0; i < size; i++) + inSamples[i] *= gpsyInfo->hannWindow[i]; + } + else + { + for (i = 0; i < size; i++) + inSamples[i] *= gpsyInfo->hannWindowS[i]; + } +} + +static void PsyCheckShort(PsyInfo * psyInfo) +{ + double totvol = 0.0; + double totchg, totchg2; + psydata_t *psydata = psyInfo->data; + int lastband = psydata->lastband; + int firstband = 1; + int sfb; + + /* long/short block switch */ + totchg = totchg2 = 0.0; + for (sfb = 0; sfb < lastband; sfb++) + { + int win; + double volb[16]; + double vavg[13]; + double maxdif = 0.0; + double totmaxdif = 0.0; + double e, v; + + // previous frame + for (win = 0; win < 4; win++) + { + e = psydata->fftEnrgPrevS[win + 4][sfb]; + + volb[win] = sqrt(e); + totvol += e; + } + + // current frame + for (win = 0; win < 8; win++) + { + e = psydata->fftEnrgS[win][sfb]; + + volb[win + 4] = sqrt(e); + totvol += e; + } + // next frame + for (win = 0; win < 4; win++) + { + e = psydata->fftEnrgNextS[win][sfb]; + + volb[win + 12] = sqrt(e); + totvol += e; + } + + // ignore lowest SFBs + if (sfb < firstband) + continue; + + v = 0.0; + for (win = 0; win < 4; win++) + { + v += volb[win]; + } + vavg[0] = 0.25 * v; + + for (win = 1; win < 13; win++) + { + v -= volb[win - 1]; + v += volb[win + 3]; + vavg[win] = 0.25 * v; + } + + for (win = 0; win < 8; win++) + { + int i; + double mina, maxv; + double voldif; + double totvoldif; + + mina = vavg[win]; + for (i = 1; i < 5; i++) + mina = min(mina, vavg[win + i]); + + maxv = volb[win + 2]; + for (i = 3; i < 6; i++) + maxv = max(maxv, volb[win + i]); + + if (!maxv || !mina) + continue; + + voldif = (maxv - mina) / mina; + totvoldif = (maxv - mina) * (maxv - mina); + + if (voldif > maxdif) + maxdif = voldif; + + if (totvoldif > totmaxdif) + totmaxdif = totvoldif; + } + totchg += maxdif; + totchg2 += totmaxdif; + } + + totvol = sqrt(totvol); + + totchg2 = sqrt(totchg2); + + totchg = totchg / lastband; + if (totvol) + totchg2 /= totvol; + else + totchg2 = 0.0; + + psyInfo->block_type = ((totchg > 1.0) && (totchg2 > 0.04)) + ? ONLY_SHORT_WINDOW : ONLY_LONG_WINDOW; + +#if 0 + { + static int total = 0, shorts = 0; + char *flash = " "; + + total++; + if (psyInfo->block_type == ONLY_SHORT_WINDOW) + { + flash = "****"; + shorts++; + } + + printf("totchg: %s %g %g\t%g\n", flash, totchg, totchg2, + (double)shorts/total); + } +#endif +} + +static void PsyInit(GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, unsigned int numChannels, + unsigned int sampleRate, int *cb_width_long, int num_cb_long, + int *cb_width_short, int num_cb_short) +{ + unsigned int channel; + int i, j, size; + + gpsyInfo->hannWindow = + (double *) AllocMemory(2 * BLOCK_LEN_LONG * sizeof(double)); + gpsyInfo->hannWindowS = + (double *) AllocMemory(2 * BLOCK_LEN_SHORT * sizeof(double)); + + for (i = 0; i < BLOCK_LEN_LONG * 2; i++) + gpsyInfo->hannWindow[i] = 0.5 * (1 - cos(2.0 * M_PI * (i + 0.5) / + (BLOCK_LEN_LONG * 2))); + for (i = 0; i < BLOCK_LEN_SHORT * 2; i++) + gpsyInfo->hannWindowS[i] = 0.5 * (1 - cos(2.0 * M_PI * (i + 0.5) / + (BLOCK_LEN_SHORT * 2))); + gpsyInfo->sampleRate = (double) sampleRate; + + for (channel = 0; channel < numChannels; channel++) + { + psydata_t *psydata = AllocMemory(sizeof(psydata_t)); + psyInfo[channel].data = psydata; + } + + size = BLOCK_LEN_LONG; + for (channel = 0; channel < numChannels; channel++) + { + psyInfo[channel].size = size; + + psyInfo[channel].prevSamples = + (double *) AllocMemory(size * sizeof(double)); + memset(psyInfo[channel].prevSamples, 0, size * sizeof(double)); + } + + size = BLOCK_LEN_SHORT; + for (channel = 0; channel < numChannels; channel++) + { + psydata_t *psydata = psyInfo[channel].data; + + psyInfo[channel].sizeS = size; + + psyInfo[channel].prevSamplesS = + (double *) AllocMemory(size * sizeof(double)); + memset(psyInfo[channel].prevSamplesS, 0, size * sizeof(double)); + + for (j = 0; j < 8; j++) + { + psydata->fftEnrgPrevS[j] = + (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat)); + memset(psydata->fftEnrgPrevS[j], 0, NSFB_SHORT * sizeof(psyfloat)); + psydata->fftEnrgS[j] = + (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat)); + memset(psydata->fftEnrgS[j], 0, NSFB_SHORT * sizeof(psyfloat)); + psydata->fftEnrgNextS[j] = + (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat)); + memset(psydata->fftEnrgNextS[j], 0, NSFB_SHORT * sizeof(psyfloat)); + psydata->fftEnrgNext2S[j] = + (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat)); + memset(psydata->fftEnrgNext2S[j], 0, NSFB_SHORT * sizeof(psyfloat)); + } + } +} + +static void PsyEnd(GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, unsigned int numChannels) +{ + unsigned int channel; + int j; + + if (gpsyInfo->hannWindow) + FreeMemory(gpsyInfo->hannWindow); + if (gpsyInfo->hannWindowS) + FreeMemory(gpsyInfo->hannWindowS); + + for (channel = 0; channel < numChannels; channel++) + { + if (psyInfo[channel].prevSamples) + FreeMemory(psyInfo[channel].prevSamples); + } + + for (channel = 0; channel < numChannels; channel++) + { + psydata_t *psydata = psyInfo[channel].data; + + if (psyInfo[channel].prevSamplesS) + FreeMemory(psyInfo[channel].prevSamplesS); + for (j = 0; j < 8; j++) + { + if (psydata->fftEnrgPrevS[j]) + FreeMemory(psydata->fftEnrgPrevS[j]); + if (psydata->fftEnrgS[j]) + FreeMemory(psydata->fftEnrgS[j]); + if (psydata->fftEnrgNextS[j]) + FreeMemory(psydata->fftEnrgNextS[j]); + if (psydata->fftEnrgNext2S[j]) + FreeMemory(psydata->fftEnrgNext2S[j]); + } + } + + for (channel = 0; channel < numChannels; channel++) + { + if (psyInfo[channel].data) + FreeMemory(psyInfo[channel].data); + } +} + +/* Do psychoacoustical analysis */ +static void PsyCalculate(ChannelInfo * channelInfo, GlobalPsyInfo * gpsyInfo, + PsyInfo * psyInfo, int *cb_width_long, int + num_cb_long, int *cb_width_short, + int num_cb_short, unsigned int numChannels) +{ + unsigned int channel; + + for (channel = 0; channel < numChannels; channel++) + { + if (channelInfo[channel].present) + { + + if (channelInfo[channel].cpe && + channelInfo[channel].ch_is_left) + { /* CPE */ + + int leftChan = channel; + int rightChan = channelInfo[channel].paired_ch; + + PsyCheckShort(&psyInfo[leftChan]); + PsyCheckShort(&psyInfo[rightChan]); + } + else if (!channelInfo[channel].cpe && + channelInfo[channel].lfe) + { /* LFE */ + // Only set block type and it should be OK + psyInfo[channel].block_type = ONLY_LONG_WINDOW; + } + else if (!channelInfo[channel].cpe) + { /* SCE */ + PsyCheckShort(&psyInfo[channel]); + } + } + } +} + +static void PsyBufferUpdate( FFT_Tables *fft_tables, GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, + double *newSamples, unsigned int bandwidth, + int *cb_width_short, int num_cb_short) +{ + int win; + double transBuff[2 * BLOCK_LEN_LONG]; + double transBuffS[2 * BLOCK_LEN_SHORT]; + psydata_t *psydata = psyInfo->data; + psyfloat *tmp; + int sfb; + + psydata->bandS = psyInfo->sizeS * bandwidth * 2 / gpsyInfo->sampleRate; + + memcpy(transBuff, psyInfo->prevSamples, psyInfo->size * sizeof(double)); + memcpy(transBuff + psyInfo->size, newSamples, psyInfo->size * sizeof(double)); + + for (win = 0; win < 8; win++) + { + int first = 0; + int last = 0; + + memcpy(transBuffS, transBuff + (win * BLOCK_LEN_SHORT) + (BLOCK_LEN_LONG - BLOCK_LEN_SHORT) / 2, + 2 * psyInfo->sizeS * sizeof(double)); + + Hann(gpsyInfo, transBuffS, 2 * psyInfo->sizeS); + rfft( fft_tables, transBuffS, 8); + + // shift bufs + tmp = psydata->fftEnrgPrevS[win]; + psydata->fftEnrgPrevS[win] = psydata->fftEnrgS[win]; + psydata->fftEnrgS[win] = psydata->fftEnrgNextS[win]; + psydata->fftEnrgNextS[win] = psydata->fftEnrgNext2S[win]; + psydata->fftEnrgNext2S[win] = tmp; + + for (sfb = 0; sfb < num_cb_short; sfb++) + { + double e; + int l; + + first = last; + last = first + cb_width_short[sfb]; + + if (first < 1) + first = 1; + + //if (last > psydata->bandS) // band out of range + if (first >= psydata->bandS) // band out of range + break; + + e = 0.0; + for (l = first; l < last; l++) + { + double a = transBuffS[l]; + double b = transBuffS[l + psyInfo->sizeS]; + + e += a * a + b * b; + } + + psydata->fftEnrgNext2S[win][sfb] = e; + } + psydata->lastband = sfb; + for (; sfb < num_cb_short; sfb++) + { + psydata->fftEnrgNext2S[win][sfb] = 0; + } + } + + memcpy(psyInfo->prevSamples, newSamples, psyInfo->size * sizeof(double)); +} + +static void BlockSwitch(CoderInfo * coderInfo, PsyInfo * psyInfo, unsigned int numChannels) +{ + unsigned int channel; + int desire = ONLY_LONG_WINDOW; + + /* Use the same block type for all channels + If there is 1 channel that wants a short block, + use a short block on all channels. + */ + for (channel = 0; channel < numChannels; channel++) + { + if (psyInfo[channel].block_type == ONLY_SHORT_WINDOW) + desire = ONLY_SHORT_WINDOW; + } + + for (channel = 0; channel < numChannels; channel++) + { + int lasttype = coderInfo[channel].block_type; + + if (desire == ONLY_SHORT_WINDOW + || coderInfo[channel].desired_block_type == ONLY_SHORT_WINDOW) + { + if (lasttype == ONLY_LONG_WINDOW || lasttype == SHORT_LONG_WINDOW) + coderInfo[channel].block_type = LONG_SHORT_WINDOW; + else + coderInfo[channel].block_type = ONLY_SHORT_WINDOW; + } + else + { + if (lasttype == ONLY_SHORT_WINDOW || lasttype == LONG_SHORT_WINDOW) + coderInfo[channel].block_type = SHORT_LONG_WINDOW; + else + coderInfo[channel].block_type = ONLY_LONG_WINDOW; + } + coderInfo[channel].desired_block_type = desire; + } +} + +psymodel_t psymodel2 = +{ + PsyInit, + PsyEnd, + PsyCalculate, + PsyBufferUpdate, + BlockSwitch +}; diff --git a/external/libfaac/libfaac/tns.c b/external/libfaac/libfaac/tns.c new file mode 100644 index 0000000..858e2fa --- /dev/null +++ b/external/libfaac/libfaac/tns.c @@ -0,0 +1,609 @@ +/********************************************************************** + +This software module was originally developed by Texas Instruments +and edited by in the course of +development of the MPEG-2 NBC/MPEG-4 Audio standard +ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an +implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools +as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives +users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this +software module or modifications thereof for use in hardware or +software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio +standards. Those intending to use this software module in hardware or +software products are advised that this use may infringe existing +patents. The original developer of this software module and his/her +company, the subsequent editors and their companies, and ISO/IEC have +no liability for use of this software module or modifications thereof +in an implementation. Copyright is not released for non MPEG-2 +NBC/MPEG-4 Audio conforming products. The original developer retains +full right to use the code for his/her own purpose, assign or donate +the code to a third party and to inhibit third party from using the +code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This +copyright notice must be included in all copies or derivative works. + +Copyright (c) 1997. +**********************************************************************/ +/* + * $Id: tns.c,v 1.10 2003/11/24 18:08:28 knik Exp $ + */ + +#include +#include "frame.h" +#include "coder.h" +#include "bitstream.h" +#include "tns.h" +#include "util.h" + +/***********************************************/ +/* TNS Profile/Frequency Dependent Parameters */ +/***********************************************/ +static unsigned long tnsSupportedSamplingRates[13] = +{ 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0 }; + +/* Limit bands to > 2.0 kHz */ +static unsigned short tnsMinBandNumberLong[12] = +{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 }; +static unsigned short tnsMinBandNumberShort[12] = +{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 }; + +/**************************************/ +/* Main/Low Profile TNS Parameters */ +/**************************************/ +static unsigned short tnsMaxBandsLongMainLow[12] = +{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 }; + +static unsigned short tnsMaxBandsShortMainLow[12] = +{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; + +static unsigned short tnsMaxOrderLongMain = 20; +static unsigned short tnsMaxOrderLongLow = 12; +static unsigned short tnsMaxOrderShortMainLow = 7; + + +/*************************/ +/* Function prototypes */ +/*************************/ +static void Autocorrelation(int maxOrder, /* Maximum autocorr order */ + int dataSize, /* Size of the data array */ + double* data, /* Data array */ + double* rArray); /* Autocorrelation array */ + +static double LevinsonDurbin(int maxOrder, /* Maximum filter order */ + int dataSize, /* Size of the data array */ + double* data, /* Data array */ + double* kArray); /* Reflection coeff array */ + +static void StepUp(int fOrder, double* kArray, double* aArray); + +static void QuantizeReflectionCoeffs(int fOrder,int coeffRes,double* rArray,int* indexArray); +static int TruncateCoeffs(int fOrder,double threshold,double* kArray); +static void TnsFilter(int length,double* spec,TnsFilterData* filter); +static void TnsInvFilter(int length,double* spec,TnsFilterData* filter); + + +/*****************************************************/ +/* InitTns: */ +/*****************************************************/ +void TnsInit(faacEncHandle hEncoder) +{ + unsigned int channel; + int fsIndex = hEncoder->sampleRateIdx; + int profile = hEncoder->config.aacObjectType; + + for (channel = 0; channel < hEncoder->numChannels; channel++) { + TnsInfo *tnsInfo = &hEncoder->coderInfo[channel].tnsInfo; + + switch( profile ) { + case MAIN: + case LTP: + tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex]; + tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex]; + if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */ + tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongMain; + } else { /* MPEG4 */ + if (fsIndex <= 5) /* fs > 32000Hz */ + tnsInfo->tnsMaxOrderLong = 12; + else + tnsInfo->tnsMaxOrderLong = 20; + } + tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow; + break; + case LOW : + tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex]; + tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex]; + if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */ + tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongLow; + } else { /* MPEG4 */ + if (fsIndex <= 5) /* fs > 32000Hz */ + tnsInfo->tnsMaxOrderLong = 12; + else + tnsInfo->tnsMaxOrderLong = 20; + } + tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow; + break; + } + tnsInfo->tnsMinBandNumberLong = tnsMinBandNumberLong[fsIndex]; + tnsInfo->tnsMinBandNumberShort = tnsMinBandNumberShort[fsIndex]; + } +} + + +/*****************************************************/ +/* TnsEncode: */ +/*****************************************************/ +void TnsEncode(TnsInfo* tnsInfo, /* TNS info */ + int numberOfBands, /* Number of bands per window */ + int maxSfb, /* max_sfb */ + enum WINDOW_TYPE blockType, /* block type */ + int* sfbOffsetTable, /* Scalefactor band offset table */ + double* spec) /* Spectral data array */ +{ + int numberOfWindows,windowSize; + int startBand,stopBand,order; /* Bands over which to apply TNS */ + int lengthInBands; /* Length to filter, in bands */ + int w; + int startIndex,length; + double gain; + + switch( blockType ) { + case ONLY_SHORT_WINDOW : + + /* TNS not used for short blocks currently */ + tnsInfo->tnsDataPresent = 0; + return; + + numberOfWindows = MAX_SHORT_WINDOWS; + windowSize = BLOCK_LEN_SHORT; + startBand = tnsInfo->tnsMinBandNumberShort; + stopBand = numberOfBands; + lengthInBands = stopBand-startBand; + order = tnsInfo->tnsMaxOrderShort; + startBand = min(startBand,tnsInfo->tnsMaxBandsShort); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort); + break; + + default: + numberOfWindows = 1; + windowSize = BLOCK_LEN_SHORT; + startBand = tnsInfo->tnsMinBandNumberLong; + stopBand = numberOfBands; + lengthInBands = stopBand - startBand; + order = tnsInfo->tnsMaxOrderLong; + startBand = min(startBand,tnsInfo->tnsMaxBandsLong); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong); + break; + } + + /* Make sure that start and stop bands < maxSfb */ + /* Make sure that start and stop bands >= 0 */ + startBand = min(startBand,maxSfb); + stopBand = min(stopBand,maxSfb); + startBand = max(startBand,0); + stopBand = max(stopBand,0); + + tnsInfo->tnsDataPresent = 0; /* default TNS not used */ + + /* Perform analysis and filtering for each window */ + for (w=0;wwindowData[w]; + TnsFilterData* tnsFilter = windowData->tnsFilter; + double* k = tnsFilter->kCoeffs; /* reflection coeffs */ + double* a = tnsFilter->aCoeffs; /* prediction coeffs */ + + windowData->numFilters=0; + windowData->coefResolution = DEF_TNS_COEFF_RES; + startIndex = w * windowSize + sfbOffsetTable[startBand]; + length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand]; + gain = LevinsonDurbin(order,length,&spec[startIndex],k); + + if (gain>DEF_TNS_GAIN_THRESH) { /* Use TNS */ + int truncatedOrder; + windowData->numFilters++; + tnsInfo->tnsDataPresent=1; + tnsFilter->direction = 0; + tnsFilter->coefCompress = 0; + tnsFilter->length = lengthInBands; + QuantizeReflectionCoeffs(order,DEF_TNS_COEFF_RES,k,tnsFilter->index); + truncatedOrder = TruncateCoeffs(order,DEF_TNS_COEFF_THRESH,k); + tnsFilter->order = truncatedOrder; + StepUp(truncatedOrder,k,a); /* Compute predictor coefficients */ + TnsInvFilter(length,&spec[startIndex],tnsFilter); /* Filter */ + } + } +} + + +/*****************************************************/ +/* TnsEncodeFilterOnly: */ +/* This is a stripped-down version of TnsEncode() */ +/* which performs TNS analysis filtering only */ +/*****************************************************/ +void TnsEncodeFilterOnly(TnsInfo* tnsInfo, /* TNS info */ + int numberOfBands, /* Number of bands per window */ + int maxSfb, /* max_sfb */ + enum WINDOW_TYPE blockType, /* block type */ + int* sfbOffsetTable, /* Scalefactor band offset table */ + double* spec) /* Spectral data array */ +{ + int numberOfWindows,windowSize; + int startBand,stopBand; /* Bands over which to apply TNS */ + int w; + int startIndex,length; + + switch( blockType ) { + case ONLY_SHORT_WINDOW : + numberOfWindows = MAX_SHORT_WINDOWS; + windowSize = BLOCK_LEN_SHORT; + startBand = tnsInfo->tnsMinBandNumberShort; + stopBand = numberOfBands; + startBand = min(startBand,tnsInfo->tnsMaxBandsShort); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort); + break; + + default: + numberOfWindows = 1; + windowSize = BLOCK_LEN_LONG; + startBand = tnsInfo->tnsMinBandNumberLong; + stopBand = numberOfBands; + startBand = min(startBand,tnsInfo->tnsMaxBandsLong); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong); + break; + } + + /* Make sure that start and stop bands < maxSfb */ + /* Make sure that start and stop bands >= 0 */ + startBand = min(startBand,maxSfb); + stopBand = min(stopBand,maxSfb); + startBand = max(startBand,0); + stopBand = max(stopBand,0); + + + /* Perform filtering for each window */ + for(w=0;wwindowData[w]; + TnsFilterData* tnsFilter = windowData->tnsFilter; + + startIndex = w * windowSize + sfbOffsetTable[startBand]; + length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand]; + + if (tnsInfo->tnsDataPresent && windowData->numFilters) { /* Use TNS */ + TnsInvFilter(length,&spec[startIndex],tnsFilter); + } + } +} + + +/*****************************************************/ +/* TnsDecodeFilterOnly: */ +/* This is a stripped-down version of TnsEncode() */ +/* which performs TNS synthesis filtering only */ +/*****************************************************/ +void TnsDecodeFilterOnly(TnsInfo* tnsInfo, /* TNS info */ + int numberOfBands, /* Number of bands per window */ + int maxSfb, /* max_sfb */ + enum WINDOW_TYPE blockType, /* block type */ + int* sfbOffsetTable, /* Scalefactor band offset table */ + double* spec) /* Spectral data array */ +{ + int numberOfWindows,windowSize; + int startBand,stopBand; /* Bands over which to apply TNS */ + int w; + int startIndex,length; + + switch( blockType ) { + case ONLY_SHORT_WINDOW : + numberOfWindows = MAX_SHORT_WINDOWS; + windowSize = BLOCK_LEN_SHORT; + startBand = tnsInfo->tnsMinBandNumberShort; + stopBand = numberOfBands; + startBand = min(startBand,tnsInfo->tnsMaxBandsShort); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort); + break; + + default: + numberOfWindows = 1; + windowSize = BLOCK_LEN_LONG; + startBand = tnsInfo->tnsMinBandNumberLong; + stopBand = numberOfBands; + startBand = min(startBand,tnsInfo->tnsMaxBandsLong); + stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong); + break; + } + + /* Make sure that start and stop bands < maxSfb */ + /* Make sure that start and stop bands >= 0 */ + startBand = min(startBand,maxSfb); + stopBand = min(stopBand,maxSfb); + startBand = max(startBand,0); + stopBand = max(stopBand,0); + + + /* Perform filtering for each window */ + for(w=0;wwindowData[w]; + TnsFilterData* tnsFilter = windowData->tnsFilter; + + startIndex = w * windowSize + sfbOffsetTable[startBand]; + length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand]; + + if (tnsInfo->tnsDataPresent && windowData->numFilters) { /* Use TNS */ + TnsFilter(length,&spec[startIndex],tnsFilter); + } + } +} + + +/*****************************************************/ +/* TnsFilter: */ +/* Filter the given spec with specified length */ +/* using the coefficients specified in filter. */ +/* Not that the order and direction are specified */ +/* withing the TNS_FILTER_DATA structure. */ +/*****************************************************/ +static void TnsFilter(int length,double* spec,TnsFilterData* filter) +{ + int i,j,k=0; + int order=filter->order; + double* a=filter->aCoeffs; + + /* Determine loop parameters for given direction */ + if (filter->direction) { + + /* Startup, initial state is zero */ + for (i=length-2;i>(length-1-order);i--) { + k++; + for (j=1;j<=k;j++) { + spec[i]-=spec[i+j]*a[j]; + } + } + + /* Now filter completely inplace */ + for (i=length-1-order;i>=0;i--) { + for (j=1;j<=order;j++) { + spec[i]-=spec[i+j]*a[j]; + } + } + + + } else { + + /* Startup, initial state is zero */ + for (i=1;iorder; + double* a=filter->aCoeffs; + double* temp; + + temp = (double *)AllocMemory(length * sizeof (double)); + + /* Determine loop parameters for given direction */ + if (filter->direction) { + + /* Startup, initial state is zero */ + temp[length-1]=spec[length-1]; + for (i=length-2;i>(length-1-order);i--) { + temp[i]=spec[i]; + k++; + for (j=1;j<=k;j++) { + spec[i]+=temp[i+j]*a[j]; + } + } + + /* Now filter the rest */ + for (i=length-1-order;i>=0;i--) { + temp[i]=spec[i]; + for (j=1;j<=order;j++) { + spec[i]+=temp[i+j]*a[j]; + } + } + + + } else { + + /* Startup, initial state is zero */ + temp[0]=spec[0]; + for (i=1;i= 0; i--) { + kArray[i] = (fabs(kArray[i])>threshold) ? kArray[i] : 0.0; + if (kArray[i]!=0.0) return i; + } + + return 0; +} + +/*****************************************************/ +/* QuantizeReflectionCoeffs: */ +/* Quantize the given array of reflection coeffs */ +/* to the specified resolution in bits. */ +/*****************************************************/ +static void QuantizeReflectionCoeffs(int fOrder, + int coeffRes, + double* kArray, + int* indexArray) +{ + double iqfac,iqfac_m; + int i; + + iqfac = ((1<<(coeffRes-1))-0.5)/(M_PI/2); + iqfac_m = ((1<<(coeffRes-1))+0.5)/(M_PI/2); + + /* Quantize and inverse quantize */ + for (i=1;i<=fOrder;i++) { + indexArray[i] = (int)(0.5+(asin(kArray[i])*((kArray[i]>=0)?iqfac:iqfac_m))); + kArray[i] = sin((double)indexArray[i]/((indexArray[i]>=0)?iqfac:iqfac_m)); + } +} + +/*****************************************************/ +/* Autocorrelation, */ +/* Compute the autocorrelation function */ +/* estimate for the given data. */ +/*****************************************************/ +static void Autocorrelation(int maxOrder, /* Maximum autocorr order */ + int dataSize, /* Size of the data array */ + double* data, /* Data array */ + double* rArray) /* Autocorrelation array */ +{ + int order,index; + + for (order=0;order<=maxOrder;order++) { + rArray[order]=0.0; + for (index=0;index + +#include "util.h" +#include "coder.h" // FRAME_LEN + +/* Returns the sample rate index */ +int GetSRIndex(unsigned int sampleRate) +{ + if (92017 <= sampleRate) return 0; + if (75132 <= sampleRate) return 1; + if (55426 <= sampleRate) return 2; + if (46009 <= sampleRate) return 3; + if (37566 <= sampleRate) return 4; + if (27713 <= sampleRate) return 5; + if (23004 <= sampleRate) return 6; + if (18783 <= sampleRate) return 7; + if (13856 <= sampleRate) return 8; + if (11502 <= sampleRate) return 9; + if (9391 <= sampleRate) return 10; + + return 11; +} + +/* Returns the maximum bitrate per channel for that sampling frequency */ +unsigned int MaxBitrate(unsigned long sampleRate) +{ + /* + * Maximum of 6144 bit for a channel + */ + return (unsigned int)(6144.0 * (double)sampleRate/(double)FRAME_LEN + .5); +} + +/* Returns the minimum bitrate per channel for that sampling frequency */ +unsigned int MinBitrate() +{ + return 8000; +} + + +/* Max prediction band for backward predictionas function of fs index */ +const int MaxPredSfb[] = { 33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34, 0 }; + +int GetMaxPredSfb(int samplingRateIdx) +{ + return MaxPredSfb[samplingRateIdx]; +} + + + +/* Calculate bit_allocation based on PE */ +unsigned int BitAllocation(double pe, int short_block) +{ + double pew1; + double pew2; + double bit_allocation; + + if (short_block) { + pew1 = 0.6; + pew2 = 24.0; + } else { + pew1 = 0.3; + pew2 = 6.0; + } + bit_allocation = pew1 * pe + pew2 * sqrt(pe); + bit_allocation = min(max(0.0, bit_allocation), 6144.0); + + return (unsigned int)(bit_allocation+0.5); +} + +/* Returns the maximum bit reservoir size */ +unsigned int MaxBitresSize(unsigned long bitRate, unsigned long sampleRate) +{ + return 6144 - (unsigned int)((double)bitRate/(double)sampleRate*(double)FRAME_LEN); +} diff --git a/external/libfaac/libfaac/util.h b/external/libfaac/libfaac/util.h new file mode 100644 index 0000000..2233e78 --- /dev/null +++ b/external/libfaac/libfaac/util.h @@ -0,0 +1,59 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: util.h,v 1.8 2003/12/20 04:32:48 stux Exp $ + */ + +#ifndef UTIL_H +#define UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* Memory functions */ +#define AllocMemory(size) malloc(size) +#define FreeMemory(block) free(block) +#define SetMemory(block, value, size) memset(block, value, size) + +int GetSRIndex(unsigned int sampleRate); +int GetMaxPredSfb(int samplingRateIdx); +unsigned int MaxBitrate(unsigned long sampleRate); +unsigned int MinBitrate(); +unsigned int MaxBitresSize(unsigned long bitRate, unsigned long sampleRate); +unsigned int BitAllocation(double pe, int short_block); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* UTIL_H */ diff --git a/external/libfaac/libfaac/version.h b/external/libfaac/libfaac/version.h new file mode 100644 index 0000000..94763e2 --- /dev/null +++ b/external/libfaac/libfaac/version.h @@ -0,0 +1,8 @@ +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#define FAAC_RELEASE 1 + +#define FAAC_VERSION "1.28" + +#endif diff --git a/external/libfaac/outDebug.h b/external/libfaac/outDebug.h new file mode 100644 index 0000000..8457512 --- /dev/null +++ b/external/libfaac/outDebug.h @@ -0,0 +1,46 @@ + +#ifndef _OUTDEBUG_H +#define _OUTDEBUG_H + + + +#define DBG_MSG_BUFF_SIZE 3000 +#define FILE_NAME "-EasyAACEncoder-" + +#ifndef __linux__ +#include +#include +#include + +#define INFO_USE(fmt, ...) \ +{ \ + TCHAR traceBuffer[DBG_MSG_BUFF_SIZE]; \ + _stprintf_s(traceBuffer, _T(FILE_NAME) _T(" :INFO: ") _T(__FUNCTION__) _T("<%d>: ") _T(fmt) _T("\n"), __LINE__, ##__VA_ARGS__); \ + OutputDebugString(traceBuffer); \ +} + + +#define INFO_CHOOSEUSE(fmt, ...) {INFO_USE(fmt, ##__VA_ARGS__);} + +#define INFO_D(OUT,fmt, ...)\ +{ \ + if(OUT)\ + {\ + INFO_CHOOSEUSE(fmt, ##__VA_ARGS__);\ + }\ +} + +#else +#define INFO_D(OUT,fmt, ...)\ +{ \ + if(OUT)\ + {\ + printf(fmt, ##__VA_ARGS__);\ + }\ +} +#endif + + +#define AAC_DEBUG 0 + +#endif