frame.c
来自「faac-1.25.rar音频编解码器demo」· C语言 代码 · 共 1,253 行 · 第 1/3 页
C
1,253 行
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?