Merge "Initial software encoder checkins" into kraken

This commit is contained in:
James Dong
2010-05-19 13:14:24 -07:00
committed by Android (Google) Code Review
217 changed files with 44262 additions and 42 deletions

View File

@ -46,7 +46,7 @@ protected:
virtual ~AudioSource(); virtual ~AudioSource();
private: private:
enum { kMaxBufferSize = 8192 }; enum { kMaxBufferSize = 2048 };
AudioRecord *mRecord; AudioRecord *mRecord;
status_t mInitCheck; status_t mInitCheck;

View File

@ -156,8 +156,8 @@ private:
void setComponentRole(); void setComponentRole();
void setAMRFormat(bool isWAMR); void setAMRFormat(bool isWAMR, int32_t bitRate);
void setAACFormat(int32_t numChannels, int32_t sampleRate); void setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate);
status_t setVideoPortFormatType( status_t setVideoPortFormatType(
OMX_U32 portIndex, OMX_U32 portIndex,

View File

@ -1,6 +1,8 @@
LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \
ESDS.cpp \ ESDS.cpp \
MediaBuffer.cpp \ MediaBuffer.cpp \
@ -65,9 +67,11 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \ LOCAL_STATIC_LIBRARIES := \
libstagefright_aacdec \ libstagefright_aacdec \
libstagefright_aacenc \
libstagefright_amrnbdec \ libstagefright_amrnbdec \
libstagefright_amrnbenc \ libstagefright_amrnbenc \
libstagefright_amrwbdec \ libstagefright_amrwbdec \
libstagefright_amrwbenc \
libstagefright_avcdec \ libstagefright_avcdec \
libstagefright_m4vh263dec \ libstagefright_m4vh263dec \
libstagefright_mp3dec \ libstagefright_mp3dec \
@ -75,10 +79,12 @@ LOCAL_STATIC_LIBRARIES := \
LOCAL_SHARED_LIBRARIES += \ LOCAL_SHARED_LIBRARIES += \
libstagefright_amrnb_common \ libstagefright_amrnb_common \
libstagefright_enc_common \
libstagefright_avc_common libstagefright_avc_common
ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true) ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
LOCAL_STATIC_LIBRARIES += \ LOCAL_STATIC_LIBRARIES += \
libstagefright_id3 libstagefright_id3

View File

@ -466,7 +466,7 @@ bool MPEG4Writer::exceedsFileSizeLimit() {
return false; return false;
} }
int64_t nTotalBytesEstimate = mEstimatedMoovBoxSize; int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
for (List<Track *>::iterator it = mTracks.begin(); for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) { it != mTracks.end(); ++it) {
nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
@ -526,6 +526,7 @@ MPEG4Writer::Track::Track(
mSource(source), mSource(source),
mDone(false), mDone(false),
mMaxTimeStampUs(0), mMaxTimeStampUs(0),
mEstimatedTrackSizeBytes(0),
mSamplesHaveSameSize(true), mSamplesHaveSameSize(true),
mCodecSpecificData(NULL), mCodecSpecificData(NULL),
mCodecSpecificDataSize(0), mCodecSpecificDataSize(0),
@ -557,6 +558,7 @@ status_t MPEG4Writer::Track::start() {
mDone = false; mDone = false;
mMaxTimeStampUs = 0; mMaxTimeStampUs = 0;
mReachedEOS = false; mReachedEOS = false;
mEstimatedTrackSizeBytes = 0;
pthread_create(&mThread, &attr, ThreadWrapper, this); pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
@ -695,6 +697,7 @@ void MPEG4Writer::Track::threadEntry() {
bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
bool is_audio = !strncasecmp(mime, "audio/", 6);
int32_t count = 0; int32_t count = 0;
const int64_t interleaveDurationUs = mOwner->interleaveDuration(); const int64_t interleaveDurationUs = mOwner->interleaveDuration();
int64_t chunkTimestampUs = 0; int64_t chunkTimestampUs = 0;
@ -705,7 +708,6 @@ void MPEG4Writer::Track::threadEntry() {
int32_t sampleCount = 1; // Sample count in the current stts table entry int32_t sampleCount = 1; // Sample count in the current stts table entry
uint32_t previousSampleSize = 0; // Size of the previous sample uint32_t previousSampleSize = 0; // Size of the previous sample
mEstimatedTrackSizeBytes = 0;
MediaBuffer *buffer; MediaBuffer *buffer;
while (!mDone && mSource->read(&buffer) == OK) { while (!mDone && mSource->read(&buffer) == OK) {
if (buffer->range_length() == 0) { if (buffer->range_length() == 0) {
@ -849,7 +851,6 @@ void MPEG4Writer::Track::threadEntry() {
break; break;
} }
bool is_audio = !strncasecmp(mime, "audio/", 6);
int64_t timestampUs; int64_t timestampUs;
CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs)); CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
@ -947,8 +948,8 @@ void MPEG4Writer::Track::threadEntry() {
SttsTableEntry sttsEntry(sampleCount, lastDuration); SttsTableEntry sttsEntry(sampleCount, lastDuration);
mSttsTableEntries.push_back(sttsEntry); mSttsTableEntries.push_back(sttsEntry);
mReachedEOS = true; mReachedEOS = true;
LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames", LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
count, nZeroLengthFrames, mSampleInfos.size()); count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video");
} }
void MPEG4Writer::Track::writeOneChunk(bool isAvc) { void MPEG4Writer::Track::writeOneChunk(bool isAvc) {
@ -1035,7 +1036,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(1); // a single entry mOwner->writeInt32(1); // a single entry
mOwner->writeInt32(mStartTimestampUs / 1000); // edit duration mOwner->writeInt32(mStartTimestampUs / 1000); // edit duration
mOwner->writeInt32(0); // edit media starting time mOwner->writeInt32(-1); // empty edit box to signal starting time offset
mOwner->writeInt32(1); // x1 rate mOwner->writeInt32(1); // x1 rate
mOwner->endBox(); mOwner->endBox();
mOwner->endBox(); mOwner->endBox();
@ -1060,7 +1061,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved
mOwner->writeCString("SoundHandler"); // name mOwner->writeCString(is_audio ? "SoundHandler": ""); // name
mOwner->endBox(); mOwner->endBox();
mOwner->beginBox("minf"); mOwner->beginBox("minf");

View File

@ -19,9 +19,11 @@
#include <utils/Log.h> #include <utils/Log.h>
#include "include/AACDecoder.h" #include "include/AACDecoder.h"
#include "include/AACEncoder.h"
#include "include/AMRNBDecoder.h" #include "include/AMRNBDecoder.h"
#include "include/AMRNBEncoder.h" #include "include/AMRNBEncoder.h"
#include "include/AMRWBDecoder.h" #include "include/AMRWBDecoder.h"
#include "include/AMRWBEncoder.h"
#include "include/AVCDecoder.h" #include "include/AVCDecoder.h"
#include "include/M4vH263Decoder.h" #include "include/M4vH263Decoder.h"
#include "include/MP3Decoder.h" #include "include/MP3Decoder.h"
@ -60,6 +62,11 @@ static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
return new name(source); \ return new name(source); \
} }
#define FACTORY_CREATE_ENCODER(name) \
static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
return new name(source, meta); \
}
#define FACTORY_REF(name) { #name, Make##name }, #define FACTORY_REF(name) { #name, Make##name },
FACTORY_CREATE(MP3Decoder) FACTORY_CREATE(MP3Decoder)
@ -69,7 +76,32 @@ FACTORY_CREATE(AACDecoder)
FACTORY_CREATE(AVCDecoder) FACTORY_CREATE(AVCDecoder)
FACTORY_CREATE(M4vH263Decoder) FACTORY_CREATE(M4vH263Decoder)
FACTORY_CREATE(VorbisDecoder) FACTORY_CREATE(VorbisDecoder)
FACTORY_CREATE(AMRNBEncoder) FACTORY_CREATE_ENCODER(AMRNBEncoder)
FACTORY_CREATE_ENCODER(AMRWBEncoder)
FACTORY_CREATE_ENCODER(AACEncoder)
static sp<MediaSource> InstantiateSoftwareEncoder(
const char *name, const sp<MediaSource> &source,
const sp<MetaData> &meta) {
struct FactoryInfo {
const char *name;
sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
};
static const FactoryInfo kFactoryInfo[] = {
FACTORY_REF(AMRNBEncoder)
FACTORY_REF(AMRWBEncoder)
FACTORY_REF(AACEncoder)
};
for (size_t i = 0;
i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
if (!strcmp(name, kFactoryInfo[i].name)) {
return (*kFactoryInfo[i].CreateFunc)(source, meta);
}
}
return NULL;
}
static sp<MediaSource> InstantiateSoftwareCodec( static sp<MediaSource> InstantiateSoftwareCodec(
const char *name, const sp<MediaSource> &source) { const char *name, const sp<MediaSource> &source) {
@ -86,7 +118,6 @@ static sp<MediaSource> InstantiateSoftwareCodec(
FACTORY_REF(AVCDecoder) FACTORY_REF(AVCDecoder)
FACTORY_REF(M4vH263Decoder) FACTORY_REF(M4vH263Decoder)
FACTORY_REF(VorbisDecoder) FACTORY_REF(VorbisDecoder)
FACTORY_REF(AMRNBEncoder)
}; };
for (size_t i = 0; for (size_t i = 0;
i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) { i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
@ -133,7 +164,9 @@ static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
@ -386,7 +419,8 @@ sp<MediaSource> OMXCodec::Create(
componentName = matchingCodecs[i].string(); componentName = matchingCodecs[i].string();
#if BUILD_WITH_FULL_STAGEFRIGHT #if BUILD_WITH_FULL_STAGEFRIGHT
sp<MediaSource> softwareCodec = sp<MediaSource> softwareCodec = createEncoder?
InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source); InstantiateSoftwareCodec(componentName, source);
if (softwareCodec != NULL) { if (softwareCodec != NULL) {
@ -511,18 +545,22 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
} }
} }
int32_t bitRate = 0;
if (mIsEncoder) {
CHECK(meta->findInt32(kKeyBitRate, &bitRate));
}
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) { if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
setAMRFormat(false /* isWAMR */); setAMRFormat(false /* isWAMR */, bitRate);
} }
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) { if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
setAMRFormat(true /* isWAMR */); setAMRFormat(true /* isWAMR */, bitRate);
} }
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) { if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
int32_t numChannels, sampleRate; int32_t numChannels, sampleRate;
CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
setAACFormat(numChannels, sampleRate); setAACFormat(numChannels, sampleRate, bitRate);
} }
if (!strncasecmp(mMIME, "video/", 6)) { if (!strncasecmp(mMIME, "video/", 6)) {
@ -2177,7 +2215,51 @@ void OMXCodec::setRawAudioFormat(
CHECK_EQ(err, OK); CHECK_EQ(err, OK);
} }
void OMXCodec::setAMRFormat(bool isWAMR) { static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
if (isAMRWB) {
if (bps <= 6600) {
return OMX_AUDIO_AMRBandModeWB0;
} else if (bps <= 8850) {
return OMX_AUDIO_AMRBandModeWB1;
} else if (bps <= 12650) {
return OMX_AUDIO_AMRBandModeWB2;
} else if (bps <= 14250) {
return OMX_AUDIO_AMRBandModeWB3;
} else if (bps <= 15850) {
return OMX_AUDIO_AMRBandModeWB4;
} else if (bps <= 18250) {
return OMX_AUDIO_AMRBandModeWB5;
} else if (bps <= 19850) {
return OMX_AUDIO_AMRBandModeWB6;
} else if (bps <= 23050) {
return OMX_AUDIO_AMRBandModeWB7;
}
// 23850 bps
return OMX_AUDIO_AMRBandModeWB8;
} else { // AMRNB
if (bps <= 4750) {
return OMX_AUDIO_AMRBandModeNB0;
} else if (bps <= 5150) {
return OMX_AUDIO_AMRBandModeNB1;
} else if (bps <= 5900) {
return OMX_AUDIO_AMRBandModeNB2;
} else if (bps <= 6700) {
return OMX_AUDIO_AMRBandModeNB3;
} else if (bps <= 7400) {
return OMX_AUDIO_AMRBandModeNB4;
} else if (bps <= 7950) {
return OMX_AUDIO_AMRBandModeNB5;
} else if (bps <= 10200) {
return OMX_AUDIO_AMRBandModeNB6;
}
// 12200 bps
return OMX_AUDIO_AMRBandModeNB7;
}
}
void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput; OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
OMX_AUDIO_PARAM_AMRTYPE def; OMX_AUDIO_PARAM_AMRTYPE def;
@ -2191,10 +2273,7 @@ void OMXCodec::setAMRFormat(bool isWAMR) {
def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
// XXX: Select bandmode based on bit rate def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
def.eAMRBandMode =
isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
CHECK_EQ(err, OK); CHECK_EQ(err, OK);
@ -2211,7 +2290,7 @@ void OMXCodec::setAMRFormat(bool isWAMR) {
} }
} }
void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) { void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
CHECK(numChannels == 1 || numChannels == 2); CHECK(numChannels == 1 || numChannels == 2);
if (mIsEncoder) { if (mIsEncoder) {
//////////////// input port //////////////////// //////////////// input port ////////////////////
@ -2256,7 +2335,7 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
profile.eChannelMode = (numChannels == 1? profile.eChannelMode = (numChannels == 1?
OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
profile.nSampleRate = sampleRate; profile.nSampleRate = sampleRate;
profile.nBitRate = 96000; // XXX profile.nBitRate = bitRate;
profile.nAudioBandWidth = 0; profile.nAudioBandWidth = 0;
profile.nFrameLength = 0; profile.nFrameLength = 0;
profile.nAACtools = OMX_AUDIO_AACToolAll; profile.nAACtools = OMX_AUDIO_AACToolAll;
@ -3034,11 +3113,13 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) { } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
mOutputFormat->setCString( mOutputFormat->setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
int32_t numChannels, sampleRate; int32_t numChannels, sampleRate, bitRate;
inputFormat->findInt32(kKeyChannelCount, &numChannels); inputFormat->findInt32(kKeyChannelCount, &numChannels);
inputFormat->findInt32(kKeySampleRate, &sampleRate); inputFormat->findInt32(kKeySampleRate, &sampleRate);
inputFormat->findInt32(kKeyBitRate, &bitRate);
mOutputFormat->setInt32(kKeyChannelCount, numChannels); mOutputFormat->setInt32(kKeyChannelCount, numChannels);
mOutputFormat->setInt32(kKeySampleRate, sampleRate); mOutputFormat->setInt32(kKeySampleRate, sampleRate);
mOutputFormat->setInt32(kKeyBitRate, bitRate);
} else { } else {
CHECK(!"Should not be here. Unknown audio encoding."); CHECK(!"Should not be here. Unknown audio encoding.");
} }

View File

@ -0,0 +1,264 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "AACEncoder"
#include <utils/Log.h>
#include "AACEncoder.h"
#include "voAAC.h"
#include "cmnMemory.h"
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
namespace android {
AACEncoder::AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
: mSource(source),
mMeta(meta),
mStarted(false),
mBufferGroup(NULL),
mInputBuffer(NULL),
mEncoderHandle(NULL),
mApiHandle(NULL),
mMemOperator(NULL) {
}
status_t AACEncoder::initCheck() {
CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels));
CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
mApiHandle = new VO_AUDIO_CODECAPI;
CHECK(mApiHandle);
if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
LOGE("Failed to get api handle");
return UNKNOWN_ERROR;
}
mMemOperator = new VO_MEM_OPERATOR;
CHECK(mMemOperator != NULL);
mMemOperator->Alloc = cmnMemAlloc;
mMemOperator->Copy = cmnMemCopy;
mMemOperator->Free = cmnMemFree;
mMemOperator->Set = cmnMemSet;
mMemOperator->Check = cmnMemCheck;
VO_CODEC_INIT_USERDATA userData;
memset(&userData, 0, sizeof(userData));
userData.memflag = VO_IMF_USERMEMOPERATOR;
userData.memData = (VO_PTR) mMemOperator;
if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
LOGE("Failed to init AAC encoder");
return UNKNOWN_ERROR;
}
if (OK != setAudioSpecificConfigData()) {
LOGE("Failed to configure AAC encoder");
return UNKNOWN_ERROR;
}
// Configure AAC encoder$
AACENC_PARAM params;
memset(&params, 0, sizeof(params));
params.sampleRate = mSampleRate;
params.bitRate = mBitRate;
params.nChannels = mChannels;
params.adtsUsed = 0; // For MP4 file, don't use adts format$
if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM, &params)) {
LOGE("Failed to set AAC encoder parameters");
return UNKNOWN_ERROR;
}
return OK;
}
static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
static const int32_t kSampleRateTable[] = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000
};
const int32_t tableSize = sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
for (int32_t i = 0; i < tableSize; ++i) {
if (sampleRate == kSampleRateTable[i]) {
index = i;
return OK;
}
}
LOGE("Sampling rate %d bps is not supported", sampleRate);
return UNKNOWN_ERROR;
}
status_t AACEncoder::setAudioSpecificConfigData() {
LOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels",
mSampleRate, mBitRate, mChannels);
int32_t index;
CHECK_EQ(OK, getSampleRateTableIndex(mSampleRate, index));
if (mChannels > 2 || mChannels <= 0) {
LOGE("Unsupported number of channels(%d)", mChannels);
return UNKNOWN_ERROR;
}
// OMX_AUDIO_AACObjectLC
mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mChannels << 3);
return OK;
}
AACEncoder::~AACEncoder() {
if (mStarted) {
stop();
}
}
status_t AACEncoder::start(MetaData *params) {
CHECK(!mStarted);
mBufferGroup = new MediaBufferGroup;
mBufferGroup->add_buffer(new MediaBuffer(2048));
CHECK_EQ(OK, initCheck());
mFrameCount = 0;
mSource->start();
mStarted = true;
return OK;
}
status_t AACEncoder::stop() {
CHECK(mStarted);
if (mInputBuffer) {
mInputBuffer->release();
mInputBuffer = NULL;
}
delete mBufferGroup;
mBufferGroup = NULL;
mSource->stop();
if (mEncoderHandle) {
CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
mEncoderHandle = NULL;
}
delete mApiHandle;
mApiHandle = NULL;
mStarted = false;
return OK;
}
sp<MetaData> AACEncoder::getFormat() {
sp<MetaData> srcFormat = mSource->getFormat();
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
int64_t durationUs;
if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
mMeta->setInt64(kKeyDuration, durationUs);
}
mMeta->setCString(kKeyDecoderComponent, "AACEncoder");
return mMeta;
}
status_t AACEncoder::read(
MediaBuffer **out, const ReadOptions *options) {
status_t err;
*out = NULL;
int64_t seekTimeUs;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs));
MediaBuffer *buffer;
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
uint8_t *outPtr = (uint8_t *)buffer->data();
if (mFrameCount == 0) {
memcpy(outPtr, mAudioSpecificConfigData, 2);
buffer->set_range(0, 2);
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
*out = buffer;
++mFrameCount;
mInputBuffer = NULL;
return OK;
} else {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
}
if (mInputBuffer == NULL) {
if (mSource->read(&mInputBuffer, options) != OK) {
LOGE("failed to read from input audio source");
return UNKNOWN_ERROR;
}
if (mInputBuffer->range_length() == 0) {
mInputBuffer->release();
mInputBuffer = NULL;
return ERROR_END_OF_STREAM;
}
VO_CODECBUFFER inputData;
memset(&inputData, 0, sizeof(inputData));
inputData.Buffer = (unsigned char*) mInputBuffer->data();
inputData.Length = mInputBuffer->range_length();
CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
}
CHECK(mInputBuffer != NULL);
VO_CODECBUFFER outputData;
memset(&outputData, 0, sizeof(outputData));
VO_AUDIO_OUTPUTINFO outputInfo;
memset(&outputInfo, 0, sizeof(outputInfo));
VO_U32 ret = VO_ERR_NONE;
int32_t outputLength = 0;
outputData.Buffer = outPtr;
outputData.Length = buffer->size();
ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
if (ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL) {
outputLength += outputData.Length;
if (ret == VO_ERR_INPUT_BUFFER_SMALL) { // All done
mInputBuffer->release();
mInputBuffer = NULL;
}
} else {
LOGE("failed to encode the input data 0x%lx", ret);
}
buffer->set_range(0, outputLength);
++mFrameCount;
int64_t timestampUs = (mFrameCount * 1000000LL * 1024) / mSampleRate;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
*out = buffer;
return OK;
}
} // namespace android

View File

@ -0,0 +1,87 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c
LOCAL_SRC_FILES += \
AACEncoder.cpp \
src/aac_rom.c \
src/aacenc.c \
src/aacenc_core.c \
src/adj_thr.c \
src/band_nrg.c \
src/bit_cnt.c \
src/bitbuffer.c \
src/bitenc.c \
src/block_switch.c \
src/channel_map.c \
src/dyn_bits.c \
src/grp_data.c \
src/interface.c \
src/line_pe.c \
src/ms_stereo.c \
src/pre_echo_control.c \
src/psy_configuration.c \
src/psy_main.c \
src/qc_main.c \
src/quantize.c \
src/sf_estim.c \
src/spreading.c \
src/stat_bits.c \
src/tns.c \
src/transform.c \
src/memalign.c
ifeq ($(VOTT), v5)
LOCAL_SRC_FILES += \
src/asm/ARMV5E/AutoCorrelation_v5.s \
src/asm/ARMV5E/band_nrg_v5.s \
src/asm/ARMV5E/CalcWindowEnergy_v5.s \
src/asm/ARMV5E/PrePostMDCT_v5.s \
src/asm/ARMV5E/R4R8First_v5.s \
src/asm/ARMV5E/Radix4FFT_v5.s
endif
ifeq ($(VOTT), v7)
LOCAL_SRC_FILES += \
src/asm/ARMV5E/AutoCorrelation_v5.s \
src/asm/ARMV5E/band_nrg_v5.s \
src/asm/ARMV5E/CalcWindowEnergy_v5.s \
src/asm/ARMV7/PrePostMDCT_v7.s \
src/asm/ARMV7/R4R8First_v7.s \
src/asm/ARMV7/Radix4FFT_v7.s
endif
LOCAL_MODULE := libstagefright_aacenc
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES := \
frameworks/base/media/libstagefright/include \
frameworks/base/media/libstagefright/codecs/common/include \
frameworks/base/include \
$(LOCAL_PATH)/src \
$(LOCAL_PATH)/inc \
$(LOCAL_PATH)/basic_op
LOCAL_CFLAGS := $(VO_CFLAGS)
ifeq ($(VOTT), v5)
LOCAL_CFLAGS += -DARMV5E -DARM_INASM -DARMV5_INASM
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
endif
ifeq ($(VOTT), v7)
LOCAL_CFLAGS += -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
endif
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,283 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: AAC_E_SAMPLES.h
Content: sample code for AAC encoder
*******************************************************************************/
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "voAAC.h"
#include "cmnMemory.h"
#define VO_AAC_E_OUTPUT 1
#define READ_SIZE (1024*8)
unsigned char outBuf[1024*8];
unsigned char inBuf[READ_SIZE];
const char* HelpString =
"VisualOn AAC encoder Usage:\n"
"voAACEncTest -if <inputfile.pcm> -of <outputfile.aac> -sr <samplerate> -ch <channel> -br <bitrate> -adts <adts> \n"
"-if input file name \n"
"-of output file name \n"
"-sr input pcm samplerate, default 44100 \n"
"-ch input pcm channel, default 2 channel \n"
"-br encoded aac bitrate, default 64000 * (samplerate/100)*channel/441(480)\n"
"-adts add or no adts header, default add adts header\n"
"For example: \n"
"./voAACEncTest -if raw.pcm -of raw.aac -sr 44100 -ch 2 -br 128000\n";
static int parsecmdline(int argc, char **argv,char **input_filename, char **output_filename, AACENC_PARAM *param)
{
// notice that:
// bitRate/nChannels > 8000
// bitRate/nChannels < 160000
// bitRate/nChannels < sampleRate*6
param->adtsUsed = 1;
param->bitRate = 0;
param->nChannels = 2;
param->sampleRate = 44100;
if(argc < 5 || argc > 13)
{
return -1;
}
argc--;
argv++;
while (argc > 0)
{
if (!strcmp(*argv, "-if"))
{
argv++;
argc--;
*input_filename = *argv;
}
else if (!strcmp(*argv, "-of"))
{
argv++;
argc--;
*output_filename = *argv;
}
else if (!strcmp(*argv, "-sr"))
{
argv++;
argc--;
param->sampleRate = atoi(*argv);
}
else if (!strcmp(*argv, "-ch"))
{
argv++;
argc--;
param->nChannels = atoi(*argv);
}
else if (!strcmp(*argv, "-br"))
{
argv++;
argc--;
param->bitRate = atoi(*argv);
}
else if(!strcmp(*argv, "-adts"))
{
argv++;
argc--;
param->adtsUsed = atoi(*argv);
}
else
{
return -1;
}
argv++;
argc--;
}
if(param->bitRate == 0)
{
int scale = 441;
if(param->sampleRate%8000 == 0)
scale = 480;
param->bitRate = 640*param->nChannels*param->sampleRate/scale;
}
return 0;
}
int ReadFile2Buf(FILE* infile,unsigned char* dest,int readSize)
{
int readBytes = 0;
readBytes = fread(dest, 1, readSize, infile);
return readBytes;
}
typedef int (VO_API * VOGETAUDIODECAPI) (VO_AUDIO_CODECAPI * pDecHandle);
int main(int argc, char **argv)
{
FILE *infile, *outfile;
int t1, t2;
VO_AUDIO_CODECAPI AudioAPI;
VO_MEM_OPERATOR moper;
VO_CODEC_INIT_USERDATA useData;
VO_HANDLE hCodec;
VO_CODECBUFFER inData;
VO_CODECBUFFER outData;
VO_AUDIO_OUTPUTINFO outInfo;
int firstWrite = 1;
int eofFile = 0;
int *info=(int*)inBuf;
int bytesLeft, nRead;
int EncoderdFrame = 0;
int total = 0;
int isOutput = 1;
int returnCode;
AACENC_PARAM aacpara;
void *handle;
void *pfunc;
VOGETAUDIODECAPI pGetAPI;
const char *infileName = NULL;
const char *outfileName = NULL;
returnCode = parsecmdline(argc,argv, &infileName, &outfileName, &aacpara);
if(returnCode)
{
printf("%s", HelpString);
return 0;
}
/* open input file */
infile = fopen(infileName, "rb");
if (!infile) {
printf("Open input file fail...");
return -1;
}
/* open output file */
if(isOutput)
{
outfile = fopen(outfileName, "wb");
if (!outfile) {
printf("Open output file fail...");
return -1;
}
}
// set memory operators;
moper.Alloc = cmnMemAlloc;
moper.Copy = cmnMemCopy;
moper.Free = cmnMemFree;
moper.Set = cmnMemSet;
moper.Check = cmnMemCheck;
useData.memflag = VO_IMF_USERMEMOPERATOR;
useData.memData = (VO_PTR)(&moper);
// open encoder dll;
handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW);
if(handle == 0)
{
printf("open dll error......");
return -1;
}
// Get API;
pfunc = dlsym(handle, "voGetAACEncAPI");
if(pfunc == 0)
{
printf("open function error......");
return -1;
}
pGetAPI = (VOGETAUDIODECAPI)pfunc;
returnCode = pGetAPI(&AudioAPI);
if(returnCode)
return -1;
//####################################### Init Encoding Section #########################################
returnCode = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAAC, &useData);
if(returnCode < 0)
{
printf("#### VOI_Error2:fail to initialize the Encoderr###\n");
return -1;
}
returnCode = AudioAPI.SetParam(hCodec, VO_PID_AAC_ENCPARAM, &aacpara);
inData.Buffer = inBuf;
bytesLeft = ReadFile2Buf(infile,inData.Buffer,READ_SIZE);
//####################################### Encoding Section #########################################
do {
inData.Length = bytesLeft;
outData.Buffer = outBuf;
outData.Length = 1024*8;
t1 = clock();
returnCode = AudioAPI.SetInputData(hCodec,&inData);
do {
outData.Buffer = outBuf;
outData.Length = 1024*8;
returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outInfo);
if(returnCode == 0)
EncoderdFrame++;
if(returnCode == VO_ERR_LICENSE_ERROR)
break;
#if VO_AAC_E_OUTPUT
if (isOutput && returnCode == 0)
{
fwrite(outData.Buffer, 1, outData.Length, outfile);
}
#endif
} while(returnCode != (VO_ERR_INPUT_BUFFER_SMALL));
if(returnCode == VO_ERR_LICENSE_ERROR)
break;
t2 = clock();
total += t2 - t1;
if (!eofFile) {
nRead = ReadFile2Buf(infile, inBuf,READ_SIZE);
bytesLeft = nRead;
inData.Buffer = inBuf;
if (feof(infile))
eofFile = 1;
}
} while (!eofFile && returnCode);
//################################################ End Encoding Section #######################################################
returnCode = AudioAPI.Uninit(hCodec);
fclose(infile);
if (outfile)
{
fclose(outfile);
}
dlclose(handle);
return 0;
}

View File

@ -0,0 +1,24 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := AAC_E_SAMPLES.c
LOCAL_SRC_FILES += \
../../../Common/cmnMemory.c
LOCAL_MODULE := TestvoAACEnc
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES := libvoAACEnc
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/ \
$(LOCAL_PATH)/../../../Common \
$(LOCAL_PATH)/../../../Include \
LOCAL_CFLAGS := $(VO_CFLAGS)
include $(BUILD_EXECUTABLE)

View File

@ -0,0 +1,55 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# target6
# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
VOTT:= v7
# module type
# please specify the type of your module: lib or exe
VOMT:= exe
# module macros
# please append the additional macro definitions here for your module if necessary.
# e.g. -DVISUALON, macro VISUALON defined for your module
VOMM:= #ARMV5E
# please specify the name of your module
VOTARGET:= voAACEncTestv7
# please modify here to be sure to see the g1.mk
include ../../../../Tools/eclair.mk
# dependent libraries.
VODEPLIBS:=-ldl
# module source
# please modify here to be sure to see the ms.mk which specifies all source info of your module
include ../ms.mk
# please specify where is the voRelease on your PC, relative path is suggested
VORELDIR:=../../../../../Release/
# please modify here to be sure to see the doit.mk
include ../../../../Tools/doit.mk

View File

@ -0,0 +1,23 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# please list all objects needed by your target here
OBJS:=AAC_E_SAMPLES.o cmnMemory.o
# please list all directories that all source files relative with your module(.h .c .cpp) locate
VOSRCDIR:=../ ../../../../include ../../../../Common

View File

@ -0,0 +1,133 @@
#/*
# ** Copyright 2003-2010, VisualOn, Inc.
# **
# ** Licensed under the Apache License, Version 2.0 (the "License");
# ** you may not use this file except in compliance with the License.
# ** You may obtain a copy of the License at
# **
# ** http://www.apache.org/licenses/LICENSE-2.0
# **
# ** Unless required by applicable law or agreed to in writing, software
# ** distributed under the License is distributed on an "AS IS" BASIS,
# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# ** See the License for the specific language governing permissions and
# ** limitations under the License.
# */
VERBOSE:=@
VOMT ?= lib
ifeq ($(VOMT), lib)
LIB_STATIC=$(VOTARGET).a
LIB_DYNAMIC=$(VOTARGET).so
endif
ifeq ($(VOMT), exe)
TARGET=$(VOTARGET)
endif
CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR))
CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR))
ifneq ($(VOTT), pc)
ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR))
endif
LDFLAGS:=$(VOLDFLAGS)
VOTEDEPS+=$(VODEPLIBS)
VOTLDEPS+=$(VODEPLIBS)
VOSTCLIBS ?=
vpath %.c $(VOSRCDIR)
vpath %.cpp $(VOSRCDIR)
ifneq ($(VOTT), pc)
vpath %.s $(VOSRCDIR)
endif
ifeq ($(VOTT), pc)
BLTDIRS=$(VORELDIR)/Linux/static
BLTDIRD=$(VORELDIR)/Linux/shared
else
BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT)
BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT)
endif
.PRECIOUS: $(OBJDIR)/%.o
ifeq ($(VOMT), lib)
all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC)
mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD)
else
all: mkdirs $(TARGET)
mkdirs: $(OBJDIR)
endif
$(OBJDIR):
@if test ! -d $@; then \
mkdir -p $@; \
fi;
ifeq ($(VOMT), lib)
$(BLTDIRS):
@if test ! -d $@; then \
mkdir -p $@; \
fi;
$(BLTDIRD):
@if test ! -d $@; then \
mkdir -p $@; \
fi;
endif
ifeq ($(VOMT), lib)
$(LIB_STATIC):$(OBJS)
$(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS)
$(RANLIB) $@
ifneq ($(VODBG), yes)
#$(STRIP) $@
endif
$(LIB_DYNAMIC):$(OBJS)
$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS)
ifneq ($(VODBG), yes)
$(STRIP) $@
endif
else
$(TARGET):$(OBJS)
$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS)
ifneq ($(VODBG), yes)
$(STRIP) $@
endif
endif
.SUFFIXES: .c .cpp .s .o
.c.o:
$(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $<
#%.c:$(OBJDIR)/%.o
# $(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $<
.cpp.o:
$(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $<
ifneq ($(VOTT), pc)
.s.o:
$(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $<
endif
.PHONY: clean devel
clean:
ifeq ($(VOMT), lib)
-rm -fr $(OBJDIR) .*.sw* $(VOTARGET).*
else
-rm -fr $(OBJDIR) .*.sw* $(VOTARGET)
endif
devel:
cp -a $(LIB_STATIC) $(BLTDIRS)
cp -a $(LIB_DYNAMIC) $(BLTDIRD)

View File

@ -0,0 +1,172 @@
#/*
# ** Copyright 2003-2010, VisualOn, Inc.
# **
# ** Licensed under the Apache License, Version 2.0 (the "License");
# ** you may not use this file except in compliance with the License.
# ** You may obtain a copy of the License at
# **
# ** http://www.apache.org/licenses/LICENSE-2.0
# **
# ** Unless required by applicable law or agreed to in writing, software
# ** distributed under the License is distributed on an "AS IS" BASIS,
# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# ** See the License for the specific language governing permissions and
# ** limitations under the License.
# */
# special macro definitions for building
VOPREDEF=-DLINUX -D_LINUX
VOPRJ ?=
VONJ ?= eclair
VOTT ?= v6
# control the version to release out
# available: eva(evaluation), rel(release)
VOVER=
ifeq ($(VOVER), eva)
VOPREDEF+=-D__VOVER_EVA__
endif
# for debug or not: yes for debug, any other for release
VODBG?=ye
# for detecting memory leak
VODML=
ifeq ($(VODML), yes)
VOPREDEF+=-DDMEMLEAK
endif
VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__
TCROOTPATH:=/opt/eclair
GCCVER:=4.4.0
TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER)
CCTPRE:=$(TCPATH)/bin/arm-eabi-
AS:=$(CCTPRE)as
AR:=$(CCTPRE)ar
NM:=$(CCTPRE)nm
CC:=$(CCTPRE)gcc
GG:=$(CCTPRE)g++
LD:=$(CCTPRE)ld
SIZE:=$(CCTPRE)size
STRIP:=$(CCTPRE)strip
RANLIB:=$(CCTPRE)ranlib
OBJCOPY:=$(CCTPRE)objcopy
OBJDUMP:=$(CCTPRE)objdump
READELF:=$(CCTPRE)readelf
STRINGS:=$(CCTPRE)strings
# target product dependcy
# available: dream, generic
VOTP:=sapphire-open
CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib
CCTINC:=-I$(TCROOTPATH)/system/core/include \
-I$(TCROOTPATH)/hardware/libhardware/include \
-I$(TCROOTPATH)/hardware/ril/include \
-I$(TCROOTPATH)/hardware/libhardware_legacy/include \
-I$(TCROOTPATH)/dalvik/libnativehelper/include \
-I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \
-I$(TCROOTPATH)/frameworks/base/include \
-I$(TCROOTPATH)/frameworks/base/core/jni \
-I$(TCROOTPATH)/frameworks/base/libs/audioflinger \
-I$(TCROOTPATH)/external/skia/include \
-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \
-I$(TCROOTPATH)/bionic/libc/arch-arm/include \
-I$(TCROOTPATH)/bionic/libc/include \
-I$(TCROOTPATH)/bionic/libstdc++/include \
-I$(TCROOTPATH)/bionic/libc/kernel/common \
-I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \
-I$(TCROOTPATH)/bionic/libm/include \
-I$(TCROOTPATH)/bionic/libm/include/arm \
-I$(TCROOTPATH)/bionic/libthread_db/include \
-I$(TCROOTPATH)/bionic/libm/arm \
-I$(TCROOTPATH)/bionic/libm \
-I$(TCROOTPATH)/frameworks/base/include/android_runtime
#-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates
CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops
#-fwide-exec-charset=charset=UTF-32
# for target exe
TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB)
VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm
# for target lib
TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a
VOTLDEPS:=-lm -lc
ifeq ($(VOTT), v4)
VOCFLAGS:=-mtune=arm9tdmi -march=armv4t
VOASFLAGS:=-march=armv4t -mfpu=softfpa
endif
ifeq ($(VOTT), v5)
VOCFLAGS:=-march=armv5te
VOASFLAGS:=-march=armv5te -mfpu=vfp
endif
ifeq ($(VOTT), v5x)
VOCFLAGS:=-march=armv5te -mtune=xscale
VOASFLAGS:=-march=armv5te -mfpu=vfp
endif
ifeq ($(VOTT), v6)
#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s
#VOASFLAGS:=-march=armv6
VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls
VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant
endif
#
# global link options
VOLDFLAGS:=-Wl,-x,-X,--as-needed
ifeq ($(VOTT), v7)
VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp
VOLDFLAGS+=-Wl,--fix-cortex-a8
endif
#global compiling options for ARM target
ifneq ($(VOTT), pc)
VOASFLAGS+=--strip-local-absolute -R
endif
ifeq ($(VODBG), yes)
VOCFLAGS+=-D_DEBUG -g
else
VOCFLAGS+=-DNDEBUG -O3
endif
VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear -mthumb -nostdinc -dD -fprefetch-loop-arrays
ifneq ($(VOTT), pc)
VOCFLAGS+=$(CCTCFLAGS) $(CCTINC)
VOCPPFLAGS:=-fno-rtti $(VOCFLAGS)
ifeq ($(VOMT), exe)
VOLDFLAGS+=$(TELDFLAGS)
endif
ifeq ($(VOMT), lib)
VOLDFLAGS+=$(TLLDFLAGS)
endif
else
VOCPPFLAGS:=$(VOCFLAGS)
ifeq ($(VOMT), lib)
VOLDFLAGS+=-shared
endif
endif
ifeq ($(VODBG), yes)
#VOLDFLAGS:=
endif
# where to place object files
OBJDIR=obj

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: oper_32b.c
Content: This file contains operations in double precision.
*******************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
/*****************************************************************************
* *
* Function L_Extract() *
* *
* Extract from a 32 bit integer two 16 bit DPF. *
* *
* Arguments: *
* *
* L_32 : 32 bit integer. *
* 0x8000 0000 <= L_32 <= 0x7fff ffff. *
* hi : b16 to b31 of L_32 *
* lo : (L_32 - hi<<16)>>1 *
*****************************************************************************
*/
void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
{
*hi = extract_h (L_32);
*lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
return;
}
/*****************************************************************************
* *
* Function L_Comp() *
* *
* Compose from two 16 bit DPF a 32 bit integer. *
* *
* L_32 = hi<<16 + lo<<1 *
* *
* Arguments: *
* *
* hi msb *
* lo lsf (with sign) *
* *
* Return Value : *
* *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x8000 0000 <= L_32 <= 0x7fff fff0. *
* *
*****************************************************************************
*/
Word32 L_Comp (Word16 hi, Word16 lo)
{
Word32 L_32;
L_32 = L_deposit_h (hi);
return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */
}
/*****************************************************************************
* Function Mpy_32() *
* *
* Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
* *
* L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
* *
* This operation can also be viewed as the multiplication of two Q31 *
* number and the result is also in Q31. *
* *
* Arguments: *
* *
* hi1 hi part of first number *
* lo1 lo part of first number *
* hi2 hi part of second number *
* lo2 lo part of second number *
* *
*****************************************************************************
*/
Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
{
Word32 L_32;
L_32 = L_mult (hi1, hi2);
L_32 = L_mac (L_32, mult (hi1, lo2), 1);
L_32 = L_mac (L_32, mult (lo1, hi2), 1);
return (L_32);
}
/*****************************************************************************
* Function Mpy_32_16() *
* *
* Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
* by 2**15 *
* *
* *
* L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
* *
* Arguments: *
* *
* hi hi part of 32 bit number. *
* lo lo part of 32 bit number. *
* n 16 bit number. *
* *
*****************************************************************************
*/
Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
{
Word32 L_32;
L_32 = L_mult (hi, n);
L_32 = L_mac (L_32, mult (lo, n), 1);
return (L_32);
}
/*****************************************************************************
* *
* Function Name : Div_32 *
* *
* Purpose : *
* Fractional integer division of two 32 bit numbers. *
* L_num / L_denom. *
* L_num and L_denom must be positive and L_num < L_denom. *
* L_denom = denom_hi<<16 + denom_lo<<1 *
* denom_hi is a normalize number. *
* *
* Inputs : *
* *
* L_num *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x0000 0000 < L_num < L_denom *
* *
* L_denom = denom_hi<<16 + denom_lo<<1 (DPF) *
* *
* denom_hi *
* 16 bit positive normalized integer whose value falls in the *
* range : 0x4000 < hi < 0x7fff *
* denom_lo *
* 16 bit positive integer whose value falls in the *
* range : 0 < lo < 0x7fff *
* *
* Return Value : *
* *
* L_div *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x0000 0000 <= L_div <= 0x7fff ffff. *
* *
* Algorithm: *
* *
* - find = 1/L_denom. *
* First approximation: approx = 1 / denom_hi *
* 1/L_denom = approx * (2.0 - L_denom * approx ) *
* *
* - result = L_num * (1/L_denom) *
*****************************************************************************
*/
Word32 Div_32 (Word32 L_num, Word32 denom)
{
Word16 approx;
Word32 L_32;
/* First approximation: 1 / L_denom = 1/denom_hi */
approx = div_s ((Word16) 0x3fff, denom >> 16);
/* 1/L_denom = approx * (2.0 - L_denom * approx) */
L_32 = L_mpy_ls (denom, approx);
L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
L_32 = L_mpy_ls (L_32, approx);
/* L_num * (1/L_denom) */
L_32 = MULHIGH(L_32, L_num);
L_32 = L_shl (L_32, 3);
return (L_32);
}
/*!
\brief calculates the log dualis times 4 of argument
iLog4(x) = (Word32)(4 * log(value)/log(2.0))
\return ilog4 value
*/
Word16 iLog4(Word32 value)
{
Word16 iLog4;
if(value != 0){
Word32 tmp;
Word16 tmp16;
iLog4 = norm_l(value);
tmp = (value << iLog4);
tmp16 = round16(tmp);
tmp = L_mult(tmp16, tmp16);
tmp16 = round16(tmp);
tmp = L_mult(tmp16, tmp16);
tmp16 = round16(tmp);
iLog4 = (-(iLog4 << 2) - norm_s(tmp16)) - 1;
}
else {
iLog4 = -128; /* -(INT_BITS*4); */
}
return iLog4;
}
#define step(shift) \
if ((0x40000000l >> shift) + root <= value) \
{ \
value -= (0x40000000l >> shift) + root; \
root = (root >> 1) | (0x40000000l >> shift); \
} else { \
root = root >> 1; \
}
Word32 rsqrt(Word32 value, /*!< Operand to square root (0.0 ... 1) */
Word32 accuracy) /*!< Number of valid bits that will be calculated */
{
Word32 root = 0;
Word32 scale;
if(value < 0)
return 0;
scale = norm_l(value);
if(scale & 1) scale--;
value <<= scale;
step( 0); step( 2); step( 4); step( 6);
step( 8); step(10); step(12); step(14);
step(16); step(18); step(20); step(22);
step(24); step(26); step(28); step(30);
scale >>= 1;
if (root < value)
++root;
root >>= scale;
return root* 46334;
}
static const Word32 pow2Table[POW2_TABLE_SIZE] = {
0x7fffffff, 0x7fa765ad, 0x7f4f08ae, 0x7ef6e8da,
0x7e9f0606, 0x7e476009, 0x7deff6b6, 0x7d98c9e6,
0x7d41d96e, 0x7ceb2523, 0x7c94acde, 0x7c3e7073,
0x7be86fb9, 0x7b92aa88, 0x7b3d20b6, 0x7ae7d21a,
0x7a92be8b, 0x7a3de5df, 0x79e947ef, 0x7994e492,
0x7940bb9e, 0x78ecccec, 0x78991854, 0x78459dac,
0x77f25cce, 0x779f5591, 0x774c87cc, 0x76f9f359,
0x76a7980f, 0x765575c8, 0x76038c5b, 0x75b1dba2,
0x75606374, 0x750f23ab, 0x74be1c20, 0x746d4cac,
0x741cb528, 0x73cc556d, 0x737c2d55, 0x732c3cba,
0x72dc8374, 0x728d015d, 0x723db650, 0x71eea226,
0x719fc4b9, 0x71511de4, 0x7102ad80, 0x70b47368,
0x70666f76, 0x7018a185, 0x6fcb096f, 0x6f7da710,
0x6f307a41, 0x6ee382de, 0x6e96c0c3, 0x6e4a33c9,
0x6dfddbcc, 0x6db1b8a8, 0x6d65ca38, 0x6d1a1057,
0x6cce8ae1, 0x6c8339b2, 0x6c381ca6, 0x6bed3398,
0x6ba27e66, 0x6b57fce9, 0x6b0daeff, 0x6ac39485,
0x6a79ad56, 0x6a2ff94f, 0x69e6784d, 0x699d2a2c,
0x69540ec9, 0x690b2601, 0x68c26fb1, 0x6879ebb6,
0x683199ed, 0x67e97a34, 0x67a18c68, 0x6759d065,
0x6712460b, 0x66caed35, 0x6683c5c3, 0x663ccf92,
0x65f60a80, 0x65af766a, 0x6569132f, 0x6522e0ad,
0x64dcdec3, 0x64970d4f, 0x64516c2e, 0x640bfb41,
0x63c6ba64, 0x6381a978, 0x633cc85b, 0x62f816eb,
0x62b39509, 0x626f4292, 0x622b1f66, 0x61e72b65,
0x61a3666d, 0x615fd05f, 0x611c6919, 0x60d9307b,
0x60962665, 0x60534ab7, 0x60109d51, 0x5fce1e12,
0x5f8bccdb, 0x5f49a98c, 0x5f07b405, 0x5ec5ec26,
0x5e8451d0, 0x5e42e4e3, 0x5e01a540, 0x5dc092c7,
0x5d7fad59, 0x5d3ef4d7, 0x5cfe6923, 0x5cbe0a1c,
0x5c7dd7a4, 0x5c3dd19c, 0x5bfdf7e5, 0x5bbe4a61,
0x5b7ec8f2, 0x5b3f7377, 0x5b0049d4, 0x5ac14bea,
0x5a82799a, 0x5a43d2c6, 0x5a055751, 0x59c7071c,
0x5988e209, 0x594ae7fb, 0x590d18d3, 0x58cf7474,
0x5891fac1, 0x5854ab9b, 0x581786e6, 0x57da8c83,
0x579dbc57, 0x57611642, 0x57249a29, 0x56e847ef,
0x56ac1f75, 0x567020a0, 0x56344b52, 0x55f89f70,
0x55bd1cdb, 0x5581c378, 0x55469329, 0x550b8bd4,
0x54d0ad5b, 0x5495f7a1, 0x545b6a8b, 0x542105fd,
0x53e6c9db, 0x53acb607, 0x5372ca68, 0x533906e0,
0x52ff6b55, 0x52c5f7aa, 0x528cabc3, 0x52538786,
0x521a8ad7, 0x51e1b59a, 0x51a907b4, 0x5170810b,
0x51382182, 0x50ffe8fe, 0x50c7d765, 0x508fec9c,
0x50582888, 0x50208b0e, 0x4fe91413, 0x4fb1c37c,
0x4f7a9930, 0x4f439514, 0x4f0cb70c, 0x4ed5ff00,
0x4e9f6cd4, 0x4e69006e, 0x4e32b9b4, 0x4dfc988c,
0x4dc69cdd, 0x4d90c68b, 0x4d5b157e, 0x4d25899c,
0x4cf022ca, 0x4cbae0ef, 0x4c85c3f1, 0x4c50cbb8,
0x4c1bf829, 0x4be7492b, 0x4bb2bea5, 0x4b7e587d,
0x4b4a169c, 0x4b15f8e6, 0x4ae1ff43, 0x4aae299b,
0x4a7a77d5, 0x4a46e9d6, 0x4a137f88, 0x49e038d0,
0x49ad1598, 0x497a15c4, 0x4947393f, 0x49147fee,
0x48e1e9ba, 0x48af768a, 0x487d2646, 0x484af8d6,
0x4818ee22, 0x47e70611, 0x47b5408c, 0x47839d7b,
0x47521cc6, 0x4720be55, 0x46ef8210, 0x46be67e0,
0x468d6fae, 0x465c9961, 0x462be4e2, 0x45fb521a,
0x45cae0f2, 0x459a9152, 0x456a6323, 0x453a564d,
0x450a6abb, 0x44daa054, 0x44aaf702, 0x447b6ead,
0x444c0740, 0x441cc0a3, 0x43ed9ac0, 0x43be9580,
0x438fb0cb, 0x4360ec8d, 0x433248ae, 0x4303c517,
0x42d561b4, 0x42a71e6c, 0x4278fb2b, 0x424af7da,
0x421d1462, 0x41ef50ae, 0x41c1aca8, 0x41942839,
0x4166c34c, 0x41397dcc, 0x410c57a2, 0x40df50b8,
0x40b268fa, 0x4085a051, 0x4058f6a8, 0x402c6be9
};
/*!
\brief calculates 2 ^ (x/y) for x<=0, y > 0, x <= 32768 * y
avoids integer division
\return
*/
Word32 pow2_xy(Word32 x, Word32 y)
{
Word32 iPart;
Word32 fPart;
Word32 res;
Word32 tmp, tmp2;
Word32 shift, shift2;
tmp2 = -x;
iPart = tmp2 / y;
fPart = tmp2 - iPart*y;
iPart = min(iPart,INT_BITS-1);
res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart;
return(res);
}

View File

@ -0,0 +1,89 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: oper_32b.h
Content: Double precision operations
*******************************************************************************/
#ifndef __OPER_32b_H
#define __OPER_32b_H
#include "typedef.h"
#ifdef __cplusplus
extern "C" {
#endif
#define POW2_TABLE_BITS 8
#define POW2_TABLE_SIZE (1<<POW2_TABLE_BITS)
void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
Word32 L_Comp (Word16 hi, Word16 lo);
Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
Word32 Div_32 (Word32 L_num, Word32 denom);
Word16 iLog4(Word32 value);
Word32 rsqrt(Word32 value, Word32 accuracy);
Word32 pow2_xy(Word32 x, Word32 y);
__inline Word32 L_mpy_ls(Word32 L_var2, Word16 var1)
{
unsigned short swLow1;
Word16 swHigh1;
Word32 l_var_out;
swLow1 = (unsigned short)(L_var2);
swHigh1 = (Word16)(L_var2 >> 16);
l_var_out = (long)swLow1 * (long)var1 >> 15;
l_var_out += swHigh1 * var1 << 1;
return(l_var_out);
}
__inline Word32 L_mpy_wx(Word32 L_var2, Word16 var1)
{
#if ARMV5TE_L_MPY_LS
Word32 result;
asm volatile(
"SMULWB %[result], %[L_var2], %[var1] \n"
:[result]"+r"(result)
:[L_var2]"r"(L_var2), [var1]"r"(var1)
);
return result;
#else
unsigned short swLow1;
Word16 swHigh1;
Word32 l_var_out;
swLow1 = (unsigned short)(L_var2);
swHigh1 = (Word16)(L_var2 >> 16);
l_var_out = (long)swLow1 * (long)var1 >> 16;
l_var_out += swHigh1 * var1;
return(l_var_out);
#endif
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,63 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: typedef.h
Content: type defined for defferent paltform
*******************************************************************************/
#ifndef typedef_h
#define typedef_h "$Id $"
#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version
of typedef.h */
#ifdef ORIGINAL_TYPEDEF_H
/*
* this is the original code from the ETSI file typedef.h
*/
#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
typedef signed char Word8;
typedef short Word16;
typedef long Word32;
typedef int Flag;
#elif defined(__sun)
typedef signed char Word8;
typedef short Word16;
typedef long Word32;
typedef int Flag;
#elif defined(__unix__) || defined(__unix)
typedef signed char Word8;
typedef short Word16;
typedef int Word32;
typedef int Flag;
#endif
#else /* not original typedef.h */
/*
* use (improved) type definition file typdefs.h and add a "Flag" type
*/
#include "typedefs.h"
typedef int Flag;
#endif
#endif

View File

@ -0,0 +1,179 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: typedefs.h
Content: type defined or const defined
*******************************************************************************/
#ifndef typedefs_h
#define typedefs_h "$Id $"
#ifndef CHAR_BIT
#define CHAR_BIT 8 /* number of bits in a char */
#endif
#ifndef VOAAC_SHRT_MAX
#define VOAAC_SHRT_MAX (32767) /* maximum (signed) short value */
#endif
#ifndef VOAAC_SHRT_MIN
#define VOAAC_SHRT_MIN (-32768) /* minimum (signed) short value */
#endif
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
#ifndef assert
#define assert(_Expression) ((void)0)
#endif
#ifdef LINUX
#define __inline static __inline__
#endif
#define INT_BITS 32
/*
********************************************************************************
* DEFINITION OF CONSTANTS
********************************************************************************
*/
/*
********* define char type
*/
typedef char Char;
/*
********* define 8 bit signed/unsigned types & constants
*/
typedef signed char Word8;
typedef unsigned char UWord8;
/*
********* define 16 bit signed/unsigned types & constants
*/
typedef short Word16;
typedef unsigned short UWord16;
/*
********* define 32 bit signed/unsigned types & constants
*/
typedef long Word32;
typedef unsigned long UWord32;
#ifdef LINUX
typedef long long Word64;
typedef unsigned long long UWord64;
#else
typedef __int64 Word64;
typedef unsigned __int64 UWord64;
#endif
#ifndef min
#define min(a,b) ( a < b ? a : b)
#endif
#ifndef max
#define max(a,b) ( a > b ? a : b)
#endif
#ifdef ARM_INASM
#ifdef ARMV5_INASM
#define ARMV5E_INASM 1
#endif
#define ARMV4_INASM 1
#endif
#if ARMV4_INASM
#define ARMV5TE_SAT 1
#define ARMV5TE_ADD 1
#define ARMV5TE_SUB 1
#define ARMV5TE_SHL 1
#define ARMV5TE_SHR 1
#define ARMV5TE_L_SHL 1
#define ARMV5TE_L_SHR 1
#endif//ARMV4
#if ARMV5E_INASM
#define ARMV5TE_L_ADD 1
#define ARMV5TE_L_SUB 1
#define ARMV5TE_L_MULT 1
#define ARMV5TE_L_MAC 1
#define ARMV5TE_L_MSU 1
#define ARMV5TE_DIV_S 1
#define ARMV5TE_ROUND 1
#define ARMV5TE_MULT 1
#define ARMV5TE_NORM_S 1
#define ARMV5TE_NORM_L 1
#define ARMV5TE_L_MPY_LS 1
#endif
//basic operation functions optimization flags
#define SATRUATE_IS_INLINE 1 //define saturate as inline function
#define SHL_IS_INLINE 1 //define shl as inline function
#define SHR_IS_INLINE 1 //define shr as inline function
#define L_MULT_IS_INLINE 1 //define L_mult as inline function
#define L_MSU_IS_INLINE 1 //define L_msu as inline function
#define L_SUB_IS_INLINE 1 //define L_sub as inline function
#define L_SHL_IS_INLINE 1 //define L_shl as inline function
#define L_SHR_IS_INLINE 1 //define L_shr as inline function
#define ADD_IS_INLINE 1 //define add as inline function //add, inline is the best
#define SUB_IS_INLINE 1 //define sub as inline function //sub, inline is the best
#define DIV_S_IS_INLINE 1 //define div_s as inline function
#define MULT_IS_INLINE 1 //define mult as inline function
#define NORM_S_IS_INLINE 1 //define norm_s as inline function
#define NORM_L_IS_INLINE 1 //define norm_l as inline function
#define ROUND_IS_INLINE 1 //define round as inline function
#define L_MAC_IS_INLINE 1 //define L_mac as inline function
#define L_ADD_IS_INLINE 1 //define L_add as inline function
#define EXTRACT_H_IS_INLINE 1 //define extract_h as inline function
#define EXTRACT_L_IS_INLINE 1 //define extract_l as inline function //???
#define MULT_R_IS_INLINE 1 //define mult_r as inline function
#define SHR_R_IS_INLINE 1 //define shr_r as inline function
#define MAC_R_IS_INLINE 1 //define mac_r as inline function
#define MSU_R_IS_INLINE 1 //define msu_r as inline function
#define L_SHR_R_IS_INLINE 1 //define L_shr_r as inline function
#define PREFIX voAACEnc
#define LINK0(x, y, z) LINK1(x,y,z)
#define LINK1(x,y,z) x##y##z
#define ADD_PREFIX(func) LINK0(PREFIX, _, func)
#define L_Extract ADD_PREFIX(L_Extract)
#define L_Comp ADD_PREFIX(L_Comp)
#define Mpy_32 ADD_PREFIX(Mpy_32)
#define Mpy_32_16 ADD_PREFIX(Mpy_32_16)
#define Div_32 ADD_PREFIX(Div_32)
#define iLog4 ADD_PREFIX(iLog4)
#define rsqrt ADD_PREFIX(rsqrt)
#define pow2_xy ADD_PREFIX(pow2_xy)
#define L_mpy_ls ADD_PREFIX(L_mpy_ls)
#define L_mpy_wx ADD_PREFIX(L_mpy_wx)
#define mem_malloc ADD_PREFIX(mem_malloc)
#define mem_free ADD_PREFIX(mem_free)
#endif

View File

@ -0,0 +1,55 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# target6
# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
VOTT:= v5
# module type
# please specify the type of your module: lib or exe
VOMT:= lib
# module macros
# please append the additional macro definitions here for your module if necessary.
# e.g. -DVISUALON, macro VISUALON defined for your module
VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM
# please specify the name of your module
VOTARGET:=libvoAACEncv5
# please modify here to be sure to see the g1.mk
include ../../../../../Tools/eclair.mk
# dependent libraries.
VODEPLIBS:=#-ldl -lstdc++
# module source
# please modify here to be sure to see the ms.mk which specifies all source info of your module
include ../../ms.mk
# please specify where is the voRelease on your PC, relative path is suggested
VORELDIR:=../../../../../../Release
# please modify here to be sure to see the doit.mk
include ../../../../../Tools/doit.mk

View File

@ -0,0 +1,55 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# target6
# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
VOTT:= v7
# module type
# please specify the type of your module: lib or exe
VOMT:= lib
# module macros
# please append the additional macro definitions here for your module if necessary.
# e.g. -DVISUALON, macro VISUALON defined for your module
VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
# please specify the name of your module
VOTARGET:=libvoAACEncv7
# please modify here to be sure to see the g1.mk
include ../../../../../Tools/eclair.mk
# dependent libraries.
VODEPLIBS:=#-ldl -lstdc++
# module source
# please modify here to be sure to see the ms.mk which specifies all source info of your module
include ../../ms.mk
# please specify where is the voRelease on your PC, relative path is suggested
VORELDIR:=../../../../../../Release
# please modify here to be sure to see the doit.mk
include ../../../../../Tools/doit.mk

View File

@ -0,0 +1,40 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# Just acting as Father Makefile of Modules
# please keep the name 'makefile' unchanged
# Module Subdirs
VOMSD:=$(dir $(shell find . -name 'Makefile'))
all:
for dir in $(VOMSD); \
do \
$(MAKE) -C $$dir; \
done
.PHONY:clean devel
clean:
for dir in $(VOMSD); \
do \
$(MAKE) -C $$dir clean; \
done
devel:
for dir in $(VOMSD); \
do \
$(MAKE) -C $$dir devel; \
done

View File

@ -0,0 +1,42 @@
#/*
#** Copyright 2003-2010, VisualOn, Inc.
#**
#** Licensed under the Apache License, Version 2.0 (the "License");
#** you may not use this file except in compliance with the License.
#** You may obtain a copy of the License at
#**
#** http://www.apache.org/licenses/LICENSE-2.0
#**
#** Unless required by applicable law or agreed to in writing, software
#** distributed under the License is distributed on an "AS IS" BASIS,
#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#** See the License for the specific language governing permissions and
#** limitations under the License.
#*/
# please list all objects needed by your target here
OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \
band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \
dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \
pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \
spreading.o stat_bits.o tns.o transform.o
# please list all directories that all source files relative with your module(.h .c .cpp) locate
VOSRCDIR:=../../../src \
../../../inc \
../../../basic_op\
../../../../../Include
ifeq ($(VOTT), v5)
OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o
VOSRCDIR+= ../../../src/asm/ARMV5E/
endif
ifeq ($(VOTT), v7)
OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o
VOSRCDIR+= ../../../src/asm/ARMV5E/
VOSRCDIR+= ../../../src/asm/ARMV7/
endif

View File

@ -0,0 +1,117 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: aac_rom.h
Content: constant tables
*******************************************************************************/
#ifndef ROM_H
#define ROM_H
#include "config.h"
#include "psy_const.h"
#include "tns_param.h"
/*
mdct
*/
extern const int ShortWindowSine[FRAME_LEN_SHORT/2];
extern const int LongWindowKBD[FRAME_LEN_LONG/2];
extern const unsigned char bitrevTab[17 + 129];
extern const int cossintab[128 + 1024];
#if defined (ARMV5E) && !defined (ARMV7Neon)
extern const int twidTab64[(4*6 + 16*6)/2];
extern const int twidTab512[(8*6 + 32*6 + 128*6)/2];
#else
extern const int twidTab64[4*6 + 16*6];
extern const int twidTab512[8*6 + 32*6 + 128*6];
#endif
/*
form factor
*/
extern const Word32 formfac_sqrttable[96];
/*
quantizer
*/
extern const Word32 mTab_3_4[512];
extern const Word32 mTab_4_3[512];
/*! $2^{-\frac{n}{16}}$ table */
extern const Word16 pow2tominusNover16[17] ;
extern Word32 specExpMantTableComb_enc[4][14];
extern const UWord8 specExpTableComb_enc[4][14];
extern const Word16 quantBorders[4][4];
//extern const Word16 quantRecon[3][4];
extern const Word16 quantRecon[4][3];
/*
huffman
*/
extern const UWord16 huff_ltab1_2[3][3][3][3];
extern const UWord16 huff_ltab3_4[3][3][3][3];
extern const UWord16 huff_ltab5_6[9][9];
extern const UWord16 huff_ltab7_8[8][8];
extern const UWord16 huff_ltab9_10[13][13];
extern const UWord16 huff_ltab11[17][17];
extern const UWord16 huff_ltabscf[121];
extern const UWord16 huff_ctab1[3][3][3][3];
extern const UWord16 huff_ctab2[3][3][3][3];
extern const UWord16 huff_ctab3[3][3][3][3];
extern const UWord16 huff_ctab4[3][3][3][3];
extern const UWord16 huff_ctab5[9][9];
extern const UWord16 huff_ctab6[9][9];
extern const UWord16 huff_ctab7[8][8];
extern const UWord16 huff_ctab8[8][8];
extern const UWord16 huff_ctab9[13][13];
extern const UWord16 huff_ctab10[13][13];
extern const UWord16 huff_ctab11[17][17];
extern const UWord32 huff_ctabscf[121];
/*
misc
*/
extern const int sampRateTab[NUM_SAMPLE_RATES];
extern const int BandwithCoefTab[8][NUM_SAMPLE_RATES];
extern const int rates[8];
extern const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES];
extern const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES];
extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES];
extern const short sfBandTabShort[76];
extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES];
extern const short sfBandTabLong[325];
extern const Word32 m_log2_table[INT_BITS];
/*
TNS
*/
extern const Word32 tnsCoeff3[8];
extern const Word32 tnsCoeff3Borders[8];
extern const Word32 tnsCoeff4[16];
extern const Word32 tnsCoeff4Borders[16];
extern const Word32 invSBF[24];
extern const Word16 sideInfoTabLong[MAX_SFB_LONG + 1];
extern const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1];
#endif

View File

@ -0,0 +1,117 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: aacenc_core.h
Content: aac encoder interface functions
*******************************************************************************/
#ifndef _aacenc_core_h_
#define _aacenc_core_h_
#include "typedef.h"
#include "config.h"
#include "bitenc.h"
#include "psy_configuration.h"
#include "psy_main.h"
#include "qc_main.h"
#include "psy_main.h"
/*-------------------------- defines --------------------------------------*/
/*-------------------- structure definitions ------------------------------*/
typedef struct {
Word32 sampleRate; /* audio file sample rate */
Word32 bitRate; /* encoder bit rate in bits/sec */
Word16 nChannelsIn; /* number of channels on input (1,2) */
Word16 nChannelsOut; /* number of channels on output (1,2) */
Word16 bandWidth; /* targeted audio bandwidth in Hz */
Word16 adtsUsed; /* whether write adts header */
} AACENC_CONFIG;
typedef struct {
AACENC_CONFIG config; /* Word16 size: 8 */
ELEMENT_INFO elInfo; /* Word16 size: 4 */
QC_STATE qcKernel; /* Word16 size: 6 + 5(PADDING) + 7(ELEMENT_BITS) + 54(ADJ_THR_STATE) = 72 */
QC_OUT qcOut; /* Word16 size: MAX_CHANNELS*920(QC_OUT_CHANNEL) + 5(QC_OUT_ELEMENT) + 7 = 932 / 1852 */
PSY_OUT psyOut; /* Word16 size: MAX_CHANNELS*186 + 2 = 188 / 374 */
PSY_KERNEL psyKernel; /* Word16 size: 2587 / 4491 */
struct BITSTREAMENCODER_INIT bseInit; /* Word16 size: 6 */
struct BIT_BUF bitStream; /* Word16 size: 8 */
HANDLE_BIT_BUF hBitStream;
int initOK;
short *intbuf;
short *encbuf;
short *inbuf;
int enclen;
int inlen;
int intlen;
int uselength;
void *hCheck;
VO_MEM_OPERATOR *voMemop;
VO_MEM_OPERATOR voMemoprator;
}AAC_ENCODER; /* Word16 size: 3809 / 6851 */
/*-----------------------------------------------------------------------------
functionname: AacInitDefaultConfig
description: gives reasonable default configuration
returns: ---
------------------------------------------------------------------------------*/
void AacInitDefaultConfig(AACENC_CONFIG *config);
/*---------------------------------------------------------------------------
functionname:AacEncOpen
description: allocate and initialize a new encoder instance
returns: AACENC_OK if success
---------------------------------------------------------------------------*/
Word16 AacEncOpen (AAC_ENCODER *hAacEnc, /* pointer to an encoder handle, initialized on return */
const AACENC_CONFIG config); /* pre-initialized config struct */
Word16 AacEncEncode(AAC_ENCODER *hAacEnc,
Word16 *timeSignal,
const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */
Word16 *numAncBytes, /*!< number of ancillary Data Bytes, send as fill element */
UWord8 *outBytes, /*!< pointer to output buffer */
Word32 *numOutBytes /*!< number of bytes in output buffer */
);
/*---------------------------------------------------------------------------
functionname:AacEncClose
description: deallocate an encoder instance
---------------------------------------------------------------------------*/
void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP); /* an encoder handle */
#endif /* _aacenc_h_ */

View File

@ -0,0 +1,57 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: adj_thr.h
Content: Threshold compensation function
*******************************************************************************/
#ifndef __ADJ_THR_H
#define __ADJ_THR_H
#include "adj_thr_data.h"
#include "qc_data.h"
#include "interface.h"
Word16 bits2pe(const Word16 bits);
Word32 AdjThrNew(ADJ_THR_STATE** phAdjThr,
Word32 nElements);
void AdjThrDelete(ADJ_THR_STATE *hAdjThr);
void AdjThrInit(ADJ_THR_STATE *hAdjThr,
const Word32 peMean,
Word32 chBitrate);
void AdjustThresholds(ADJ_THR_STATE *adjThrState,
ATS_ELEMENT* AdjThrStateElement,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
PSY_OUT_ELEMENT *psyOutElement,
Word16 *chBitDistribution,
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
QC_OUT_ELEMENT* qcOE,
ELEMENT_BITS* elBits,
const Word16 nChannels,
const Word16 maxBitFac);
void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
const Word16 dynBitsUsed);
#endif

View File

@ -0,0 +1,69 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: adj_thr_data.h
Content: Threshold compensation parameter
*******************************************************************************/
#ifndef __ADJ_THR_DATA_H
#define __ADJ_THR_DATA_H
#include "typedef.h"
#include "psy_const.h"
#include "line_pe.h"
typedef struct {
Word16 clipSaveLow, clipSaveHigh;
Word16 minBitSave, maxBitSave;
Word16 clipSpendLow, clipSpendHigh;
Word16 minBitSpend, maxBitSpend;
} BRES_PARAM;
typedef struct {
UWord8 modifyMinSnr;
Word16 startSfbL, startSfbS;
} AH_PARAM;
typedef struct {
Word32 maxRed;
Word32 startRatio, maxRatio;
Word32 redRatioFac;
Word32 redOffs;
} MINSNR_ADAPT_PARAM;
typedef struct {
/* parameters for bitreservoir control */
Word16 peMin, peMax;
/* constant offset to pe */
Word16 peOffset;
/* avoid hole parameters */
AH_PARAM ahParam;
/* paramters for adaptation of minSnr */
MINSNR_ADAPT_PARAM minSnrAdaptParam;
/* values for correction of pe */
Word16 peLast;
Word16 dynBitsLast;
Word16 peCorrectionFactor;
} ATS_ELEMENT;
typedef struct {
BRES_PARAM bresParamLong, bresParamShort; /* Word16 size: 2*8 */
ATS_ELEMENT adjThrStateElem; /* Word16 size: 19 */
} ADJ_THR_STATE;
#endif

View File

@ -0,0 +1,46 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: band_nrg.h
Content: Band/Line energy calculations functions
*******************************************************************************/
#ifndef _BAND_NRG_H
#define _BAND_NRG_H
#include "typedef.h"
void CalcBandEnergy(const Word32 *mdctSpectrum,
const Word16 *bandOffset,
const Word16 numBands,
Word32 *bandEnergy,
Word32 *bandEnergySum);
void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
const Word32 *mdctSpectrumRight,
const Word16 *bandOffset,
const Word16 numBands,
Word32 *bandEnergyMid,
Word32 *bandEnergyMidSum,
Word32 *bandEnergySide,
Word32 *bandEnergySideSum);
#endif

View File

@ -0,0 +1,106 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bit_cnt.h
Content: Huffman Bitcounter & coder structure and functions
*******************************************************************************/
#ifndef __BITCOUNT_H
#define __BITCOUNT_H
#include "bitbuffer.h"
#include "basic_op.h"
#define INVALID_BITCOUNT (MAX_16/4)
/*
code book number table
*/
enum codeBookNo{
CODE_BOOK_ZERO_NO= 0,
CODE_BOOK_1_NO= 1,
CODE_BOOK_2_NO= 2,
CODE_BOOK_3_NO= 3,
CODE_BOOK_4_NO= 4,
CODE_BOOK_5_NO= 5,
CODE_BOOK_6_NO= 6,
CODE_BOOK_7_NO= 7,
CODE_BOOK_8_NO= 8,
CODE_BOOK_9_NO= 9,
CODE_BOOK_10_NO= 10,
CODE_BOOK_ESC_NO= 11,
CODE_BOOK_RES_NO= 12,
CODE_BOOK_PNS_NO= 13
};
/*
code book index table
*/
enum codeBookNdx{
CODE_BOOK_ZERO_NDX=0,
CODE_BOOK_1_NDX,
CODE_BOOK_2_NDX,
CODE_BOOK_3_NDX,
CODE_BOOK_4_NDX,
CODE_BOOK_5_NDX,
CODE_BOOK_6_NDX,
CODE_BOOK_7_NDX,
CODE_BOOK_8_NDX,
CODE_BOOK_9_NDX,
CODE_BOOK_10_NDX,
CODE_BOOK_ESC_NDX,
CODE_BOOK_RES_NDX,
CODE_BOOK_PNS_NDX,
NUMBER_OF_CODE_BOOKS
};
/*
code book lav table
*/
enum codeBookLav{
CODE_BOOK_ZERO_LAV=0,
CODE_BOOK_1_LAV=1,
CODE_BOOK_2_LAV=1,
CODE_BOOK_3_LAV=2,
CODE_BOOK_4_LAV=2,
CODE_BOOK_5_LAV=4,
CODE_BOOK_6_LAV=4,
CODE_BOOK_7_LAV=7,
CODE_BOOK_8_LAV=7,
CODE_BOOK_9_LAV=12,
CODE_BOOK_10_LAV=12,
CODE_BOOK_ESC_LAV=16,
CODE_BOOK_SCF_LAV=60,
CODE_BOOK_PNS_LAV=60
};
Word16 bitCount(const Word16 *aQuantSpectrum,
const Word16 noOfSpecLines,
Word16 maxVal,
Word16 *bitCountLut);
Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream);
Word16 bitCountScalefactorDelta(Word16 delta);
Word16 codeScalefactorDelta(Word16 scalefactor, HANDLE_BIT_BUF hBitstream);
#endif

View File

@ -0,0 +1,89 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bitbuffer.h
Content: Bit Buffer Management structure and functions
*******************************************************************************/
#ifndef BITBUFFER_H
#define BITBUFFER_H
#include "typedef.h"
enum direction
{
forwardDirection,
backwardDirection
};
/*!
The pointer 'pReadNext' points to the next available word, where bits can be read from. The pointer
'pWriteNext' points to the next available word, where bits can be written to. The pointer pBitBufBase
points to the start of the bitstream buffer and the pointer pBitBufEnd points to the end of the bitstream
buffer. The two pointers are used as lower-bound respectively upper-bound address for the modulo addressing
mode.
The element cntBits contains the currently available bits in the bit buffer. It will be incremented when
bits are written to the bitstream buffer and decremented when bits are read from the bitstream buffer.
*/
struct BIT_BUF
{
UWord8 *pBitBufBase; /*!< pointer points to first position in bitstream buffer */
UWord8 *pBitBufEnd; /*!< pointer points to last position in bitstream buffer */
UWord8 *pWriteNext; /*!< pointer points to next available word in bitstream buffer to write */
UWord32 cache;
Word16 wBitPos; /*!< 31<=wBitPos<=0*/
Word16 cntBits; /*!< number of available bits in the bitstream buffer
write bits to bitstream buffer => increment cntBits
read bits from bitstream buffer => decrement cntBits */
Word16 size; /*!< size of bitbuffer in bits */
Word16 isValid; /*!< indicates whether the instance has been initialized */
}; /* size Word16: 8 */
/*! Define pointer to bit buffer structure */
typedef struct BIT_BUF *HANDLE_BIT_BUF;
HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
UWord8 *pBitBufBase,
Word16 bitBufSize);
void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf);
Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf);
Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
Word32 writeValue,
Word16 noBitsToWrite);
void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
UWord8 *pBitBufBase,
Word16 bitBufSize);
#define GetNrBitsAvailable(hBitBuf) ( (hBitBuf)->cntBits)
#define GetNrBitsRead(hBitBuf) ((hBitBuf)->size-(hBitBuf)->cntBits)
#endif /* BITBUFFER_H */

View File

@ -0,0 +1,50 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bitenc.h
Content: Bitstream encoder structure and functions
*******************************************************************************/
#ifndef _BITENC_H
#define _BITENC_H
#include "qc_data.h"
#include "tns.h"
#include "channel_map.h"
#include "interface.h"
struct BITSTREAMENCODER_INIT
{
Word16 nChannels;
Word32 bitrate;
Word32 sampleRate;
Word16 profile;
};
Word16 WriteBitstream (HANDLE_BIT_BUF hBitstream,
ELEMENT_INFO elInfo,
QC_OUT *qcOut,
PSY_OUT *psyOut,
Word16 *globUsedBits,
const UWord8 *ancBytes,
Word16 samplerate
);
#endif /* _BITENC_H */

View File

@ -0,0 +1,72 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: block_switch.h
Content: Block switching structure and functions
*******************************************************************************/
#ifndef _BLOCK_SWITCH_H
#define _BLOCK_SWITCH_H
#include "typedef.h"
/****************** Defines ******************************/
#define BLOCK_SWITCHING_IIR_LEN 2 /* Length of HighPass-FIR-Filter for Attack-Detection */
#define BLOCK_SWITCH_WINDOWS TRANS_FAC /* number of windows for energy calculation */
#define BLOCK_SWITCH_WINDOW_LEN FRAME_LEN_SHORT /* minimal granularity of energy calculation */
/****************** Structures ***************************/
typedef struct{
Word32 invAttackRatio;
Word16 windowSequence;
Word16 nextwindowSequence;
Flag attack;
Flag lastattack;
Word16 attackIndex;
Word16 lastAttackIndex;
Word16 noOfGroups;
Word16 groupLen[TRANS_FAC];
Word32 windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows (last and current) */
Word32 windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy in segments (last and current) */
Word32 iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */
Word32 maxWindowNrg; /* max energy in subwindows */
Word32 accWindowNrg; /* recursively accumulated windowNrgF */
}BLOCK_SWITCHING_CONTROL;
Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
const Word32 bitRate, const Word16 nChannels);
Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
Word16 *timeSignal,
Word32 sampleRate,
Word16 chIncrement);
Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
const Word16 noOfChannels);
#endif /* #ifndef _BLOCK_SWITCH_H */

View File

@ -0,0 +1,37 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: channel_map.h
Content: channel mapping functions
*******************************************************************************/
#ifndef _CHANNEL_MAP_H
#define _CHANNEL_MAP_H
#include "psy_const.h"
#include "qc_data.h"
Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo);
Word16 InitElementBits(ELEMENT_BITS *elementBits,
ELEMENT_INFO elInfo,
Word32 bitrateTot,
Word16 averageBitsTot,
Word16 staticBitsTot);
#endif /* CHANNEL_MAP_H */

View File

@ -0,0 +1,36 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: config.h
Content: aac encoder parameter
*******************************************************************************/
#ifndef _AACENC_CONFIG_H_
#define _AACENC_CONFIG_H_
#define MAX_CHANNELS 2
#define AACENC_BLOCKSIZE 1024 /*! encoder only takes BLOCKSIZE samples at a time */
#define AACENC_TRANS_FAC 8 /*! encoder short long ratio */
#define MAXBITS_COEF 6144
#define MINBITS_COEF 744
#endif

View File

@ -0,0 +1,82 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: dyn_bits.h
Content: Noiseless coder module structure and functions
*******************************************************************************/
#ifndef __DYN_BITS_H
#define __DYN_BITS_H
#include "psy_const.h"
#include "tns.h"
#include "bit_cnt.h"
#define MAX_SECTIONS MAX_GROUPED_SFB
#define SECT_ESC_VAL_LONG 31
#define SECT_ESC_VAL_SHORT 7
#define CODE_BOOK_BITS 4
#define SECT_BITS_LONG 5
#define SECT_BITS_SHORT 3
typedef struct
{
Word16 codeBook;
Word16 sfbStart;
Word16 sfbCnt;
Word16 sectionBits;
}
SECTION_INFO;
typedef struct
{
Word16 blockType;
Word16 noOfGroups;
Word16 sfbCnt;
Word16 maxSfbPerGroup;
Word16 sfbPerGroup;
Word16 noOfSections;
SECTION_INFO sectionInfo[MAX_SECTIONS];
Word16 sideInfoBits; /* sectioning bits */
Word16 huffmanBits; /* huffman coded bits */
Word16 scalefacBits; /* scalefac coded bits */
Word16 firstScf; /* first scf to be coded */
Word16 bitLookUp[MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)];
Word16 mergeGainLookUp[MAX_SFB_LONG];
}
SECTION_DATA; /* Word16 size: 10 + 60(MAX_SECTIONS)*4(SECTION_INFO) + 51(MAX_SFB_LONG)*12(CODE_BOOK_ESC_NDX+1) + 51(MAX_SFB_LONG) = 913 */
Word16 BCInit(void);
Word16 dynBitCount(const Word16 *quantSpectrum,
const UWord16 *maxValueInSfb,
const Word16 *scalefac,
const Word16 blockType,
const Word16 sfbCnt,
const Word16 maxSfbPerGroup,
const Word16 sfbPerGroup,
const Word16 *sfbOffset,
SECTION_DATA *sectionData);
#endif

View File

@ -0,0 +1,44 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: grp_data.h
Content: Short block grouping function
*******************************************************************************/
#ifndef __GRP_DATA_H__
#define __GRP_DATA_H__
#include "psy_data.h"
#include "typedefs.h"
void
groupShortData(Word32 *mdctSpectrum,
Word32 *tmpSpectrum,
SFB_THRESHOLD *sfbThreshold,
SFB_ENERGY *sfbEnergy,
SFB_ENERGY *sfbEnergyMS,
SFB_ENERGY *sfbSpreadedEnergy,
const Word16 sfbCnt,
const Word16 *sfbOffset,
const Word16 *sfbMinSnr,
Word16 *groupedSfbOffset,
Word16 *maxSfbPerGroup,
Word16 *groupedSfbMinSnr,
const Word16 noOfGroups,
const Word16 *groupLen);
#endif /* _INTERFACE_H */

View File

@ -0,0 +1,106 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: interface.h
Content: psychoaccoustic/quantizer structures and interface
*******************************************************************************/
#ifndef _INTERFACE_H
#define _INTERFACE_H
#include "config.h"
#include "psy_const.h"
#include "psy_data.h"
#include "typedefs.h"
enum
{
MS_NONE = 0,
MS_SOME = 1,
MS_ALL = 2
};
enum
{
MS_ON = 1
};
struct TOOLSINFO {
Word16 msDigest;
Word16 msMask[MAX_GROUPED_SFB];
};
typedef struct {
Word16 sfbCnt;
Word16 sfbPerGroup;
Word16 maxSfbPerGroup;
Word16 windowSequence;
Word16 windowShape;
Word16 groupingMask;
Word16 sfbOffsets[MAX_GROUPED_SFB+1];
Word16 mdctScale;
Word32 *sfbEnergy;
Word32 *sfbSpreadedEnergy;
Word32 *sfbThreshold;
Word32 *mdctSpectrum;
Word32 sfbEnSumLR;
Word32 sfbEnSumMS;
Word32 sfbDist[MAX_GROUPED_SFB];
Word32 sfbDistNew[MAX_GROUPED_SFB];
Word16 sfbMinSnr[MAX_GROUPED_SFB];
Word16 minSfMaxQuant[MAX_GROUPED_SFB];
Word16 minScfCalculated[MAX_GROUPED_SFB];
Word16 prevScfLast[MAX_GROUPED_SFB];
Word16 prevScfNext[MAX_GROUPED_SFB];
Word16 deltaPeLast[MAX_GROUPED_SFB];
TNS_INFO tnsInfo;
} PSY_OUT_CHANNEL; /* Word16 size: 14 + 60(MAX_GROUPED_SFB) + 112(TNS_INFO) = 186 */
typedef struct {
struct TOOLSINFO toolsInfo;
Word16 groupedSfbOffset[MAX_CHANNELS][MAX_GROUPED_SFB+1]; /* plus one for last dummy offset ! */
Word16 groupedSfbMinSnr[MAX_CHANNELS][MAX_GROUPED_SFB];
} PSY_OUT_ELEMENT;
typedef struct {
/* information shared by both channels */
PSY_OUT_ELEMENT psyOutElement;
/* information specific to each channel */
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS];
}PSY_OUT;
void BuildInterface(Word32 *mdctSpectrum,
const Word16 mdctScale,
SFB_THRESHOLD *sfbThreshold,
SFB_ENERGY *sfbEnergy,
SFB_ENERGY *sfbSpreadedEnergy,
const SFB_ENERGY_SUM sfbEnergySumLR,
const SFB_ENERGY_SUM sfbEnergySumMS,
const Word16 windowSequence,
const Word16 windowShape,
const Word16 sfbCnt,
const Word16 *sfbOffset,
const Word16 maxSfbPerGroup,
const Word16 *groupedSfbMinSnr,
const Word16 noOfGroups,
const Word16 *groupLen,
PSY_OUT_CHANNEL *psyOutCh);
#endif /* _INTERFACE_H */

View File

@ -0,0 +1,75 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: line_pe.h
Content: Perceptual entropie module structure and functions
*******************************************************************************/
#ifndef __LINE_PE_H
#define __LINE_PE_H
#include "psy_const.h"
#include "interface.h"
typedef struct {
Word16 sfbLdEnergy[MAX_GROUPED_SFB]; /* 4*log(sfbEnergy)/log(2) */
Word16 sfbNLines4[MAX_GROUPED_SFB]; /* 4*number of relevant lines in sfb */
Word16 sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */
Word16 sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */
Word16 sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */
Word16 pe; /* sum of sfbPe */
Word16 constPart; /* sum of sfbConstPart */
Word16 nActiveLines; /* sum of sfbNActiveLines */
} PE_CHANNEL_DATA; /* size Word16: 303 */
typedef struct {
PE_CHANNEL_DATA peChannelData[MAX_CHANNELS];
Word16 pe;
Word16 constPart;
Word16 nActiveLines;
Word16 offset;
Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB];
Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB];
Word32 sfbPeFactors[MAX_CHANNELS][MAX_GROUPED_SFB];
} PE_DATA; /* size Word16: 303 + 4 + 120 + 240 = 667 */
void prepareSfbPe(PE_DATA *peData,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
const Word16 nChannels,
const Word16 peOffset);
void calcSfbPe(PE_DATA *peData,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
const Word16 nChannels);
#endif

View File

@ -0,0 +1,35 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: memalign.h
Content: Memory alloc alignments functions
*******************************************************************************/
#ifndef __VO_AACENC_MEM_ALIGN_H__
#define __VO_AACENC_MEM_ALIGN_H__
#include "voMem.h"
#include "typedef.h"
extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID);
extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID);
#endif /* __VO_MEM_ALIGN_H__ */

View File

@ -0,0 +1,45 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: ms_stereo.h
Content: Declaration MS stereo processing structure and functions
*******************************************************************************/
#ifndef __MS_STEREO_H__
#define __MS_STEREO_H__
#include "typedef.h"
void MsStereoProcessing(Word32 *sfbEnergyLeft,
Word32 *sfbEnergyRight,
const Word32 *sfbEnergyMid,
const Word32 *sfbEnergySide,
Word32 *mdctSpectrumLeft,
Word32 *mdctSpectrumRight,
Word32 *sfbThresholdLeft,
Word32 *sfbThresholdRight,
Word32 *sfbSpreadedEnLeft,
Word32 *sfbSpreadedEnRight,
Word16 *msDigest,
Word16 *msMask,
const Word16 sfbCnt,
const Word16 sfbPerGroup,
const Word16 maxSfbPerGroup,
const Word16 *sfbOffset);
#endif

View File

@ -0,0 +1,42 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: pre_echo_control.h
Content: Pre echo control functions
*******************************************************************************/
#ifndef __PRE_ECHO_CONTROL_H
#define __PRE_ECHO_CONTROL_H
#include "typedefs.h"
void InitPreEchoControl(Word32 *pbThresholdnm1,
Word16 numPb,
Word32 *pbThresholdQuiet);
void PreEchoControl(Word32 *pbThresholdNm1,
Word16 numPb,
Word32 maxAllowedIncreaseFactor,
Word16 minRemainingThresholdFactor,
Word32 *pbThreshold,
Word16 mdctScale,
Word16 mdctScalenm1);
#endif

View File

@ -0,0 +1,107 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_configuration.h
Content: Psychoaccoustic configuration structure and functions
*******************************************************************************/
#ifndef _PSY_CONFIGURATION_H
#define _PSY_CONFIGURATION_H
#include "typedefs.h"
#include "psy_const.h"
#include "tns.h"
typedef struct{
Word16 sfbCnt;
Word16 sfbActive; /* number of sf bands containing energy after lowpass */
Word16 *sfbOffset;
Word32 sfbThresholdQuiet[MAX_SFB_LONG];
Word16 maxAllowedIncreaseFactor; /* preecho control */
Word16 minRemainingThresholdFactor;
Word16 lowpassLine;
Word16 sampRateIdx;
Word32 clipEnergy; /* for level dependend tmn */
Word16 ratio;
Word16 sfbMaskLowFactor[MAX_SFB_LONG];
Word16 sfbMaskHighFactor[MAX_SFB_LONG];
Word16 sfbMaskLowFactorSprEn[MAX_SFB_LONG];
Word16 sfbMaskHighFactorSprEn[MAX_SFB_LONG];
Word16 sfbMinSnr[MAX_SFB_LONG]; /* minimum snr (formerly known as bmax) */
TNS_CONFIG tnsConf;
}PSY_CONFIGURATION_LONG; /*Word16 size: 8 + 52 + 102 + 51 + 51 + 51 + 51 + 47 = 515 */
typedef struct{
Word16 sfbCnt;
Word16 sfbActive; /* number of sf bands containing energy after lowpass */
Word16 *sfbOffset;
Word32 sfbThresholdQuiet[MAX_SFB_SHORT];
Word16 maxAllowedIncreaseFactor; /* preecho control */
Word16 minRemainingThresholdFactor;
Word16 lowpassLine;
Word16 sampRateIdx;
Word32 clipEnergy; /* for level dependend tmn */
Word16 ratio;
Word16 sfbMaskLowFactor[MAX_SFB_SHORT];
Word16 sfbMaskHighFactor[MAX_SFB_SHORT];
Word16 sfbMaskLowFactorSprEn[MAX_SFB_SHORT];
Word16 sfbMaskHighFactorSprEn[MAX_SFB_SHORT];
Word16 sfbMinSnr[MAX_SFB_SHORT]; /* minimum snr (formerly known as bmax) */
TNS_CONFIG tnsConf;
}PSY_CONFIGURATION_SHORT; /*Word16 size: 8 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 47 = 167 */
/* Returns the sample rate index */
Word32 GetSRIndex(Word32 sampleRate);
Word16 InitPsyConfigurationLong(Word32 bitrate,
Word32 samplerate,
Word16 bandwidth,
PSY_CONFIGURATION_LONG *psyConf);
Word16 InitPsyConfigurationShort(Word32 bitrate,
Word32 samplerate,
Word16 bandwidth,
PSY_CONFIGURATION_SHORT *psyConf);
#endif /* _PSY_CONFIGURATION_H */

View File

@ -0,0 +1,80 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_const.h
Content: Global psychoacoustic constants structures
*******************************************************************************/
#ifndef _PSYCONST_H
#define _PSYCONST_H
#include "config.h"
#define TRUE 1
#define FALSE 0
#define FRAME_LEN_LONG AACENC_BLOCKSIZE
#define TRANS_FAC 8
#define FRAME_LEN_SHORT (FRAME_LEN_LONG/TRANS_FAC)
/* Block types */
enum
{
LONG_WINDOW = 0,
START_WINDOW,
SHORT_WINDOW,
STOP_WINDOW
};
/* Window shapes */
enum
{
SINE_WINDOW = 0,
KBD_WINDOW = 1
};
/*
MS stuff
*/
enum
{
SI_MS_MASK_NONE = 0,
SI_MS_MASK_SOME = 1,
SI_MS_MASK_ALL = 2
};
#define MAX_NO_OF_GROUPS 4
#define MAX_SFB_SHORT 15 /* 15 for a memory optimized implementation, maybe 16 for convenient debugging */
#define MAX_SFB_LONG 51 /* 51 for a memory optimized implementation, maybe 64 for convenient debugging */
#define MAX_SFB (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = MAX_SFB_LONG */
#define MAX_GROUPED_SFB (MAX_NO_OF_GROUPS*MAX_SFB_SHORT > MAX_SFB_LONG ? \
MAX_NO_OF_GROUPS*MAX_SFB_SHORT : MAX_SFB_LONG)
#define BLOCK_SWITCHING_OFFSET (1*1024+3*128+64+128)
#define BLOCK_SWITCHING_DATA_SIZE FRAME_LEN_LONG
#define TRANSFORM_OFFSET_LONG 0
#define TRANSFORM_OFFSET_SHORT 448
#define LOG_NORM_PCM -15
#define NUM_SAMPLE_RATES 12
#endif /* _PSYCONST_H */

View File

@ -0,0 +1,66 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_data.h
Content: Psychoacoustic data and structures
*******************************************************************************/
#ifndef _PSY_DATA_H
#define _PSY_DATA_H
#include "block_switch.h"
#include "tns.h"
/*
the structs can be implemented as unions
*/
typedef struct{
Word32 sfbLong[MAX_GROUPED_SFB];
Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
}SFB_THRESHOLD; /* Word16 size: 260 */
typedef struct{
Word32 sfbLong[MAX_GROUPED_SFB];
Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
}SFB_ENERGY; /* Word16 size: 260 */
typedef struct{
Word32 sfbLong;
Word32 sfbShort[TRANS_FAC];
}SFB_ENERGY_SUM; /* Word16 size: 18 */
typedef struct{
BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */
Word16 *mdctDelayBuffer; /* mdct delay buffer [BLOCK_SWITCHING_OFFSET]*/
Word32 sfbThresholdnm1[MAX_SFB]; /* PreEchoControl */
Word16 mdctScalenm1; /* scale of last block's mdct (PreEchoControl) */
SFB_THRESHOLD sfbThreshold; /* adapt */
SFB_ENERGY sfbEnergy; /* sfb Energy */
SFB_ENERGY sfbEnergyMS;
SFB_ENERGY_SUM sfbEnergySum;
SFB_ENERGY_SUM sfbEnergySumMS;
SFB_ENERGY sfbSpreadedEnergy;
Word32 *mdctSpectrum; /* mdct spectrum [FRAME_LEN_LONG] */
Word16 mdctScale; /* scale of mdct */
}PSY_DATA; /* Word16 size: 4 + 87 + 102 + 360 + 360 + 360 + 18 + 18 + 360 = 1669 */
#endif /* _PSY_DATA_H */

View File

@ -0,0 +1,69 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_main.h
Content: Psychoacoustic major function block
*******************************************************************************/
#ifndef _PSYMAIN_H
#define _PSYMAIN_H
#include "psy_configuration.h"
#include "qc_data.h"
#include "memalign.h"
/*
psy kernel
*/
typedef struct {
PSY_CONFIGURATION_LONG psyConfLong; /* Word16 size: 515 */
PSY_CONFIGURATION_SHORT psyConfShort; /* Word16 size: 167 */
PSY_DATA psyData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*1669*/
TNS_DATA tnsData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*235 */
Word32* pScratchTns;
Word16 sampleRateIdx;
}PSY_KERNEL; /* Word16 size: 2587 / 4491 */
Word16 PsyNew( PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP);
Word16 PsyDelete( PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP);
Word16 PsyOutNew( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
Word16 PsyOutDelete( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
Word16 psyMainInit( PSY_KERNEL *hPsy,
Word32 sampleRate,
Word32 bitRate,
Word16 channels,
Word16 tnsMask,
Word16 bandwidth);
Word16 psyMain(Word16 nChannels, /*!< total number of channels */
ELEMENT_INFO *elemInfo,
Word16 *timeSignal, /*!< interleaved time signal */
PSY_DATA psyData[MAX_CHANNELS],
TNS_DATA tnsData[MAX_CHANNELS],
PSY_CONFIGURATION_LONG* psyConfLong,
PSY_CONFIGURATION_SHORT* psyConfShort,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
PSY_OUT_ELEMENT *psyOutElement,
Word32 *pScratchTns,
Word32 sampleRate);
#endif /* _PSYMAIN_H */

View File

@ -0,0 +1,143 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: qc_data.h
Content: Quantizing & coding structures
*******************************************************************************/
#ifndef _QC_DATA_H
#define _QC_DATA_H
#include "psy_const.h"
#include "dyn_bits.h"
#include "adj_thr_data.h"
#define MAX_MODES 10
typedef enum {
MODE_INVALID = 0,
MODE_1, /* mono */
MODE_1_1, /* dual mono */
MODE_2 /* stereo */
} ENCODER_MODE;
typedef enum {
ID_SCE=0, /* Single Channel Element */
ID_CPE=1, /* Channel Pair Element */
ID_CCE=2, /* Coupling Channel Element */
ID_LFE=3, /* LFE Channel Element */
ID_DSE=4, /* current one DSE element for ancillary is supported */
ID_PCE=5,
ID_FIL=6,
ID_END=7
}ELEMENT_TYPE;
typedef struct {
ELEMENT_TYPE elType;
Word16 instanceTag;
Word16 nChannelsInEl;
Word16 ChannelIndex[MAX_CHANNELS];
} ELEMENT_INFO;
typedef struct {
Word32 paddingRest;
} PADDING;
/* Quantizing & coding stage */
struct QC_INIT{
ELEMENT_INFO *elInfo;
Word16 maxBits; /* maximum number of bits in reservoir */
Word16 averageBits; /* average number of bits we should use */
Word16 bitRes;
Word16 meanPe;
Word32 chBitrate;
Word16 maxBitFac;
Word32 bitrate;
PADDING padding;
};
typedef struct
{
Word16 *quantSpec; /* [FRAME_LEN_LONG]; */
UWord16 *maxValueInSfb; /* [MAX_GROUPED_SFB]; */
Word16 *scf; /* [MAX_GROUPED_SFB]; */
Word16 globalGain;
Word16 mdctScale;
Word16 groupingMask;
SECTION_DATA sectionData;
Word16 windowShape;
} QC_OUT_CHANNEL;
typedef struct
{
Word16 adtsUsed;
Word16 staticBitsUsed; /* for verification purposes */
Word16 dynBitsUsed; /* for verification purposes */
Word16 pe;
Word16 ancBitsUsed;
Word16 fillBits;
} QC_OUT_ELEMENT;
typedef struct
{
QC_OUT_CHANNEL qcChannel[MAX_CHANNELS];
QC_OUT_ELEMENT qcElement;
Word16 totStaticBitsUsed; /* for verification purposes */
Word16 totDynBitsUsed; /* for verification purposes */
Word16 totAncBitsUsed; /* for verification purposes */
Word16 totFillBits;
Word16 alignBits;
Word16 bitResTot;
Word16 averageBitsTot;
} QC_OUT;
typedef struct {
Word32 chBitrate;
Word16 averageBits; /* brutto -> look ancillary.h */
Word16 maxBits;
Word16 bitResLevel;
Word16 maxBitResBits;
Word16 relativeBits; /* Bits relative to total Bits scaled down by 2 */
} ELEMENT_BITS;
typedef struct
{
/* this is basically struct QC_INIT */
Word16 averageBitsTot;
Word16 maxBitsTot;
Word16 globStatBits;
Word16 nChannels;
Word16 bitResTot;
Word16 maxBitFac;
PADDING padding;
ELEMENT_BITS elementBits;
ADJ_THR_STATE adjThr;
Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB];
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB];
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB];
} QC_STATE;
#endif /* _QC_DATA_H */

View File

@ -0,0 +1,64 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: qc_main.h
Content: Quantizing & coding functions
*******************************************************************************/
#ifndef _QC_MAIN_H
#define _QC_MAIN_H
#include "qc_data.h"
#include "interface.h"
#include "memalign.h"
/* Quantizing & coding stage */
Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP);
void QCOutDelete(QC_OUT *hQC, VO_MEM_OPERATOR *pMemOP);
Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
Word16 QCInit(QC_STATE *hQC,
struct QC_INIT *init);
void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
Word16 QCMain(QC_STATE *hQC,
ELEMENT_BITS* elBits,
ATS_ELEMENT* adjThrStateElement,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */
PSY_OUT_ELEMENT* psyOutElement,
QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */
QC_OUT_ELEMENT* qcOutElement,
Word16 nChannels,
Word16 ancillaryDataBytes); /* returns error code */
void updateBitres(QC_STATE* qcKernel,
QC_OUT* qcOut);
Word16 FinalizeBitConsumption(QC_STATE *hQC,
QC_OUT* qcOut);
Word16 AdjustBitrate(QC_STATE *hQC,
Word32 bitRate,
Word32 sampleRate);
#endif /* _QC_MAIN_H */

View File

@ -0,0 +1,42 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: quantize.h
Content: Quantization functions
*******************************************************************************/
#ifndef _QUANTIZE_H_
#define _QUANTIZE_H_
#include "typedefs.h"
/* quantizing */
#define MAX_QUANT 8191
void QuantizeSpectrum(Word16 sfbCnt,
Word16 maxSfbPerGroup,
Word16 sfbPerGroup,
Word16 *sfbOffset, Word32 *mdctSpectrum,
Word16 globalGain, Word16 *scalefactors,
Word16 *quantizedSpectrum);
Word32 calcSfbDist(const Word32 *spec,
Word16 sfbWidth,
Word16 gain);
#endif /* _QUANTIZE_H_ */

View File

@ -0,0 +1,46 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: sf_estim.h
Content: Scale factor estimation functions
*******************************************************************************/
#ifndef __SF_ESTIM_H__
#define __SF_ESTIM_H__
/*
Scale factor estimation
*/
#include "psy_const.h"
#include "interface.h"
#include "qc_data.h"
void
CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
const Word16 nChannels);
void
EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
const Word16 nChannels);
#endif

View File

@ -0,0 +1,33 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: spreading.h
Content: Spreading of energy functions
*******************************************************************************/
#ifndef _SPREADING_H
#define _SPREADING_H
#include "typedefs.h"
void SpreadingMax(const Word16 pbCnt,
const Word16 *maskLowFactor,
const Word16 *maskHighFactor,
Word32 *pbSpreadedEnergy);
#endif /* #ifndef _SPREADING_H */

View File

@ -0,0 +1,34 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: stat_bits.h
Content: Static bit counter functions
*******************************************************************************/
#ifndef __STAT_BITS_H
#define __STAT_BITS_H
#include "psy_const.h"
#include "interface.h"
Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
PSY_OUT_ELEMENT *psyOutElement,
Word16 nChannels,
Word16 adtsUsed);
#endif /* __STAT_BITS_H */

View File

@ -0,0 +1,108 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: tns.h
Content: TNS structures
*******************************************************************************/
#ifndef _TNS_H
#define _TNS_H
#include "typedef.h"
#include "psy_const.h"
#define TNS_MAX_ORDER 12
#define TNS_MAX_ORDER_SHORT 5
#define FILTER_DIRECTION 0
typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */
Word16 threshOn; /* min. prediction gain for using tns TABUL * 100*/
Word32 lpcStartFreq; /* lowest freq for lpc TABUL*/
Word32 lpcStopFreq; /* TABUL */
Word32 tnsTimeResolution;
}TNS_CONFIG_TABULATED;
typedef struct { /*assigned at InitTime*/
Word16 tnsActive;
Word16 tnsMaxSfb;
Word16 maxOrder; /* max. order of tns filter */
Word16 tnsStartFreq; /* lowest freq. for tns filtering */
Word16 coefRes;
TNS_CONFIG_TABULATED confTab;
Word32 acfWindow[TNS_MAX_ORDER+1];
Word16 tnsStartBand;
Word16 tnsStartLine;
Word16 tnsStopBand;
Word16 tnsStopLine;
Word16 lpcStartBand;
Word16 lpcStartLine;
Word16 lpcStopBand;
Word16 lpcStopLine;
Word16 tnsRatioPatchLowestCb;
Word16 tnsModifyBeginCb;
Word16 threshold; /* min. prediction gain for using tns TABUL * 100 */
}TNS_CONFIG;
typedef struct {
Word16 tnsActive;
Word32 parcor[TNS_MAX_ORDER];
Word16 predictionGain;
} TNS_SUBBLOCK_INFO; /* Word16 size: 26 */
typedef struct{
TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC];
} TNS_DATA_SHORT;
typedef struct{
TNS_SUBBLOCK_INFO subBlockInfo;
} TNS_DATA_LONG;
typedef struct{
TNS_DATA_LONG tnsLong;
TNS_DATA_SHORT tnsShort;
}TNS_DATA_RAW;
typedef struct{
Word16 numOfSubblocks;
TNS_DATA_RAW dataRaw;
}TNS_DATA; /* Word16 size: 1 + 8*26 + 26 = 235 */
typedef struct{
Word16 tnsActive[TRANS_FAC];
Word16 coefRes[TRANS_FAC];
Word16 length[TRANS_FAC];
Word16 order[TRANS_FAC];
Word16 coef[TRANS_FAC*TNS_MAX_ORDER_SHORT];
}TNS_INFO; /* Word16 size: 72 */
#endif /* _TNS_H */

View File

@ -0,0 +1,75 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: tns_func.h
Content: TNS functions
*******************************************************************************/
/*
Temporal noise shaping
*/
#ifndef _TNS_FUNC_H
#define _TNS_FUNC_H
#include "typedef.h"
#include "psy_configuration.h"
Word16 InitTnsConfigurationLong(Word32 bitrate,
Word32 samplerate,
Word16 channels,
TNS_CONFIG *tnsConfig,
PSY_CONFIGURATION_LONG *psyConfig,
Word16 active);
Word16 InitTnsConfigurationShort(Word32 bitrate,
Word32 samplerate,
Word16 channels,
TNS_CONFIG *tnsConfig,
PSY_CONFIGURATION_SHORT *psyConfig,
Word16 active);
Word32 TnsDetect(TNS_DATA* tnsData,
TNS_CONFIG tC,
Word32* pScratchTns,
const Word16 sfbOffset[],
Word32* spectrum,
Word16 subBlockNumber,
Word16 blockType,
Word32 * sfbEnergy);
void TnsSync(TNS_DATA *tnsDataDest,
const TNS_DATA *tnsDataSrc,
const TNS_CONFIG tC,
const Word16 subBlockNumber,
const Word16 blockType);
Word16 TnsEncode(TNS_INFO* tnsInfo,
TNS_DATA* tnsData,
Word16 numOfSfb,
TNS_CONFIG tC,
Word16 lowPassLine,
Word32* spectrum,
Word16 subBlockNumber,
Word16 blockType);
void ApplyTnsMultTableToRatios(Word16 startCb,
Word16 stopCb,
TNS_SUBBLOCK_INFO subInfo,
Word32 *thresholds);
#endif /* _TNS_FUNC_H */

View File

@ -0,0 +1,52 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: tns_param.h
Content: TNS parameters
*******************************************************************************/
/*
TNS parameters
*/
#ifndef _TNS_PARAM_H
#define _TNS_PARAM_H
#include "tns.h"
typedef struct{
Word32 samplingRate;
Word16 maxBandLong;
Word16 maxBandShort;
}TNS_MAX_TAB_ENTRY;
typedef struct{
Word32 bitRateFrom;
Word32 bitRateTo;
const TNS_CONFIG_TABULATED *paramMono_Long; /* contains TNS parameters */
const TNS_CONFIG_TABULATED *paramMono_Short;
const TNS_CONFIG_TABULATED *paramStereo_Long;
const TNS_CONFIG_TABULATED *paramStereo_Short;
}TNS_INFO_TAB;
void GetTnsParam(TNS_CONFIG_TABULATED *tnsConfigTab,
Word32 bitRate, Word16 channels, Word16 blockType);
void GetTnsMaxBands(Word32 samplingRate, Word16 blockType, Word16* tnsMaxSfb);
#endif /* _TNS_PARAM_H */

View File

@ -0,0 +1,36 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: transform.h
Content: MDCT Transform functions
*******************************************************************************/
#ifndef __TRANSFORM_H__
#define __TRANSFORM_H__
#include "typedef.h"
void Transform_Real(Word16 *mdctDelayBuffer,
Word16 *timeSignal,
Word16 chIncrement, /*! channel increment */
Word32 *realOut,
Word16 *mdctScale,
Word16 windowSequence
);
#endif

View File

@ -0,0 +1,9 @@
THIS IS NOT A GRANT OF PATENT RIGHTS.
Google makes no representation or warranty that the codecs for which
source code is made available hereunder are unencumbered by
third-party patents. Those intending to use this source code in
hardware or software products are advised that implementations of
these codecs, including in open source software or shareware, may
require patent licenses from the relevant patent holders.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,495 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: aacenc.c
Content: aac encoder interface functions
*******************************************************************************/
#include "voAAC.h"
#include "typedef.h"
#include "aacenc_core.h"
#include "aac_rom.h"
#include "cmnMemory.h"
#include "memalign.h"
/**
* Init the audio codec module and return codec handle
* \param phCodec [OUT] Return the video codec handle
* \param vType [IN] The codec type if the module support multi codec.
* \param pUserData [IN] The init param. It is memory operator or alloced memory
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
{
AAC_ENCODER*hAacEnc;
AACENC_CONFIG config;
int error;
#ifdef USE_DEAULT_MEM
VO_MEM_OPERATOR voMemoprator;
#endif
VO_MEM_OPERATOR *pMemOP;
int interMem;
interMem = 0;
error = 0;
/* init the memory operator */
if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
{
#ifdef USE_DEAULT_MEM
voMemoprator.Alloc = cmnMemAlloc;
voMemoprator.Copy = cmnMemCopy;
voMemoprator.Free = cmnMemFree;
voMemoprator.Set = cmnMemSet;
voMemoprator.Check = cmnMemCheck;
interMem = 1;
pMemOP = &voMemoprator;
#else
*phCodec = NULL;
return VO_ERR_INVALID_ARG;
#endif
}
else
{
pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
}
/* init the aac encoder handle */
hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
if(NULL == hAacEnc)
{
error = 1;
}
if(!error)
{
/* init the aac encoder intra memory */
hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
if(NULL == hAacEnc->intbuf)
{
error = 1;
}
}
if (!error) {
/* init the aac encoder psychoacoustic */
error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
PsyOutNew(&hAacEnc->psyOut, pMemOP));
}
if (!error) {
/* init the aac encoder quantization elements */
error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
}
if (!error) {
/* init the aac encoder quantization state */
error = QCNew(&hAacEnc->qcKernel, pMemOP);
}
/* uninit the aac encoder if error is nozero */
if(error)
{
AacEncClose(hAacEnc, pMemOP);
if(hAacEnc)
{
mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
hAacEnc = NULL;
}
*phCodec = NULL;
return VO_ERR_OUTOF_MEMORY;
}
/* init the aac encoder memory operator */
#ifdef USE_DEAULT_MEM
if(interMem)
{
hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
hAacEnc->voMemoprator.Copy = cmnMemCopy;
hAacEnc->voMemoprator.Free = cmnMemFree;
hAacEnc->voMemoprator.Set = cmnMemSet;
hAacEnc->voMemoprator.Check = cmnMemCheck;
pMemOP = &hAacEnc->voMemoprator;
}
#endif
/* init the aac encoder default parameter */
if(hAacEnc->initOK == 0)
{
AACENC_CONFIG config;
config.adtsUsed = 1;
config.bitRate = 128000;
config.nChannelsIn = 2;
config.nChannelsOut = 2;
config.sampleRate = 44100;
config.bandWidth = 20000;
AacEncOpen(hAacEnc, config);
}
hAacEnc->voMemop = pMemOP;
*phCodec = hAacEnc;
return VO_ERR_NONE;
}
/**
* Set input audio data.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pInput [IN] The input buffer param.
* \param pOutBuffer [OUT] The output buffer info.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
{
AAC_ENCODER *hAacEnc;
int length;
if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
{
return VO_ERR_INVALID_ARG;
}
hAacEnc = (AAC_ENCODER *)hCodec;
/* init input pcm buffer and length*/
hAacEnc->inbuf = (short *)pInput->Buffer;
hAacEnc->inlen = pInput->Length / sizeof(short);
hAacEnc->uselength = 0;
hAacEnc->encbuf = hAacEnc->inbuf;
hAacEnc->enclen = hAacEnc->inlen;
/* rebuild intra pcm buffer and length*/
if(hAacEnc->intlen)
{
length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
hAacEnc->inbuf, length*sizeof(short));
hAacEnc->encbuf = hAacEnc->intbuf;
hAacEnc->enclen = hAacEnc->intlen + length;
hAacEnc->inbuf += length;
hAacEnc->inlen -= length;
}
return VO_ERR_NONE;
}
/**
* Get the outut audio data
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pOutBuffer [OUT] The output audio data
* \param pOutInfo [OUT] The dec module filled audio format and used the input size.
* pOutInfo->InputUsed is total used the input size.
* \retval VO_ERR_NONE Succeeded.
* VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
*/
VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
{
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
Word16 numAncDataBytes=0;
Word32 inbuflen;
int ret, length;
if(NULL == hAacEnc)
return VO_ERR_INVALID_ARG;
inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;
/* check the input pcm buffer and length*/
if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
{
length = hAacEnc->enclen;
if(hAacEnc->intlen == 0)
{
hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
hAacEnc->encbuf, length*sizeof(short));
hAacEnc->uselength += length*sizeof(short);
}
else
{
hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
}
hAacEnc->intlen = length;
pOutput->Length = 0;
if(pOutInfo)
pOutInfo->InputUsed = hAacEnc->uselength;
return VO_ERR_INPUT_BUFFER_SMALL;
}
/* check the output aac buffer and length*/
if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
return VO_ERR_OUTPUT_BUFFER_SMALL;
/* aac encoder core function */
AacEncEncode( hAacEnc,
(Word16*)hAacEnc->encbuf,
NULL,
&numAncDataBytes,
pOutput->Buffer,
&pOutput->Length);
/* update the input pcm buffer and length*/
if(hAacEnc->intlen)
{
length = inbuflen - hAacEnc->intlen;
hAacEnc->encbuf = hAacEnc->inbuf;
hAacEnc->enclen = hAacEnc->inlen;
hAacEnc->uselength += length*sizeof(short);
hAacEnc->intlen = 0;
}
else
{
hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
hAacEnc->enclen = hAacEnc->enclen - inbuflen;
hAacEnc->uselength += inbuflen*sizeof(short);
}
/* update the output aac information */
if(pOutInfo)
{
pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
pOutInfo->Format.SampleBits = 16;
pOutInfo->InputUsed = hAacEnc->uselength;
}
return VO_ERR_NONE;
}
/**
* Uninit the Codec.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
{
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
if(NULL != hAacEnc)
{
/* close the aac encoder */
AacEncClose(hAacEnc, hAacEnc->voMemop);
/* free the aac encoder handle*/
mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
hAacEnc = NULL;
}
return VO_ERR_NONE;
}
/**
* Set the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
AACENC_CONFIG config;
AACENC_PARAM* pAAC_param;
VO_AUDIO_FORMAT *pWAV_Format;
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
int ret, i, bitrate, tmp;
int SampleRateIdx;
if(NULL == hAacEnc)
return VO_ERR_INVALID_ARG;
switch(uParamID)
{
case VO_PID_AAC_ENCPARAM: /* init aac encoder parameter*/
AacInitDefaultConfig(&config);
if(pData == NULL)
return VO_ERR_INVALID_ARG;
pAAC_param = (AACENC_PARAM*)pData;
config.adtsUsed = pAAC_param->adtsUsed;
config.bitRate = pAAC_param->bitRate;
config.nChannelsIn = pAAC_param->nChannels;
config.nChannelsOut = pAAC_param->nChannels;
config.sampleRate = pAAC_param->sampleRate;
/* check the channel */
if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
return VO_ERR_AUDIO_UNSCHANNEL;
/* check the samplerate */
ret = -1;
for(i = 0; i < NUM_SAMPLE_RATES; i++)
{
if(config.sampleRate == sampRateTab[i])
{
ret = 0;
break;
}
}
if(ret < 0)
return VO_ERR_AUDIO_UNSSAMPLERATE;
SampleRateIdx = i;
tmp = 441;
if(config.sampleRate%8000 == 0)
tmp =480;
/* check the bitrate */
if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) ||
(config.bitRate/config.nChannelsOut > 160000) ||
(config.bitRate > config.sampleRate*6*config.nChannelsOut))
{
config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
if(config.bitRate/config.nChannelsOut < 4000)
config.bitRate = 4000 * config.nChannelsOut;
else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
config.bitRate = config.sampleRate*6*config.nChannelsOut;
else if(config.bitRate/config.nChannelsOut > 160000)
config.bitRate = config.nChannelsOut*160000;
}
/* check the bandwidth */
bitrate = config.bitRate / config.nChannelsOut;
bitrate = bitrate * tmp / config.sampleRate;
for (i = 0; rates[i]; i++)
{
if (rates[i] >= bitrate)
break;
}
config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
/* init aac encoder core */
ret = AacEncOpen(hAacEnc, config);
if(ret)
return VO_ERR_AUDIO_UNSFEATURE;
break;
case VO_PID_AUDIO_FORMAT: /* init pcm channel and samplerate*/
AacInitDefaultConfig(&config);
if(pData == NULL)
return VO_ERR_INVALID_ARG;
pWAV_Format = (VO_AUDIO_FORMAT*)pData;
config.adtsUsed = 1;
config.nChannelsIn = pWAV_Format->Channels;
config.nChannelsOut = pWAV_Format->Channels;
config.sampleRate = pWAV_Format->SampleRate;
/* check the channel */
if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
return VO_ERR_AUDIO_UNSCHANNEL;
/* check the samplebits */
if(pWAV_Format->SampleBits != 16)
{
return VO_ERR_AUDIO_UNSFEATURE;
}
/* check the samplerate */
ret = -1;
for(i = 0; i < NUM_SAMPLE_RATES; i++)
{
if(config.sampleRate == sampRateTab[i])
{
ret = 0;
break;
}
}
if(ret < 0)
return VO_ERR_AUDIO_UNSSAMPLERATE;
SampleRateIdx = i;
/* update the bitrates */
tmp = 441;
if(config.sampleRate%8000 == 0)
tmp =480;
config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
if(config.bitRate/config.nChannelsOut < 4000)
config.bitRate = 4000 * config.nChannelsOut;
else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
config.bitRate = config.sampleRate*6*config.nChannelsOut;
else if(config.bitRate/config.nChannelsOut > 160000)
config.bitRate = config.nChannelsOut*160000;
/* check the bandwidth */
bitrate = config.bitRate / config.nChannelsOut;
bitrate = bitrate * tmp / config.sampleRate;
for (i = 0; rates[i]; i++)
{
if (rates[i] >= bitrate)
break;
}
config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
/* init aac encoder core */
ret = AacEncOpen(hAacEnc, config);
if(ret)
return VO_ERR_AUDIO_UNSFEATURE;
break;
default:
return VO_ERR_WRONG_PARAM_ID;
}
return VO_ERR_NONE;
}
/**
* Get the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
return VO_ERR_NONE;
}
/**
* Get audio codec API interface
* \param pEncHandle [out] Return the AAC Encoder handle.
* \retval VO_ERR_OK Succeeded.
*/
VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
{
if(pDecHandle == NULL)
return VO_ERR_INVALID_ARG;
pDecHandle->Init = voAACEncInit;
pDecHandle->SetInputData = voAACEncSetInputData;
pDecHandle->GetOutputData = voAACEncGetOutputData;
pDecHandle->SetParam = voAACEncSetParam;
pDecHandle->GetParam = voAACEncGetParam;
pDecHandle->Uninit = voAACEncUninit;
return VO_ERR_NONE;
}

View File

@ -0,0 +1,239 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: aacenc_core.c
Content: aac encoder core functions
*******************************************************************************/
#include "typedef.h"
#include "aacenc_core.h"
#include "bitenc.h"
#include "psy_configuration.h"
#include "psy_main.h"
#include "qc_main.h"
#include "psy_main.h"
#include "channel_map.h"
#include "aac_rom.h"
/********************************************************************************
*
* function name: AacInitDefaultConfig
* description: gives reasonable default configuration
*
**********************************************************************************/
void AacInitDefaultConfig(AACENC_CONFIG *config)
{
/* default configurations */
config->adtsUsed = 1;
config->nChannelsIn = 2;
config->nChannelsOut = 2;
config->bitRate = 128000;
config->bandWidth = 0;
}
/********************************************************************************
*
* function name: AacEncOpen
* description: allocate and initialize a new encoder instance
* returns: 0 if success
*
**********************************************************************************/
Word16 AacEncOpen( AAC_ENCODER* hAacEnc, /* pointer to an encoder handle, initialized on return */
const AACENC_CONFIG config /* pre-initialized config struct */
)
{
Word32 i;
Word32 error = 0;
Word16 profile = 1;
ELEMENT_INFO *elInfo = NULL;
if (hAacEnc==0) {
error=1;
}
if (!error) {
hAacEnc->config = config;
}
if (!error) {
error = InitElementInfo (config.nChannelsOut,
&hAacEnc->elInfo);
}
if (!error) {
elInfo = &hAacEnc->elInfo;
}
if (!error) {
/* use or not tns tool for long and short block */
Word16 tnsMask=3;
/* init encoder psychoacoustic */
error = psyMainInit(&hAacEnc->psyKernel,
config.sampleRate,
config.bitRate,
elInfo->nChannelsInEl,
tnsMask,
hAacEnc->config.bandWidth);
}
/* use or not adts header */
if(!error) {
hAacEnc->qcOut.qcElement.adtsUsed = config.adtsUsed;
}
/* init encoder quantization */
if (!error) {
struct QC_INIT qcInit;
/*qcInit.channelMapping = &hAacEnc->channelMapping;*/
qcInit.elInfo = &hAacEnc->elInfo;
qcInit.maxBits = (Word16) (MAXBITS_COEF*elInfo->nChannelsInEl);
qcInit.bitRes = qcInit.maxBits;
qcInit.averageBits = (Word16) ((config.bitRate * FRAME_LEN_LONG) / config.sampleRate);
qcInit.padding.paddingRest = config.sampleRate;
qcInit.meanPe = (Word16) ((10 * FRAME_LEN_LONG * hAacEnc->config.bandWidth) /
(config.sampleRate>>1));
qcInit.maxBitFac = (Word16) ((100 * (MAXBITS_COEF-MINBITS_COEF)* elInfo->nChannelsInEl)/
(qcInit.averageBits?qcInit.averageBits:1));
qcInit.bitrate = config.bitRate;
error = QCInit(&hAacEnc->qcKernel, &qcInit);
}
/* init bitstream encoder */
if (!error) {
hAacEnc->bseInit.nChannels = elInfo->nChannelsInEl;
hAacEnc->bseInit.bitrate = config.bitRate;
hAacEnc->bseInit.sampleRate = config.sampleRate;
hAacEnc->bseInit.profile = profile;
}
return error;
}
/********************************************************************************
*
* function name: AacEncEncode
* description: encode pcm to aac data core function
* returns: 0 if success
*
**********************************************************************************/
Word16 AacEncEncode(AAC_ENCODER *aacEnc, /*!< an encoder handle */
Word16 *timeSignal, /*!< BLOCKSIZE*nChannels audio samples, interleaved */
const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */
Word16 *numAncBytes, /*!< number of ancillary Data Bytes */
UWord8 *outBytes, /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */
Word32 *numOutBytes /*!< number of bytes in output buffer after processing */
)
{
ELEMENT_INFO *elInfo = &aacEnc->elInfo;
Word16 globUsedBits;
Word16 ancDataBytes, ancDataBytesLeft;
ancDataBytes = ancDataBytesLeft = *numAncBytes;
/* init output aac data buffer and length */
aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream, outBytes, *numOutBytes);
/* psychoacoustic process */
psyMain(aacEnc->config.nChannelsOut,
elInfo,
timeSignal,
&aacEnc->psyKernel.psyData[elInfo->ChannelIndex[0]],
&aacEnc->psyKernel.tnsData[elInfo->ChannelIndex[0]],
&aacEnc->psyKernel.psyConfLong,
&aacEnc->psyKernel.psyConfShort,
&aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
&aacEnc->psyOut.psyOutElement,
aacEnc->psyKernel.pScratchTns,
aacEnc->config.sampleRate);
/* adjust bitrate and frame length */
AdjustBitrate(&aacEnc->qcKernel,
aacEnc->config.bitRate,
aacEnc->config.sampleRate);
/* quantization and coding process */
QCMain(&aacEnc->qcKernel,
&aacEnc->qcKernel.elementBits,
&aacEnc->qcKernel.adjThr.adjThrStateElem,
&aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
&aacEnc->psyOut.psyOutElement,
&aacEnc->qcOut.qcChannel[elInfo->ChannelIndex[0]],
&aacEnc->qcOut.qcElement,
elInfo->nChannelsInEl,
min(ancDataBytesLeft,ancDataBytes));
ancDataBytesLeft = ancDataBytesLeft - ancDataBytes;
globUsedBits = FinalizeBitConsumption(&aacEnc->qcKernel,
&aacEnc->qcOut);
/* write bitstream process */
WriteBitstream(aacEnc->hBitStream,
*elInfo,
&aacEnc->qcOut,
&aacEnc->psyOut,
&globUsedBits,
ancBytes,
aacEnc->psyKernel.sampleRateIdx);
updateBitres(&aacEnc->qcKernel,
&aacEnc->qcOut);
/* write out the bitstream */
*numOutBytes = GetBitsAvail(aacEnc->hBitStream) >> 3;
return 0;
}
/********************************************************************************
*
* function name:AacEncClose
* description: deallocate an encoder instance
*
**********************************************************************************/
void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP)
{
if (hAacEnc) {
QCDelete(&hAacEnc->qcKernel, pMemOP);
QCOutDelete(&hAacEnc->qcOut, pMemOP);
PsyDelete(&hAacEnc->psyKernel, pMemOP);
PsyOutDelete(&hAacEnc->psyOut, pMemOP);
DeleteBitBuffer(&hAacEnc->hBitStream);
if(hAacEnc->intbuf)
{
mem_free(pMemOP, hAacEnc->intbuf, VO_INDEX_ENC_AAC);
hAacEnc->intbuf = NULL;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,167 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: AutoCorrelation_v5.s
@
@ Content: AutoCorrelation function armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global AutoCorrelation
AutoCorrelation:
stmdb sp!, {r4 - r11, lr}
sub r13, r13, #20
mov r5, r0
mov r7, r1
mov r9, r3
mov r2, r2, lsl #16
mov r0, #0
mov r4, r2, asr #16
mov r8, #0
cmp r4, #0
ble L136
cmp r4, #8
mov r2, #0
blt L133
sub r12, r4, #8
L132:
ldr r6, [r5, r2]
add r2, r2, #4
smulbb r3, r6, r6
ldr r1, [r5, r2]
smultt r10, r6, r6
mov r3, r3, asr #9
smulbb r6, r1, r1
mov r10, r10, asr #9
qadd r0, r0, r3
smultt r11, r1, r1
add r2, r2, #4
qadd r0, r0, r10
mov r6, r6, asr #9
mov r11, r11, asr #9
ldr r1, [r5, r2]
qadd r0, r0, r6
smulbb r10, r1, r1
smultt r6, r1, r1
qadd r0, r0, r11
mov r10, r10, asr #9
mov r6, r6, asr #9
qadd r0, r0, r10
add r2, r2, #4
add r8, r8, #6
qadd r0, r0, r6
cmp r8, r12
blt L132
L133:
ldrsh r6, [r5, r2]
mul r10, r6, r6
add r2, r2, #2
mov r1, r10, asr #9
qadd r0, r0, r1
L134:
add r8, r8, #1
cmp r8, r4
blt L133
L135:
L136:
str r0, [r7, #0]
cmp r0, #0
beq L1320
L137:
mov r2, r9, lsl #16
mov r8, #1
mov r2, r2, asr #16
cmp r2, #1
ble L1319
L138:
L139:
sub r4, r4, #1
mov r14, #0
mov r3, #0
cmp r4, #0
ble L1317
L1310:
cmp r4, #6
addlt r6, r5, r8, lsl #1
blt L1314
L1311:
add r6, r5, r8, lsl #1
sub r12, r4, #6
str r8, [r13, #8]
str r7, [r13, #4]
L1312:
mov r1, r3, lsl #1
ldrsh r7, [r6, r1]
ldrsh r10, [r5, r1]
add r8, r1, r6
add r9, r5, r1
mul r7, r10, r7
ldrsh r1, [r8, #2]
ldrsh r10, [r8, #4]
add r7, r14, r7, asr #9
ldrsh r0, [r9, #2]
ldrsh r11, [r9, #4]
mul r1, r0, r1
ldrsh r14, [r8, #6]
mul r10, r11, r10
add r7, r7, r1, asr #9
ldrsh r8, [r8, #8]
add r3, r3, #5
ldrsh r11, [r9, #6]
ldrsh r1, [r9, #8]
mul r14, r11, r14
add r7, r7, r10, asr #9
mul r1, r1, r8
add r14, r7, r14, asr #9
cmp r3, r12
add r14, r14, r1, asr #9
ble L1312
L1313:
ldr r8, [r13, #8]
ldr r7, [r13, #4]
L1314:
L1315:
mov r12, r3, lsl #1
ldrsh r9, [r6, r12]
ldrsh r12, [r5, r12]
add r3, r3, #1
cmp r3, r4
mul r12, r12, r9
add r14, r14, r12, asr #9
blt L1315
L1316:
L1317:
str r14, [r7, +r8, lsl #2]
add r8, r8, #1
cmp r8, r2
blt L139
L1319:
L1320:
add r13, r13, #20
ldmia sp!, {r4 - r11, pc}
@ENDP @ |AutoCorrelation|
.end

View File

@ -0,0 +1,112 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: CalcWindowEnergy_v5.s
@
@ Content: CalcWindowEnergy function armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global CalcWindowEnergy
CalcWindowEnergy:
stmdb sp!, {r4 - r11, lr}
sub r13, r13, #20
mov r3, r3, lsl #16
ldr r10, [r0, #168] @ states0 = blockSwitchingControl->iirStates[0];
mov r3, r3, asr #16
ldr r11, [r0, #172] @ states1 = blockSwitchingControl->iirStates[1];
mov r2, r2, lsl #16
ldr r12, hiPassCoeff @ Coeff0 = hiPassCoeff[0];
mov r2, r2, asr #16
ldr r14, hiPassCoeff + 4 @ Coeff1 = hiPassCoeff[1];
mov r8, #0 @ w=0
mov r5, #0 @ wOffset = 0;
BLOCK_BEGIN:
mov r6, #0 @ accuUE = 0;
mov r7, #0 @ accuFE = 0;
mov r4, #0 @ i=0
str r8, [r13, #4]
str r0, [r13, #8]
str r3, [r13, #12]
ENERGY_BEG:
mov r9, r5, lsl #1
ldrsh r9, [r1, r9] @ tempUnfiltered = timeSignal[tidx];
add r5, r5, r2 @ tidx = tidx + chIncrement;
smulwb r3, r14, r9 @ accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
smull r0, r8, r12, r11 @ accu2 = fixmul( Coeff0, states1 );
mov r3, r3, lsl #1
mov r8, r8, lsl #1
sub r0, r3, r10 @ accu3 = accu1 - states0;
sub r8, r0, r8 @ out = accu3 - accu2;
mov r10, r3 @ states0 = accu1;
mov r11, r8 @ states1 = out;
mul r3, r9, r9
mov r8, r8, asr #16
add r4, r4, #1
add r6, r6, r3, asr #7
mul r9, r8, r8
ldr r3, [r13, #12]
add r7, r7, r9, asr #7
cmp r4, r3
blt ENERGY_BEG
ldr r0, [r13, #8]
ldr r8, [r13, #4]
ENERGY_END:
add r4, r0, r8, lsl #2
str r6, [r4, #72]
add r8, r8, #1
str r7, [r4, #136]
cmp r8, #8
blt BLOCK_BEGIN
BLOCK_END:
str r10, [r0, #168]
str r11, [r0, #172]
mov r0, #1
add r13, r13, #20
ldmia sp!, {r4 - r11, pc}
hiPassCoeff:
.word 0xbec8b439
.word 0x609d4952
@ENDP
.end

View File

@ -0,0 +1,131 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: PrePostMDCT_v5.s
@
@ Content: premdct and postmdct function armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global PreMDCT
PreMDCT:
stmdb sp!, {r4 - r11, lr}
add r9, r0, r1, lsl #2
sub r3, r9, #8
movs r1, r1, asr #2
beq PreMDCT_END
PreMDCT_LOOP:
ldr r8, [r2], #4
ldr r9, [r2], #4
ldrd r4, [r0]
ldrd r6, [r3]
smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa)
smull r10, r12, r7, r8 @ MULHIGH(ti1, cosa)
smull r14, r8, r7, r9 @ MULHIGH(ti1, sina)
smull r7, r10, r4, r9 @ MULHIGH(tr1, sina)
add r11, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
sub r7, r12, r10 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)
ldr r8, [r2], #4
ldr r9, [r2], #4
smull r14, r4, r6, r8 @ MULHIGH(tr2, cosa)
smull r10, r12, r5, r8 @ MULHIGH(ti2, cosa)
smull r14, r8, r5, r9 @ MULHIGH(ti2, sina)
smull r5, r10, r6, r9 @ MULHIGH(tr2, sina)
add r8, r8, r4
sub r9, r12, r10
mov r6, r11
strd r6, [r0]
strd r8, [r3]
subs r1, r1, #1
sub r3, r3, #8
add r0, r0, #8
bne PreMDCT_LOOP
PreMDCT_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |PreMDCT|
.section .text
.global PostMDCT
PostMDCT:
stmdb sp!, {r4 - r11, lr}
add r9, r0, r1, lsl #2
sub r3, r9, #8
movs r1, r1, asr #2
beq PostMDCT_END
PostMDCT_LOOP:
ldr r8, [r2], #4
ldr r9, [r2], #4
ldrd r4, [r0]
ldrd r6, [r3]
smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa)
smull r10, r12, r5, r8 @ MULHIGH(ti1, cosa)
smull r14, r8, r5, r9 @ MULHIGH(ti1, sina)
smull r5, r10, r4, r9 @ MULHIGH(tr1, sina)
add r4, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
sub r11, r10, r12 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)@
ldr r8, [r2], #4 @
ldr r9, [r2], #4
smull r14, r5, r6, r8 @ MULHIGH(tr2, cosa)
smull r10, r12, r7, r8 @ MULHIGH(ti2, cosa)
smull r14, r8, r7, r9 @ MULHIGH(ti2, sina)
smull r7, r10, r6, r9 @ MULHIGH(tr2, sina)
add r6, r8, r5 @ MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2)@
sub r5, r10, r12 @ MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2)@
mov r7, r11
strd r4, [r0]
strd r6, [r3]
subs r1, r1, #1
sub r3, r3, #8
add r0, r0, #8
bne PostMDCT_LOOP
PostMDCT_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |PostMDCT|
.end

View File

@ -0,0 +1,252 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: R4R8First_v5.s
@
@ Content: Radix8First and Radix4First function armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global Radix4First
Radix4First:
stmdb sp!, {r4 - r11, lr}
movs r10, r1
mov r11, r0
beq Radix4First_END
Radix4First_LOOP:
ldrd r0, [r11]
ldrd r2, [r11, #8]
ldrd r4, [r11, #16]
ldrd r6, [r11, #24]
add r8, r0, r2
add r9, r1, r3
sub r0, r0, r2
sub r1, r1, r3
add r2, r4, r6
add r3, r5, r7
sub r4, r4, r6
sub r5, r5, r7
add r6, r8, r2
add r7, r9, r3
sub r8, r8, r2
sub r9, r9, r3
add r2, r0, r5
sub r3, r1, r4
sub r0, r0, r5
add r1, r1, r4
strd r6, [r11]
strd r2, [r11, #8]
strd r8, [r11, #16]
strd r0, [r11, #24]
subs r10, r10, #1
add r11, r11, #32
bne Radix4First_LOOP
Radix4First_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |Radix4First|
.section .text
.global Radix8First
Radix8First:
stmdb sp!, {r4 - r11, lr}
sub sp, sp, #0x24
mov r12, r1
mov r14, r0
cmp r12, #0
beq Radix8First_END
Radix8First_LOOP:
ldrd r0, [r14]
ldrd r2, [r14, #8]
ldrd r4, [r14, #16]
ldrd r6, [r14, #24]
add r8, r0, r2 @ r0 = buf[0] + buf[2]@
add r9, r1, r3 @ i0 = buf[1] + buf[3]@
sub r0, r0, r2 @ r1 = buf[0] - buf[2]@
sub r1, r1, r3 @ i1 = buf[1] - buf[3]@
add r2, r4, r6 @ r2 = buf[4] + buf[6]@
add r3, r5, r7 @ i2 = buf[5] + buf[7]@
sub r4, r4, r6 @ r3 = buf[4] - buf[6]@
sub r5, r5, r7 @ i3 = buf[5] - buf[7]@
add r6, r8, r2 @ r4 = (r0 + r2) >> 1@
add r7, r9, r3 @ i4 = (i0 + i2) >> 1@
sub r8, r8, r2 @ r5 = (r0 - r2) >> 1@
sub r9, r9, r3 @ i5 = (i0 - i2) >> 1@
sub r2, r0, r5 @ r6 = (r1 - i3) >> 1@
add r3, r1, r4 @ i6 = (i1 + r3) >> 1@
add r0, r0, r5 @ r7 = (r1 + i3) >> 1@
sub r1, r1, r4 @ i7 = (i1 - r3) >> 1@
mov r6, r6, asr #1 @
mov r7, r7, asr #1 @
mov r8, r8, asr #1
mov r9, r9, asr #1
mov r2, r2, asr #1
mov r3, r3, asr #1
mov r0, r0, asr #1
mov r1, r1, asr #1
str r6, [sp]
str r7, [sp, #4]
str r8, [sp, #8]
str r9, [sp, #12]
str r2, [sp, #16]
str r3, [sp, #20]
str r0, [sp, #24]
str r1, [sp, #28]
ldrd r2, [r14, #32]
ldrd r4, [r14, #40]
ldrd r6, [r14, #48]
ldrd r8, [r14, #56]
add r0, r2, r4 @ r0 = buf[ 8] + buf[10]@
add r1, r3, r5 @ i0 = buf[ 9] + buf[11]@
sub r2, r2, r4 @ r1 = buf[ 8] - buf[10]@
sub r3, r3, r5 @ i1 = buf[ 9] - buf[11]@
add r4, r6, r8 @ r2 = buf[12] + buf[14]@
add r5, r7, r9 @ i2 = buf[13] + buf[15]@
sub r6, r6, r8 @ r3 = buf[12] - buf[14]@
sub r7, r7, r9 @ i3 = buf[13] - buf[15]@
add r8, r0, r4 @ t0 = (r0 + r2)
add r9, r1, r5 @ t1 = (i0 + i2)
sub r0, r0, r4 @ t2 = (r0 - r2)
sub r1, r1, r5 @ t3 = (i0 - i2)
mov r8, r8, asr #1
ldr r4, [sp]
mov r9, r9, asr #1
ldr r5, [sp, #4]
mov r0, r0, asr #1
mov r1, r1, asr #1
add r10, r4, r8 @ buf[ 0] = r4 + t0@
add r11, r5, r9 @ buf[ 1] = i4 + t1@
sub r4, r4, r8 @ buf[ 8] = r4 - t0@
sub r5, r5, r9 @ buf[ 9] = i4 - t1@
strd r10, [r14]
strd r4, [r14, #32]
ldr r10, [sp, #8]
ldr r11, [sp, #12]
add r4, r10, r1 @ buf[ 4] = r5 + t3@
sub r5, r11, r0 @ buf[ 5] = i5 - t2@
sub r10, r10, r1 @ buf[12] = r5 - t3@
add r11, r11, r0 @ buf[13] = i5 + t2@
strd r4, [r14, #16]
strd r10, [r14, #48]
sub r0, r2, r7 @ r0 = r1 - i3@
add r1, r3, r6 @ i0 = i1 + r3@
ldr r11, DATATab
add r2, r2, r7 @ r2 = r1 + i3@
sub r3, r3, r6 @ i2 = i1 - r3@
sub r4, r0, r1 @ r0 - i0
add r5, r0, r1 @ r0 + i0
sub r0, r2, r3 @ r2 - i2
add r1, r2, r3 @ r2 + i2
smull r8, r6, r4, r11
smull r9, r7, r5, r11
ldr r2, [sp, #16]
ldr r3, [sp, #20]
smull r8, r4, r0, r11
smull r9, r5, r1, r11
ldr r10, [sp, #24]
ldr r11, [sp, #28]
sub r8, r2, r6
sub r9, r3, r7
add r2, r2, r6
add r3, r3, r7
add r6, r10, r5
sub r7, r11, r4
sub r0, r10, r5
add r1, r11, r4
strd r6, [r14, #8]
strd r8, [r14, #24]
strd r0, [r14, #40]
strd r2, [r14, #56]
subs r12, r12, #1
add r14, r14, #64
bne Radix8First_LOOP
Radix8First_END:
add sp, sp, #0x24
ldmia sp!, {r4 - r11, pc}
DATATab:
.word 0x5a82799a
@ENDP @ |Radix8First|
.end

View File

@ -0,0 +1,169 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: Radix4FFT_v5.s
@
@ Content: Radix4FFT armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global Radix4FFT
Radix4FFT:
stmdb sp!, {r4 - r11, lr}
sub sp, sp, #32
mov r1, r1, asr #2
cmp r1, #0
beq Radix4FFT_END
Radix4FFT_LOOP1:
mov r14, r0 @ xptr = buf@
mov r10, r1 @ i = num@
mov r9, r2, lsl #3 @ step = 2*bgn@
cmp r10, #0
str r0, [sp]
str r1, [sp, #4]
str r2, [sp, #8]
str r3, [sp, #12]
beq Radix4FFT_LOOP1_END
Radix4FFT_LOOP2:
mov r12, r3 @ csptr = twidTab@
mov r11, r2 @ j = bgn
cmp r11, #0
str r10, [sp, #16]
beq Radix4FFT_LOOP2_END
Radix4FFT_LOOP3:
str r11, [sp, #20]
ldrd r0, [r14, #0] @ r0 = xptr[0]@ r1 = xptr[1]@
add r14, r14, r9 @ xptr += step@
ldrd r10, [r14, #0] @ r2 = xptr[0]@ r3 = xptr[1]@
ldr r8, [r12], #4 @ cosxsinx = csptr[0]@
smulwt r4, r10, r8 @ L_mpy_wx(cosx, t0)
smulwt r3, r11, r8 @ L_mpy_wx(cosx, t1)
smlawb r2, r11, r8, r4 @ r2 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
smulwb r5, r10, r8 @ L_mpy_wx(sinx, t0)
mov r10, r0, asr #2 @ t0 = r0 >> 2@
mov r11, r1, asr #2 @ t1 = r1 >> 2@
sub r3, r3, r5 @ r3 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
add r14, r14, r9 @ xptr += step@
sub r0, r10, r2 @ r0 = t0 - r2@
sub r1, r11, r3 @ r1 = t1 - r3@
add r2, r10, r2 @ r2 = t0 + r2@
add r3, r11, r3 @ r3 = t1 + r3@
str r2, [sp, #24]
str r3, [sp, #28]
ldrd r10, [r14, #0] @ r4 = xptr[0]@ r5 = xptr[1]@
ldr r8, [r12], #4 @ cosxsinx = csptr[1]@
smulwt r6, r10, r8 @ L_mpy_wx(cosx, t0)
smulwt r5, r11, r8 @ L_mpy_wx(cosx, t1)
smlawb r4, r11, r8, r6 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
smulwb r7, r10, r8 @ L_mpy_wx(sinx, t0)
add r14, r14, r9 @ xptr += step@
sub r5, r5, r7 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
ldrd r10, [r14] @ r6 = xptr[0]@ r7 = xptr[1]@
ldr r8, [r12], #4 @ cosxsinx = csptr[1]@
smulwt r2, r10, r8 @ L_mpy_wx(cosx, t0)
smulwt r7, r11, r8 @ L_mpy_wx(cosx, t1)
smlawb r6, r11, r8, r2 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
smulwb r3, r10, r8 @ L_mpy_wx(sinx, t0)
mov r10, r4 @ t0 = r4@
mov r11, r5 @ t1 = r5@
sub r7, r7, r3 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
add r4, r10, r6 @ r4 = t0 + r6@
sub r5, r7, r11 @ r5 = r7 - t1@
sub r6, r10, r6 @ r6 = t0 - r6@
add r7, r7, r11 @ r7 = r7 + t1@
ldr r2, [sp, #24]
ldr r3, [sp, #28]
add r10, r0, r5 @ xptr[0] = r0 + r5@
add r11, r1, r6 @ xptr[0] = r1 + r6
strd r10, [r14]
sub r14, r14, r9 @ xptr -= step@
sub r10, r2, r4 @ xptr[0] = r2 - r4@
sub r11, r3, r7 @ xptr[1] = r3 - r7@
strd r10, [r14]
sub r14, r14, r9 @ xptr -= step@
sub r10, r0, r5 @ xptr[0] = r0 - r5@
sub r11, r1, r6 @ xptr[0] = r1 - r6
strd r10, [r14]
sub r14, r14, r9 @ xptr -= step@
add r10, r2, r4 @ xptr[0] = r2 - r4@
add r11, r3, r7 @ xptr[1] = r3 - r7@
strd r10, [r14]
add r14, r14, #8 @ xptr += 2@
ldr r11, [sp, #20]
subs r11, r11, #1
bne Radix4FFT_LOOP3
Radix4FFT_LOOP2_END:
ldr r10, [sp, #16]
ldr r3, [sp, #12]
ldr r2, [sp, #8]
rsb r8, r9, r9, lsl #2
sub r10, r10, #1
add r14, r14, r8
cmp r10, #0
bhi Radix4FFT_LOOP2
Radix4FFT_LOOP1_END:
ldr r0, [sp]
ldr r1, [sp, #4]
add r3, r3, r8, asr #1
mov r2, r2, lsl #2
movs r1, r1, asr #2
bne Radix4FFT_LOOP1
Radix4FFT_END:
add sp, sp, #32
ldmia sp!, {r4 - r11, pc}
@ENDP @ |Radix4FFT|
.end

View File

@ -0,0 +1,204 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: band_nrg_v5.s
@
@ Content: CalcBandEnergy and CalcBandEnergyMS function armv5 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global CalcBandEnergy
CalcBandEnergy:
stmdb sp!, {r4 - r11, lr}
mov r2, r2, lsl #16
ldr r12, [r13, #36]
mov r9, #0
mov r5, r2, asr #16
mov r4, #0
cmp r5, #0
ble L212
L22:
mov r2, r4, lsl #1
ldrsh r10, [r1, r2]
add r11, r1, r2
ldrsh r2, [r11, #2]
mov r14, #0
cmp r10, r2
bge L28
L23:
ldr r11, [r0, +r10, lsl #2]
add r10, r10, #1
ldr r6, [r0, +r10, lsl #2]
smull r11, r7, r11, r11
add r10, r10, #1
smull r6, r8, r6, r6
ldr r11, [r0, +r10, lsl #2]
qadd r14, r14, r7
add r10, r10, #1
smull r11, r7, r11, r11
ldr r6, [r0, +r10, lsl #2]
qadd r14, r14, r8
smull r6, r8, r6, r6
add r10, r10, #1
qadd r14, r14, r7
cmp r10, r2
qadd r14, r14, r8
blt L23
L28:
qadd r14, r14, r14
str r14, [r3, +r4, lsl #2]
add r4, r4, #1
qadd r9, r9, r14
cmp r4, r5
blt L22
L212:
str r9, [r12, #0]
ldmia sp!, {r4 - r11, pc}
@ENDP ; |CalcBandEnergy|
.global CalcBandEnergyMS
CalcBandEnergyMS:
stmdb sp!, {r4 - r11, lr}
sub r13, r13, #24
mov r12, #0
mov r3, r3, lsl #16
mov r14, #0
mov r3, r3, asr #16
cmp r3, #0
mov r4, #0
ble L315
L32:
mov r5, r4, lsl #1
mov r6, #0
ldrsh r10, [r2, r5]
add r5, r2, r5
mov r7, #0
ldrsh r11, [r5, #2]
cmp r10, r11
bge L39
str r3, [r13, #4]
str r4, [r13, #8]
str r12, [r13, #12]
str r14, [r13, #16]
L33:
ldr r8, [r0, +r10, lsl #2]
ldr r9, [r1, +r10, lsl #2]
mov r8, r8, asr #1
add r10, r10, #1
mov r9, r9, asr #1
ldr r12, [r0, +r10, lsl #2]
add r5, r8, r9
ldr r14, [r1, +r10, lsl #2]
sub r8, r8, r9
smull r5, r3, r5, r5
mov r12, r12, asr #1
smull r8, r4, r8, r8
mov r14, r14, asr #1
qadd r6, r6, r3
add r5, r12, r14
qadd r7, r7, r4
sub r8, r12, r14
smull r5, r3, r5, r5
add r10, r10, #1
smull r8, r4, r8, r8
qadd r6, r6, r3
qadd r7, r7, r4
ldr r8, [r0, +r10, lsl #2]
ldr r9, [r1, +r10, lsl #2]
mov r8, r8, asr #1
add r10, r10, #1
mov r9, r9, asr #1
ldr r12, [r0, +r10, lsl #2]
add r5, r8, r9
ldr r14, [r1, +r10, lsl #2]
sub r8, r8, r9
smull r5, r3, r5, r5
mov r12, r12, asr #1
smull r8, r4, r8, r8
mov r14, r14, asr #1
qadd r6, r6, r3
add r5, r12, r14
qadd r7, r7, r4
sub r8, r12, r14
smull r5, r3, r5, r5
add r10, r10, #1
smull r8, r4, r8, r8
qadd r6, r6, r3
qadd r7, r7, r4
cmp r10, r11
blt L33
ldr r3, [r13, #4]
ldr r4, [r13, #8]
ldr r12, [r13, #12]
ldr r14, [r13, #16]
L39:
qadd r6, r6, r6
qadd r7, r7, r7
ldr r8, [r13, #60]
ldr r9, [r13, #68]
qadd r12, r12, r6
qadd r14, r14, r7
str r6, [r8, +r4, lsl #2]
str r7, [r9, +r4, lsl #2]
add r4, r4, #1
cmp r4, r3
blt L32
L315:
ldr r8, [r13, #64]
ldr r9, [r13, #72]
str r12, [r8, #0]
str r14, [r9, #0]
add r13, r13, #24
ldmia sp!, {r4 - r11, pc}
@ENDP ; |CalcBandEnergyMS|
.end

View File

@ -0,0 +1,135 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: PrePostMDCT_v7.s
@
@ Content: premdct and postmdct function armv7 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global PreMDCT
PreMDCT:
stmdb sp!, {r4 - r11, lr}
add r9, r0, r1, lsl #2
sub r3, r9, #32
movs r1, r1, asr #2
beq PreMDCT_END
PreMDCT_LOOP:
VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@
VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@
VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(buf0 + 0)@ ti2 = *(buf0 + 1)@
VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@
VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@
VREV64.32 Q8, Q7
VREV64.32 Q9, Q6
VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1)
VQDMULH.S32 Q11, Q1, Q8 @ MULHIGH(sina, ti1)
VQDMULH.S32 Q12, Q0, Q8 @ MULHIGH(cosa, ti1)
VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1)
VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
VSUB.S32 Q1, Q12, Q13 @ *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1)@
VST2.I32 {d0, d1, d2, d3}, [r0]!
sub r3, r3, #32
VQDMULH.S32 Q10, Q2, Q9 @ MULHIGH(cosb, tr2)
VQDMULH.S32 Q11, Q3, Q5 @ MULHIGH(sinb, ti2)
VQDMULH.S32 Q12, Q2, Q5 @ MULHIGH(cosb, ti2)
VQDMULH.S32 Q13, Q3, Q9 @ MULHIGH(sinb, tr2)
VADD.S32 Q0, Q10, Q11 @ MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@
VSUB.S32 Q1, Q12, Q13 @ MULHIGH(cosa, ti2) - MULHIGH(sina, tr2)@
VREV64.32 Q3, Q1
VREV64.32 Q2, Q0
VST2.I32 {d5, d7}, [r3]!
VST2.I32 {d4, d6}, [r3]!
subs r1, r1, #4
sub r3, r3, #64
bne PreMDCT_LOOP
PreMDCT_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |PreMDCT|
.section .text
.global PostMDCT
PostMDCT:
stmdb sp!, {r4 - r11, lr}
add r9, r0, r1, lsl #2
sub r3, r9, #32
movs r1, r1, asr #2
beq PostMDCT_END
PostMDCT_LOOP:
VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@
VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@
VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(zbuf1 + 0)@ ti1 = *(zbuf1 + 1)@
VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@
VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@
VREV64.32 Q8, Q6
VREV64.32 Q9, Q7
VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1)
VQDMULH.S32 Q11, Q1, Q5 @ MULHIGH(sina, ti1)
VQDMULH.S32 Q12, Q0, Q5 @ MULHIGH(cosa, ti1)
VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1)
VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
VSUB.S32 Q5, Q13, Q12 @ *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1)@
VQDMULH.S32 Q10, Q2, Q8 @ MULHIGH(cosb, tr2)
VQDMULH.S32 Q11, Q3, Q9 @ MULHIGH(sinb, ti2)
VQDMULH.S32 Q12, Q2, Q9 @ MULHIGH(cosb, ti2)
VQDMULH.S32 Q13, Q3, Q8 @ MULHIGH(sinb, tr2)
VADD.S32 Q4, Q10, Q11 @ *buf1-- = MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@
VSUB.S32 Q1, Q13, Q12 @ *buf0++ = MULHIGH(sina, tr2) - MULHIGH(cosa, ti2)@
VREV64.32 Q2, Q4
VREV64.32 Q3, Q5
sub r3, r3, #32
VST2.I32 {d0, d1, d2, d3}, [r0]!
VST2.I32 {d5, d7}, [r3]!
VST2.I32 {d4, d6}, [r3]!
subs r1, r1, #4
sub r3, r3, #64
bne PostMDCT_LOOP
PostMDCT_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |PostMDCT|
.end

View File

@ -0,0 +1,146 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: R4R8First_v7.s
@
@ Content: Radix8First and Radix4First function armv7 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global Radix8First
Radix8First:
stmdb sp!, {r4 - r11, lr}
ldr r3, SQRT1_2
cmp r1, #0
VDUP.I32 Q15, r3
beq Radix8First_END
Radix8First_LOOP:
VLD1.I32 {d0, d1, d2, d3}, [r0]!
VLD1.I32 {d8, d9, d10, d11}, [r0]!
VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@i0 = buf[1] + buf[3]@
VSUB.S32 d5, d0, d1 @ r1 = buf[0] - buf[2]@i1 = buf[1] - buf[3]@
VSUB.S32 d7, d2, d3 @ r2 = buf[4] - buf[6]@i2 = buf[5] - buf[7]@
VADD.S32 d6, d2, d3 @ r3 = buf[4] + buf[6]@i3 = buf[5] + buf[7]@
VREV64.I32 d7, d7
VADD.S32 Q0, Q2, Q3 @ r4 = (r0 + r2)@i4 = (i0 + i2)@i6 = (i1 + r3)@r7 = (r1 + i3)
VSUB.S32 Q1, Q2, Q3 @ r5 = (r0 - r2)@i5 = (i0 - i2)@r6 = (r1 - i3)@i7 = (i1 - r3)@
VREV64.I32 d3, d3
VADD.S32 d4, d8, d9 @ r0 = buf[ 8] + buf[10]@i0 = buf[ 9] + buf[11]@
VSUB.S32 d7, d10, d11 @ r1 = buf[12] - buf[14]@i1 = buf[13] - buf[15]@
VADD.S32 d6, d10, d11 @ r2 = buf[12] + buf[14]@i2 = buf[13] + buf[15]@
VREV64.I32 d7, d7
VSUB.S32 d5, d8, d9 @ r3 = buf[ 8] - buf[10]@i3 = buf[ 9] - buf[11]@
VTRN.32 d1, d3
VADD.S32 Q4, Q2, Q3 @ t0 = (r0 + r2) >> 1@t1 = (i0 + i2) >> 1@i0 = i1 + r3@r2 = r1 + i3@
VSUB.S32 Q5, Q2, Q3 @ t2 = (r0 - r2) >> 1@t3 = (i0 - i2) >> 1@r0 = r1 - i3@i2 = i1 - r3@
VREV64.I32 d3, d3
VSHR.S32 d8, d8, #1
VSHR.S32 Q0, Q0, #1
VREV64.I32 d10, d10
VTRN.32 d11, d9
VSHR.S32 Q1, Q1, #1
VSHR.S32 d10, d10, #1
VREV64.I32 d9, d9
sub r0, r0, #0x40
VADD.S32 d12, d0, d8
VSUB.S32 d16, d0, d8
VADD.S32 d14, d2, d10
VSUB.S32 d18, d2, d10
VSUB.S32 d4, d11, d9
VADD.S32 d5, d11, d9
VREV64.I32 d18, d18
VQDMULH.S32 Q3, Q2, Q15
VTRN.32 d14, d18
VTRN.32 d6, d7
VREV64.I32 d18, d18
VSUB.S32 d15, d3, d6
VREV64.I32 d7, d7
VADD.S32 d19, d3, d6
VADD.S32 d13, d1, d7
VSUB.S32 d17, d1, d7
VREV64.I32 d17, d17
VTRN.32 d13, d17
VREV64.I32 d17, d17
subs r1, r1, #1
VST1.I32 {d12, d13, d14, d15}, [r0]!
VST1.I32 {d16, d17, d18, d19}, [r0]!
bne Radix8First_LOOP
Radix8First_END:
ldmia sp!, {r4 - r11, pc}
SQRT1_2:
.word 0x2d413ccd
@ENDP @ |Radix8First|
.section .text
.global Radix4First
Radix4First:
stmdb sp!, {r4 - r11, lr}
cmp r1, #0
beq Radix4First_END
Radix4First_LOOP:
VLD1.I32 {d0, d1, d2, d3}, [r0]
VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@ r1 = buf[1] + buf[3]@
VSUB.S32 d5, d0, d1 @ r2 = buf[0] - buf[2]@ r3 = buf[1] - buf[3]@
VSUB.S32 d7, d2, d3 @ r4 = buf[4] + buf[6]@ r5 = buf[5] + buf[7]@
VADD.S32 d6, d2, d3 @ r6 = buf[4] - buf[6]@ r7 = buf[5] - buf[7]@
VREV64.I32 d7, d7 @
VADD.S32 Q4, Q2, Q3
VSUB.S32 Q5, Q2, Q3
VREV64.I32 d11, d11
VTRN.32 d9, d11
subs r1, r1, #1
VREV64.I32 d11, d11
VST1.I32 {d8, d9, d10, d11}, [r0]!
bne Radix4First_LOOP
Radix4First_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |Radix4First|
.end

View File

@ -0,0 +1,143 @@
@/*
@ ** Copyright 2003-2010, VisualOn, Inc.
@ **
@ ** Licensed under the Apache License, Version 2.0 (the "License");
@ ** you may not use this file except in compliance with the License.
@ ** You may obtain a copy of the License at
@ **
@ ** http://www.apache.org/licenses/LICENSE-2.0
@ **
@ ** Unless required by applicable law or agreed to in writing, software
@ ** distributed under the License is distributed on an "AS IS" BASIS,
@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ ** See the License for the specific language governing permissions and
@ ** limitations under the License.
@ */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ File: Radix4FFT_v7.s
@
@ Content: Radix4FFT armv7 assemble
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.section .text
.global Radix4FFT
Radix4FFT:
stmdb sp!, {r4 - r11, lr}
mov r1, r1, asr #2
cmp r1, #0
beq Radix4FFT_END
Radix4FFT_LOOP1:
mov r5, r2, lsl #1
mov r8, r0
mov r7, r1
mov r5, r5, lsl #2
cmp r1, #0
rsbeq r12, r5, r5, lsl #2
beq Radix4FFT_LOOP1_END
rsb r12, r5, r5, lsl #2
Radix4FFT_LOOP2:
mov r6, r3
mov r4, r2
cmp r2, #0
beq Radix4FFT_LOOP2_END
Radix4FFT_LOOP3:
@r0 = xptr[0]@
@r1 = xptr[1]@
VLD2.I32 {D0, D1, D2, D3}, [r8]
VLD2.I32 {D28, D29, D30, D31}, [r6]! @ cosx = csptr[0]@ sinx = csptr[1]@
add r8, r8, r5 @ xptr += step@
VLD2.I32 {D4, D5, D6,D7}, [r8] @ r2 = xptr[0]@ r3 = xptr[1]@
VQDMULH.S32 Q10, Q2, Q14 @ MULHIGH(cosx, t0)
VQDMULH.S32 Q11, Q3, Q15 @ MULHIGH(sinx, t1)
VQDMULH.S32 Q12, Q3, Q14 @ MULHIGH(cosx, t1)
VQDMULH.S32 Q13, Q2, Q15 @ MULHIGH(sinx, t0)
VADD.S32 Q2, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
VSUB.S32 Q3, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
add r8, r8, r5 @ xptr += step@
VSHR.S32 Q10, Q0, #2 @ t0 = r0 >> 2@
VSHR.S32 Q11, Q1, #2 @ t1 = r1 >> 2@
VSUB.S32 Q0, Q10, Q2 @ r0 = t0 - r2@
VSUB.S32 Q1, Q11, Q3 @ r1 = t1 - r3@
VADD.S32 Q2, Q10, Q2 @ r2 = t0 + r2@
VADD.S32 Q3, Q11, Q3 @ r3 = t1 + r3@
VLD2.I32 {D8, D9, D10, D11}, [r8]
VLD2.I32 {D28, D29, D30, D31}, [r6]!
add r8, r8, r5
VQDMULH.S32 Q10, Q4, Q14 @ MULHIGH(cosx, t0)
VQDMULH.S32 Q11, Q5, Q15 @ MULHIGH(sinx, t1)
VQDMULH.S32 Q12, Q5, Q14 @ MULHIGH(cosx, t1)
VQDMULH.S32 Q13, Q4, Q15 @ MULHIGH(sinx, t0)
VADD.S32 Q8, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
VSUB.S32 Q9, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
VLD2.I32 {D12, D13, D14, D15}, [r8]
VLD2.I32 {D28, D29, D30, D31}, [r6]!
VQDMULH.S32 Q10, Q6, Q14 @ MULHIGH(cosx, t0)
VQDMULH.S32 Q11, Q7, Q15 @ MULHIGH(sinx, t1)
VQDMULH.S32 Q12, Q7, Q14 @ MULHIGH(cosx, t1)
VQDMULH.S32 Q13, Q6, Q15 @ MULHIGH(sinx, t0)
VADD.S32 Q6, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
VSUB.S32 Q7, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
VADD.S32 Q4, Q8, Q6 @ r4 = t0 + r6@
VSUB.S32 Q5, Q7, Q9 @ r5 = r7 - t1@
VSUB.S32 Q6, Q8, Q6 @ r6 = t0 - r6@
VADD.S32 Q7, Q7, Q9 @ r7 = r7 + t1@
VADD.S32 Q8, Q0, Q5 @ xptr[0] = r0 + r5@
VADD.S32 Q9, Q1, Q6 @ xptr[1] = r1 + r6@
VST2.I32 {D16, D17, D18, D19}, [r8]
VSUB.S32 Q10, Q2, Q4 @ xptr[0] = r2 - r4@
sub r8, r8, r5 @ xptr -= step@
VSUB.S32 Q11, Q3, Q7 @ xptr[1] = r3 - r7@
VST2.I32 {D20, D21, D22, D23}, [r8]
VSUB.S32 Q8, Q0, Q5 @ xptr[0] = r0 - r5@
sub r8, r8, r5 @ xptr -= step@
VSUB.S32 Q9, Q1, Q6 @ xptr[1] = r1 - r6@
VST2.I32 {D16, D17, D18, D19}, [r8]
VADD.S32 Q10, Q2, Q4 @ xptr[0] = r2 + r4@
sub r8, r8, r5 @ xptr -= step@
VADD.S32 Q11, Q3, Q7 @ xptr[1] = r3 + r7@
VST2.I32 {D20, D21, D22, D23}, [r8]!
subs r4, r4, #4
bne Radix4FFT_LOOP3
Radix4FFT_LOOP2_END:
add r8, r8, r12
sub r7, r7, #1
cmp r7, #0
bhi Radix4FFT_LOOP2
Radix4FFT_LOOP1_END:
add r3, r12, r3
mov r2, r2, lsl #2
movs r1, r1, asr #2
bne Radix4FFT_LOOP1
Radix4FFT_END:
ldmia sp!, {r4 - r11, pc}
@ENDP @ |Radix4FFT|
.end

View File

@ -0,0 +1,102 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: band_nrg.c
Content: Band/Line energy calculations functions
*******************************************************************************/
#include "basic_op.h"
#include "band_nrg.h"
#ifndef ARMV5E
/********************************************************************************
*
* function name: CalcBandEnergy
* description: Calc sfb-bandwise mdct-energies for left and right channel
*
**********************************************************************************/
void CalcBandEnergy(const Word32 *mdctSpectrum,
const Word16 *bandOffset,
const Word16 numBands,
Word32 *bandEnergy,
Word32 *bandEnergySum)
{
Word32 i, j;
Word32 accuSum = 0;
for (i=0; i<numBands; i++) {
Word32 accu = 0;
for (j=bandOffset[i]; j<bandOffset[i+1]; j++)
accu = L_add(accu, MULHIGH(mdctSpectrum[j], mdctSpectrum[j]));
accu = L_add(accu, accu);
accuSum = L_add(accuSum, accu);
bandEnergy[i] = accu;
}
*bandEnergySum = accuSum;
}
/********************************************************************************
*
* function name: CalcBandEnergyMS
* description: Calc sfb-bandwise mdct-energies for left add or minus right channel
*
**********************************************************************************/
void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
const Word32 *mdctSpectrumRight,
const Word16 *bandOffset,
const Word16 numBands,
Word32 *bandEnergyMid,
Word32 *bandEnergyMidSum,
Word32 *bandEnergySide,
Word32 *bandEnergySideSum)
{
Word32 i, j;
Word32 accuMidSum = 0;
Word32 accuSideSum = 0;
for(i=0; i<numBands; i++) {
Word32 accuMid = 0;
Word32 accuSide = 0;
for (j=bandOffset[i]; j<bandOffset[i+1]; j++) {
Word32 specm, specs;
Word32 l, r;
l = mdctSpectrumLeft[j] >> 1;
r = mdctSpectrumRight[j] >> 1;
specm = l + r;
specs = l - r;
accuMid = L_add(accuMid, MULHIGH(specm, specm));
accuSide = L_add(accuSide, MULHIGH(specs, specs));
}
accuMid = L_add(accuMid, accuMid);
accuSide = L_add(accuSide, accuSide);
bandEnergyMid[i] = accuMid;
accuMidSum = L_add(accuMidSum, accuMid);
bandEnergySide[i] = accuSide;
accuSideSum = L_add(accuSideSum, accuSide);
}
*bandEnergyMidSum = accuMidSum;
*bandEnergySideSum = accuSideSum;
}
#endif

View File

@ -0,0 +1,885 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bit_cnt.c
Content: Huffman Bitcounter & coder functions
*******************************************************************************/
#include "bit_cnt.h"
#include "aac_rom.h"
#define HI_LTAB(a) (a>>8)
#define LO_LTAB(a) (a & 0xff)
#define EXPAND(a) ((((Word32)(a&0xff00)) << 8)|(Word32)(a&0xff))
/*****************************************************************************
*
* function name: count1_2_3_4_5_6_7_8_9_10_11
* description: counts tables 1-11
* returns:
* input: quantized spectrum
* output: bitCount for tables 1-11
*
*****************************************************************************/
static void count1_2_3_4_5_6_7_8_9_10_11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,t2,t3,i;
Word32 bc1_2,bc3_4,bc5_6,bc7_8,bc9_10;
Word16 bc11,sc;
bc1_2=0;
bc3_4=0;
bc5_6=0;
bc7_8=0;
bc9_10=0;
bc11=0;
sc=0;
for(i=0;i<width;i+=4){
t0= values[i+0];
t1= values[i+1];
t2= values[i+2];
t3= values[i+3];
/* 1,2 */
bc1_2 = bc1_2 + EXPAND(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
/* 5,6 */
bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);
t0=ABS(t0);
t1=ABS(t1);
t2=ABS(t2);
t3=ABS(t3);
bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);
bc11 = bc11 + huff_ltab11[t0][t1];
bc11 = bc11 + huff_ltab11[t2][t3];
sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);
}
bitCount[1]=extract_h(bc1_2);
bitCount[2]=extract_l(bc1_2);
bitCount[3]=extract_h(bc3_4) + sc;
bitCount[4]=extract_l(bc3_4) + sc;
bitCount[5]=extract_h(bc5_6);
bitCount[6]=extract_l(bc5_6);
bitCount[7]=extract_h(bc7_8) + sc;
bitCount[8]=extract_l(bc7_8) + sc;
bitCount[9]=extract_h(bc9_10) + sc;
bitCount[10]=extract_l(bc9_10) + sc;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: count3_4_5_6_7_8_9_10_11
* description: counts tables 3-11
* returns:
* input: quantized spectrum
* output: bitCount for tables 3-11
*
*****************************************************************************/
static void count3_4_5_6_7_8_9_10_11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,t2,t3, i;
Word32 bc3_4,bc5_6,bc7_8,bc9_10;
Word16 bc11,sc;
bc3_4=0;
bc5_6=0;
bc7_8=0;
bc9_10=0;
bc11=0;
sc=0;
for(i=0;i<width;i+=4){
t0= values[i+0];
t1= values[i+1];
t2= values[i+2];
t3= values[i+3];
/*
5,6
*/
bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);
t0=ABS(t0);
t1=ABS(t1);
t2=ABS(t2);
t3=ABS(t3);
bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);
bc11 = bc11 + huff_ltab11[t0][t1];
bc11 = bc11 + huff_ltab11[t2][t3];
sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=extract_h(bc3_4) + sc;
bitCount[4]=extract_l(bc3_4) + sc;
bitCount[5]=extract_h(bc5_6);
bitCount[6]=extract_l(bc5_6);
bitCount[7]=extract_h(bc7_8) + sc;
bitCount[8]=extract_l(bc7_8) + sc;
bitCount[9]=extract_h(bc9_10) + sc;
bitCount[10]=extract_l(bc9_10) + sc;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: count5_6_7_8_9_10_11
* description: counts tables 5-11
* returns:
* input: quantized spectrum
* output: bitCount for tables 5-11
*
*****************************************************************************/
static void count5_6_7_8_9_10_11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,i;
Word32 bc5_6,bc7_8,bc9_10;
Word16 bc11,sc;
bc5_6=0;
bc7_8=0;
bc9_10=0;
bc11=0;
sc=0;
for(i=0;i<width;i+=2){
t0 = values[i+0];
t1 = values[i+1];
bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
t0=ABS(t0);
t1=ABS(t1);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
bc11 = bc11 + huff_ltab11[t0][t1];
sc = sc + (t0>0) + (t1>0);
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=INVALID_BITCOUNT;
bitCount[4]=INVALID_BITCOUNT;
bitCount[5]=extract_h(bc5_6);
bitCount[6]=extract_l(bc5_6);
bitCount[7]=extract_h(bc7_8) + sc;
bitCount[8]=extract_l(bc7_8) + sc;
bitCount[9]=extract_h(bc9_10) + sc;
bitCount[10]=extract_l(bc9_10) + sc;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: count7_8_9_10_11
* description: counts tables 7-11
* returns:
* input: quantized spectrum
* output: bitCount for tables 7-11
*
*****************************************************************************/
static void count7_8_9_10_11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1, i;
Word32 bc7_8,bc9_10;
Word16 bc11,sc;
bc7_8=0;
bc9_10=0;
bc11=0;
sc=0;
for(i=0;i<width;i+=2){
t0=ABS(values[i+0]);
t1=ABS(values[i+1]);
bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
bc11 = bc11 + huff_ltab11[t0][t1];
sc = sc + (t0>0) + (t1>0);
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=INVALID_BITCOUNT;
bitCount[4]=INVALID_BITCOUNT;
bitCount[5]=INVALID_BITCOUNT;
bitCount[6]=INVALID_BITCOUNT;
bitCount[7]=extract_h(bc7_8) + sc;
bitCount[8]=extract_l(bc7_8) + sc;
bitCount[9]=extract_h(bc9_10) + sc;
bitCount[10]=extract_l(bc9_10) + sc;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: count9_10_11
* description: counts tables 9-11
* returns:
* input: quantized spectrum
* output: bitCount for tables 9-11
*
*****************************************************************************/
static void count9_10_11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,i;
Word32 bc9_10;
Word16 bc11,sc;
bc9_10=0;
bc11=0;
sc=0;
for(i=0;i<width;i+=2){
t0=ABS(values[i+0]);
t1=ABS(values[i+1]);
bc9_10 += EXPAND(huff_ltab9_10[t0][t1]);
bc11 = bc11 + huff_ltab11[t0][t1];
sc = sc + (t0>0) + (t1>0);
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=INVALID_BITCOUNT;
bitCount[4]=INVALID_BITCOUNT;
bitCount[5]=INVALID_BITCOUNT;
bitCount[6]=INVALID_BITCOUNT;
bitCount[7]=INVALID_BITCOUNT;
bitCount[8]=INVALID_BITCOUNT;
bitCount[9]=extract_h(bc9_10) + sc;
bitCount[10]=extract_l(bc9_10) + sc;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: count11
* description: counts table 11
* returns:
* input: quantized spectrum
* output: bitCount for table 11
*
*****************************************************************************/
static void count11(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,i;
Word16 bc11,sc;
bc11=0;
sc=0;
for(i=0;i<width;i+=2){
t0=ABS(values[i+0]);
t1=ABS(values[i+1]);
bc11 = bc11 + huff_ltab11[t0][t1];
sc = sc + (t0>0) + (t1>0);
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=INVALID_BITCOUNT;
bitCount[4]=INVALID_BITCOUNT;
bitCount[5]=INVALID_BITCOUNT;
bitCount[6]=INVALID_BITCOUNT;
bitCount[7]=INVALID_BITCOUNT;
bitCount[8]=INVALID_BITCOUNT;
bitCount[9]=INVALID_BITCOUNT;
bitCount[10]=INVALID_BITCOUNT;
bitCount[11]=bc11 + sc;
}
/*****************************************************************************
*
* function name: countEsc
* description: counts table 11 (with Esc)
* returns:
* input: quantized spectrum
* output: bitCount for tables 11 (with Esc)
*
*****************************************************************************/
static void countEsc(const Word16 *values,
const Word16 width,
Word16 *bitCount)
{
Word32 t0,t1,t00,t01,i;
Word16 bc11,ec,sc;
bc11=0;
sc=0;
ec=0;
for(i=0;i<width;i+=2){
t0=ABS(values[i+0]);
t1=ABS(values[i+1]);
sc = sc + (t0>0) + (t1>0);
t00 = min(t0,16);
t01 = min(t1,16);
bc11 = bc11 + huff_ltab11[t00][t01];
if(t0 >= 16){
ec = ec + 5;
while(sub(t0=(t0 >> 1), 16) >= 0) {
ec = ec + 2;
}
}
if(t1 >= 16){
ec = ec + 5;
while(sub(t1=(t1 >> 1), 16) >= 0) {
ec = ec + 2;
}
}
}
bitCount[1]=INVALID_BITCOUNT;
bitCount[2]=INVALID_BITCOUNT;
bitCount[3]=INVALID_BITCOUNT;
bitCount[4]=INVALID_BITCOUNT;
bitCount[5]=INVALID_BITCOUNT;
bitCount[6]=INVALID_BITCOUNT;
bitCount[7]=INVALID_BITCOUNT;
bitCount[8]=INVALID_BITCOUNT;
bitCount[9]=INVALID_BITCOUNT;
bitCount[10]=INVALID_BITCOUNT;
bitCount[11]=bc11 + sc + ec;
}
typedef void (*COUNT_FUNCTION)(const Word16 *values,
const Word16 width,
Word16 *bitCount);
static COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV+1] =
{
count1_2_3_4_5_6_7_8_9_10_11, /* 0 */
count1_2_3_4_5_6_7_8_9_10_11, /* 1 */
count3_4_5_6_7_8_9_10_11, /* 2 */
count5_6_7_8_9_10_11, /* 3 */
count5_6_7_8_9_10_11, /* 4 */
count7_8_9_10_11, /* 5 */
count7_8_9_10_11, /* 6 */
count7_8_9_10_11, /* 7 */
count9_10_11, /* 8 */
count9_10_11, /* 9 */
count9_10_11, /* 10 */
count9_10_11, /* 11 */
count9_10_11, /* 12 */
count11, /* 13 */
count11, /* 14 */
count11, /* 15 */
countEsc /* 16 */
};
/*****************************************************************************
*
* function name: bitCount
* description: count bits
*
*****************************************************************************/
Word16 bitCount(const Word16 *values,
const Word16 width,
Word16 maxVal,
Word16 *bitCount)
{
/*
check if we can use codebook 0
*/
if(maxVal == 0)
bitCount[0] = 0;
else
bitCount[0] = INVALID_BITCOUNT;
maxVal = min(maxVal, CODE_BOOK_ESC_LAV);
countFuncTable[maxVal](values,width,bitCount);
return(0);
}
/*****************************************************************************
*
* function name: codeValues
* description: write huffum bits
*
*****************************************************************************/
Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream)
{
Word32 i, t0, t1, t2, t3, t00, t01;
Word16 codeWord, codeLength;
Word16 sign, signLength;
switch (codeBook) {
case CODE_BOOK_ZERO_NO:
break;
case CODE_BOOK_1_NO:
for(i=0; i<width; i+=4) {
t0 = values[i+0];
t1 = values[i+1];
t2 = values[i+2];
t3 = values[i+3];
codeWord = huff_ctab1[t0+1][t1+1][t2+1][t3+1];
codeLength = HI_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
WriteBits(hBitstream, codeWord, codeLength);
}
break;
case CODE_BOOK_2_NO:
for(i=0; i<width; i+=4) {
t0 = values[i+0];
t1 = values[i+1];
t2 = values[i+2];
t3 = values[i+3];
codeWord = huff_ctab2[t0+1][t1+1][t2+1][t3+1];
codeLength = LO_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
WriteBits(hBitstream,codeWord,codeLength);
}
break;
case CODE_BOOK_3_NO:
for(i=0; i<width; i+=4) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
t2 = values[i+2];
if(t2 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t2 < 0){
sign|=1;
t2=-t2;
}
}
t3 = values[i+3];
if(t3 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t3 < 0){
sign|=1;
t3=-t3;
}
}
codeWord = huff_ctab3[t0][t1][t2][t3];
codeLength = HI_LTAB(huff_ltab3_4[t0][t1][t2][t3]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_4_NO:
for(i=0; i<width; i+=4) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
t2 = values[i+2];
if(t2 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t2 < 0){
sign|=1;
t2=-t2;
}
}
t3 = values[i+3];
if(t3 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t3 < 0){
sign|=1;
t3=-t3;
}
}
codeWord = huff_ctab4[t0][t1][t2][t3];
codeLength = LO_LTAB(huff_ltab3_4[t0][t1][t2][t3]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_5_NO:
for(i=0; i<width; i+=2) {
t0 = values[i+0];
t1 = values[i+1];
codeWord = huff_ctab5[t0+4][t1+4];
codeLength = HI_LTAB(huff_ltab5_6[t0+4][t1+4]);
WriteBits(hBitstream,codeWord,codeLength);
}
break;
case CODE_BOOK_6_NO:
for(i=0; i<width; i+=2) {
t0 = values[i+0];
t1 = values[i+1];
codeWord = huff_ctab6[t0+4][t1+4];
codeLength = LO_LTAB(huff_ltab5_6[t0+4][t1+4]);
WriteBits(hBitstream,codeWord,codeLength);
}
break;
case CODE_BOOK_7_NO:
for(i=0; i<width; i+=2){
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
codeWord = huff_ctab7[t0][t1];
codeLength = HI_LTAB(huff_ltab7_8[t0][t1]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_8_NO:
for(i=0; i<width; i+=2) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
codeWord = huff_ctab8[t0][t1];
codeLength = LO_LTAB(huff_ltab7_8[t0][t1]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_9_NO:
for(i=0; i<width; i+=2) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
codeWord = huff_ctab9[t0][t1];
codeLength = HI_LTAB(huff_ltab9_10[t0][t1]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_10_NO:
for(i=0; i<width; i+=2) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
codeWord = huff_ctab10[t0][t1];
codeLength = LO_LTAB(huff_ltab9_10[t0][t1]);
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
}
break;
case CODE_BOOK_ESC_NO:
for(i=0; i<width; i+=2) {
sign=0;
signLength=0;
t0 = values[i+0];
if(t0 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t0 < 0){
sign|=1;
t0=-t0;
}
}
t1 = values[i+1];
if(t1 != 0){
signLength = signLength + 1;
sign = sign << 1;
if(t1 < 0){
sign|=1;
t1=-t1;
}
}
t00 = min(t0,16);
t01 = min(t1,16);
codeWord = huff_ctab11[t00][t01];
codeLength = huff_ltab11[t00][t01];
WriteBits(hBitstream,codeWord,codeLength);
WriteBits(hBitstream,sign,signLength);
if(t0 >= 16){
Word16 n, p;
n=0;
p=t0;
while(sub(p=(p >> 1), 16) >= 0){
WriteBits(hBitstream,1,1);
n = n + 1;
}
WriteBits(hBitstream,0,1);
n = n + 4;
WriteBits(hBitstream,(t0 - (1 << n)),n);
}
if(t1 >= 16){
Word16 n, p;
n=0;
p=t1;
while(sub(p=(p >> 1), 16) >= 0){
WriteBits(hBitstream,1,1);
n = n + 1;
}
WriteBits(hBitstream,0,1);
n = n + 4;
WriteBits(hBitstream,(t1 - (1 << n)),n);
}
}
break;
default:
break;
}
return(0);
}
Word16 bitCountScalefactorDelta(Word16 delta)
{
return(huff_ltabscf[delta+CODE_BOOK_SCF_LAV]);
}
Word16 codeScalefactorDelta(Word16 delta, HANDLE_BIT_BUF hBitstream)
{
Word32 codeWord;
Word16 codeLength;
if(delta > CODE_BOOK_SCF_LAV || delta < -CODE_BOOK_SCF_LAV)
return(1);
codeWord = huff_ctabscf[delta + CODE_BOOK_SCF_LAV];
codeLength = huff_ltabscf[delta + CODE_BOOK_SCF_LAV];
WriteBits(hBitstream,codeWord,codeLength);
return(0);
}

View File

@ -0,0 +1,172 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bitbuffer.c
Content: Bit Buffer Management functions
*******************************************************************************/
#include "bitbuffer.h"
/*****************************************************************************
*
* function name: updateBitBufWordPtr
* description: update Bit Buffer pointer
*
*****************************************************************************/
static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf,
UWord8 **pBitBufWord,
Word16 cnt)
{
*pBitBufWord += cnt;
if(*pBitBufWord > hBitBuf->pBitBufEnd) {
*pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
}
if(*pBitBufWord < hBitBuf->pBitBufBase) {
*pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
}
}
/*****************************************************************************
*
* function name: CreateBitBuffer
* description: create and init Bit Buffer Management
*
*****************************************************************************/
HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
UWord8 *pBitBufBase,
Word16 bitBufSize)
{
assert(bitBufSize*8 <= 32768);
hBitBuf->pBitBufBase = pBitBufBase;
hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1;
hBitBuf->pWriteNext = pBitBufBase;
hBitBuf->cache = 0;
hBitBuf->wBitPos = 0;
hBitBuf->cntBits = 0;
hBitBuf->size = (bitBufSize << 3);
hBitBuf->isValid = 1;
return hBitBuf;
}
/*****************************************************************************
*
* function name: DeleteBitBuffer
* description: uninit Bit Buffer Management
*
*****************************************************************************/
void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf)
{
if(*hBitBuf)
(*hBitBuf)->isValid = 0;
*hBitBuf = NULL;
}
/*****************************************************************************
*
* function name: ResetBitBuf
* description: reset Bit Buffer Management
*
*****************************************************************************/
void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
UWord8 *pBitBufBase,
Word16 bitBufSize)
{
hBitBuf->pBitBufBase = pBitBufBase;
hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1;
hBitBuf->pWriteNext = pBitBufBase;
hBitBuf->wBitPos = 0;
hBitBuf->cntBits = 0;
hBitBuf->cache = 0;
}
/*****************************************************************************
*
* function name: CopyBitBuf
* description: copy Bit Buffer Management
*
*****************************************************************************/
void CopyBitBuf(HANDLE_BIT_BUF hBitBufSrc,
HANDLE_BIT_BUF hBitBufDst)
{
*hBitBufDst = *hBitBufSrc;
}
/*****************************************************************************
*
* function name: GetBitsAvail
* description: get available bits
*
*****************************************************************************/
Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf)
{
return hBitBuf->cntBits;
}
/*****************************************************************************
*
* function name: WriteBits
* description: write bits to the buffer
*
*****************************************************************************/
Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
Word32 writeValue,
Word16 noBitsToWrite)
{
Word16 wBitPos;
assert(noBitsToWrite <= (Word16)sizeof(Word32)*8);
if(noBitsToWrite == 0)
return noBitsToWrite;
hBitBuf->cntBits += noBitsToWrite;
wBitPos = hBitBuf->wBitPos;
wBitPos += noBitsToWrite;
writeValue <<= 32 - wBitPos;
writeValue |= hBitBuf->cache;
while (wBitPos >= 8)
{
UWord8 tmp;
tmp = (UWord8)((writeValue >> 24) & 0xFF);
*hBitBuf->pWriteNext++ = tmp;
writeValue <<= 8;
wBitPos -= 8;
}
hBitBuf->wBitPos = wBitPos;
hBitBuf->cache = writeValue;
return noBitsToWrite;
}

View File

@ -0,0 +1,690 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: bitenc.c
Content: Bitstream encoder functions
*******************************************************************************/
#include "bitenc.h"
#include "bit_cnt.h"
#include "dyn_bits.h"
#include "qc_data.h"
#include "interface.h"
static const Word16 globalGainOffset = 100;
static const Word16 icsReservedBit = 0;
/*****************************************************************************
*
* function name: encodeSpectralData
* description: encode spectral data
* returns: spectral bits used
*
*****************************************************************************/
static Word32 encodeSpectralData(Word16 *sfbOffset,
SECTION_DATA *sectionData,
Word16 *quantSpectrum,
HANDLE_BIT_BUF hBitStream)
{
Word16 i,sfb;
Word16 dbgVal;
SECTION_INFO* psectioninfo;
dbgVal = GetBitsAvail(hBitStream);
for(i=0; i<sectionData->noOfSections; i++) {
psectioninfo = &(sectionData->sectionInfo[i]);
/*
huffencode spectral data for this section
*/
for(sfb=psectioninfo->sfbStart;
sfb<psectioninfo->sfbStart+psectioninfo->sfbCnt;
sfb++) {
codeValues(quantSpectrum+sfbOffset[sfb],
sfbOffset[sfb+1] - sfbOffset[sfb],
psectioninfo->codeBook,
hBitStream);
}
}
return(GetBitsAvail(hBitStream)-dbgVal);
}
/*****************************************************************************
*
* function name:encodeGlobalGain
* description: encodes Global Gain (common scale factor)
* returns: none
*
*****************************************************************************/
static void encodeGlobalGain(Word16 globalGain,
Word16 logNorm,
Word16 scalefac,
HANDLE_BIT_BUF hBitStream)
{
WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8);
}
/*****************************************************************************
*
* function name:encodeIcsInfo
* description: encodes Ics Info
* returns: none
*
*****************************************************************************/
static void encodeIcsInfo(Word16 blockType,
Word16 windowShape,
Word16 groupingMask,
SECTION_DATA *sectionData,
HANDLE_BIT_BUF hBitStream)
{
WriteBits(hBitStream,icsReservedBit,1);
WriteBits(hBitStream,blockType,2);
WriteBits(hBitStream,windowShape,1);
switch(blockType){
case LONG_WINDOW:
case START_WINDOW:
case STOP_WINDOW:
WriteBits(hBitStream,sectionData->maxSfbPerGroup,6);
/* No predictor data present */
WriteBits(hBitStream, 0, 1);
break;
case SHORT_WINDOW:
WriteBits(hBitStream,sectionData->maxSfbPerGroup,4);
/*
Write grouping bits
*/
WriteBits(hBitStream,groupingMask,TRANS_FAC-1);
break;
}
}
/*****************************************************************************
*
* function name: encodeSectionData
* description: encode section data (common Huffman codebooks for adjacent
* SFB's)
* returns: none
*
*****************************************************************************/
static Word32 encodeSectionData(SECTION_DATA *sectionData,
HANDLE_BIT_BUF hBitStream)
{
Word16 sectEscapeVal=0,sectLenBits=0;
Word16 sectLen;
Word16 i;
Word16 dbgVal=GetBitsAvail(hBitStream);
switch(sectionData->blockType)
{
case LONG_WINDOW:
case START_WINDOW:
case STOP_WINDOW:
sectEscapeVal = SECT_ESC_VAL_LONG;
sectLenBits = SECT_BITS_LONG;
break;
case SHORT_WINDOW:
sectEscapeVal = SECT_ESC_VAL_SHORT;
sectLenBits = SECT_BITS_SHORT;
break;
}
for(i=0;i<sectionData->noOfSections;i++) {
WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4);
sectLen = sectionData->sectionInfo[i].sfbCnt;
while(sectLen >= sectEscapeVal) {
WriteBits(hBitStream,sectEscapeVal,sectLenBits);
sectLen = sectLen - sectEscapeVal;
}
WriteBits(hBitStream,sectLen,sectLenBits);
}
return(GetBitsAvail(hBitStream)-dbgVal);
}
/*****************************************************************************
*
* function name: encodeScaleFactorData
* description: encode DPCM coded scale factors
* returns: none
*
*****************************************************************************/
static Word32 encodeScaleFactorData(UWord16 *maxValueInSfb,
SECTION_DATA *sectionData,
Word16 *scalefac,
HANDLE_BIT_BUF hBitStream)
{
Word16 i,j,lastValScf,deltaScf;
Word16 dbgVal = GetBitsAvail(hBitStream);
SECTION_INFO* psectioninfo;
lastValScf=scalefac[sectionData->firstScf];
for(i=0;i<sectionData->noOfSections;i++){
psectioninfo = &(sectionData->sectionInfo[i]);
if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){
for (j=psectioninfo->sfbStart;
j<psectioninfo->sfbStart+psectioninfo->sfbCnt; j++){
if(maxValueInSfb[j] == 0) {
deltaScf = 0;
}
else {
deltaScf = lastValScf - scalefac[j];
lastValScf = scalefac[j];
}
if(codeScalefactorDelta(deltaScf,hBitStream)){
return(1);
}
}
}
}
return(GetBitsAvail(hBitStream)-dbgVal);
}
/*****************************************************************************
*
* function name:encodeMsInfo
* description: encodes MS-Stereo Info
* returns: none
*
*****************************************************************************/
static void encodeMSInfo(Word16 sfbCnt,
Word16 grpSfb,
Word16 maxSfb,
Word16 msDigest,
Word16 *jsFlags,
HANDLE_BIT_BUF hBitStream)
{
Word16 sfb, sfbOff;
switch(msDigest)
{
case MS_NONE:
WriteBits(hBitStream,SI_MS_MASK_NONE,2);
break;
case MS_ALL:
WriteBits(hBitStream,SI_MS_MASK_ALL,2);
break;
case MS_SOME:
WriteBits(hBitStream,SI_MS_MASK_SOME,2);
for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) {
for(sfb=0; sfb<maxSfb; sfb++) {
if(jsFlags[sfbOff+sfb] & MS_ON) {
WriteBits(hBitStream,1,1);
}
else{
WriteBits(hBitStream,0,1);
}
}
}
break;
}
}
/*****************************************************************************
*
* function name: encodeTnsData
* description: encode TNS data (filter order, coeffs, ..)
* returns: none
*
*****************************************************************************/
static void encodeTnsData(TNS_INFO tnsInfo,
Word16 blockType,
HANDLE_BIT_BUF hBitStream) {
Word16 i,k;
Flag tnsPresent;
Word16 numOfWindows;
Word16 coefBits;
Flag isShort;
if (blockType==2) {
isShort = 1;
numOfWindows = TRANS_FAC;
}
else {
isShort = 0;
numOfWindows = 1;
}
tnsPresent=0;
for (i=0; i<numOfWindows; i++) {
if (tnsInfo.tnsActive[i]) {
tnsPresent=1;
}
}
if (tnsPresent==0) {
WriteBits(hBitStream,0,1);
}
else{ /* there is data to be written*/
WriteBits(hBitStream,1,1); /*data_present */
for (i=0; i<numOfWindows; i++) {
WriteBits(hBitStream,tnsInfo.tnsActive[i],(isShort?1:2));
if (tnsInfo.tnsActive[i]) {
WriteBits(hBitStream,((tnsInfo.coefRes[i] - 4)==0?1:0),1);
WriteBits(hBitStream,tnsInfo.length[i],(isShort?4:6));
WriteBits(hBitStream,tnsInfo.order[i],(isShort?3:5));
if (tnsInfo.order[i]){
WriteBits(hBitStream, FILTER_DIRECTION, 1);
if(tnsInfo.coefRes[i] == 4) {
coefBits = 3;
for(k=0; k<tnsInfo.order[i]; k++) {
if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 3 ||
tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) {
coefBits = 4;
break;
}
}
}
else {
coefBits = 2;
for(k=0; k<tnsInfo.order[i]; k++) {
if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 1 ||
tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) {
coefBits = 3;
break;
}
}
}
WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/
for (k=0; k<tnsInfo.order[i]; k++ ) {
static const Word16 rmask[] = {0,1,3,7,15};
WriteBits(hBitStream,tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] & rmask[coefBits],coefBits);
}
}
}
}
}
}
/*****************************************************************************
*
* function name: encodeGainControlData
* description: unsupported
* returns: none
*
*****************************************************************************/
static void encodeGainControlData(HANDLE_BIT_BUF hBitStream)
{
WriteBits(hBitStream,0,1);
}
/*****************************************************************************
*
* function name: encodePulseData
* description: not supported yet (dummy)
* returns: none
*
*****************************************************************************/
static void encodePulseData(HANDLE_BIT_BUF hBitStream)
{
WriteBits(hBitStream,0,1);
}
/*****************************************************************************
*
* function name: WriteIndividualChannelStream
* description: management of write process of individual channel stream
* returns: none
*
*****************************************************************************/
static void
writeIndividualChannelStream(Flag commonWindow,
Word16 mdctScale,
Word16 windowShape,
Word16 groupingMask,
Word16 *sfbOffset,
Word16 scf[],
UWord16 *maxValueInSfb,
Word16 globalGain,
Word16 quantSpec[],
SECTION_DATA *sectionData,
HANDLE_BIT_BUF hBitStream,
TNS_INFO tnsInfo)
{
Word16 logNorm;
logNorm = LOG_NORM_PCM - (mdctScale + 1);
encodeGlobalGain(globalGain, logNorm,scf[sectionData->firstScf], hBitStream);
if(!commonWindow) {
encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream);
}
encodeSectionData(sectionData, hBitStream);
encodeScaleFactorData(maxValueInSfb,
sectionData,
scf,
hBitStream);
encodePulseData(hBitStream);
encodeTnsData(tnsInfo, sectionData->blockType, hBitStream);
encodeGainControlData(hBitStream);
encodeSpectralData(sfbOffset,
sectionData,
quantSpec,
hBitStream);
}
/*****************************************************************************
*
* function name: writeSingleChannelElement
* description: write single channel element to bitstream
* returns: none
*
*****************************************************************************/
static Word16 writeSingleChannelElement(Word16 instanceTag,
Word16 *sfbOffset,
QC_OUT_CHANNEL* qcOutChannel,
HANDLE_BIT_BUF hBitStream,
TNS_INFO tnsInfo)
{
WriteBits(hBitStream,ID_SCE,3);
WriteBits(hBitStream,instanceTag,4);
writeIndividualChannelStream(0,
qcOutChannel->mdctScale,
qcOutChannel->windowShape,
qcOutChannel->groupingMask,
sfbOffset,
qcOutChannel->scf,
qcOutChannel->maxValueInSfb,
qcOutChannel->globalGain,
qcOutChannel->quantSpec,
&(qcOutChannel->sectionData),
hBitStream,
tnsInfo
);
return(0);
}
/*****************************************************************************
*
* function name: writeChannelPairElement
* description:
* returns: none
*
*****************************************************************************/
static Word16 writeChannelPairElement(Word16 instanceTag,
Word16 msDigest,
Word16 msFlags[MAX_GROUPED_SFB],
Word16 *sfbOffset[2],
QC_OUT_CHANNEL qcOutChannel[2],
HANDLE_BIT_BUF hBitStream,
TNS_INFO tnsInfo[2])
{
WriteBits(hBitStream,ID_CPE,3);
WriteBits(hBitStream,instanceTag,4);
WriteBits(hBitStream,1,1); /* common window */
encodeIcsInfo(qcOutChannel[0].sectionData.blockType,
qcOutChannel[0].windowShape,
qcOutChannel[0].groupingMask,
&(qcOutChannel[0].sectionData),
hBitStream);
encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt,
qcOutChannel[0].sectionData.sfbPerGroup,
qcOutChannel[0].sectionData.maxSfbPerGroup,
msDigest,
msFlags,
hBitStream);
writeIndividualChannelStream(1,
qcOutChannel[0].mdctScale,
qcOutChannel[0].windowShape,
qcOutChannel[0].groupingMask,
sfbOffset[0],
qcOutChannel[0].scf,
qcOutChannel[0].maxValueInSfb,
qcOutChannel[0].globalGain,
qcOutChannel[0].quantSpec,
&(qcOutChannel[0].sectionData),
hBitStream,
tnsInfo[0]);
writeIndividualChannelStream(1,
qcOutChannel[1].mdctScale,
qcOutChannel[1].windowShape,
qcOutChannel[1].groupingMask,
sfbOffset[1],
qcOutChannel[1].scf,
qcOutChannel[1].maxValueInSfb,
qcOutChannel[1].globalGain,
qcOutChannel[1].quantSpec,
&(qcOutChannel[1].sectionData),
hBitStream,
tnsInfo[1]);
return(0);
}
/*****************************************************************************
*
* function name: writeFillElement
* description: write fill elements to bitstream
* returns: none
*
*****************************************************************************/
static void writeFillElement( const UWord8 *ancBytes,
Word16 totFillBits,
HANDLE_BIT_BUF hBitStream)
{
Word16 i;
Word16 cnt,esc_count;
/*
Write fill Element(s):
amount of a fill element can be 7+X*8 Bits, X element of [0..270]
*/
while(totFillBits >= (3+4)) {
cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1));
WriteBits(hBitStream,ID_FIL,3);
WriteBits(hBitStream,cnt,4);
totFillBits = totFillBits - (3+4);
if ((cnt == (1<<4)-1)) {
esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1);
WriteBits(hBitStream,esc_count,8);
totFillBits = (totFillBits - 8);
cnt = cnt + (esc_count - 1);
}
for(i=0;i<cnt;i++) {
if(ancBytes)
WriteBits(hBitStream, *ancBytes++,8);
else
WriteBits(hBitStream,0,8);
totFillBits = totFillBits - 8;
}
}
}
/*****************************************************************************
*
* function name: WriteBitStream
* description: main function of write bitsteam process
* returns: 0 if success
*
*****************************************************************************/
Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream,
ELEMENT_INFO elInfo,
QC_OUT *qcOut,
PSY_OUT *psyOut,
Word16 *globUsedBits,
const UWord8 *ancBytes,
Word16 sampindex
) /* returns error code */
{
Word16 bitMarkUp;
Word16 elementUsedBits;
Word16 frameBits=0;
/* struct bitbuffer bsWriteCopy; */
bitMarkUp = GetBitsAvail(hBitStream);
if(qcOut->qcElement.adtsUsed) /* write adts header*/
{
WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */
WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */
WriteBits(hBitStream, 0, 2); /* layer == 0 */
WriteBits(hBitStream, 1, 1); /* protection absent */
WriteBits(hBitStream, 1, 2); /* profile */
WriteBits(hBitStream, sampindex, 4); /* sampling rate */
WriteBits(hBitStream, 0, 1); /* private bit */
WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */
/* simply using numChannels only works for
6 channels or less, else a channel
configuration should be written */
WriteBits(hBitStream, 0, 1); /* original/copy */
WriteBits(hBitStream, 0, 1); /* home */
/* Variable ADTS header */
WriteBits(hBitStream, 0, 1); /* copyr. id. bit */
WriteBits(hBitStream, 0, 1); /* copyr. id. start */
WriteBits(hBitStream, *globUsedBits >> 3, 13);
WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */
WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */
}
*globUsedBits=0;
{
Word16 *sfbOffset[2];
TNS_INFO tnsInfo[2];
elementUsedBits = 0;
switch (elInfo.elType) {
case ID_SCE: /* single channel */
sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
writeSingleChannelElement(elInfo.instanceTag,
sfbOffset[0],
&qcOut->qcChannel[elInfo.ChannelIndex[0]],
hBitStream,
tnsInfo[0]);
break;
case ID_CPE: /* channel pair */
{
Word16 msDigest;
Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask;
msDigest = psyOut->psyOutElement.toolsInfo.msDigest;
sfbOffset[0] =
psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
sfbOffset[1] =
psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets;
tnsInfo[0]=
psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
tnsInfo[1]=
psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo;
writeChannelPairElement(elInfo.instanceTag,
msDigest,
msFlags,
sfbOffset,
&qcOut->qcChannel[elInfo.ChannelIndex[0]],
hBitStream,
tnsInfo);
}
break;
default:
return(1);
} /* switch */
elementUsedBits = elementUsedBits - bitMarkUp;
bitMarkUp = GetBitsAvail(hBitStream);
frameBits = frameBits + elementUsedBits + bitMarkUp;
}
writeFillElement(NULL,
qcOut->totFillBits,
hBitStream);
WriteBits(hBitStream,ID_END,3);
/* byte alignement */
WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7);
*globUsedBits = *globUsedBits- bitMarkUp;
bitMarkUp = GetBitsAvail(hBitStream);
*globUsedBits = *globUsedBits + bitMarkUp;
frameBits = frameBits + *globUsedBits;
if (frameBits != (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed +
qcOut->totFillBits + qcOut->alignBits)) {
return(-1);
}
return(0);
}

View File

@ -0,0 +1,431 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: block_switch.c
Content: Block switching functions
*******************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "psy_const.h"
#include "block_switch.h"
#define ENERGY_SHIFT (8 - 1)
/**************** internal function prototypes ***********/
static Word16
IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]);
static Word32
SrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
Word32
CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
Word16 *timeSignal,
Word16 chIncrement,
Word16 windowLen);
/****************** Constants *****************************/
/*
IIR high pass coeffs
*/
Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
0xbec8b439, 0x609d4952 /* -0.5095f, 0.7548f */
};
static const Word32 accWindowNrgFac = 0x26666666; /* factor for accumulating filtered window energies 0.3 */
static const Word32 oneMinusAccWindowNrgFac = 0x5999999a; /* 0.7 */
static const Word32 invAttackRatioHighBr = 0x0ccccccd; /* inverted lower ratio limit for attacks 0.1*/
static const Word32 invAttackRatioLowBr = 0x072b020c; /* 0.056 */
static const Word32 minAttackNrg = 0x00001e84; /* minimum energy for attacks 1e+6 */
/****************** Routines ****************************/
/*****************************************************************************
*
* function name: InitBlockSwitching
* description: init Block Switching parameter.
* returns: TRUE if success
*
**********************************************************************************/
Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
const Word32 bitRate, const Word16 nChannels)
{
/* select attackRatio */
if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) ||
(sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) {
blockSwitchingControl->invAttackRatio = invAttackRatioHighBr;
}
else {
blockSwitchingControl->invAttackRatio = invAttackRatioLowBr;
}
return(TRUE);
}
static Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
/* Attack in Window 0 */ {1, 3, 3, 1},
/* Attack in Window 1 */ {1, 1, 3, 3},
/* Attack in Window 2 */ {2, 1, 3, 2},
/* Attack in Window 3 */ {3, 1, 3, 1},
/* Attack in Window 4 */ {3, 1, 1, 3},
/* Attack in Window 5 */ {3, 2, 1, 2},
/* Attack in Window 6 */ {3, 3, 1, 1},
/* Attack in Window 7 */ {3, 3, 1, 1}
};
/*****************************************************************************
*
* function name: BlockSwitching
* description: detect this frame whether there is an attack
* returns: TRUE if success
*
**********************************************************************************/
Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
Word16 *timeSignal,
Word32 sampleRate,
Word16 chIncrement)
{
Word32 i, w;
Word32 enM1, enMax;
/* Reset grouping info */
for (i=0; i<TRANS_FAC; i++) {
blockSwitchingControl->groupLen[i] = 0;
}
/* Search for position and amplitude of attack in last frame (1 windows delay) */
blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1],
&blockSwitchingControl->attackIndex,
BLOCK_SWITCH_WINDOWS);
blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex;
/* Set grouping info */
blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
for (i=0; i<MAX_NO_OF_GROUPS; i++) {
blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i];
}
/* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */
if(sampleRate >= 16000) {
/* Save current window energy as last window energy */
for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w];
blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w];
}
/* Calculate unfiltered and filtered energies in subwindows and combine to segments */
CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN);
/* reset attack */
blockSwitchingControl->attack = FALSE;
enMax = 0;
enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1];
for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp;
Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf;
accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg);
enM1_Shf = norm_l(enM1);
windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]);
accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf;
enM1_Tmp = enM1 << enM1_Shf;
windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf;
/* a sliding average of the previous energies */
blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) +
(fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf);
/* if the energy with the ratio is bigger than the average, and the attack and short block */
if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) >
blockSwitchingControl->accWindowNrg ) {
blockSwitchingControl->attack = TRUE;
blockSwitchingControl->lastAttackIndex = w;
}
enM1 = blockSwitchingControl->windowNrgF[1][w];
enMax = max(enMax, enM1);
}
if (enMax < minAttackNrg) {
blockSwitchingControl->attack = FALSE;
}
}
else
{
blockSwitchingControl->attack = TRUE;
}
/* Check if attack spreads over frame border */
if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) {
if (blockSwitchingControl->attackIndex == TRANS_FAC-1) {
blockSwitchingControl->attack = TRUE;
}
blockSwitchingControl->lastattack = FALSE;
}
else {
blockSwitchingControl->lastattack = blockSwitchingControl->attack;
}
blockSwitchingControl->windowSequence = blockSwitchingControl->nextwindowSequence;
if (blockSwitchingControl->attack) {
blockSwitchingControl->nextwindowSequence = SHORT_WINDOW;
}
else {
blockSwitchingControl->nextwindowSequence = LONG_WINDOW;
}
/* update short block group */
if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) {
if (blockSwitchingControl->windowSequence== LONG_WINDOW) {
blockSwitchingControl->windowSequence = START_WINDOW;
}
if (blockSwitchingControl->windowSequence == STOP_WINDOW) {
blockSwitchingControl->windowSequence = SHORT_WINDOW;
blockSwitchingControl->noOfGroups = 3;
blockSwitchingControl->groupLen[0] = 3;
blockSwitchingControl->groupLen[1] = 3;
blockSwitchingControl->groupLen[2] = 2;
}
}
/* update block type */
if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) {
if (blockSwitchingControl->windowSequence == SHORT_WINDOW) {
blockSwitchingControl->nextwindowSequence = STOP_WINDOW;
}
}
return(TRUE);
}
/*****************************************************************************
*
* function name: SrchMaxWithIndex
* description: search for the biggest value in an array
* returns: the max value
*
**********************************************************************************/
static Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n)
{
Word32 max;
Word32 i, idx;
/* Search maximum value in array and return index and value */
max = 0;
idx = 0;
for (i = 0; i < n; i++) {
if (in[i+1] > max) {
max = in[i+1];
idx = i;
}
}
*index = idx;
return(max);
}
/*****************************************************************************
*
* function name: CalcWindowEnergy
* description: calculate the energy before iir-filter and after irr-filter
* returns: TRUE if success
*
**********************************************************************************/
#ifndef ARMV5E
Word32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
Word16 *timeSignal,
Word16 chIncrement,
Word16 windowLen)
{
Word32 w, i, wOffset, tidx, ch;
Word32 accuUE, accuFE;
Word32 tempUnfiltered;
Word32 tempFiltered;
Word32 states0, states1;
Word32 Coeff0, Coeff1;
states0 = blockSwitchingControl->iirStates[0];
states1 = blockSwitchingControl->iirStates[1];
Coeff0 = hiPassCoeff[0];
Coeff1 = hiPassCoeff[1];
tidx = 0;
for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) {
accuUE = 0;
accuFE = 0;
for(i=0; i<windowLen; i++) {
Word32 accu1, accu2, accu3;
Word32 out;
tempUnfiltered = timeSignal[tidx];
tidx = tidx + chIncrement;
accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
accu2 = fixmul( Coeff0, states1 );
accu3 = accu1 - states0;
out = accu3 - accu2;
states0 = accu1;
states1 = out;
tempFiltered = extract_h(out);
accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT;
accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT;
}
blockSwitchingControl->windowNrg[1][w] = accuUE;
blockSwitchingControl->windowNrgF[1][w] = accuFE;
}
blockSwitchingControl->iirStates[0] = states0;
blockSwitchingControl->iirStates[1] = states1;
return(TRUE);
}
#endif
/*****************************************************************************
*
* function name: IIRFilter
* description: calculate the iir-filter for an array
* returns: the result after iir-filter
*
**********************************************************************************/
static Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[])
{
Word32 accu1, accu2, accu3;
Word32 out;
accu1 = L_mpy_ls(coeff[1], in);
accu3 = accu1 - states[0];
accu2 = fixmul( coeff[0], states[1] );
out = accu3 - accu2;
states[0] = accu1;
states[1] = out;
return round16(out);
}
static Word16 synchronizedBlockTypeTable[4][4] = {
/* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW */
/* LONG_WINDOW */{LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
/* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
/* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
/* STOP_WINDOW */{STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW}
};
/*****************************************************************************
*
* function name: SyncBlockSwitching
* description: update block type and group value
* returns: TRUE if success
*
**********************************************************************************/
Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
const Word16 nChannels)
{
Word16 i;
Word16 patchType = LONG_WINDOW;
if (nChannels == 1) { /* Mono */
if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) {
blockSwitchingControlLeft->noOfGroups = 1;
blockSwitchingControlLeft->groupLen[0] = 1;
for (i=1; i<TRANS_FAC; i++) {
blockSwitchingControlLeft->groupLen[i] = 0;
}
}
}
else { /* Stereo common Window */
patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence];
patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence];
/* Set synchronized Blocktype */
blockSwitchingControlLeft->windowSequence = patchType;
blockSwitchingControlRight->windowSequence = patchType;
/* Synchronize grouping info */
if(patchType != SHORT_WINDOW) { /* Long Blocks */
/* Set grouping info */
blockSwitchingControlLeft->noOfGroups = 1;
blockSwitchingControlRight->noOfGroups = 1;
blockSwitchingControlLeft->groupLen[0] = 1;
blockSwitchingControlRight->groupLen[0] = 1;
for (i=1; i<TRANS_FAC; i++) {
blockSwitchingControlLeft->groupLen[i] = 0;
blockSwitchingControlRight->groupLen[i] = 0;
}
}
else {
if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
/* Left Channel wins */
blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
for (i=0; i<TRANS_FAC; i++) {
blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
}
}
else {
/* Right Channel wins */
blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
for (i=0; i<TRANS_FAC; i++) {
blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
}
}
}
} /*endif Mono or Stereo */
return(TRUE);
}

View File

@ -0,0 +1,123 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: channel_map.c
Content: channel mapping functions
*******************************************************************************/
#include "channel_map.h"
#include "bitenc.h"
#include "psy_const.h"
#include "qc_data.h"
static const Word16 maxChannelBits = MAXBITS_COEF;
static Word16 initElement(ELEMENT_INFO* elInfo, ELEMENT_TYPE elType)
{
Word16 error=0;
elInfo->elType=elType;
switch(elInfo->elType) {
case ID_SCE:
elInfo->nChannelsInEl=1;
elInfo->ChannelIndex[0]=0;
elInfo->instanceTag=0;
break;
case ID_CPE:
elInfo->nChannelsInEl=2;
elInfo->ChannelIndex[0]=0;
elInfo->ChannelIndex[1]=1;
elInfo->instanceTag=0;
break;
default:
error=1;
}
return error;
}
Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo)
{
Word16 error;
error = 0;
switch(nChannels) {
case 1:
initElement(elInfo, ID_SCE);
break;
case 2:
initElement(elInfo, ID_CPE);
break;
default:
error=4;
}
return error;
}
Word16 InitElementBits(ELEMENT_BITS *elementBits,
ELEMENT_INFO elInfo,
Word32 bitrateTot,
Word16 averageBitsTot,
Word16 staticBitsTot)
{
Word16 error;
error = 0;
switch(elInfo.nChannelsInEl) {
case 1:
elementBits->chBitrate = bitrateTot;
elementBits->averageBits = averageBitsTot - staticBitsTot;
elementBits->maxBits = maxChannelBits;
elementBits->maxBitResBits = maxChannelBits - averageBitsTot;
elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7);
elementBits->bitResLevel = elementBits->maxBitResBits;
elementBits->relativeBits = 0x4000; /* 1.0f/2 */
break;
case 2:
elementBits->chBitrate = bitrateTot >> 1;
elementBits->averageBits = averageBitsTot - staticBitsTot;
elementBits->maxBits = maxChannelBits << 1;
elementBits->maxBitResBits = (maxChannelBits << 1) - averageBitsTot;
elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7);
elementBits->bitResLevel = elementBits->maxBitResBits;
elementBits->relativeBits = 0x4000; /* 1.0f/2 */
break;
default:
error = 1;
}
return error;
}

View File

@ -0,0 +1,545 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: dyn_bits.c
Content: Noiseless coder module functions
*******************************************************************************/
#include "aac_rom.h"
#include "dyn_bits.h"
#include "bit_cnt.h"
#include "psy_const.h"
/*****************************************************************************
*
* function name: buildBitLookUp
* description: count bits using all possible tables
*
*****************************************************************************/
static void
buildBitLookUp(const Word16 *quantSpectrum,
const Word16 maxSfb,
const Word16 *sfbOffset,
const UWord16 *sfbMax,
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
SECTION_INFO * sectionInfo)
{
Word32 i;
for (i=0; i<maxSfb; i++) {
Word16 sfbWidth, maxVal;
sectionInfo[i].sfbCnt = 1;
sectionInfo[i].sfbStart = i;
sectionInfo[i].sectionBits = INVALID_BITCOUNT;
sectionInfo[i].codeBook = -1;
sfbWidth = sfbOffset[i + 1] - sfbOffset[i];
maxVal = sfbMax[i];
bitCount(quantSpectrum + sfbOffset[i], sfbWidth, maxVal, bitLookUp[i]);
}
}
/*****************************************************************************
*
* function name: findBestBook
* description: essential helper functions
*
*****************************************************************************/
static Word16
findBestBook(const Word16 *bc, Word16 *book)
{
Word32 minBits, j;
minBits = INVALID_BITCOUNT;
for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
if (bc[j] < minBits) {
minBits = bc[j];
*book = j;
}
}
return extract_l(minBits);
}
static Word16
findMinMergeBits(const Word16 *bc1, const Word16 *bc2)
{
Word32 minBits, j, sum;
minBits = INVALID_BITCOUNT;
for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
sum = bc1[j] + bc2[j];
if (sum < minBits) {
minBits = sum;
}
}
return extract_l(minBits);
}
static void
mergeBitLookUp(Word16 *bc1, const Word16 *bc2)
{
Word32 j;
for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
bc1[j] = min(bc1[j] + bc2[j], INVALID_BITCOUNT);
}
}
static Word16
findMaxMerge(const Word16 mergeGainLookUp[MAX_SFB_LONG],
const SECTION_INFO *sectionInfo,
const Word16 maxSfb, Word16 *maxNdx)
{
Word32 i, maxMergeGain;
maxMergeGain = 0;
for (i=0; i+sectionInfo[i].sfbCnt < maxSfb; i += sectionInfo[i].sfbCnt) {
if (mergeGainLookUp[i] > maxMergeGain) {
maxMergeGain = mergeGainLookUp[i];
*maxNdx = i;
}
}
return extract_l(maxMergeGain);
}
static Word16
CalcMergeGain(const SECTION_INFO *sectionInfo,
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
const Word16 *sideInfoTab,
const Word16 ndx1,
const Word16 ndx2)
{
Word32 SplitBits;
Word32 MergeBits;
Word32 MergeGain;
/*
Bit amount for splitted sections
*/
SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits;
MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] +
findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]);
MergeGain = (SplitBits - MergeBits);
return extract_l(MergeGain);
}
/*
sectioning Stage 0:find minimum codbooks
*/
static void
gmStage0(SECTION_INFO * sectionInfo,
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
const Word16 maxSfb)
{
Word32 i;
for (i=0; i<maxSfb; i++) {
/* Side-Info bits will be calculated in Stage 1! */
if (sectionInfo[i].sectionBits == INVALID_BITCOUNT) {
sectionInfo[i].sectionBits = findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
}
}
}
/*
sectioning Stage 1:merge all connected regions with the same code book and
calculate side info
*/
static void
gmStage1(SECTION_INFO * sectionInfo,
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
const Word16 maxSfb,
const Word16 *sideInfoTab)
{
SECTION_INFO * sectionInfo_s;
SECTION_INFO * sectionInfo_e;
Word32 mergeStart, mergeEnd;
mergeStart = 0;
do {
sectionInfo_s = sectionInfo + mergeStart;
for (mergeEnd=mergeStart+1; mergeEnd<maxSfb; mergeEnd++) {
sectionInfo_e = sectionInfo + mergeEnd;
if (sectionInfo_s->codeBook != sectionInfo_e->codeBook)
break;
sectionInfo_s->sfbCnt += 1;
sectionInfo_s->sectionBits += sectionInfo_e->sectionBits;
mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]);
}
sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt];
sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart; /* speed up prev search */
mergeStart = mergeEnd;
} while (mergeStart - maxSfb < 0);
}
/*
sectioning Stage 2:greedy merge algorithm, merge connected sections with
maximum bit gain until no more gain is possible
*/
static void
gmStage2(SECTION_INFO *sectionInfo,
Word16 mergeGainLookUp[MAX_SFB_LONG],
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
const Word16 maxSfb,
const Word16 *sideInfoTab)
{
Word16 i;
for (i=0; i+sectionInfo[i].sfbCnt<maxSfb; i+=sectionInfo[i].sfbCnt) {
mergeGainLookUp[i] = CalcMergeGain(sectionInfo,
bitLookUp,
sideInfoTab,
i,
(i + sectionInfo[i].sfbCnt));
}
while (TRUE) {
Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast;
maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx);
if (maxMergeGain <= 0)
break;
maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
sectionInfo[maxNdx].sfbCnt = sectionInfo[maxNdx].sfbCnt + sectionInfo[maxNdxNext].sfbCnt;
sectionInfo[maxNdx].sectionBits = sectionInfo[maxNdx].sectionBits +
(sectionInfo[maxNdxNext].sectionBits - maxMergeGain);
mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]);
if (maxNdx != 0) {
maxNdxLast = sectionInfo[maxNdx - 1].sfbStart;
mergeGainLookUp[maxNdxLast] = CalcMergeGain(sectionInfo,
bitLookUp,
sideInfoTab,
maxNdxLast,
maxNdx);
}
maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
sectionInfo[maxNdxNext - 1].sfbStart = sectionInfo[maxNdx].sfbStart;
if (maxNdxNext - maxSfb < 0) {
mergeGainLookUp[maxNdx] = CalcMergeGain(sectionInfo,
bitLookUp,
sideInfoTab,
maxNdx,
maxNdxNext);
}
}
}
/*
count bits used by the noiseless coder
*/
static void
noiselessCounter(SECTION_DATA *sectionData,
Word16 mergeGainLookUp[MAX_SFB_LONG],
Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
const Word16 *quantSpectrum,
const UWord16 *maxValueInSfb,
const Word16 *sfbOffset,
const Word32 blockType)
{
Word32 grpNdx, i;
Word16 *sideInfoTab = NULL;
SECTION_INFO *sectionInfo;
/*
use appropriate side info table
*/
switch (blockType)
{
case LONG_WINDOW:
case START_WINDOW:
case STOP_WINDOW:
sideInfoTab = sideInfoTabLong;
break;
case SHORT_WINDOW:
sideInfoTab = sideInfoTabShort;
break;
}
sectionData->noOfSections = 0;
sectionData->huffmanBits = 0;
sectionData->sideInfoBits = 0;
if (sectionData->maxSfbPerGroup == 0)
return;
/*
loop trough groups
*/
for (grpNdx=0; grpNdx<sectionData->sfbCnt; grpNdx+=sectionData->sfbPerGroup) {
sectionInfo = sectionData->sectionInfo + sectionData->noOfSections;
buildBitLookUp(quantSpectrum,
sectionData->maxSfbPerGroup,
sfbOffset + grpNdx,
maxValueInSfb + grpNdx,
bitLookUp,
sectionInfo);
/*
0.Stage
*/
gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup);
/*
1.Stage
*/
gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab);
/*
2.Stage
*/
gmStage2(sectionInfo,
mergeGainLookUp,
bitLookUp,
sectionData->maxSfbPerGroup,
sideInfoTab);
/*
compress output, calculate total huff and side bits
*/
for (i=0; i<sectionData->maxSfbPerGroup; i+=sectionInfo[i].sfbCnt) {
findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx;
sectionData->huffmanBits = (sectionData->huffmanBits +
(sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt]));
sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]);
sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i];
sectionData->noOfSections = sectionData->noOfSections + 1;
}
}
}
/*******************************************************************************
*
* functionname: scfCount
* returns : ---
* description : count bits used by scalefactors.
*
********************************************************************************/
static void scfCount(const Word16 *scalefacGain,
const UWord16 *maxValueInSfb,
SECTION_DATA * sectionData)
{
SECTION_INFO *psectionInfo;
SECTION_INFO *psectionInfom;
/* counter */
Word32 i = 0; /* section counter */
Word32 j = 0; /* sfb counter */
Word32 k = 0; /* current section auxiliary counter */
Word32 m = 0; /* other section auxiliary counter */
Word32 n = 0; /* other sfb auxiliary counter */
/* further variables */
Word32 lastValScf = 0;
Word32 deltaScf = 0;
Flag found = 0;
Word32 scfSkipCounter = 0;
sectionData->scalefacBits = 0;
if (scalefacGain == NULL) {
return;
}
lastValScf = 0;
sectionData->firstScf = 0;
psectionInfo = sectionData->sectionInfo;
for (i=0; i<sectionData->noOfSections; i++) {
if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) {
sectionData->firstScf = psectionInfo->sfbStart;
lastValScf = scalefacGain[sectionData->firstScf];
break;
}
psectionInfo += 1;
}
psectionInfo = sectionData->sectionInfo;
for (i=0; i<sectionData->noOfSections; i++, psectionInfo += 1) {
if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO
&& psectionInfo->codeBook != CODE_BOOK_PNS_NO) {
for (j = psectionInfo->sfbStart;
j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) {
/* check if we can repeat the last value to save bits */
if (maxValueInSfb[j] == 0) {
found = 0;
if (scfSkipCounter == 0) {
/* end of section */
if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) {
found = 0;
}
else {
for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) {
if (maxValueInSfb[k] != 0) {
int tmp = L_abs(scalefacGain[k] - lastValScf);
found = 1;
if ( tmp < CODE_BOOK_SCF_LAV) {
/* save bits */
deltaScf = 0;
}
else {
/* do not save bits */
deltaScf = lastValScf - scalefacGain[j];
lastValScf = scalefacGain[j];
scfSkipCounter = 0;
}
break;
}
/* count scalefactor skip */
scfSkipCounter = scfSkipCounter + 1;
}
}
psectionInfom = psectionInfo + 1;
/* search for the next maxValueInSfb[] != 0 in all other sections */
for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) {
if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) &&
(psectionInfom->codeBook != CODE_BOOK_PNS_NO)) {
for (n = psectionInfom->sfbStart;
n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) {
if (maxValueInSfb[n] != 0) {
found = 1;
if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) {
deltaScf = 0;
}
else {
deltaScf = (lastValScf - scalefacGain[j]);
lastValScf = scalefacGain[j];
scfSkipCounter = 0;
}
break;
}
/* count scalefactor skip */
scfSkipCounter = scfSkipCounter + 1;
}
}
psectionInfom += 1;
}
if (found == 0) {
deltaScf = 0;
scfSkipCounter = 0;
}
}
else {
deltaScf = 0;
scfSkipCounter = scfSkipCounter - 1;
}
}
else {
deltaScf = lastValScf - scalefacGain[j];
lastValScf = scalefacGain[j];
}
sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf);
}
}
}
}
typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1];
Word16
dynBitCount(const Word16 *quantSpectrum,
const UWord16 *maxValueInSfb,
const Word16 *scalefac,
const Word16 blockType,
const Word16 sfbCnt,
const Word16 maxSfbPerGroup,
const Word16 sfbPerGroup,
const Word16 *sfbOffset,
SECTION_DATA *sectionData)
{
sectionData->blockType = blockType;
sectionData->sfbCnt = sfbCnt;
sectionData->sfbPerGroup = sfbPerGroup;
if(sfbPerGroup)
sectionData->noOfGroups = sfbCnt/sfbPerGroup;
else
sectionData->noOfGroups = 0x7fff;
sectionData->maxSfbPerGroup = maxSfbPerGroup;
noiselessCounter(sectionData,
sectionData->mergeGainLookUp,
(lookUpTable)sectionData->bitLookUp,
quantSpectrum,
maxValueInSfb,
sfbOffset,
blockType);
scfCount(scalefac,
maxValueInSfb,
sectionData);
return (sectionData->huffmanBits + sectionData->sideInfoBits +
sectionData->scalefacBits);
}

View File

@ -0,0 +1,188 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: grp_data.c
Content: Short block grouping function
*******************************************************************************/
#include "basic_op.h"
#include "psy_const.h"
#include "interface.h"
#include "grp_data.h"
/*****************************************************************************
*
* function name: groupShortData
* description: group short data for next quantization and coding
*
**********************************************************************************/
void
groupShortData(Word32 *mdctSpectrum,
Word32 *tmpSpectrum,
SFB_THRESHOLD *sfbThreshold,
SFB_ENERGY *sfbEnergy,
SFB_ENERGY *sfbEnergyMS,
SFB_ENERGY *sfbSpreadedEnergy,
const Word16 sfbCnt,
const Word16 *sfbOffset,
const Word16 *sfbMinSnr,
Word16 *groupedSfbOffset,
Word16 *maxSfbPerGroup,
Word16 *groupedSfbMinSnr,
const Word16 noOfGroups,
const Word16 *groupLen)
{
Word32 i, j;
Word32 line;
Word32 sfb;
Word32 grp;
Word32 wnd;
Word32 offset;
Word32 highestSfb;
/* for short: regroup and */
/* cumulate energies und thresholds group-wise . */
/* calculate sfbCnt */
highestSfb = 0;
for (wnd=0; wnd<TRANS_FAC; wnd++) {
for (sfb=sfbCnt - 1; sfb>=highestSfb; sfb--) {
for (line=(sfbOffset[sfb + 1] - 1); line>=sfbOffset[sfb]; line--) {
if (mdctSpectrum[wnd*FRAME_LEN_SHORT+line] != 0) break;
}
if (line >= sfbOffset[sfb]) break;
}
highestSfb = max(highestSfb, sfb);
}
if (highestSfb < 0) {
highestSfb = 0;
}
*maxSfbPerGroup = highestSfb + 1;
/* calculate sfbOffset */
i = 0;
offset = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
groupedSfbOffset[i] = offset + sfbOffset[sfb] * groupLen[grp];
i += 1;
}
offset += groupLen[grp] * FRAME_LEN_SHORT;
}
groupedSfbOffset[i] = FRAME_LEN_LONG;
i += 1;
/* calculate minSnr */
i = 0;
offset = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
groupedSfbMinSnr[i] = sfbMinSnr[sfb];
i += 1;
}
offset += groupLen[grp] * FRAME_LEN_SHORT;
}
/* sum up sfbThresholds */
wnd = 0;
i = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
Word32 thresh = sfbThreshold->sfbShort[wnd][sfb];
for (j=1; j<groupLen[grp]; j++) {
thresh = L_add(thresh, sfbThreshold->sfbShort[wnd+j][sfb]);
}
sfbThreshold->sfbLong[i] = thresh;
i += 1;
}
wnd += groupLen[grp];
}
/* sum up sfbEnergies left/right */
wnd = 0;
i = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
Word32 energy = sfbEnergy->sfbShort[wnd][sfb];
for (j=1; j<groupLen[grp]; j++) {
energy = L_add(energy, sfbEnergy->sfbShort[wnd+j][sfb]);
}
sfbEnergy->sfbLong[i] = energy;
i += 1;
}
wnd += groupLen[grp];
}
/* sum up sfbEnergies mid/side */
wnd = 0;
i = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
Word32 energy = sfbEnergyMS->sfbShort[wnd][sfb];
for (j=1; j<groupLen[grp]; j++) {
energy = L_add(energy, sfbEnergyMS->sfbShort[wnd+j][sfb]);
}
sfbEnergyMS->sfbLong[i] = energy;
i += 1;
}
wnd += groupLen[grp];
}
/* sum up sfbSpreadedEnergies */
wnd = 0;
i = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
Word32 energy = sfbSpreadedEnergy->sfbShort[wnd][sfb];
for (j=1; j<groupLen[grp]; j++) {
energy = L_add(energy, sfbSpreadedEnergy->sfbShort[wnd+j][sfb]);
}
sfbSpreadedEnergy->sfbLong[i] = energy;
i += 1;
}
wnd += groupLen[grp];
}
/* re-group spectrum */
wnd = 0;
i = 0;
for (grp = 0; grp < noOfGroups; grp++) {
for (sfb = 0; sfb < sfbCnt; sfb++) {
for (j = 0; j < groupLen[grp]; j++) {
Word16 lineOffset = FRAME_LEN_SHORT * (wnd + j);
for (line = lineOffset + sfbOffset[sfb]; line < lineOffset + sfbOffset[sfb+1]; line++) {
tmpSpectrum[i] = mdctSpectrum[line];
i = i + 1;
}
}
}
wnd += groupLen[grp];
}
for(i=0;i<FRAME_LEN_LONG;i+=4) {
mdctSpectrum[i] = tmpSpectrum[i];
mdctSpectrum[i+1] = tmpSpectrum[i+1];
mdctSpectrum[i+2] = tmpSpectrum[i+2];
mdctSpectrum[i+3] = tmpSpectrum[i+3];
}
}

View File

@ -0,0 +1,112 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: interface.c
Content: Interface psychoaccoustic/quantizer functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "psy_const.h"
#include "interface.h"
/*****************************************************************************
*
* function name: BuildInterface
* description: update output parameter
*
**********************************************************************************/
void BuildInterface(Word32 *groupedMdctSpectrum,
const Word16 mdctScale,
SFB_THRESHOLD *groupedSfbThreshold,
SFB_ENERGY *groupedSfbEnergy,
SFB_ENERGY *groupedSfbSpreadedEnergy,
const SFB_ENERGY_SUM sfbEnergySumLR,
const SFB_ENERGY_SUM sfbEnergySumMS,
const Word16 windowSequence,
const Word16 windowShape,
const Word16 groupedSfbCnt,
const Word16 *groupedSfbOffset,
const Word16 maxSfbPerGroup,
const Word16 *groupedSfbMinSnr,
const Word16 noOfGroups,
const Word16 *groupLen,
PSY_OUT_CHANNEL *psyOutCh)
{
Word32 j;
Word32 grp;
Word32 mask;
Word16 *tmpV;
/*
copy values to psyOut
*/
psyOutCh->maxSfbPerGroup = maxSfbPerGroup;
psyOutCh->sfbCnt = groupedSfbCnt;
if(noOfGroups)
psyOutCh->sfbPerGroup = groupedSfbCnt/ noOfGroups;
else
psyOutCh->sfbPerGroup = 0x7fff;
psyOutCh->windowSequence = windowSequence;
psyOutCh->windowShape = windowShape;
psyOutCh->mdctScale = mdctScale;
psyOutCh->mdctSpectrum = groupedMdctSpectrum;
psyOutCh->sfbEnergy = groupedSfbEnergy->sfbLong;
psyOutCh->sfbThreshold = groupedSfbThreshold->sfbLong;
psyOutCh->sfbSpreadedEnergy = groupedSfbSpreadedEnergy->sfbLong;
tmpV = psyOutCh->sfbOffsets;
for(j=0; j<groupedSfbCnt + 1; j++) {
*tmpV++ = groupedSfbOffset[j];
}
tmpV = psyOutCh->sfbMinSnr;
for(j=0;j<groupedSfbCnt; j++) {
*tmpV++ = groupedSfbMinSnr[j];
}
/* generate grouping mask */
mask = 0;
for (grp = 0; grp < noOfGroups; grp++) {
mask = mask << 1;
for (j=1; j<groupLen[grp]; j++) {
mask = mask << 1;
mask |= 1;
}
}
psyOutCh->groupingMask = mask;
if (windowSequence != SHORT_WINDOW) {
psyOutCh->sfbEnSumLR = sfbEnergySumLR.sfbLong;
psyOutCh->sfbEnSumMS = sfbEnergySumMS.sfbLong;
}
else {
Word32 i;
Word32 accuSumMS=0;
Word32 accuSumLR=0;
Word32 *pSumMS = sfbEnergySumMS.sfbShort;
Word32 *pSumLR = sfbEnergySumLR.sfbShort;
for (i=TRANS_FAC; i; i--) {
accuSumLR = L_add(accuSumLR, *pSumLR); pSumLR++;
accuSumMS = L_add(accuSumMS, *pSumMS); pSumMS++;
}
psyOutCh->sfbEnSumMS = accuSumMS;
psyOutCh->sfbEnSumLR = accuSumLR;
}
}

View File

@ -0,0 +1,145 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: line_pe.c
Content: Perceptual entropie module functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "typedef.h"
#include "line_pe.h"
static const Word16 C1_I = 12; /* log(8.0)/log(2) *4 */
static const Word32 C2_I = 10830; /* log(2.5)/log(2) * 1024 * 4 * 2 */
static const Word16 C3_I = 573; /* (1-C2/C1) *1024 */
/*****************************************************************************
*
* function name: prepareSfbPe
* description: constants that do not change during successive pe calculations
*
**********************************************************************************/
void prepareSfbPe(PE_DATA *peData,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
const Word16 nChannels,
const Word16 peOffset)
{
Word32 sfbGrp, sfb;
Word32 ch;
for(ch=0; ch<nChannels; ch++) {
PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
PE_CHANNEL_DATA *peChanData=&peData->peChannelData[ch];
for(sfbGrp=0;sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){
for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
peChanData->sfbNLines4[sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb];
sfbNRelevantLines[ch][sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb] >> 2;
peChanData->sfbLdEnergy[sfbGrp+sfb] = logSfbEnergy[ch][sfbGrp+sfb];
}
}
}
peData->offset = peOffset;
}
/*****************************************************************************
*
* function name: calcSfbPe
* description: constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr)
*
**********************************************************************************/
void calcSfbPe(PE_DATA *peData,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
const Word16 nChannels)
{
Word32 ch;
Word32 sfbGrp, sfb;
Word32 nLines4;
Word32 ldThr, ldRatio;
Word32 pe, constPart, nActiveLines;
peData->pe = peData->offset;
peData->constPart = 0;
peData->nActiveLines = 0;
for(ch=0; ch<nChannels; ch++) {
PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
const Word32 *sfbEnergy = psyOutChan->sfbEnergy;
const Word32 *sfbThreshold = psyOutChan->sfbThreshold;
pe = 0;
constPart = 0;
nActiveLines = 0;
for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
Word32 nrg = sfbEnergy[sfbGrp+sfb];
Word32 thres = sfbThreshold[sfbGrp+sfb];
Word32 sfbLDEn = peChanData->sfbLdEnergy[sfbGrp+sfb];
if (nrg > thres) {
ldThr = iLog4(thres);
ldRatio = sfbLDEn - ldThr;
nLines4 = peChanData->sfbNLines4[sfbGrp+sfb];
/* sfbPe = nl*log2(en/thr)*/
if (ldRatio >= C1_I) {
peChanData->sfbPe[sfbGrp+sfb] = (nLines4*ldRatio + 8) >> 4;
peChanData->sfbConstPart[sfbGrp+sfb] = ((nLines4*sfbLDEn)) >> 4;
}
else {
/* sfbPe = nl*(c2 + c3*log2(en/thr))*/
peChanData->sfbPe[sfbGrp+sfb] = extract_l((L_mpy_wx(
(C2_I + C3_I * ldRatio * 2) << 4, nLines4) + 4) >> 3);
peChanData->sfbConstPart[sfbGrp+sfb] = extract_l(( L_mpy_wx(
(C2_I + C3_I * sfbLDEn * 2) << 4, nLines4) + 4) >> 3);
nLines4 = (nLines4 * C3_I + (1024<<1)) >> 10;
}
peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines4 >> 2;
}
else {
peChanData->sfbPe[sfbGrp+sfb] = 0;
peChanData->sfbConstPart[sfbGrp+sfb] = 0;
peChanData->sfbNActiveLines[sfbGrp+sfb] = 0;
}
pe = pe + peChanData->sfbPe[sfbGrp+sfb];
constPart = constPart + peChanData->sfbConstPart[sfbGrp+sfb];
nActiveLines = nActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
}
}
peChanData->pe = saturate(pe);
peChanData->constPart = saturate(constPart);
peChanData->nActiveLines = saturate(nActiveLines);
pe += peData->pe;
peData->pe = saturate(pe);
constPart += peData->constPart;
peData->constPart = saturate(constPart);
nActiveLines += peData->nActiveLines;
peData->nActiveLines = saturate(nActiveLines);
}
}

View File

@ -0,0 +1,107 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: mem_align.c
Content: Memory alloc alignments functions
*******************************************************************************/
#include "memalign.h"
/*****************************************************************************
*
* function name: mem_malloc
* description: malloc the alignments memory
* returns: the point of the memory
*
**********************************************************************************/
void *
mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID)
{
int ret;
unsigned char *mem_ptr;
VO_MEM_INFO MemInfo;
if (!alignment) {
MemInfo.Flag = 0;
MemInfo.Size = size + 1;
ret = pMemop->Alloc(CodecID, &MemInfo);
if(ret != 0)
return 0;
mem_ptr = (unsigned char *)MemInfo.VBuffer;
pMemop->Set(CodecID, mem_ptr, 0, size + 1);
*mem_ptr = (unsigned char)1;
return ((void *)(mem_ptr+1));
} else {
unsigned char *tmp;
MemInfo.Flag = 0;
MemInfo.Size = size + alignment;
ret = pMemop->Alloc(CodecID, &MemInfo);
if(ret != 0)
return 0;
tmp = (unsigned char *)MemInfo.VBuffer;
pMemop->Set(CodecID, tmp, 0, size + alignment);
mem_ptr =
(unsigned char *) ((unsigned int) (tmp + alignment - 1) &
(~((unsigned int) (alignment - 1))));
if (mem_ptr == tmp)
mem_ptr += alignment;
*(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp);
return ((void *)mem_ptr);
}
return(0);
}
/*****************************************************************************
*
* function name: mem_free
* description: free the memory
*
*******************************************************************************/
void
mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID)
{
unsigned char *ptr;
if (mem_ptr == 0)
return;
ptr = mem_ptr;
ptr -= *(ptr - 1);
pMemop->Free(CodecID, ptr);
}

View File

@ -0,0 +1,139 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: ms_stereo.c
Content: MS stereo processing function
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "psy_const.h"
#include "ms_stereo.h"
/********************************************************************************
*
* function name: MsStereoProcessing
* description: detect use ms stereo or not
* if ((min(thrLn, thrRn)*min(thrLn, thrRn))/(enMn*enSn))
* >= ((thrLn *thrRn)/(enLn*enRn)) then ms stereo
*
**********************************************************************************/
void MsStereoProcessing(Word32 *sfbEnergyLeft,
Word32 *sfbEnergyRight,
const Word32 *sfbEnergyMid,
const Word32 *sfbEnergySide,
Word32 *mdctSpectrumLeft,
Word32 *mdctSpectrumRight,
Word32 *sfbThresholdLeft,
Word32 *sfbThresholdRight,
Word32 *sfbSpreadedEnLeft,
Word32 *sfbSpreadedEnRight,
Word16 *msDigest,
Word16 *msMask,
const Word16 sfbCnt,
const Word16 sfbPerGroup,
const Word16 maxSfbPerGroup,
const Word16 *sfbOffset) {
Word32 temp;
Word32 sfb,sfboffs, j;
Word32 msMaskTrueSomewhere = 0;
Word32 msMaskFalseSomewhere = 0;
for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
for (sfboffs=0;sfboffs<maxSfbPerGroup;sfboffs++) {
Word32 temp;
Word32 pnlr,pnms;
Word32 minThreshold;
Word32 thrL, thrR, nrgL, nrgR;
Word32 idx, shift;
idx = sfb + sfboffs;
thrL = sfbThresholdLeft[idx];
thrR = sfbThresholdRight[idx];
nrgL = sfbEnergyLeft[idx];
nrgR = sfbEnergyRight[idx];
minThreshold = min(thrL, thrR);
nrgL = max(nrgL,thrL) + 1;
shift = norm_l(nrgL);
nrgL = Div_32(thrL << shift, nrgL << shift);
nrgR = max(nrgR,thrR) + 1;
shift = norm_l(nrgR);
nrgR = Div_32(thrR << shift, nrgR << shift);
pnlr = fixmul(nrgL, nrgR);
nrgL = sfbEnergyMid[idx];
nrgR = sfbEnergySide[idx];
nrgL = max(nrgL,minThreshold) + 1;
shift = norm_l(nrgL);
nrgL = Div_32(minThreshold << shift, nrgL << shift);
nrgR = max(nrgR,minThreshold) + 1;
shift = norm_l(nrgR);
nrgR = Div_32(minThreshold << shift, nrgR << shift);
pnms = fixmul(nrgL, nrgR);
temp = (pnlr + 1) / ((pnms >> 8) + 1);
temp = pnms - pnlr;
if( temp > 0 ){
msMask[idx] = 1;
msMaskTrueSomewhere = 1;
for (j=sfbOffset[idx]; j<sfbOffset[idx+1]; j++) {
Word32 left, right;
left = (mdctSpectrumLeft[j] >> 1);
right = (mdctSpectrumRight[j] >> 1);
mdctSpectrumLeft[j] = left + right;
mdctSpectrumRight[j] = left - right;
}
sfbThresholdLeft[idx] = minThreshold;
sfbThresholdRight[idx] = minThreshold;
sfbEnergyLeft[idx] = sfbEnergyMid[idx];
sfbEnergyRight[idx] = sfbEnergySide[idx];
sfbSpreadedEnRight[idx] = min(sfbSpreadedEnLeft[idx],sfbSpreadedEnRight[idx]) >> 1;
sfbSpreadedEnLeft[idx] = sfbSpreadedEnRight[idx];
}
else {
msMask[idx] = 0;
msMaskFalseSomewhere = 1;
}
}
if ( msMaskTrueSomewhere ) {
if(msMaskFalseSomewhere ) {
*msDigest = SI_MS_MASK_SOME;
} else {
*msDigest = SI_MS_MASK_ALL;
}
} else {
*msDigest = SI_MS_MASK_NONE;
}
}
}

View File

@ -0,0 +1,113 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: pre_echo_control.c
Content: Pre echo control functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "oper_32b.h"
#include "pre_echo_control.h"
/*****************************************************************************
*
* function name:InitPreEchoControl
* description: init pre echo control parameter
*
*****************************************************************************/
void InitPreEchoControl(Word32 *pbThresholdNm1,
Word16 numPb,
Word32 *pbThresholdQuiet)
{
Word16 pb;
for(pb=0; pb<numPb; pb++) {
pbThresholdNm1[pb] = pbThresholdQuiet[pb];
}
}
/*****************************************************************************
*
* function name:PreEchoControl
* description: update shreshold to avoid pre echo
* thr(n) = max(rpmin*thrq(n), min(thrq(n), rpelev*thrq1(n)))
*
*
*****************************************************************************/
void PreEchoControl(Word32 *pbThresholdNm1,
Word16 numPb,
Word32 maxAllowedIncreaseFactor,
Word16 minRemainingThresholdFactor,
Word32 *pbThreshold,
Word16 mdctScale,
Word16 mdctScalenm1)
{
Word32 i;
Word32 tmpThreshold1, tmpThreshold2;
Word32 scaling;
/* maxAllowedIncreaseFactor is hard coded to 2 */
(void)maxAllowedIncreaseFactor;
scaling = ((mdctScale - mdctScalenm1) << 1);
if ( scaling > 0 ) {
for(i = 0; i < numPb; i++) {
tmpThreshold1 = pbThresholdNm1[i] >> (scaling-1);
tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
/* copy thresholds to internal memory */
pbThresholdNm1[i] = pbThreshold[i];
if(pbThreshold[i] > tmpThreshold1) {
pbThreshold[i] = tmpThreshold1;
}
if(tmpThreshold2 > pbThreshold[i]) {
pbThreshold[i] = tmpThreshold2;
}
}
}
else {
scaling = -scaling;
for(i = 0; i < numPb; i++) {
tmpThreshold1 = pbThresholdNm1[i] << 1;
tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
/* copy thresholds to internal memory */
pbThresholdNm1[i] = pbThreshold[i];
if(((pbThreshold[i] >> scaling) > tmpThreshold1)) {
pbThreshold[i] = tmpThreshold1 << scaling;
}
if(tmpThreshold2 > pbThreshold[i]) {
pbThreshold[i] = tmpThreshold2;
}
}
}
}

View File

@ -0,0 +1,505 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_configuration.c
Content: Psychoaccoustic configuration functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "psy_configuration.h"
#include "adj_thr.h"
#include "aac_rom.h"
#define BARC_SCALE 100 /* integer barc values are scaled with 100 */
#define LOG2_1000 301 /* log2*1000 */
#define PI2_1000 1571 /* pi/2*1000*/
#define ATAN_COEF1 3560 /* 1000/0.280872f*/
#define ATAN_COEF2 281 /* 1000*0.280872f*/
typedef struct{
Word32 sampleRate;
const UWord8 *paramLong;
const UWord8 *paramShort;
}SFB_INFO_TAB;
static const Word16 ABS_LEV = 20;
static const Word16 BARC_THR_QUIET[] = {15, 10, 7, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3, 5, 10, 20, 30};
static const Word16 max_bark = 24; /* maximum bark-value */
static const Word16 maskLow = 30; /* in 1dB/bark */
static const Word16 maskHigh = 15; /* in 1*dB/bark */
static const Word16 c_ratio = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */
static const Word16 maskLowSprEnLong = 30; /* in 1dB/bark */
static const Word16 maskHighSprEnLong = 20; /* in 1dB/bark */
static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */
static const Word16 maskLowSprEnShort = 20; /* in 1dB/bark */
static const Word16 maskHighSprEnShort = 15; /* in 1dB/bark */
static const Word16 c_minRemainingThresholdFactor = 0x0148; /* 0.01 *(1 << 15)*/
static const Word32 c_maxsnr = 0x66666666; /* upper limit is -1 dB */
static const Word32 c_minsnr = 0x00624dd3; /* lower limit is -25 dB */
static const Word32 c_maxClipEnergyLong = 0x77359400; /* 2.0e9f*/
static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/
Word32 GetSRIndex(Word32 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;
}
/*********************************************************************************
*
* function name: atan_1000
* description: calculates 1000*atan(x/1000)
* based on atan approx for x > 0
* atan(x) = x/((float)1.0f+(float)0.280872f*x*x) if x < 1
* = pi/2 - x/((float)0.280872f +x*x) if x >= 1
* return: 1000*atan(x/1000)
*
**********************************************************************************/
static Word16 atan_1000(Word32 val)
{
Word32 y;
if(L_sub(val, 1000) < 0) {
y = extract_l(((1000 * val) / (1000 + ((val * val) / ATAN_COEF1))));
}
else {
y = PI2_1000 - ((1000 * val) / (ATAN_COEF2 + ((val * val) / 1000)));
}
return extract_l(y);
}
/*****************************************************************************
*
* function name: BarcLineValue
* description: Calculates barc value for one frequency line
* returns: barc value of line * BARC_SCALE
* input: number of lines in transform, index of line to check, Fs
* output:
*
*****************************************************************************/
static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFreq)
{
Word32 center_freq, temp, bvalFFTLine;
/* center frequency of fft line */
center_freq = (fftLine * samplingFreq) / (noOfLines << 1);
temp = atan_1000((center_freq << 2) / (3*10));
bvalFFTLine =
(26600 * atan_1000((center_freq*76) / 100) + 7*temp*temp) / (2*1000*1000 / BARC_SCALE);
return saturate(bvalFFTLine);
}
/*****************************************************************************
*
* function name: initThrQuiet
* description: init thredhold in quiet
*
*****************************************************************************/
static void initThrQuiet(Word16 numPb,
Word16 *pbOffset,
Word16 *pbBarcVal,
Word32 *pbThresholdQuiet) {
Word16 i;
Word16 barcThrQuiet;
for(i=0; i<numPb; i++) {
Word16 bv1, bv2;
if (i>0)
bv1 = (pbBarcVal[i] + pbBarcVal[i-1]) >> 1;
else
bv1 = pbBarcVal[i] >> 1;
if (i < (numPb - 1))
bv2 = (pbBarcVal[i] + pbBarcVal[i+1]) >> 1;
else {
bv2 = pbBarcVal[i];
}
bv1 = min((bv1 / BARC_SCALE), max_bark);
bv2 = min((bv2 / BARC_SCALE), max_bark);
barcThrQuiet = min(BARC_THR_QUIET[bv1], BARC_THR_QUIET[bv2]);
/*
we calculate
pow(10.0f,(float)(barcThrQuiet - ABS_LEV)*0.1)*(float)ABS_LOW*(pbOffset[i+1] - pbOffset[i]);
*/
pbThresholdQuiet[i] = pow2_xy((((barcThrQuiet - ABS_LEV) * 100) +
LOG2_1000*(14+2*LOG_NORM_PCM)), LOG2_1000) * (pbOffset[i+1] - pbOffset[i]);
}
}
/*****************************************************************************
*
* function name: initSpreading
* description: init energy spreading parameter
*
*****************************************************************************/
static void initSpreading(Word16 numPb,
Word16 *pbBarcValue,
Word16 *pbMaskLoFactor,
Word16 *pbMaskHiFactor,
Word16 *pbMaskLoFactorSprEn,
Word16 *pbMaskHiFactorSprEn,
const Word32 bitrate,
const Word16 blockType)
{
Word16 i;
Word16 maskLowSprEn, maskHighSprEn;
if (sub(blockType, SHORT_WINDOW) != 0) {
maskLowSprEn = maskLowSprEnLong;
if (bitrate > 22000)
maskHighSprEn = maskHighSprEnLong;
else
maskHighSprEn = maskHighSprEnLongLowBr;
}
else {
maskLowSprEn = maskLowSprEnShort;
maskHighSprEn = maskHighSprEnShort;
}
for(i=0; i<numPb; i++) {
if (i > 0) {
Word32 dbVal;
Word16 dbark = pbBarcValue[i] - pbBarcValue[i-1];
/*
we calulate pow(10.0f, -0.1*dbVal/BARC_SCALE)
*/
dbVal = (maskHigh * dbark);
pbMaskHiFactor[i] = round16(pow2_xy(L_negate(dbVal), (Word32)LOG2_1000)); /* 0.301 log10(2) */
dbVal = (maskLow * dbark);
pbMaskLoFactor[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
dbVal = (maskHighSprEn * dbark);
pbMaskHiFactorSprEn[i] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
dbVal = (maskLowSprEn * dbark);
pbMaskLoFactorSprEn[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
}
else {
pbMaskHiFactor[i] = 0;
pbMaskLoFactor[numPb-1] = 0;
pbMaskHiFactorSprEn[i] = 0;
pbMaskLoFactorSprEn[numPb-1] = 0;
}
}
}
/*****************************************************************************
*
* function name: initBarcValues
* description: init bark value
*
*****************************************************************************/
static void initBarcValues(Word16 numPb,
Word16 *pbOffset,
Word16 numLines,
Word32 samplingFrequency,
Word16 *pbBval)
{
Word16 i;
Word16 pbBval0, pbBval1;
pbBval0 = 0;
for(i=0; i<numPb; i++){
pbBval1 = BarcLineValue(numLines, pbOffset[i+1], samplingFrequency);
pbBval[i] = (pbBval0 + pbBval1) >> 1;
pbBval0 = pbBval1;
}
}
/*****************************************************************************
*
* function name: initMinSnr
* description: calculate min snr parameter
* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)
*
*****************************************************************************/
static void initMinSnr(const Word32 bitrate,
const Word32 samplerate,
const Word16 numLines,
const Word16 *sfbOffset,
const Word16 *pbBarcVal,
const Word16 sfbActive,
Word16 *sfbMinSnr)
{
Word16 sfb;
Word16 barcWidth;
Word16 pePerWindow;
Word32 pePart;
Word32 snr;
Word16 pbVal0, pbVal1, shift;
/* relative number of active barks */
pePerWindow = bits2pe(extract_l((bitrate * numLines) / samplerate));
pbVal0 = 0;
for (sfb=0; sfb<sfbActive; sfb++) {
pbVal1 = (pbBarcVal[sfb] << 1) - pbVal0;
barcWidth = pbVal1 - pbVal0;
pbVal0 = pbVal1;
/* allow at least 2.4% of pe for each active barc */
pePart = ((pePerWindow * 24) * (max_bark * barcWidth)) /
(pbBarcVal[sfbActive-1] * (sfbOffset[sfb+1] - sfbOffset[sfb]));
pePart = min(pePart, 8400);
pePart = max(pePart, 1400);
/* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)*/
/* we add an offset of 2^16 to the pow functions */
/* 0xc000 = 1.5*(1 << 15)*/
snr = pow2_xy((pePart - 16*1000),1000) - 0x0000c000;
if(snr > 0x00008000)
{
shift = norm_l(snr);
snr = Div_32(0x00008000 << shift, snr << shift);
}
else
{
snr = 0x7fffffff;
}
/* upper limit is -1 dB */
snr = min(snr, c_maxsnr);
/* lower limit is -25 dB */
snr = max(snr, c_minsnr);
sfbMinSnr[sfb] = round16(snr);
}
}
/*****************************************************************************
*
* function name: InitPsyConfigurationLong
* description: init long block psychoacoustic configuration
*
*****************************************************************************/
Word16 InitPsyConfigurationLong(Word32 bitrate,
Word32 samplerate,
Word16 bandwidth,
PSY_CONFIGURATION_LONG *psyConf)
{
Word32 samplerateindex;
Word16 sfbBarcVal[MAX_SFB_LONG];
Word16 sfb;
/*
init sfb table
*/
samplerateindex = GetSRIndex(samplerate);
psyConf->sfbCnt = sfBandTotalLong[samplerateindex];
psyConf->sfbOffset = sfBandTabLong + sfBandTabLongOffset[samplerateindex];
psyConf->sampRateIdx = samplerateindex;
/*
calculate barc values for each pb
*/
initBarcValues(psyConf->sfbCnt,
psyConf->sfbOffset,
psyConf->sfbOffset[psyConf->sfbCnt],
samplerate,
sfbBarcVal);
/*
init thresholds in quiet
*/
initThrQuiet(psyConf->sfbCnt,
psyConf->sfbOffset,
sfbBarcVal,
psyConf->sfbThresholdQuiet);
/*
calculate spreading function
*/
initSpreading(psyConf->sfbCnt,
sfbBarcVal,
psyConf->sfbMaskLowFactor,
psyConf->sfbMaskHighFactor,
psyConf->sfbMaskLowFactorSprEn,
psyConf->sfbMaskHighFactorSprEn,
bitrate,
LONG_WINDOW);
/*
init ratio
*/
psyConf->ratio = c_ratio;
psyConf->maxAllowedIncreaseFactor = 2;
psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; /* 0.01 *(1 << 15)*/
psyConf->clipEnergy = c_maxClipEnergyLong;
psyConf->lowpassLine = extract_l((bandwidth<<1) * FRAME_LEN_LONG / samplerate);
for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
if (sub(psyConf->sfbOffset[sfb], psyConf->lowpassLine) >= 0)
break;
}
psyConf->sfbActive = sfb;
/*
calculate minSnr
*/
initMinSnr(bitrate,
samplerate,
psyConf->sfbOffset[psyConf->sfbCnt],
psyConf->sfbOffset,
sfbBarcVal,
psyConf->sfbActive,
psyConf->sfbMinSnr);
return(0);
}
/*****************************************************************************
*
* function name: InitPsyConfigurationShort
* description: init short block psychoacoustic configuration
*
*****************************************************************************/
Word16 InitPsyConfigurationShort(Word32 bitrate,
Word32 samplerate,
Word16 bandwidth,
PSY_CONFIGURATION_SHORT *psyConf)
{
Word32 samplerateindex;
Word16 sfbBarcVal[MAX_SFB_SHORT];
Word16 sfb;
/*
init sfb table
*/
samplerateindex = GetSRIndex(samplerate);
psyConf->sfbCnt = sfBandTotalShort[samplerateindex];
psyConf->sfbOffset = sfBandTabShort + sfBandTabShortOffset[samplerateindex];
psyConf->sampRateIdx = samplerateindex;
/*
calculate barc values for each pb
*/
initBarcValues(psyConf->sfbCnt,
psyConf->sfbOffset,
psyConf->sfbOffset[psyConf->sfbCnt],
samplerate,
sfbBarcVal);
/*
init thresholds in quiet
*/
initThrQuiet(psyConf->sfbCnt,
psyConf->sfbOffset,
sfbBarcVal,
psyConf->sfbThresholdQuiet);
/*
calculate spreading function
*/
initSpreading(psyConf->sfbCnt,
sfbBarcVal,
psyConf->sfbMaskLowFactor,
psyConf->sfbMaskHighFactor,
psyConf->sfbMaskLowFactorSprEn,
psyConf->sfbMaskHighFactorSprEn,
bitrate,
SHORT_WINDOW);
/*
init ratio
*/
psyConf->ratio = c_ratio;
psyConf->maxAllowedIncreaseFactor = 2;
psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor;
psyConf->clipEnergy = c_maxClipEnergyShort;
psyConf->lowpassLine = extract_l(((bandwidth << 1) * FRAME_LEN_SHORT) / samplerate);
for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine)
break;
}
psyConf->sfbActive = sfb;
/*
calculate minSnr
*/
initMinSnr(bitrate,
samplerate,
psyConf->sfbOffset[psyConf->sfbCnt],
psyConf->sfbOffset,
sfbBarcVal,
psyConf->sfbActive,
psyConf->sfbMinSnr);
return(0);
}

View File

@ -0,0 +1,810 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: psy_main.c
Content: Psychoacoustic major functions
*******************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "psy_const.h"
#include "block_switch.h"
#include "transform.h"
#include "spreading.h"
#include "pre_echo_control.h"
#include "band_nrg.h"
#include "psy_configuration.h"
#include "psy_data.h"
#include "ms_stereo.h"
#include "interface.h"
#include "psy_main.h"
#include "grp_data.h"
#include "tns_func.h"
#include "memalign.h"
/* long start short stop */
static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
/*
forward definitions
*/
static Word16 advancePsychLong(PSY_DATA* psyData,
TNS_DATA* tnsData,
PSY_CONFIGURATION_LONG *hPsyConfLong,
PSY_OUT_CHANNEL* psyOutChannel,
Word32 *pScratchTns,
const TNS_DATA *tnsData2,
const Word16 ch);
static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
const PSY_CONFIGURATION_LONG *hPsyConfLong);
static Word16 advancePsychShort(PSY_DATA* psyData,
TNS_DATA* tnsData,
const PSY_CONFIGURATION_SHORT *hPsyConfShort,
PSY_OUT_CHANNEL* psyOutChannel,
Word32 *pScratchTns,
const TNS_DATA *tnsData2,
const Word16 ch);
static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
const PSY_CONFIGURATION_SHORT *hPsyConfShort);
/*****************************************************************************
*
* function name: PsyNew
* description: allocates memory for psychoacoustic
* returns: an error code
* input: pointer to a psych handle
*
*****************************************************************************/
Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
{
Word16 i;
Word32 *mdctSpectrum;
Word32 *scratchTNS;
Word16 *mdctDelayBuffer;
mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
if(NULL == mdctSpectrum)
return 1;
scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
if(NULL == scratchTNS)
{
return 1;
}
mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
if(NULL == mdctDelayBuffer)
{
return 1;
}
for (i=0; i<nChan; i++){
hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;
hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
}
hPsy->pScratchTns = scratchTNS;
return 0;
}
/*****************************************************************************
*
* function name: PsyDelete
* description: allocates memory for psychoacoustic
* returns: an error code
*
*****************************************************************************/
Word16 PsyDelete(PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP)
{
Word32 nch;
if(hPsy)
{
if(hPsy->psyData[0].mdctDelayBuffer)
mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);
if(hPsy->psyData[0].mdctSpectrum)
mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);
for (nch=0; nch<MAX_CHANNELS; nch++){
hPsy->psyData[nch].mdctDelayBuffer = NULL;
hPsy->psyData[nch].mdctSpectrum = NULL;
}
if(hPsy->pScratchTns)
{
mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);
hPsy->pScratchTns = NULL;
}
}
return 0;
}
/*****************************************************************************
*
* function name: PsyOutNew
* description: allocates memory for psyOut struc
* returns: an error code
* input: pointer to a psych handle
*
*****************************************************************************/
Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
{
pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
/*
alloc some more stuff, tbd
*/
return 0;
}
/*****************************************************************************
*
* function name: PsyOutDelete
* description: allocates memory for psychoacoustic
* returns: an error code
*
*****************************************************************************/
Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
{
hPsyOut=NULL;
return 0;
}
/*****************************************************************************
*
* function name: psyMainInit
* description: initializes psychoacoustic
* returns: an error code
*
*****************************************************************************/
Word16 psyMainInit(PSY_KERNEL *hPsy,
Word32 sampleRate,
Word32 bitRate,
Word16 channels,
Word16 tnsMask,
Word16 bandwidth)
{
Word16 ch, err;
Word32 channelBitRate = bitRate/channels;
err = InitPsyConfigurationLong(channelBitRate,
sampleRate,
bandwidth,
&(hPsy->psyConfLong));
if (!err) {
hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;
err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
&hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
}
if (!err)
err = InitPsyConfigurationShort(channelBitRate,
sampleRate,
bandwidth,
&hPsy->psyConfShort);
if (!err) {
err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
&hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
}
if (!err)
for(ch=0;ch < channels;ch++){
InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
bitRate, channels);
InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
hPsy->psyConfLong.sfbCnt,
hPsy->psyConfLong.sfbThresholdQuiet);
hPsy->psyData[ch].mdctScalenm1 = 0;
}
return(err);
}
/*****************************************************************************
*
* function name: psyMain
* description: psychoacoustic main function
* returns: an error code
*
* This function assumes that enough input data is in the modulo buffer.
*
*****************************************************************************/
Word16 psyMain(Word16 nChannels,
ELEMENT_INFO *elemInfo,
Word16 *timeSignal,
PSY_DATA psyData[MAX_CHANNELS],
TNS_DATA tnsData[MAX_CHANNELS],
PSY_CONFIGURATION_LONG *hPsyConfLong,
PSY_CONFIGURATION_SHORT *hPsyConfShort,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
PSY_OUT_ELEMENT *psyOutElement,
Word32 *pScratchTns,
Word32 sampleRate)
{
Word16 maxSfbPerGroup[MAX_CHANNELS];
Word16 mdctScalingArray[MAX_CHANNELS];
Word16 ch; /* counts through channels */
Word16 sfb; /* counts through scalefactor bands */
Word16 line; /* counts through lines */
Word16 channels;
Word16 maxScale;
channels = elemInfo->nChannelsInEl;
maxScale = 0;
/* block switching */
for(ch = 0; ch < channels; ch++) {
BlockSwitching(&psyData[ch].blockSwitchingControl,
timeSignal+elemInfo->ChannelIndex[ch],
sampleRate,
nChannels);
}
/* synch left and right block type */
SyncBlockSwitching(&psyData[0].blockSwitchingControl,
&psyData[1].blockSwitchingControl,
channels);
/* transform
and get maxScale (max mdctScaling) for all channels */
for(ch=0; ch<channels; ch++) {
Transform_Real(psyData[ch].mdctDelayBuffer,
timeSignal+elemInfo->ChannelIndex[ch],
nChannels,
psyData[ch].mdctSpectrum,
&(mdctScalingArray[ch]),
psyData[ch].blockSwitchingControl.windowSequence);
maxScale = max(maxScale, mdctScalingArray[ch]);
}
/* common scaling for all channels */
for (ch=0; ch<channels; ch++) {
Word16 scaleDiff = maxScale - mdctScalingArray[ch];
if (scaleDiff > 0) {
Word32 *Spectrum = psyData[ch].mdctSpectrum;
for(line=0; line<FRAME_LEN_LONG; line++) {
*Spectrum = (*Spectrum) >> scaleDiff;
Spectrum++;
}
}
psyData[ch].mdctScale = maxScale;
}
for (ch=0; ch<channels; ch++) {
if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
/* update long block parameter */
advancePsychLong(&psyData[ch],
&tnsData[ch],
hPsyConfLong,
&psyOutChannel[ch],
pScratchTns,
&tnsData[1 - ch],
ch);
/* determine maxSfb */
for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
if (psyData[ch].mdctSpectrum[line] != 0) break;
}
if (line >= hPsyConfLong->sfbOffset[sfb]) break;
}
maxSfbPerGroup[ch] = sfb + 1;
/* Calc bandwise energies for mid and side channel
Do it only if 2 channels exist */
if (ch == 1)
advancePsychLongMS(psyData, hPsyConfLong);
}
else {
advancePsychShort(&psyData[ch],
&tnsData[ch],
hPsyConfShort,
&psyOutChannel[ch],
pScratchTns,
&tnsData[1 - ch],
ch);
/* Calc bandwise energies for mid and side channel
Do it only if 2 channels exist */
if (ch == 1)
advancePsychShortMS (psyData, hPsyConfShort);
}
}
/* group short data */
for(ch=0; ch<channels; ch++) {
if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
groupShortData(psyData[ch].mdctSpectrum,
pScratchTns,
&psyData[ch].sfbThreshold,
&psyData[ch].sfbEnergy,
&psyData[ch].sfbEnergyMS,
&psyData[ch].sfbSpreadedEnergy,
hPsyConfShort->sfbCnt,
hPsyConfShort->sfbOffset,
hPsyConfShort->sfbMinSnr,
psyOutElement->groupedSfbOffset[ch],
&maxSfbPerGroup[ch],
psyOutElement->groupedSfbMinSnr[ch],
psyData[ch].blockSwitchingControl.noOfGroups,
psyData[ch].blockSwitchingControl.groupLen);
}
}
#if (MAX_CHANNELS>1)
/*
stereo Processing
*/
if (channels == 2) {
psyOutElement->toolsInfo.msDigest = MS_NONE;
maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
psyData[1].sfbEnergy.sfbLong,
psyData[0].sfbEnergyMS.sfbLong,
psyData[1].sfbEnergyMS.sfbLong,
psyData[0].mdctSpectrum,
psyData[1].mdctSpectrum,
psyData[0].sfbThreshold.sfbLong,
psyData[1].sfbThreshold.sfbLong,
psyData[0].sfbSpreadedEnergy.sfbLong,
psyData[1].sfbSpreadedEnergy.sfbLong,
(Word16*)&psyOutElement->toolsInfo.msDigest,
(Word16*)psyOutElement->toolsInfo.msMask,
hPsyConfLong->sfbCnt,
hPsyConfLong->sfbCnt,
maxSfbPerGroup[0],
(const Word16*)hPsyConfLong->sfbOffset);
else
MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
psyData[1].sfbEnergy.sfbLong,
psyData[0].sfbEnergyMS.sfbLong,
psyData[1].sfbEnergyMS.sfbLong,
psyData[0].mdctSpectrum,
psyData[1].mdctSpectrum,
psyData[0].sfbThreshold.sfbLong,
psyData[1].sfbThreshold.sfbLong,
psyData[0].sfbSpreadedEnergy.sfbLong,
psyData[1].sfbSpreadedEnergy.sfbLong,
(Word16*)&psyOutElement->toolsInfo.msDigest,
(Word16*)psyOutElement->toolsInfo.msMask,
psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
hPsyConfShort->sfbCnt,
maxSfbPerGroup[0],
(const Word16*)psyOutElement->groupedSfbOffset[0]);
}
#endif /* (MAX_CHANNELS>1) */
/*
build output
*/
for(ch=0;ch<channels;ch++) {
if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
BuildInterface(psyData[ch].mdctSpectrum,
psyData[ch].mdctScale,
&psyData[ch].sfbThreshold,
&psyData[ch].sfbEnergy,
&psyData[ch].sfbSpreadedEnergy,
psyData[ch].sfbEnergySum,
psyData[ch].sfbEnergySumMS,
psyData[ch].blockSwitchingControl.windowSequence,
blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
hPsyConfLong->sfbCnt,
hPsyConfLong->sfbOffset,
maxSfbPerGroup[ch],
hPsyConfLong->sfbMinSnr,
psyData[ch].blockSwitchingControl.noOfGroups,
psyData[ch].blockSwitchingControl.groupLen,
&psyOutChannel[ch]);
else
BuildInterface(psyData[ch].mdctSpectrum,
psyData[ch].mdctScale,
&psyData[ch].sfbThreshold,
&psyData[ch].sfbEnergy,
&psyData[ch].sfbSpreadedEnergy,
psyData[ch].sfbEnergySum,
psyData[ch].sfbEnergySumMS,
SHORT_WINDOW,
SINE_WINDOW,
psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
psyOutElement->groupedSfbOffset[ch],
maxSfbPerGroup[ch],
psyOutElement->groupedSfbMinSnr[ch],
psyData[ch].blockSwitchingControl.noOfGroups,
psyData[ch].blockSwitchingControl.groupLen,
&psyOutChannel[ch]);
}
return(0); /* no error */
}
/*****************************************************************************
*
* function name: advancePsychLong
* description: psychoacoustic for long blocks
*
*****************************************************************************/
static Word16 advancePsychLong(PSY_DATA* psyData,
TNS_DATA* tnsData,
PSY_CONFIGURATION_LONG *hPsyConfLong,
PSY_OUT_CHANNEL* psyOutChannel,
Word32 *pScratchTns,
const TNS_DATA* tnsData2,
const Word16 ch)
{
Word32 i;
Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;
Word32 *data0, *data1, tdata;
/* low pass */
data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;
for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
*data0++ = 0;
}
/* Calc sfb-bandwise mdct-energies for left and right channel */
CalcBandEnergy( psyData->mdctSpectrum,
hPsyConfLong->sfbOffset,
hPsyConfLong->sfbActive,
psyData->sfbEnergy.sfbLong,
&psyData->sfbEnergySum.sfbLong);
/*
TNS detect
*/
TnsDetect(tnsData,
hPsyConfLong->tnsConf,
pScratchTns,
(const Word16*)hPsyConfLong->sfbOffset,
psyData->mdctSpectrum,
0,
psyData->blockSwitchingControl.windowSequence,
psyData->sfbEnergy.sfbLong);
/* TnsSync */
if (ch == 1) {
TnsSync(tnsData,
tnsData2,
hPsyConfLong->tnsConf,
0,
psyData->blockSwitchingControl.windowSequence);
}
/* Tns Encoder */
TnsEncode(&psyOutChannel->tnsInfo,
tnsData,
hPsyConfLong->sfbCnt,
hPsyConfLong->tnsConf,
hPsyConfLong->lowpassLine,
psyData->mdctSpectrum,
0,
psyData->blockSwitchingControl.windowSequence);
/* first part of threshold calculation */
data0 = psyData->sfbEnergy.sfbLong;
data1 = psyData->sfbThreshold.sfbLong;
for (i=hPsyConfLong->sfbCnt; i; i--) {
tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
*data1++ = min(tdata, clipEnergy);
}
/* Calc sfb-bandwise mdct-energies for left and right channel again */
if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;
CalcBandEnergy( psyData->mdctSpectrum,
hPsyConfLong->sfbOffset+tnsStartBand,
hPsyConfLong->sfbActive - tnsStartBand,
psyData->sfbEnergy.sfbLong+tnsStartBand,
&psyData->sfbEnergySum.sfbLong);
data0 = psyData->sfbEnergy.sfbLong;
tdata = psyData->sfbEnergySum.sfbLong;
for (i=0; i<tnsStartBand; i++)
tdata += *data0++;
psyData->sfbEnergySum.sfbLong = tdata;
}
/* spreading energy */
SpreadingMax(hPsyConfLong->sfbCnt,
hPsyConfLong->sfbMaskLowFactor,
hPsyConfLong->sfbMaskHighFactor,
psyData->sfbThreshold.sfbLong);
/* threshold in quiet */
data0 = psyData->sfbThreshold.sfbLong;
data1 = hPsyConfLong->sfbThresholdQuiet;
for (i=hPsyConfLong->sfbCnt; i; i--)
{
*data0 = max(*data0, (*data1 >> normEnergyShift));
data0++; data1++;
}
/* preecho control */
if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
data0 = psyData->sfbThresholdnm1;
for (i=hPsyConfLong->sfbCnt; i; i--) {
*data0++ = MAX_32;
}
psyData->mdctScalenm1 = 0;
}
PreEchoControl( psyData->sfbThresholdnm1,
hPsyConfLong->sfbCnt,
hPsyConfLong->maxAllowedIncreaseFactor,
hPsyConfLong->minRemainingThresholdFactor,
psyData->sfbThreshold.sfbLong,
psyData->mdctScale,
psyData->mdctScalenm1);
psyData->mdctScalenm1 = psyData->mdctScale;
if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
data0 = psyData->sfbThresholdnm1;
for (i=hPsyConfLong->sfbCnt; i; i--) {
*data0++ = MAX_32;
}
psyData->mdctScalenm1 = 0;
}
/* apply tns mult table on cb thresholds */
ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
hPsyConfLong->tnsConf.tnsStartBand,
tnsData->dataRaw.tnsLong.subBlockInfo,
psyData->sfbThreshold.sfbLong);
/* spreaded energy */
data0 = psyData->sfbSpreadedEnergy.sfbLong;
data1 = psyData->sfbEnergy.sfbLong;
for (i=hPsyConfLong->sfbCnt; i; i--) {
//psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];
*data0++ = *data1++;
}
/* spreading energy */
SpreadingMax(hPsyConfLong->sfbCnt,
hPsyConfLong->sfbMaskLowFactorSprEn,
hPsyConfLong->sfbMaskHighFactorSprEn,
psyData->sfbSpreadedEnergy.sfbLong);
return 0;
}
/*****************************************************************************
*
* function name: advancePsychLongMS
* description: update mdct-energies for left add or minus right channel
* for long block
*
*****************************************************************************/
static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
const PSY_CONFIGURATION_LONG *hPsyConfLong)
{
CalcBandEnergyMS(psyData[0].mdctSpectrum,
psyData[1].mdctSpectrum,
hPsyConfLong->sfbOffset,
hPsyConfLong->sfbActive,
psyData[0].sfbEnergyMS.sfbLong,
&psyData[0].sfbEnergySumMS.sfbLong,
psyData[1].sfbEnergyMS.sfbLong,
&psyData[1].sfbEnergySumMS.sfbLong);
return 0;
}
/*****************************************************************************
*
* function name: advancePsychShort
* description: psychoacoustic for short blocks
*
*****************************************************************************/
static Word16 advancePsychShort(PSY_DATA* psyData,
TNS_DATA* tnsData,
const PSY_CONFIGURATION_SHORT *hPsyConfShort,
PSY_OUT_CHANNEL* psyOutChannel,
Word32 *pScratchTns,
const TNS_DATA *tnsData2,
const Word16 ch)
{
Word32 w;
Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
Word32 wOffset = 0;
Word32 *data0, *data1;
for(w = 0; w < TRANS_FAC; w++) {
Word32 i, tdata;
/* low pass */
data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;
for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
*data0++ = 0;
}
/* Calc sfb-bandwise mdct-energies for left and right channel */
CalcBandEnergy( psyData->mdctSpectrum+wOffset,
hPsyConfShort->sfbOffset,
hPsyConfShort->sfbActive,
psyData->sfbEnergy.sfbShort[w],
&psyData->sfbEnergySum.sfbShort[w]);
/*
TNS
*/
TnsDetect(tnsData,
hPsyConfShort->tnsConf,
pScratchTns,
(const Word16*)hPsyConfShort->sfbOffset,
psyData->mdctSpectrum+wOffset,
w,
psyData->blockSwitchingControl.windowSequence,
psyData->sfbEnergy.sfbShort[w]);
/* TnsSync */
if (ch == 1) {
TnsSync(tnsData,
tnsData2,
hPsyConfShort->tnsConf,
w,
psyData->blockSwitchingControl.windowSequence);
}
TnsEncode(&psyOutChannel->tnsInfo,
tnsData,
hPsyConfShort->sfbCnt,
hPsyConfShort->tnsConf,
hPsyConfShort->lowpassLine,
psyData->mdctSpectrum+wOffset,
w,
psyData->blockSwitchingControl.windowSequence);
/* first part of threshold calculation */
data0 = psyData->sfbThreshold.sfbShort[w];
data1 = psyData->sfbEnergy.sfbShort[w];
for (i=hPsyConfShort->sfbCnt; i; i--) {
tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
*data0++ = min(tdata, clipEnergy);
}
/* Calc sfb-bandwise mdct-energies for left and right channel again */
if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;
CalcBandEnergy( psyData->mdctSpectrum+wOffset,
hPsyConfShort->sfbOffset+tnsStartBand,
(hPsyConfShort->sfbActive - tnsStartBand),
psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
&psyData->sfbEnergySum.sfbShort[w]);
tdata = psyData->sfbEnergySum.sfbShort[w];
data0 = psyData->sfbEnergy.sfbShort[w];
for (i=tnsStartBand; i; i--)
tdata += *data0++;
psyData->sfbEnergySum.sfbShort[w] = tdata;
}
/* spreading */
SpreadingMax(hPsyConfShort->sfbCnt,
hPsyConfShort->sfbMaskLowFactor,
hPsyConfShort->sfbMaskHighFactor,
psyData->sfbThreshold.sfbShort[w]);
/* threshold in quiet */
data0 = psyData->sfbThreshold.sfbShort[w];
data1 = hPsyConfShort->sfbThresholdQuiet;
for (i=hPsyConfShort->sfbCnt; i; i--)
{
*data0 = max(*data0, (*data1 >> normEnergyShift));
data0++; data1++;
}
/* preecho */
PreEchoControl( psyData->sfbThresholdnm1,
hPsyConfShort->sfbCnt,
hPsyConfShort->maxAllowedIncreaseFactor,
hPsyConfShort->minRemainingThresholdFactor,
psyData->sfbThreshold.sfbShort[w],
psyData->mdctScale,
w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
/* apply tns mult table on cb thresholds */
ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
hPsyConfShort->tnsConf.tnsStartBand,
tnsData->dataRaw.tnsShort.subBlockInfo[w],
psyData->sfbThreshold.sfbShort[w]);
/* spreaded energy */
data0 = psyData->sfbSpreadedEnergy.sfbShort[w];
data1 = psyData->sfbEnergy.sfbShort[w];
for (i=hPsyConfShort->sfbCnt; i; i--) {
*data0++ = *data1++;
}
SpreadingMax(hPsyConfShort->sfbCnt,
hPsyConfShort->sfbMaskLowFactorSprEn,
hPsyConfShort->sfbMaskHighFactorSprEn,
psyData->sfbSpreadedEnergy.sfbShort[w]);
wOffset += FRAME_LEN_SHORT;
} /* for TRANS_FAC */
psyData->mdctScalenm1 = psyData->mdctScale;
return 0;
}
/*****************************************************************************
*
* function name: advancePsychShortMS
* description: update mdct-energies for left add or minus right channel
* for short block
*
*****************************************************************************/
static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
const PSY_CONFIGURATION_SHORT *hPsyConfShort)
{
Word32 w, wOffset;
wOffset = 0;
for(w=0; w<TRANS_FAC; w++) {
CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
psyData[1].mdctSpectrum+wOffset,
hPsyConfShort->sfbOffset,
hPsyConfShort->sfbActive,
psyData[0].sfbEnergyMS.sfbShort[w],
&psyData[0].sfbEnergySumMS.sfbShort[w],
psyData[1].sfbEnergyMS.sfbShort[w],
&psyData[1].sfbEnergySumMS.sfbShort[w]);
wOffset += FRAME_LEN_SHORT;
}
return 0;
}

View File

@ -0,0 +1,580 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: qc_main.c
Content: Quantizing & coding functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "qc_main.h"
#include "quantize.h"
#include "interface.h"
#include "adj_thr.h"
#include "sf_estim.h"
#include "stat_bits.h"
#include "bit_cnt.h"
#include "dyn_bits.h"
#include "channel_map.h"
#include "memalign.h"
typedef enum{
FRAME_LEN_BYTES_MODULO = 1,
FRAME_LEN_BYTES_INT = 2
}FRAME_LEN_RESULT_MODE;
static const Word16 maxFillElemBits = 7 + 270*8;
/* forward declarations */
static Word16 calcMaxValueInSfb(Word16 sfbCnt,
Word16 maxSfbPerGroup,
Word16 sfbPerGroup,
Word16 sfbOffset[MAX_GROUPED_SFB],
Word16 quantSpectrum[FRAME_LEN_LONG],
UWord16 maxValue[MAX_GROUPED_SFB]);
/*****************************************************************************
*
* function name: calcFrameLen
* description: estimate the frame length according the bitrates
*
*****************************************************************************/
static Word16 calcFrameLen(Word32 bitRate,
Word32 sampleRate,
FRAME_LEN_RESULT_MODE mode)
{
Word32 result;
Word32 quot;
result = (FRAME_LEN_LONG >> 3) * bitRate;
quot = result / sampleRate;
if (mode == FRAME_LEN_BYTES_MODULO) {
result -= quot * sampleRate;
}
else { /* FRAME_LEN_BYTES_INT */
result = quot;
}
return result;
}
/*****************************************************************************
*
* function name:framePadding
* description: Calculates if padding is needed for actual frame
* returns: paddingOn or not
*
*****************************************************************************/
static Word16 framePadding(Word32 bitRate,
Word32 sampleRate,
Word32 *paddingRest)
{
Word16 paddingOn;
Word16 difference;
paddingOn = 0;
difference = calcFrameLen( bitRate,
sampleRate,
FRAME_LEN_BYTES_MODULO );
*paddingRest = *paddingRest - difference;
if (*paddingRest <= 0 ) {
paddingOn = 1;
*paddingRest = *paddingRest + sampleRate;
}
return paddingOn;
}
/*********************************************************************************
*
* function name: QCOutNew
* description: init qcout parameter
* returns: 0 if success
*
**********************************************************************************/
Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP)
{
Word32 i;
Word16 *quantSpec;
Word16 *scf;
UWord16 *maxValueInSfb;
quantSpec = (Word16 *)mem_malloc(pMemOP, nChannels * FRAME_LEN_LONG * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
if(NULL == quantSpec)
return 1;
scf = (Word16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
if(NULL == scf)
{
return 1;
}
maxValueInSfb = (UWord16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(UWord16), 32, VO_INDEX_ENC_AAC);
if(NULL == maxValueInSfb)
{
return 1;
}
for (i=0; i<nChannels; i++) {
hQC->qcChannel[i].quantSpec = quantSpec + i*FRAME_LEN_LONG;
hQC->qcChannel[i].maxValueInSfb = maxValueInSfb + i*MAX_GROUPED_SFB;
hQC->qcChannel[i].scf = scf + i*MAX_GROUPED_SFB;
}
return 0;
}
/*********************************************************************************
*
* function name: QCOutDelete
* description: unint qcout parameter
* returns: 0 if success
*
**********************************************************************************/
void QCOutDelete(QC_OUT* hQC, VO_MEM_OPERATOR *pMemOP)
{
Word32 i;
if(hQC)
{
if(hQC->qcChannel[0].quantSpec);
mem_free(pMemOP, hQC->qcChannel[0].quantSpec, VO_INDEX_ENC_AAC);
if(hQC->qcChannel[0].maxValueInSfb)
mem_free(pMemOP, hQC->qcChannel[0].maxValueInSfb, VO_INDEX_ENC_AAC);
if(hQC->qcChannel[0].scf)
mem_free(pMemOP, hQC->qcChannel[0].scf, VO_INDEX_ENC_AAC);
for (i=0; i<MAX_CHANNELS; i++) {
hQC->qcChannel[i].quantSpec = NULL;
hQC->qcChannel[i].maxValueInSfb = NULL;
hQC->qcChannel[i].scf = NULL;
}
}
}
/*********************************************************************************
*
* function name: QCNew
* description: set QC to zero
* returns: 0 if success
*
**********************************************************************************/
Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
{
pMemOP->Set(VO_INDEX_ENC_AAC, hQC,0,sizeof(QC_STATE));
return (0);
}
/*********************************************************************************
*
* function name: QCDelete
* description: unint qcout parameter
*
**********************************************************************************/
void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
{
/*
nothing to do
*/
hQC=NULL;
}
/*********************************************************************************
*
* function name: QCInit
* description: init QD parameter
* returns: 0 if success
*
**********************************************************************************/
Word16 QCInit(QC_STATE *hQC,
struct QC_INIT *init)
{
hQC->nChannels = init->elInfo->nChannelsInEl;
hQC->maxBitsTot = init->maxBits;
hQC->bitResTot = sub(init->bitRes, init->averageBits);
hQC->averageBitsTot = init->averageBits;
hQC->maxBitFac = init->maxBitFac;
hQC->padding.paddingRest = init->padding.paddingRest;
hQC->globStatBits = 3; /* for ID_END */
/* channel elements init */
InitElementBits(&hQC->elementBits,
*init->elInfo,
init->bitrate,
init->averageBits,
hQC->globStatBits);
/* threshold parameter init */
AdjThrInit(&hQC->adjThr,
init->meanPe,
hQC->elementBits.chBitrate);
return 0;
}
/*********************************************************************************
*
* function name: QCMain
* description: quantization and coding the spectrum
* returns: 0 if success
*
**********************************************************************************/
Word16 QCMain(QC_STATE* hQC,
ELEMENT_BITS* elBits,
ATS_ELEMENT* adjThrStateElement,
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */
PSY_OUT_ELEMENT* psyOutElement,
QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */
QC_OUT_ELEMENT* qcOutElement,
Word16 nChannels,
Word16 ancillaryDataBytes)
{
Word16 maxChDynBits[MAX_CHANNELS];
Word16 chBitDistribution[MAX_CHANNELS];
Word32 ch;
if (elBits->bitResLevel < 0) {
return -1;
}
if (elBits->bitResLevel > elBits->maxBitResBits) {
return -1;
}
qcOutElement->staticBitsUsed = countStaticBitdemand(psyOutChannel,
psyOutElement,
nChannels,
qcOutElement->adtsUsed);
if (ancillaryDataBytes) {
qcOutElement->ancBitsUsed = 7 + (ancillaryDataBytes << 3);
if (ancillaryDataBytes >= 15)
qcOutElement->ancBitsUsed = qcOutElement->ancBitsUsed + 8;
}
else {
qcOutElement->ancBitsUsed = 0;
}
CalcFormFactor(hQC->logSfbFormFactor, hQC->sfbNRelevantLines, hQC->logSfbEnergy, psyOutChannel, nChannels);
/*adjust thresholds for the desired bitrate */
AdjustThresholds(&hQC->adjThr,
adjThrStateElement,
psyOutChannel,
psyOutElement,
chBitDistribution,
hQC->logSfbEnergy,
hQC->sfbNRelevantLines,
qcOutElement,
elBits,
nChannels,
hQC->maxBitFac);
/*estimate scale factors */
EstimateScaleFactors(psyOutChannel,
qcOutChannel,
hQC->logSfbEnergy,
hQC->logSfbFormFactor,
hQC->sfbNRelevantLines,
nChannels);
/* condition to prevent empty bitreservoir */
for (ch = 0; ch < nChannels; ch++) {
Word32 maxDynBits;
maxDynBits = elBits->averageBits + elBits->bitResLevel - 7; /* -7 bec. of align bits */
maxDynBits = maxDynBits - qcOutElement->staticBitsUsed + qcOutElement->ancBitsUsed;
maxChDynBits[ch] = extract_l(chBitDistribution[ch] * maxDynBits / 1000);
}
qcOutElement->dynBitsUsed = 0;
for (ch = 0; ch < nChannels; ch++) {
Word32 chDynBits;
Flag constraintsFulfilled;
Word32 iter;
iter = 0;
do {
constraintsFulfilled = 1;
QuantizeSpectrum(psyOutChannel[ch].sfbCnt,
psyOutChannel[ch].maxSfbPerGroup,
psyOutChannel[ch].sfbPerGroup,
psyOutChannel[ch].sfbOffsets,
psyOutChannel[ch].mdctSpectrum,
qcOutChannel[ch].globalGain,
qcOutChannel[ch].scf,
qcOutChannel[ch].quantSpec);
if (calcMaxValueInSfb(psyOutChannel[ch].sfbCnt,
psyOutChannel[ch].maxSfbPerGroup,
psyOutChannel[ch].sfbPerGroup,
psyOutChannel[ch].sfbOffsets,
qcOutChannel[ch].quantSpec,
qcOutChannel[ch].maxValueInSfb) > MAX_QUANT) {
constraintsFulfilled = 0;
}
chDynBits = dynBitCount(qcOutChannel[ch].quantSpec,
qcOutChannel[ch].maxValueInSfb,
qcOutChannel[ch].scf,
psyOutChannel[ch].windowSequence,
psyOutChannel[ch].sfbCnt,
psyOutChannel[ch].maxSfbPerGroup,
psyOutChannel[ch].sfbPerGroup,
psyOutChannel[ch].sfbOffsets,
&qcOutChannel[ch].sectionData);
if (chDynBits >= maxChDynBits[ch]) {
constraintsFulfilled = 0;
}
if (!constraintsFulfilled) {
qcOutChannel[ch].globalGain = qcOutChannel[ch].globalGain + 1;
}
iter = iter + 1;
} while(!constraintsFulfilled);
qcOutElement->dynBitsUsed = qcOutElement->dynBitsUsed + chDynBits;
qcOutChannel[ch].mdctScale = psyOutChannel[ch].mdctScale;
qcOutChannel[ch].groupingMask = psyOutChannel[ch].groupingMask;
qcOutChannel[ch].windowShape = psyOutChannel[ch].windowShape;
}
/* save dynBitsUsed for correction of bits2pe relation */
AdjThrUpdate(adjThrStateElement, qcOutElement->dynBitsUsed);
{
Word16 bitResSpace = elBits->maxBitResBits - elBits->bitResLevel;
Word16 deltaBitRes = elBits->averageBits -
(qcOutElement->staticBitsUsed +
qcOutElement->dynBitsUsed + qcOutElement->ancBitsUsed);
qcOutElement->fillBits = max(0, (deltaBitRes - bitResSpace));
}
return 0; /* OK */
}
/*********************************************************************************
*
* function name: calcMaxValueInSfb
* description: search the max Spectrum in one sfb
*
**********************************************************************************/
static Word16 calcMaxValueInSfb(Word16 sfbCnt,
Word16 maxSfbPerGroup,
Word16 sfbPerGroup,
Word16 sfbOffset[MAX_GROUPED_SFB],
Word16 quantSpectrum[FRAME_LEN_LONG],
UWord16 maxValue[MAX_GROUPED_SFB])
{
Word16 sfbOffs, sfb;
Word16 maxValueAll;
maxValueAll = 0;
for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
Word16 line;
Word16 maxThisSfb;
maxThisSfb = 0;
for (line = sfbOffset[sfbOffs+sfb]; line < sfbOffset[sfbOffs+sfb+1]; line++) {
Word16 absVal;
absVal = abs_s(quantSpectrum[line]);
maxThisSfb = max(maxThisSfb, absVal);
}
maxValue[sfbOffs+sfb] = maxThisSfb;
maxValueAll = max(maxValueAll, maxThisSfb);
}
}
return maxValueAll;
}
/*********************************************************************************
*
* function name: updateBitres
* description: update bitreservoir
*
**********************************************************************************/
void updateBitres(QC_STATE* qcKernel,
QC_OUT* qcOut)
{
ELEMENT_BITS *elBits;
qcKernel->bitResTot = 0;
elBits = &qcKernel->elementBits;
if (elBits->averageBits > 0) {
/* constant bitrate */
Word16 bitsUsed;
bitsUsed = (qcOut->qcElement.staticBitsUsed + qcOut->qcElement.dynBitsUsed) +
(qcOut->qcElement.ancBitsUsed + qcOut->qcElement.fillBits);
elBits->bitResLevel = elBits->bitResLevel + (elBits->averageBits - bitsUsed);
qcKernel->bitResTot = qcKernel->bitResTot + elBits->bitResLevel;
}
else {
/* variable bitrate */
elBits->bitResLevel = elBits->maxBits;
qcKernel->bitResTot = qcKernel->maxBitsTot;
}
}
/*********************************************************************************
*
* function name: FinalizeBitConsumption
* description: count bits used
*
**********************************************************************************/
Word16 FinalizeBitConsumption(QC_STATE *qcKernel,
QC_OUT* qcOut)
{
Word32 nFullFillElem;
Word32 totFillBits;
Word16 diffBits;
Word16 bitsUsed;
totFillBits = 0;
qcOut->totStaticBitsUsed = qcKernel->globStatBits;
qcOut->totStaticBitsUsed += qcOut->qcElement.staticBitsUsed;
qcOut->totDynBitsUsed = qcOut->qcElement.dynBitsUsed;
qcOut->totAncBitsUsed = qcOut->qcElement.ancBitsUsed;
qcOut->totFillBits = qcOut->qcElement.fillBits;
if (qcOut->qcElement.fillBits) {
totFillBits += qcOut->qcElement.fillBits;
}
nFullFillElem = (max((qcOut->totFillBits - 1), 0) / maxFillElemBits) * maxFillElemBits;
qcOut->totFillBits = qcOut->totFillBits - nFullFillElem;
/* check fill elements */
if (qcOut->totFillBits > 0) {
/* minimum Fillelement contains 7 (TAG + byte cnt) bits */
qcOut->totFillBits = max(7, qcOut->totFillBits);
/* fill element size equals n*8 + 7 */
qcOut->totFillBits = qcOut->totFillBits + ((8 - ((qcOut->totFillBits - 7) & 0x0007)) & 0x0007);
}
qcOut->totFillBits = qcOut->totFillBits + nFullFillElem;
/* now distribute extra fillbits and alignbits over channel elements */
qcOut->alignBits = 7 - ((qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed +
qcOut->totAncBitsUsed + qcOut->totFillBits - 1) & 0x0007);
if ( (qcOut->alignBits + qcOut->totFillBits - totFillBits == 8) &&
(qcOut->totFillBits > 8))
qcOut->totFillBits = qcOut->totFillBits - 8;
diffBits = qcOut->alignBits + qcOut->totFillBits - totFillBits;
if(diffBits>=0) {
qcOut->qcElement.fillBits += diffBits;
}
bitsUsed = qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed + qcOut->totAncBitsUsed;
bitsUsed = bitsUsed + qcOut->totFillBits + qcOut->alignBits;
if (bitsUsed > qcKernel->maxBitsTot) {
return -1;
}
return bitsUsed;
}
/*********************************************************************************
*
* function name: AdjustBitrate
* description: adjusts framelength via padding on a frame to frame basis,
* to achieve a bitrate that demands a non byte aligned
* framelength
* return: errorcode
*
**********************************************************************************/
Word16 AdjustBitrate(QC_STATE *hQC,
Word32 bitRate, /* total bitrate */
Word32 sampleRate) /* output sampling rate */
{
Word16 paddingOn;
Word16 frameLen;
Word16 codeBits;
Word16 codeBitsLast;
/* Do we need a extra padding byte? */
paddingOn = framePadding(bitRate,
sampleRate,
&hQC->padding.paddingRest);
/* frame length */
frameLen = paddingOn + calcFrameLen(bitRate,
sampleRate,
FRAME_LEN_BYTES_INT);
frameLen = frameLen << 3;
codeBitsLast = hQC->averageBitsTot - hQC->globStatBits;
codeBits = frameLen - hQC->globStatBits;
/* calculate bits for every channel element */
if (codeBits != codeBitsLast) {
Word16 totalBits = 0;
hQC->elementBits.averageBits = (hQC->elementBits.relativeBits * codeBits) >> 16; /* relativeBits was scaled down by 2 */
totalBits += hQC->elementBits.averageBits;
hQC->elementBits.averageBits = hQC->elementBits.averageBits + (codeBits - totalBits);
}
hQC->averageBitsTot = frameLen;
return 0;
}

View File

@ -0,0 +1,445 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: quantize.c
Content: quantization functions
*******************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "quantize.h"
#include "aac_rom.h"
#define MANT_DIGITS 9
#define MANT_SIZE (1<<MANT_DIGITS)
static const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */
/*****************************************************************************
*
* function name:pow34
* description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$.
*
*****************************************************************************/
__inline Word32 pow34(Word32 x)
{
/* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB
which is always one */
return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)];
}
/*****************************************************************************
*
* function name:quantizeSingleLine
* description: quantizes spectrum
* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
*
*****************************************************************************/
static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum)
{
Word32 e, minusFinalExp, finalShift;
Word32 x;
Word16 qua = 0;
if (absSpectrum) {
e = norm_l(absSpectrum);
x = pow34(absSpectrum << e);
/* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */
minusFinalExp = (e << 2) + gain;
minusFinalExp = (minusFinalExp << 1) + minusFinalExp;
minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4);
/* separate the exponent into a shift, and a multiply */
finalShift = minusFinalExp >> 4;
if (finalShift < INT_BITS) {
x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]);
x += XROUND >> (INT_BITS - finalShift);
/* shift and quantize */
finalShift--;
if(finalShift >= 0)
x >>= finalShift;
else
x <<= (-finalShift);
qua = saturate(x);
}
}
return qua;
}
/*****************************************************************************
*
* function name:quantizeLines
* description: quantizes spectrum lines
* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
* input: global gain, number of lines to process, spectral data
* output: quantized spectrum
*
*****************************************************************************/
static void quantizeLines(const Word16 gain,
const Word16 noOfLines,
const Word32 *mdctSpectrum,
Word16 *quaSpectrum)
{
Word32 line;
Word32 m = gain&3;
Word32 g = (gain >> 2) + 4;
Word32 mdctSpeL;
Word16 *pquat;
/* gain&3 */
pquat = quantBorders[m];
g += 16;
if(g >= 0)
{
for (line=0; line<noOfLines; line++) {
Word32 qua;
qua = 0;
mdctSpeL = mdctSpectrum[line];
if (mdctSpeL) {
Word32 sa;
Word32 saShft;
sa = L_abs(mdctSpeL);
//saShft = L_shr(sa, 16 + g);
saShft = sa >> g;
if (saShft > pquat[0]) {
if (saShft < pquat[1]) {
qua = mdctSpeL>0 ? 1 : -1;
}
else {
if (saShft < pquat[2]) {
qua = mdctSpeL>0 ? 2 : -2;
}
else {
if (saShft < pquat[3]) {
qua = mdctSpeL>0 ? 3 : -3;
}
else {
qua = quantizeSingleLine(gain, sa);
/* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
if (mdctSpeL < 0)
qua = -qua;
}
}
}
}
}
quaSpectrum[line] = qua ;
}
}
else
{
for (line=0; line<noOfLines; line++) {
Word32 qua;
qua = 0;
mdctSpeL = mdctSpectrum[line];
if (mdctSpeL) {
Word32 sa;
Word32 saShft;
sa = L_abs(mdctSpeL);
saShft = sa << g;
if (saShft > pquat[0]) {
if (saShft < pquat[1]) {
qua = mdctSpeL>0 ? 1 : -1;
}
else {
if (saShft < pquat[2]) {
qua = mdctSpeL>0 ? 2 : -2;
}
else {
if (saShft < pquat[3]) {
qua = mdctSpeL>0 ? 3 : -3;
}
else {
qua = quantizeSingleLine(gain, sa);
/* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
if (mdctSpeL < 0)
qua = -qua;
}
}
}
}
}
quaSpectrum[line] = qua ;
}
}
}
/*****************************************************************************
*
* function name:iquantizeLines
* description: iquantizes spectrum lines without sign
* mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain)
* input: global gain, number of lines to process,quantized spectrum
* output: spectral data
*
*****************************************************************************/
static void iquantizeLines(const Word16 gain,
const Word16 noOfLines,
const Word16 *quantSpectrum,
Word32 *mdctSpectrum)
{
Word32 iquantizermod;
Word32 iquantizershift;
Word32 line;
iquantizermod = gain & 3;
iquantizershift = gain >> 2;
for (line=0; line<noOfLines; line++) {
if( quantSpectrum[line] != 0 ) {
Word32 accu;
Word32 ex;
Word32 tabIndex;
Word32 specExp;
Word32 s,t;
accu = quantSpectrum[line];
ex = norm_l(accu);
accu = accu << ex;
specExp = INT_BITS-1 - ex;
tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE);
/* calculate "mantissa" ^4/3 */
s = mTab_4_3[tabIndex];
/* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */
t = specExpMantTableComb_enc[iquantizermod][specExp];
/* multiply "mantissa" ^4/3 with exponent multiplier */
accu = MULHIGH(s, t);
/* get approperiate exponent shifter */
specExp = specExpTableComb_enc[iquantizermod][specExp];
specExp += iquantizershift + 1;
if(specExp >= 0)
mdctSpectrum[line] = accu << specExp;
else
mdctSpectrum[line] = accu >> (-specExp);
}
else {
mdctSpectrum[line] = 0;
}
}
}
/*****************************************************************************
*
* function name: QuantizeSpectrum
* description: quantizes the entire spectrum
* returns:
* input: number of scalefactor bands to be quantized, ...
* output: quantized spectrum
*
*****************************************************************************/
void QuantizeSpectrum(Word16 sfbCnt,
Word16 maxSfbPerGroup,
Word16 sfbPerGroup,
Word16 *sfbOffset,
Word32 *mdctSpectrum,
Word16 globalGain,
Word16 *scalefactors,
Word16 *quantizedSpectrum)
{
Word32 sfbOffs, sfb;
for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
Word32 sfbNext ;
for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) {
Word16 scalefactor = scalefactors[sfbOffs+sfb];
/* coalesce sfbs with the same scalefactor */
for (sfbNext = sfb+1;
sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext];
sfbNext++) ;
quantizeLines(globalGain - scalefactor,
sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb],
mdctSpectrum + sfbOffset[sfbOffs+sfb],
quantizedSpectrum + sfbOffset[sfbOffs+sfb]);
}
}
}
/*****************************************************************************
*
* function name:calcSfbDist
* description: quantizes and requantizes lines to calculate distortion
* input: number of lines to be quantized, ...
* output: distortion
*
*****************************************************************************/
Word32 calcSfbDist(const Word32 *spec,
Word16 sfbWidth,
Word16 gain)
{
Word32 line;
Word32 dist;
Word32 m = gain&3;
Word32 g = (gain >> 2) + 4;
Word32 g2 = (g << 1) + 1;
Word16 *pquat, *repquat;
/* gain&3 */
pquat = quantBorders[m];
repquat = quantRecon[m];
dist = 0;
g += 16;
if(g2 < 0 && g >= 0)
{
g2 = -g2;
for(line=0; line<sfbWidth; line++) {
if (spec[line]) {
Word32 diff;
Word32 distSingle;
Word32 sa;
Word32 saShft;
sa = L_abs(spec[line]);
//saShft = round16(L_shr(sa, g));
//saShft = L_shr(sa, 16+g);
saShft = sa >> g;
if (saShft < pquat[0]) {
distSingle = (saShft * saShft) >> g2;
}
else {
if (saShft < pquat[1]) {
diff = saShft - repquat[0];
distSingle = (diff * diff) >> g2;
}
else {
if (saShft < pquat[2]) {
diff = saShft - repquat[1];
distSingle = (diff * diff) >> g2;
}
else {
if (saShft < pquat[3]) {
diff = saShft - repquat[2];
distSingle = (diff * diff) >> g2;
}
else {
Word16 qua = quantizeSingleLine(gain, sa);
Word32 iqval, diff32;
/* now that we have quantized x, re-quantize it. */
iquantizeLines(gain, 1, &qua, &iqval);
diff32 = sa - iqval;
distSingle = fixmul(diff32, diff32);
}
}
}
}
dist = L_add(dist, distSingle);
}
}
}
else
{
for(line=0; line<sfbWidth; line++) {
if (spec[line]) {
Word32 diff;
Word32 distSingle;
Word32 sa;
Word32 saShft;
sa = L_abs(spec[line]);
//saShft = round16(L_shr(sa, g));
saShft = L_shr(sa, g);
if (saShft < pquat[0]) {
distSingle = L_shl((saShft * saShft), g2);
}
else {
if (saShft < pquat[1]) {
diff = saShft - repquat[0];
distSingle = L_shl((diff * diff), g2);
}
else {
if (saShft < pquat[2]) {
diff = saShft - repquat[1];
distSingle = L_shl((diff * diff), g2);
}
else {
if (saShft < pquat[3]) {
diff = saShft - repquat[2];
distSingle = L_shl((diff * diff), g2);
}
else {
Word16 qua = quantizeSingleLine(gain, sa);
Word32 iqval, diff32;
/* now that we have quantized x, re-quantize it. */
iquantizeLines(gain, 1, &qua, &iqval);
diff32 = sa - iqval;
distSingle = fixmul(diff32, diff32);
}
}
}
}
dist = L_add(dist, distSingle);
}
}
}
return dist;
}

View File

@ -0,0 +1,882 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: sf_estim.c
Content: Scale factor estimation functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "sf_estim.h"
#include "quantize.h"
#include "bit_cnt.h"
#include "aac_rom.h"
static const Word16 MAX_SCF_DELTA = 60;
/*!
constants reference in comments
C0 = 6.75f;
C1 = -69.33295f; -16/3*log(MAX_QUANT+0.5-logCon)/log(2)
C2 = 4.0f;
C3 = 2.66666666f;
PE_C1 = 3.0f; log(8.0)/log(2)
PE_C2 = 1.3219281f; log(2.5)/log(2)
PE_C3 = 0.5593573f; 1-C2/C1
*/
#define FF_SQRT_BITS 7
#define FF_SQRT_TABLE_SIZE (1<<FF_SQRT_BITS - 1<<(FF_SQRT_BITS-2))
#define COEF08_31 0x66666666 /* 0.8*(1 << 31) */
#define PE_C1_8 24 /* PE_C1*8 */
#define PE_C2_16 21 /* PE_C2*8/PE_C3 */
#define PE_SCALE 0x059a /* 0.7 * (1 << (15 - 1 - 3))*/
#define SCALE_ESTIMATE_COEF 0x5555 /* (8.8585/(4*log2(10))) * (1 << 15)*/
/*********************************************************************************
*
* function name: formfac_sqrt
* description: calculates sqrt(x)/256
*
**********************************************************************************/
__inline Word32 formfac_sqrt(Word32 x)
{
Word32 y;
Word32 preshift, postshift;
if (x==0) return 0;
preshift = norm_l(x) - (INT_BITS-1-FF_SQRT_BITS);
postshift = preshift >> 1;
preshift = postshift << 1;
postshift = postshift + 8; /* sqrt/256 */
if(preshift >= 0)
y = x << preshift; /* now 1/4 <= y < 1 */
else
y = x >> (-preshift);
y = formfac_sqrttable[y-32];
if(postshift >= 0)
y = y >> postshift;
else
y = y << (-postshift);
return y;
}
/*********************************************************************************
*
* function name: CalcFormFactorChannel
* description: calculate the form factor one channel
* ffac(n) = sqrt(abs(X(k)) + sqrt(abs(X(k+1)) + ....
*
**********************************************************************************/
static void
CalcFormFactorChannel(Word16 *logSfbFormFactor,
Word16 *sfbNRelevantLines,
Word16 *logSfbEnergy,
PSY_OUT_CHANNEL *psyOutChan)
{
Word32 sfbw, sfbw1;
Word32 i, j;
Word32 sfbOffs, sfb, shift;
sfbw = sfbw1 = 0;
for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){
for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
i = sfbOffs+sfb;
if (psyOutChan->sfbEnergy[i] > psyOutChan->sfbThreshold[i]) {
Word32 accu, avgFormFactor,iSfbWidth;
Word32 *mdctSpec;
sfbw = psyOutChan->sfbOffsets[i+1] - psyOutChan->sfbOffsets[i];
iSfbWidth = invSBF[(sfbw >> 2) - 1];
mdctSpec = psyOutChan->mdctSpectrum + psyOutChan->sfbOffsets[i];
accu = 0;
/* calc sum of sqrt(spec) */
for (j=sfbw; j; j--) {
accu += formfac_sqrt(L_abs(*mdctSpec)); mdctSpec++;
}
logSfbFormFactor[i] = iLog4(accu);
logSfbEnergy[i] = iLog4(psyOutChan->sfbEnergy[i]);
avgFormFactor = fixmul(rsqrt(psyOutChan->sfbEnergy[i],INT_BITS), iSfbWidth);
avgFormFactor = rsqrt((Word32)avgFormFactor,INT_BITS) >> 10;
/* result is multiplied by 4 */
if(avgFormFactor)
sfbNRelevantLines[i] = accu / avgFormFactor;
else
sfbNRelevantLines[i] = 0x7fff;
}
else {
/* set number of lines to zero */
sfbNRelevantLines[i] = 0;
}
}
}
}
/*********************************************************************************
*
* function name: improveScf
* description: find better scalefactor with analysis by synthesis
*
**********************************************************************************/
static Word16 improveScf(Word32 *spec,
Word16 sfbWidth,
Word32 thresh,
Word16 scf,
Word16 minScf,
Word32 *dist,
Word16 *minScfCalculated)
{
Word32 cnt;
Word32 sfbDist;
Word32 scfBest;
Word32 thresh125 = L_add(thresh, (thresh >> 2));
scfBest = scf;
/* calc real distortion */
sfbDist = calcSfbDist(spec, sfbWidth, scf);
*minScfCalculated = scf;
if(!sfbDist)
return scfBest;
if (sfbDist > thresh125) {
Word32 scfEstimated;
Word32 sfbDistBest;
scfEstimated = scf;
sfbDistBest = sfbDist;
cnt = 0;
while (sfbDist > thresh125 && (cnt < 3)) {
scf = scf + 1;
sfbDist = calcSfbDist(spec, sfbWidth, scf);
if (sfbDist < sfbDistBest) {
scfBest = scf;
sfbDistBest = sfbDist;
}
cnt = cnt + 1;
}
cnt = 0;
scf = scfEstimated;
sfbDist = sfbDistBest;
while ((sfbDist > thresh125) && (cnt < 1) && (scf > minScf)) {
scf = scf - 1;
sfbDist = calcSfbDist(spec, sfbWidth, scf);
if (sfbDist < sfbDistBest) {
scfBest = scf;
sfbDistBest = sfbDist;
}
*minScfCalculated = scf;
cnt = cnt + 1;
}
*dist = sfbDistBest;
}
else {
Word32 sfbDistBest;
Word32 sfbDistAllowed;
Word32 thresh08 = fixmul(COEF08_31, thresh);
sfbDistBest = sfbDist;
if (sfbDist < thresh08)
sfbDistAllowed = sfbDist;
else
sfbDistAllowed = thresh08;
for (cnt=0; cnt<3; cnt++) {
scf = scf + 1;
sfbDist = calcSfbDist(spec, sfbWidth, scf);
if (fixmul(COEF08_31,sfbDist) < sfbDistAllowed) {
*minScfCalculated = scfBest + 1;
scfBest = scf;
sfbDistBest = sfbDist;
}
}
*dist = sfbDistBest;
}
/* return best scalefactor */
return scfBest;
}
/*********************************************************************************
*
* function name: countSingleScfBits
* description: count single scf bits in huffum
*
**********************************************************************************/
static Word16 countSingleScfBits(Word16 scf, Word16 scfLeft, Word16 scfRight)
{
Word16 scfBits;
scfBits = bitCountScalefactorDelta(scfLeft - scf) +
bitCountScalefactorDelta(scf - scfRight);
return scfBits;
}
/*********************************************************************************
*
* function name: calcSingleSpecPe
* description: ldRatio = log2(en(n)) - 0,375*scfGain(n)
* nbits = 0.7*nLines*ldRation for ldRation >= c1
* nbits = 0.7*nLines*(c2 + c3*ldRatio) for ldRation < c1
*
**********************************************************************************/
static Word16 calcSingleSpecPe(Word16 scf, Word16 sfbConstPePart, Word16 nLines)
{
Word32 specPe;
Word32 ldRatio;
Word32 scf3;
ldRatio = sfbConstPePart << 3; /* (sfbConstPePart -0.375*scf)*8 */
scf3 = scf + scf + scf;
ldRatio = ldRatio - scf3;
if (ldRatio < PE_C1_8) {
/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
ldRatio = (ldRatio + PE_C2_16) >> 1;
}
specPe = nLines * ldRatio;
specPe = (specPe * PE_SCALE) >> 14;
return saturate(specPe);
}
/*********************************************************************************
*
* function name: countScfBitsDiff
* description: count different scf bits used
*
**********************************************************************************/
static Word16 countScfBitsDiff(Word16 *scfOld, Word16 *scfNew,
Word16 sfbCnt, Word16 startSfb, Word16 stopSfb)
{
Word32 scfBitsDiff;
Word32 sfb, sfbLast;
Word32 sfbPrev, sfbNext;
scfBitsDiff = 0;
sfb = 0;
/* search for first relevant sfb */
sfbLast = startSfb;
while (sfbLast < stopSfb && scfOld[sfbLast] == VOAAC_SHRT_MIN) {
sfbLast = sfbLast + 1;
}
/* search for previous relevant sfb and count diff */
sfbPrev = startSfb - 1;
while ((sfbPrev>=0) && scfOld[sfbPrev] == VOAAC_SHRT_MIN) {
sfbPrev = sfbPrev - 1;
}
if (sfbPrev>=0) {
scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) -
bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]);
}
/* now loop through all sfbs and count diffs of relevant sfbs */
for (sfb=sfbLast+1; sfb<stopSfb; sfb++) {
if (scfOld[sfb] != VOAAC_SHRT_MIN) {
scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfb]) -
bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfb]);
sfbLast = sfb;
}
}
/* search for next relevant sfb and count diff */
sfbNext = stopSfb;
while (sfbNext < sfbCnt && scfOld[sfbNext] == VOAAC_SHRT_MIN) {
sfbNext = sfbNext + 1;
}
if (sfbNext < sfbCnt)
scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfbNext]) -
bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfbNext]);
return saturate(scfBitsDiff);
}
static Word16 calcSpecPeDiff(Word16 *scfOld,
Word16 *scfNew,
Word16 *sfbConstPePart,
Word16 *logSfbEnergy,
Word16 *logSfbFormFactor,
Word16 *sfbNRelevantLines,
Word16 startSfb,
Word16 stopSfb)
{
Word32 specPeDiff;
Word32 sfb;
specPeDiff = 0;
/* loop through all sfbs and count pe difference */
for (sfb=startSfb; sfb<stopSfb; sfb++) {
if (scfOld[sfb] != VOAAC_SHRT_MIN) {
Word32 ldRatioOld, ldRatioNew;
Word32 scf3;
if (sfbConstPePart[sfb] == MIN_16) {
sfbConstPePart[sfb] = ((logSfbEnergy[sfb] -
logSfbFormFactor[sfb]) + 11-8*4+3) >> 2;
}
ldRatioOld = sfbConstPePart[sfb] << 3;
scf3 = scfOld[sfb] + scfOld[sfb] + scfOld[sfb];
ldRatioOld = ldRatioOld - scf3;
ldRatioNew = sfbConstPePart[sfb] << 3;
scf3 = scfNew[sfb] + scfNew[sfb] + scfNew[sfb];
ldRatioNew = ldRatioNew - scf3;
if (ldRatioOld < PE_C1_8) {
/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
ldRatioOld = (ldRatioOld + PE_C2_16) >> 1;
}
if (ldRatioNew < PE_C1_8) {
/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
ldRatioNew = (ldRatioNew + PE_C2_16) >> 1;
}
specPeDiff += sfbNRelevantLines[sfb] * (ldRatioNew - ldRatioOld);
}
}
specPeDiff = (specPeDiff * PE_SCALE) >> 14;
return saturate(specPeDiff);
}
/*********************************************************************************
*
* function name: assimilateSingleScf
* description: searched for single scalefactor bands, where the number of bits gained
* by using a smaller scfgain(n) is greater than the estimated increased
* bit demand
*
**********************************************************************************/
static void assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
Word16 *scf,
Word16 *minScf,
Word32 *sfbDist,
Word16 *sfbConstPePart,
Word16 *logSfbEnergy,
Word16 *logSfbFormFactor,
Word16 *sfbNRelevantLines,
Word16 *minScfCalculated,
Flag restartOnSuccess)
{
Word32 sfbLast, sfbAct, sfbNext, scfAct, scfMin;
Word16 *scfLast, *scfNext;
Word32 sfbPeOld, sfbPeNew;
Word32 sfbDistNew;
Word32 j;
Flag success;
Word16 deltaPe, deltaPeNew, deltaPeTmp;
Word16 *prevScfLast = psyOutChan->prevScfLast;
Word16 *prevScfNext = psyOutChan->prevScfNext;
Word16 *deltaPeLast = psyOutChan->deltaPeLast;
Flag updateMinScfCalculated;
success = 0;
deltaPe = 0;
for(j=0;j<psyOutChan->sfbCnt;j++){
prevScfLast[j] = MAX_16;
prevScfNext[j] = MAX_16;
deltaPeLast[j] = MAX_16;
}
sfbLast = -1;
sfbAct = -1;
sfbNext = -1;
scfLast = 0;
scfNext = 0;
scfMin = MAX_16;
do {
/* search for new relevant sfb */
sfbNext = sfbNext + 1;
while (sfbNext < psyOutChan->sfbCnt && scf[sfbNext] == MIN_16) {
sfbNext = sfbNext + 1;
}
if ((sfbLast>=0) && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
/* relevant scfs to the left and to the right */
scfAct = scf[sfbAct];
scfLast = scf + sfbLast;
scfNext = scf + sfbNext;
scfMin = min(*scfLast, *scfNext);
}
else {
if (sfbLast == -1 && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
/* first relevant scf */
scfAct = scf[sfbAct];
scfLast = &scfAct;
scfNext = scf + sfbNext;
scfMin = *scfNext;
}
else {
if ((sfbLast>=0) && (sfbAct>=0) && sfbNext == psyOutChan->sfbCnt) {
/* last relevant scf */
scfAct = scf[sfbAct];
scfLast = scf + sfbLast;
scfNext = &scfAct;
scfMin = *scfLast;
}
}
}
if (sfbAct>=0)
scfMin = max(scfMin, minScf[sfbAct]);
if ((sfbAct >= 0) &&
(sfbLast>=0 || sfbNext < psyOutChan->sfbCnt) &&
scfAct > scfMin &&
(*scfLast != prevScfLast[sfbAct] ||
*scfNext != prevScfNext[sfbAct] ||
deltaPe < deltaPeLast[sfbAct])) {
success = 0;
/* estimate required bits for actual scf */
if (sfbConstPePart[sfbAct] == MIN_16) {
sfbConstPePart[sfbAct] = logSfbEnergy[sfbAct] -
logSfbFormFactor[sfbAct] + 11-8*4; /* 4*log2(6.75) - 32 */
if (sfbConstPePart[sfbAct] < 0)
sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] + 3;
sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] >> 2;
}
sfbPeOld = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
countSingleScfBits(scfAct, *scfLast, *scfNext);
deltaPeNew = deltaPe;
updateMinScfCalculated = 1;
do {
scfAct = scfAct - 1;
/* check only if the same check was not done before */
if (scfAct < minScfCalculated[sfbAct]) {
sfbPeNew = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
countSingleScfBits(scfAct, *scfLast, *scfNext);
/* use new scf if no increase in pe and
quantization error is smaller */
deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld;
if (deltaPeTmp < 10) {
sfbDistNew = calcSfbDist(psyOutChan->mdctSpectrum+
psyOutChan->sfbOffsets[sfbAct],
(psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct]),
scfAct);
if (sfbDistNew < sfbDist[sfbAct]) {
/* success, replace scf by new one */
scf[sfbAct] = scfAct;
sfbDist[sfbAct] = sfbDistNew;
deltaPeNew = deltaPeTmp;
success = 1;
}
/* mark as already checked */
if (updateMinScfCalculated) {
minScfCalculated[sfbAct] = scfAct;
}
}
else {
updateMinScfCalculated = 0;
}
}
} while (scfAct > scfMin);
deltaPe = deltaPeNew;
/* save parameters to avoid multiple computations of the same sfb */
prevScfLast[sfbAct] = *scfLast;
prevScfNext[sfbAct] = *scfNext;
deltaPeLast[sfbAct] = deltaPe;
}
if (success && restartOnSuccess) {
/* start again at first sfb */
sfbLast = -1;
sfbAct = -1;
sfbNext = -1;
scfLast = 0;
scfNext = 0;
scfMin = MAX_16;
success = 0;
}
else {
/* shift sfbs for next band */
sfbLast = sfbAct;
sfbAct = sfbNext;
}
} while (sfbNext < psyOutChan->sfbCnt);
}
/*********************************************************************************
*
* function name: assimilateMultipleScf
* description: scalefactor difference reduction
*
**********************************************************************************/
static void assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
Word16 *scf,
Word16 *minScf,
Word32 *sfbDist,
Word16 *sfbConstPePart,
Word16 *logSfbEnergy,
Word16 *logSfbFormFactor,
Word16 *sfbNRelevantLines)
{
Word32 sfb, startSfb, stopSfb, scfMin, scfMax, scfAct;
Flag possibleRegionFound;
Word32 deltaScfBits;
Word32 deltaSpecPe;
Word32 deltaPe, deltaPeNew;
Word32 sfbCnt;
Word32 *sfbDistNew = psyOutChan->sfbDistNew;
Word16 *scfTmp = psyOutChan->prevScfLast;
deltaPe = 0;
sfbCnt = psyOutChan->sfbCnt;
/* calc min and max scalfactors */
scfMin = MAX_16;
scfMax = MIN_16;
for (sfb=0; sfb<sfbCnt; sfb++) {
if (scf[sfb] != MIN_16) {
scfMin = min(scfMin, scf[sfb]);
scfMax = max(scfMax, scf[sfb]);
}
}
if (scfMax != MIN_16) {
scfAct = scfMax;
do {
scfAct = scfAct - 1;
for (sfb=0; sfb<sfbCnt; sfb++) {
scfTmp[sfb] = scf[sfb];
}
stopSfb = 0;
do {
sfb = stopSfb;
while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] <= scfAct)) {
sfb = sfb + 1;
}
startSfb = sfb;
sfb = sfb + 1;
while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] > scfAct)) {
sfb = sfb + 1;
}
stopSfb = sfb;
possibleRegionFound = 0;
if (startSfb < sfbCnt) {
possibleRegionFound = 1;
for (sfb=startSfb; sfb<stopSfb; sfb++) {
if (scf[sfb]!=MIN_16) {
if (scfAct < minScf[sfb]) {
possibleRegionFound = 0;
break;
}
}
}
}
if (possibleRegionFound) { /* region found */
/* replace scfs in region by scfAct */
for (sfb=startSfb; sfb<stopSfb; sfb++) {
if (scfTmp[sfb]!=MIN_16)
scfTmp[sfb] = scfAct;
}
/* estimate change in bit demand for new scfs */
deltaScfBits = countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
deltaSpecPe = calcSpecPeDiff(scf, scfTmp, sfbConstPePart,
logSfbEnergy, logSfbFormFactor, sfbNRelevantLines,
startSfb, stopSfb);
deltaPeNew = deltaPe + deltaScfBits + deltaSpecPe;
if (deltaPeNew < 10) {
Word32 distOldSum, distNewSum;
/* quantize and calc sum of new distortion */
distOldSum = 0;
distNewSum = 0;
for (sfb=startSfb; sfb<stopSfb; sfb++) {
if (scfTmp[sfb] != MIN_16) {
distOldSum = L_add(distOldSum, sfbDist[sfb]);
sfbDistNew[sfb] = calcSfbDist(psyOutChan->mdctSpectrum +
psyOutChan->sfbOffsets[sfb],
(psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb]),
scfAct);
if (sfbDistNew[sfb] > psyOutChan->sfbThreshold[sfb]) {
distNewSum = distOldSum << 1;
break;
}
distNewSum = L_add(distNewSum, sfbDistNew[sfb]);
}
}
if (distNewSum < distOldSum) {
deltaPe = deltaPeNew;
for (sfb=startSfb; sfb<stopSfb; sfb++) {
if (scf[sfb]!=MIN_16) {
scf[sfb] = scfAct;
sfbDist[sfb] = sfbDistNew[sfb];
}
}
}
}
}
} while (stopSfb <= sfbCnt);
} while (scfAct > scfMin);
}
}
/*********************************************************************************
*
* function name: EstimateScaleFactorsChannel
* description: estimate scale factors for one channel
*
**********************************************************************************/
static void
EstimateScaleFactorsChannel(PSY_OUT_CHANNEL *psyOutChan,
Word16 *scf,
Word16 *globalGain,
Word16 *logSfbEnergy,
Word16 *logSfbFormFactor,
Word16 *sfbNRelevantLines)
{
Word32 i, j;
Word32 thresh, energy;
Word32 energyPart, thresholdPart;
Word32 scfInt, minScf, maxScf, maxAllowedScf, lastSf;
Word32 maxSpec;
Word32 *sfbDist = psyOutChan->sfbDist;
Word16 *minSfMaxQuant = psyOutChan->minSfMaxQuant;
Word16 *minScfCalculated = psyOutChan->minScfCalculated;
for (i=0; i<psyOutChan->sfbCnt; i++) {
Word32 sbfwith, sbfStart;
Word32 *mdctSpec;
thresh = psyOutChan->sfbThreshold[i];
energy = psyOutChan->sfbEnergy[i];
sbfStart = psyOutChan->sfbOffsets[i];
sbfwith = psyOutChan->sfbOffsets[i+1] - sbfStart;
mdctSpec = psyOutChan->mdctSpectrum+sbfStart;
maxSpec = 0;
/* maximum of spectrum */
for (j=sbfwith; j; j-- ) {
Word32 absSpec = L_abs(*mdctSpec); mdctSpec++;
maxSpec |= absSpec;
}
/* scfs without energy or with thresh>energy are marked with MIN_16 */
scf[i] = MIN_16;
minSfMaxQuant[i] = MIN_16;
if ((maxSpec > 0) && (energy > thresh)) {
energyPart = logSfbFormFactor[i];
thresholdPart = iLog4(thresh);
/* -20 = 4*log2(6.75) - 32 */
scfInt = ((thresholdPart - energyPart - 20) * SCALE_ESTIMATE_COEF) >> 15;
minSfMaxQuant[i] = iLog4(maxSpec) - 68; /* 68 -16/3*log(MAX_QUANT+0.5-logCon)/log(2) + 1 */
if (minSfMaxQuant[i] > scfInt) {
scfInt = minSfMaxQuant[i];
}
/* find better scalefactor with analysis by synthesis */
scfInt = improveScf(psyOutChan->mdctSpectrum+sbfStart,
sbfwith,
thresh, scfInt, minSfMaxQuant[i],
&sfbDist[i], &minScfCalculated[i]);
scf[i] = scfInt;
}
}
/* scalefactor differece reduction */
{
Word16 sfbConstPePart[MAX_GROUPED_SFB];
for(i=0;i<psyOutChan->sfbCnt;i++) {
sfbConstPePart[i] = MIN_16;
}
assimilateSingleScf(psyOutChan, scf,
minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
logSfbFormFactor, sfbNRelevantLines, minScfCalculated, 1);
assimilateMultipleScf(psyOutChan, scf,
minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
logSfbFormFactor, sfbNRelevantLines);
}
/* get max scalefac for global gain */
maxScf = MIN_16;
minScf = MAX_16;
for (i=0; i<psyOutChan->sfbCnt; i++) {
if (maxScf < scf[i]) {
maxScf = scf[i];
}
if ((scf[i] != MIN_16) && (minScf > scf[i])) {
minScf = scf[i];
}
}
/* limit scf delta */
maxAllowedScf = minScf + MAX_SCF_DELTA;
for(i=0; i<psyOutChan->sfbCnt; i++) {
if ((scf[i] != MIN_16) && (maxAllowedScf < scf[i])) {
scf[i] = maxAllowedScf;
}
}
/* new maxScf if any scf has been limited */
if (maxAllowedScf < maxScf) {
maxScf = maxAllowedScf;
}
/* calc loop scalefactors */
if (maxScf > MIN_16) {
*globalGain = maxScf;
lastSf = 0;
for(i=0; i<psyOutChan->sfbCnt; i++) {
if (scf[i] == MIN_16) {
scf[i] = lastSf;
/* set band explicitely to zero */
for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
psyOutChan->mdctSpectrum[j] = 0;
}
}
else {
scf[i] = maxScf - scf[i];
lastSf = scf[i];
}
}
}
else{
*globalGain = 0;
/* set spectrum explicitely to zero */
for(i=0; i<psyOutChan->sfbCnt; i++) {
scf[i] = 0;
for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
psyOutChan->mdctSpectrum[j] = 0;
}
}
}
}
/*********************************************************************************
*
* function name: CalcFormFactor
* description: estimate Form factors for all channel
*
**********************************************************************************/
void
CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
const Word16 nChannels)
{
Word16 j;
for (j=0; j<nChannels; j++) {
CalcFormFactorChannel(logSfbFormFactor[j], sfbNRelevantLines[j], logSfbEnergy[j], &psyOutChannel[j]);
}
}
/*********************************************************************************
*
* function name: EstimateScaleFactors
* description: estimate scale factors for all channel
*
**********************************************************************************/
void
EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS],
Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
const Word16 nChannels)
{
Word16 j;
for (j=0; j<nChannels; j++) {
EstimateScaleFactorsChannel(&psyOutChannel[j],
qcOutChannel[j].scf,
&(qcOutChannel[j].globalGain),
logSfbEnergy[j],
logSfbFormFactor[j],
sfbNRelevantLines[j]);
}
}

View File

@ -0,0 +1,52 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: spreading.c
Content: Spreading of energy function
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "spreading.h"
/*********************************************************************************
*
* function name: SpreadingMax
* description: spreading the energy
* higher frequencies thr(n) = max(thr(n), sh(n)*thr(n-1))
* lower frequencies thr(n) = max(thr(n), sl(n)*thr(n+1))
*
**********************************************************************************/
void SpreadingMax(const Word16 pbCnt,
const Word16 *maskLowFactor,
const Word16 *maskHighFactor,
Word32 *pbSpreadedEnergy)
{
Word32 i;
/* slope to higher frequencies */
for (i=1; i<pbCnt; i++) {
pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],
L_mpy_ls(pbSpreadedEnergy[i-1], maskHighFactor[i]));
}
/* slope to lower frequencies */
for (i=pbCnt - 2; i>=0; i--) {
pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],
L_mpy_ls(pbSpreadedEnergy[i+1], maskLowFactor[i]));
}
}

View File

@ -0,0 +1,237 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: stat_bits.c
Content: Static bit counter functions
*******************************************************************************/
#include "stat_bits.h"
#include "bitenc.h"
#include "tns.h"
typedef enum {
SI_ID_BITS =(3),
SI_FILL_COUNT_BITS =(4),
SI_FILL_ESC_COUNT_BITS =(8),
SI_FILL_EXTENTION_BITS =(4),
SI_FILL_NIBBLE_BITS =(4),
SI_SCE_BITS =(4),
SI_CPE_BITS =(5),
SI_CPE_MS_MASK_BITS =(2) ,
SI_ICS_INFO_BITS_LONG =(1+2+1+6+1),
SI_ICS_INFO_BITS_SHORT =(1+2+1+4+7),
SI_ICS_BITS =(8+1+1+1)
} SI_BITS;
/*********************************************************************************
*
* function name: countMsMaskBits
* description: count ms stereo bits demand
*
**********************************************************************************/
static Word16 countMsMaskBits(Word16 sfbCnt,
Word16 sfbPerGroup,
Word16 maxSfbPerGroup,
struct TOOLSINFO *toolsInfo)
{
Word16 msBits, sfbOff, sfb;
msBits = 0;
switch(toolsInfo->msDigest) {
case MS_NONE:
case MS_ALL:
break;
case MS_SOME:
for(sfbOff=0; sfbOff<sfbCnt; sfbOff+=sfbPerGroup)
for(sfb=0; sfb<maxSfbPerGroup; sfb++)
msBits += 1;
break;
}
return(msBits);
}
/*********************************************************************************
*
* function name: tnsCount
* description: count tns bit demand core function
*
**********************************************************************************/
static Word16 tnsCount(TNS_INFO *tnsInfo, Word16 blockType)
{
Word32 i, k;
Flag tnsPresent;
Word32 numOfWindows;
Word32 count;
Word32 coefBits;
Word16 *ptcoef;
count = 0;
if (blockType == 2)
numOfWindows = 8;
else
numOfWindows = 1;
tnsPresent = 0;
for (i=0; i<numOfWindows; i++) {
if (tnsInfo->tnsActive[i]!=0) {
tnsPresent = 1;
}
}
if (tnsPresent) {
/* there is data to be written*/
/*count += 1; */
for (i=0; i<numOfWindows; i++) {
if (blockType == 2)
count += 1;
else
count += 2;
if (tnsInfo->tnsActive[i]) {
count += 1;
if (blockType == 2) {
count += 4;
count += 3;
}
else {
count += 6;
count += 5;
}
if (tnsInfo->order[i]) {
count += 1; /*direction*/
count += 1; /*coef_compression */
if (tnsInfo->coefRes[i] == 4) {
ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;
coefBits = 3;
for(k=0; k<tnsInfo->order[i]; k++) {
if ((ptcoef[k] > 3) || (ptcoef[k] < -4)) {
coefBits = 4;
break;
}
}
}
else {
coefBits = 2;
ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;
for(k=0; k<tnsInfo->order[i]; k++) {
if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) {
coefBits = 3;
break;
}
}
}
for (k=0; k<tnsInfo->order[i]; k++ ) {
count += coefBits;
}
}
}
}
}
return count;
}
/**********************************************************************************
*
* function name: countTnsBits
* description: count tns bit demand
*
**********************************************************************************/
static Word16 countTnsBits(TNS_INFO *tnsInfo,Word16 blockType)
{
return(tnsCount(tnsInfo, blockType));
}
/*********************************************************************************
*
* function name: countStaticBitdemand
* description: count static bit demand include tns
*
**********************************************************************************/
Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
PSY_OUT_ELEMENT *psyOutElement,
Word16 channels,
Word16 adtsUsed)
{
Word32 statBits;
Word32 ch;
statBits = 0;
/* if adts used, add 56 bits */
if(adtsUsed) statBits += 56;
switch (channels) {
case 1:
statBits += SI_ID_BITS+SI_SCE_BITS+SI_ICS_BITS;
statBits += countTnsBits(&(psyOutChannel[0].tnsInfo),
psyOutChannel[0].windowSequence);
switch(psyOutChannel[0].windowSequence){
case LONG_WINDOW:
case START_WINDOW:
case STOP_WINDOW:
statBits += SI_ICS_INFO_BITS_LONG;
break;
case SHORT_WINDOW:
statBits += SI_ICS_INFO_BITS_SHORT;
break;
}
break;
case 2:
statBits += SI_ID_BITS+SI_CPE_BITS+2*SI_ICS_BITS;
statBits += SI_CPE_MS_MASK_BITS;
statBits += countMsMaskBits(psyOutChannel[0].sfbCnt,
psyOutChannel[0].sfbPerGroup,
psyOutChannel[0].maxSfbPerGroup,
&psyOutElement->toolsInfo);
switch (psyOutChannel[0].windowSequence) {
case LONG_WINDOW:
case START_WINDOW:
case STOP_WINDOW:
statBits += SI_ICS_INFO_BITS_LONG;
break;
case SHORT_WINDOW:
statBits += SI_ICS_INFO_BITS_SHORT;
break;
}
for(ch=0; ch<2; ch++)
statBits += countTnsBits(&(psyOutChannel[ch].tnsInfo),
psyOutChannel[ch].windowSequence);
break;
}
return statBits;
}

View File

@ -0,0 +1,932 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: tns.c
Content: Definition TNS tools functions
*******************************************************************************/
#include "basic_op.h"
#include "oper_32b.h"
#include "assert.h"
#include "aac_rom.h"
#include "psy_const.h"
#include "tns.h"
#include "tns_param.h"
#include "psy_configuration.h"
#include "tns_func.h"
#define TNS_MODIFY_BEGIN 2600 /* Hz */
#define RATIO_PATCH_LOWER_BORDER 380 /* Hz */
#define TNS_GAIN_THRESH 141 /* 1.41*100 */
#define NORM_COEF 0x028f5c28
static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
/* 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 void CalcWeightedSpectrum(const Word32 spectrum[],
Word16 weightedSpectrum[],
Word32* sfbEnergy,
const Word16* sfbOffset, Word16 lpcStartLine,
Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand,
Word32 *pWork32);
void AutoCorrelation(const Word16 input[], Word32 corr[],
Word16 samples, Word16 corrCoeff);
static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
Word16 tnsOrder, Word32 parcor[]);
static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
Word16 bitsPerCoeff);
static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
Word16 bitsPerCoeff);
static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines,
const Word32 parCoeff[], Word16 order,
Word32 output[]);
/**
*
* function name: FreqToBandWithRounding
* description: Retrieve index of nearest band border
* returnt: index
*
*/
static Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */
Word32 fs, /*!< Sampling frequency in Hertz */
Word16 numOfBands, /*!< total number of bands */
const Word16 *bandStartOffset) /*!< table of band borders */
{
Word32 lineNumber, band;
Word32 temp, shift;
/* assert(freq >= 0); */
shift = norm_l(fs);
lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1;
/* freq > fs/2 */
temp = lineNumber - bandStartOffset[numOfBands] ;
if (temp >= 0)
return numOfBands;
/* find band the line number lies in */
for (band=0; band<numOfBands; band++) {
temp = bandStartOffset[band + 1] - lineNumber;
if (temp > 0) break;
}
temp = (lineNumber - bandStartOffset[band]);
temp = (temp - (bandStartOffset[band + 1] - lineNumber));
if ( temp > 0 )
{
band = band + 1;
}
return extract_l(band);
}
/**
*
* function name: InitTnsConfigurationLong
* description: Fill TNS_CONFIG structure with sensible content for long blocks
* returns: 0 if success
*
*/
Word16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */
Word32 sampleRate, /*!< Sampling frequency */
Word16 channels, /*!< number of channels */
TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */
Word16 active) /*!< tns active flag */
{
Word32 bitratePerChannel;
tC->maxOrder = TNS_MAX_ORDER;
tC->tnsStartFreq = 1275;
tC->coefRes = 4;
/* to avoid integer division */
if ( sub(channels,2) == 0 ) {
bitratePerChannel = bitRate >> 1;
}
else {
bitratePerChannel = bitRate;
}
tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx];
tC->tnsActive = active;
/* now calc band and line borders */
tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
pC->sfbCnt, (const Word16*)pC->sfbOffset);
tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
sampleRate,
pC->sfbCnt,
(const Word16*)pC->sfbOffset);
tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
sampleRate,
pC->sfbCnt,
(const Word16*)pC->sfbOffset);
tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx];
tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx];
tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
tC->threshold = TNS_GAIN_THRESH;
return(0);
}
/**
*
* function name: InitTnsConfigurationShort
* description: Fill TNS_CONFIG structure with sensible content for short blocks
* returns: 0 if success
*
*/
Word16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */
Word32 sampleRate, /*!< Sampling frequency */
Word16 channels, /*!< number of channels */
TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
Word16 active) /*!< tns active flag */
{
Word32 bitratePerChannel;
tC->maxOrder = TNS_MAX_ORDER_SHORT;
tC->tnsStartFreq = 2750;
tC->coefRes = 3;
/* to avoid integer division */
if ( sub(channels,2) == 0 ) {
bitratePerChannel = L_shr(bitRate,1);
}
else {
bitratePerChannel = bitRate;
}
tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx];
tC->tnsActive = active;
/* now calc band and line borders */
tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
pC->sfbCnt, (const Word16*)pC->sfbOffset);
tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
sampleRate,
pC->sfbCnt,
(const Word16*)pC->sfbOffset);
tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
sampleRate,
pC->sfbCnt,
(const Word16*)pC->sfbOffset);
tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx];
tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx];
tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
tC->threshold = TNS_GAIN_THRESH;
return(0);
}
/**
*
* function name: TnsDetect
* description: Calculate TNS filter and decide on TNS usage
* returns: 0 if success
*
*/
Word32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */
TNS_CONFIG tC, /*!< tns config structure */
Word32* pScratchTns, /*!< pointer to scratch space */
const Word16 sfbOffset[], /*!< scalefactor size and table */
Word32* spectrum, /*!< spectral data */
Word16 subBlockNumber, /*!< subblock num */
Word16 blockType, /*!< blocktype (long or short) */
Word32 * sfbEnergy) /*!< sfb-wise energy */
{
Word32 predictionGain;
Word32 temp;
Word32* pWork32 = &pScratchTns[subBlockNumber >> 8];
Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8];
if (tC.tnsActive) {
CalcWeightedSpectrum(spectrum,
pWeightedSpectrum,
sfbEnergy,
sfbOffset,
tC.lpcStartLine,
tC.lpcStopLine,
tC.lpcStartBand,
tC.lpcStopBand,
pWork32);
temp = blockType - SHORT_WINDOW;
if ( temp != 0 ) {
predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
tC.acfWindow,
tC.lpcStopLine - tC.lpcStartLine,
tC.maxOrder,
tnsData->dataRaw.tnsLong.subBlockInfo.parcor);
temp = predictionGain - tC.threshold;
if ( temp > 0 ) {
tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1;
}
else {
tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
}
tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain;
}
else{
predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
tC.acfWindow,
tC.lpcStopLine - tC.lpcStartLine,
tC.maxOrder,
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor);
temp = predictionGain - tC.threshold;
if ( temp > 0 ) {
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1;
}
else {
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
}
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain;
}
}
else{
temp = blockType - SHORT_WINDOW;
if ( temp != 0 ) {
tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0;
}
else {
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0;
}
}
return(0);
}
/*****************************************************************************
*
* function name: TnsSync
* description: update tns parameter
*
*****************************************************************************/
void TnsSync(TNS_DATA *tnsDataDest,
const TNS_DATA *tnsDataSrc,
const TNS_CONFIG tC,
const Word16 subBlockNumber,
const Word16 blockType)
{
TNS_SUBBLOCK_INFO *sbInfoDest;
const TNS_SUBBLOCK_INFO *sbInfoSrc;
Word32 i, temp;
temp = blockType - SHORT_WINDOW;
if ( temp != 0 ) {
sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo;
sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo;
}
else {
sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
}
if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) <
(3 * sbInfoDest->predictionGain)) {
sbInfoDest->tnsActive = sbInfoSrc->tnsActive;
for ( i=0; i< tC.maxOrder; i++) {
sbInfoDest->parcor[i] = sbInfoSrc->parcor[i];
}
}
}
/*****************************************************************************
*
* function name: TnsEncode
* description: do TNS filtering
* returns: 0 if success
*
*****************************************************************************/
Word16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */
TNS_DATA* tnsData, /*!< tns data structure (modified) */
Word16 numOfSfb, /*!< number of scale factor bands */
TNS_CONFIG tC, /*!< tns config structure */
Word16 lowPassLine, /*!< lowpass line */
Word32* spectrum, /*!< spectral data (modified) */
Word16 subBlockNumber, /*!< subblock num */
Word16 blockType) /*!< blocktype (long or short) */
{
Word32 i;
Word32 temp_s;
Word32 temp;
TNS_SUBBLOCK_INFO *psubBlockInfo;
temp_s = blockType - SHORT_WINDOW;
if ( temp_s != 0) {
psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo;
if (psubBlockInfo->tnsActive == 0) {
tnsInfo->tnsActive[subBlockNumber] = 0;
return(0);
}
else {
Parcor2Index(psubBlockInfo->parcor,
tnsInfo->coef,
tC.maxOrder,
tC.coefRes);
Index2Parcor(tnsInfo->coef,
psubBlockInfo->parcor,
tC.maxOrder,
tC.coefRes);
for (i=tC.maxOrder - 1; i>=0; i--) {
temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
if ( temp > 0 )
break;
temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
if ( temp < 0 )
break;
}
tnsInfo->order[subBlockNumber] = i + 1;
tnsInfo->tnsActive[subBlockNumber] = 1;
for (i=subBlockNumber+1; i<TRANS_FAC; i++) {
tnsInfo->tnsActive[i] = 0;
}
tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]),
(min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine),
psubBlockInfo->parcor,
tnsInfo->order[subBlockNumber],
&(spectrum[tC.tnsStartLine]));
}
} /* if (blockType!=SHORT_WINDOW) */
else /*short block*/ {
psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
if (psubBlockInfo->tnsActive == 0) {
tnsInfo->tnsActive[subBlockNumber] = 0;
return(0);
}
else {
Parcor2Index(psubBlockInfo->parcor,
&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
tC.maxOrder,
tC.coefRes);
Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
psubBlockInfo->parcor,
tC.maxOrder,
tC.coefRes);
for (i=(tC.maxOrder - 1); i>=0; i--) {
temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
if ( temp > 0 )
break;
temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
if ( temp < 0 )
break;
}
tnsInfo->order[subBlockNumber] = i + 1;
tnsInfo->tnsActive[subBlockNumber] = 1;
tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine),
psubBlockInfo->parcor,
tnsInfo->order[subBlockNumber],
&(spectrum[tC.tnsStartLine]));
}
}
return(0);
}
/*****************************************************************************
*
* function name: m_pow2_cordic
* description: Iterative power function
*
* Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision
* using modified cordic algorithm
* returns: the result of pow2
*
*****************************************************************************/
static Word32 m_pow2_cordic(Word32 x, Word16 scale)
{
Word32 k;
Word32 accu_y = 0x40000000;
accu_y = L_shr(accu_y,scale);
for(k=1; k<INT_BITS; k++) {
const Word32 z = m_log2_table[k];
while(L_sub(x,z) >= 0) {
x = L_sub(x, z);
accu_y = L_add(accu_y, (accu_y >> k));
}
}
return(accu_y);
}
/*****************************************************************************
*
* function name: CalcWeightedSpectrum
* description: Calculate weighted spectrum for LPC calculation
*
*****************************************************************************/
static void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */
Word16 weightedSpectrum[],
Word32 *sfbEnergy, /*!< sfb energies */
const Word16 *sfbOffset,
Word16 lpcStartLine,
Word16 lpcStopLine,
Word16 lpcStartBand,
Word16 lpcStopBand,
Word32 *pWork32)
{
#define INT_BITS_SCAL 1<<(INT_BITS/2)
Word32 i, sfb, shift;
Word32 maxShift;
Word32 tmp_s, tmp2_s;
Word32 tmp, tmp2;
Word32 maxWS;
Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */
maxWS = 0;
/* calc 1.0*2^-INT_BITS/2/sqrt(en) */
for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
tmp2 = sfbEnergy[sfb] - 2;
if( tmp2 > 0) {
tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
if(tmp > INT_BITS_SCAL)
{
shift = norm_l(tmp);
tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift );
}
else
{
tmp = 0x7fffffff;
}
}
else {
tmp = 0x7fffffff;
}
tnsSfbMean[sfb] = tmp;
}
/* spread normalized values from sfbs to lines */
sfb = lpcStartBand;
tmp = tnsSfbMean[sfb];
for ( i=lpcStartLine; i<lpcStopLine; i++){
tmp_s = sfbOffset[sfb + 1] - i;
if ( tmp_s == 0 ) {
sfb = sfb + 1;
tmp2_s = sfb + 1 - lpcStopBand;
if (tmp2_s <= 0) {
tmp = tnsSfbMean[sfb];
}
}
pWork32[i] = tmp;
}
/*filter down*/
for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
}
/* filter up */
for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
}
/* weight and normalize */
for (i=lpcStartLine; i<lpcStopLine; i++){
pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);
maxWS |= L_abs(pWork32[i]);
}
maxShift = norm_l(maxWS);
maxShift = 16 - maxShift;
if(maxShift >= 0)
{
for (i=lpcStartLine; i<lpcStopLine; i++){
weightedSpectrum[i] = pWork32[i] >> maxShift;
}
}
else
{
maxShift = -maxShift;
for (i=lpcStartLine; i<lpcStopLine; i++){
weightedSpectrum[i] = saturate(pWork32[i] << maxShift);
}
}
}
/*****************************************************************************
*
* function name: CalcTnsFilter
* description: LPC calculation for one TNS filter
* returns: prediction gain
* input: signal spectrum, acf window, no. of spectral lines,
* max. TNS order, ptr. to reflection ocefficients
* output: reflection coefficients
*(half) window size must be larger than tnsOrder !!*
******************************************************************************/
static Word16 CalcTnsFilter(const Word16 *signal,
const Word32 window[],
Word16 numOfLines,
Word16 tnsOrder,
Word32 parcor[])
{
Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
Word32 predictionGain;
Word32 i;
Word32 tnsOrderPlus1 = tnsOrder + 1;
assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */
for(i=0;i<tnsOrder;i++) {
parcor[i] = 0;
}
AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
/* early return if signal is very low: signal prediction off, with zero parcor coeffs */
if (parcorWorkBuffer[0] == 0)
return 0;
predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
return(predictionGain);
}
/*****************************************************************************
*
* function name: AutoCorrelation
* description: calc. autocorrelation (acf)
* returns: -
* input: input values, no. of input values, no. of acf values
* output: acf values
*
*****************************************************************************/
#ifndef ARMV5E
void AutoCorrelation(const Word16 input[],
Word32 corr[],
Word16 samples,
Word16 corrCoeff) {
Word32 i, j, isamples;
Word32 accu;
Word32 scf;
scf = 10 - 1;
isamples = samples;
/* calc first corrCoef: R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
accu = 0;
for(j=0; j<isamples; j++) {
accu = L_add(accu, ((input[j] * input[j]) >> scf));
}
corr[0] = accu;
/* early termination if all corr coeffs are likely going to be zero */
if(corr[0] == 0) return ;
/* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
for(i=1; i<corrCoeff; i++) {
isamples = isamples - 1;
accu = 0;
for(j=0; j<isamples; j++) {
accu = L_add(accu, ((input[j] * input[j+i]) >> scf));
}
corr[i] = accu;
}
}
#endif
/*****************************************************************************
*
* function name: AutoToParcor
* description: conversion autocorrelation to reflection coefficients
* returns: prediction gain
* input: <order+1> input values, no. of output values (=order),
* ptr. to workbuffer (required size: 2*order)
* output: <order> reflection coefficients
*
*****************************************************************************/
static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
Word32 i, j, shift;
Word32 *pWorkBuffer; /* temp pointer */
Word32 predictionGain = 0;
Word32 num, denom;
Word32 temp, workBuffer0;
num = workBuffer[0];
temp = workBuffer[numOfCoeff];
for(i=0; i<numOfCoeff-1; i++) {
workBuffer[i + numOfCoeff] = workBuffer[i + 1];
}
workBuffer[i + numOfCoeff] = temp;
for(i=0; i<numOfCoeff; i++) {
Word32 refc;
if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
return 0 ;
}
shift = norm_l(workBuffer[0]);
workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
/* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
reflCoeff[i] = refc;
pWorkBuffer = &(workBuffer[numOfCoeff]);
for(j=i; j<numOfCoeff; j++) {
Word32 accu1, accu2;
accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
pWorkBuffer[j] = accu1;
workBuffer[j - i] = accu2;
}
}
denom = MULHIGH(workBuffer[0], NORM_COEF);
if (denom != 0) {
Word32 temp;
shift = norm_l(denom);
temp = Div_32(1 << shift, denom << shift);
predictionGain = fixmul(num, temp);
}
return extract_l(predictionGain);
}
static Word16 Search3(Word32 parcor)
{
Word32 index = 0;
Word32 i;
Word32 temp;
for (i=0;i<8;i++) {
temp = L_sub( parcor, tnsCoeff3Borders[i]);
if (temp > 0)
index=i;
}
return extract_l(index - 4);
}
static Word16 Search4(Word32 parcor)
{
Word32 index = 0;
Word32 i;
Word32 temp;
for (i=0;i<16;i++) {
temp = L_sub(parcor, tnsCoeff4Borders[i]);
if (temp > 0)
index=i;
}
return extract_l(index - 8);
}
/*****************************************************************************
*
* functionname: Parcor2Index
* description: quantization index for reflection coefficients
*
*****************************************************************************/
static void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */
Word16 index[], /*!< quantized coeff indices */
Word16 order, /*!< filter order */
Word16 bitsPerCoeff) { /*!< quantizer resolution */
Word32 i;
Word32 temp;
for(i=0; i<order; i++) {
temp = bitsPerCoeff - 3;
if (temp == 0) {
index[i] = Search3(parcor[i]);
}
else {
index[i] = Search4(parcor[i]);
}
}
}
/*****************************************************************************
*
* functionname: Index2Parcor
* description: Inverse quantization for reflection coefficients
*
*****************************************************************************/
static void Index2Parcor(const Word16 index[], /*!< quantized values */
Word32 parcor[], /*!< ptr. to reflection coefficients (output) */
Word16 order, /*!< no. of coefficients */
Word16 bitsPerCoeff) /*!< quantizer resolution */
{
Word32 i;
Word32 temp;
for (i=0; i<order; i++) {
temp = bitsPerCoeff - 4;
if ( temp == 0 ) {
parcor[i] = tnsCoeff4[index[i] + 8];
}
else {
parcor[i] = tnsCoeff3[index[i] + 4];
}
}
}
/*****************************************************************************
*
* functionname: FIRLattice
* description: in place lattice filtering of spectral data
* returns: pointer to modified data
*
*****************************************************************************/
static Word32 FIRLattice(Word16 order, /*!< filter order */
Word32 x, /*!< spectral data */
Word32 *state_par, /*!< filter states */
const Word32 *coef_par) /*!< filter coefficients */
{
Word32 i;
Word32 accu,tmp,tmpSave;
x = x >> 1;
tmpSave = x;
for (i=0; i<(order - 1); i++) {
tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
x = L_add(fixmul(coef_par[i], state_par[i]), x);
state_par[i] = tmpSave;
tmpSave = tmp;
}
/* last stage: only need half operations */
accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
state_par[(order - 1)] = tmpSave;
x = L_add(accu, x);
x = L_add(x, x);
return x;
}
/*****************************************************************************
*
* functionname: AnalysisFilterLattice
* description: filters spectral lines with TNS filter
*
*****************************************************************************/
static void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */
Word16 numOfLines, /*!< no. of lines */
const Word32 parCoeff[],/*!< PARC coefficients */
Word16 order, /*!< filter order */
Word32 output[]) /*!< filtered signal values */
{
Word32 state_par[TNS_MAX_ORDER];
Word32 j;
for ( j=0; j<TNS_MAX_ORDER; j++ ) {
state_par[j] = 0;
}
for(j=0; j<numOfLines; j++) {
output[j] = FIRLattice(order,signal[j],state_par,parCoeff);
}
}
/*****************************************************************************
*
* functionname: ApplyTnsMultTableToRatios
* description: Change thresholds according to tns
*
*****************************************************************************/
void ApplyTnsMultTableToRatios(Word16 startCb,
Word16 stopCb,
TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
Word32 *thresholds) /*!< thresholds (modified) */
{
Word32 i;
if (subInfo.tnsActive) {
for(i=startCb; i<stopCb; i++) {
/* thresholds[i] * 0.25 */
thresholds[i] = (thresholds[i] >> 2);
}
}
}

View File

@ -0,0 +1,672 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*******************************************************************************
File: transform.c
Content: MDCT Transform functionss
*******************************************************************************/
#include "basic_op.h"
#include "psy_const.h"
#include "transform.h"
#include "aac_rom.h"
#define LS_TRANS ((FRAME_LEN_LONG-FRAME_LEN_SHORT)/2) /* 448 */
#define SQRT1_2 0x5a82799a /* sqrt(1/2) in Q31 */
#define swap2(p0,p1) \
t = p0; t1 = *(&(p0)+1); \
p0 = p1; *(&(p0)+1) = *(&(p1)+1); \
p1 = t; *(&(p1)+1) = t1
/*********************************************************************************
*
* function name: Shuffle
* description: Shuffle points prepared function for fft
*
**********************************************************************************/
static void Shuffle(int *buf, int num, const unsigned char* bitTab)
{
int *part0, *part1;
int i, j;
int t, t1;
part0 = buf;
part1 = buf + num;
while ((i = *bitTab++) != 0) {
j = *bitTab++;
swap2(part0[4*i+0], part0[4*j+0]);
swap2(part0[4*i+2], part1[4*j+0]);
swap2(part1[4*i+0], part0[4*j+2]);
swap2(part1[4*i+2], part1[4*j+2]);
}
do {
swap2(part0[4*i+2], part1[4*i+0]);
} while ((i = *bitTab++) != 0);
}
#if !defined(ARMV5E) && !defined(ARMV7Neon)
/*****************************************************************************
*
* function name: Radix4First
* description: Radix 4 point prepared function for fft
*
**********************************************************************************/
static void Radix4First(int *buf, int num)
{
int r0, r1, r2, r3;
int r4, r5, r6, r7;
for (; num != 0; num--)
{
r0 = buf[0] + buf[2];
r1 = buf[1] + buf[3];
r2 = buf[0] - buf[2];
r3 = buf[1] - buf[3];
r4 = buf[4] + buf[6];
r5 = buf[5] + buf[7];
r6 = buf[4] - buf[6];
r7 = buf[5] - buf[7];
buf[0] = r0 + r4;
buf[1] = r1 + r5;
buf[4] = r0 - r4;
buf[5] = r1 - r5;
buf[2] = r2 + r7;
buf[3] = r3 - r6;
buf[6] = r2 - r7;
buf[7] = r3 + r6;
buf += 8;
}
}
/*****************************************************************************
*
* function name: Radix8First
* description: Radix 8 point prepared function for fft
*
**********************************************************************************/
static void Radix8First(int *buf, int num)
{
int r0, r1, r2, r3;
int i0, i1, i2, i3;
int r4, r5, r6, r7;
int i4, i5, i6, i7;
int t0, t1, t2, t3;
for ( ; num != 0; num--)
{
r0 = buf[0] + buf[2];
i0 = buf[1] + buf[3];
r1 = buf[0] - buf[2];
i1 = buf[1] - buf[3];
r2 = buf[4] + buf[6];
i2 = buf[5] + buf[7];
r3 = buf[4] - buf[6];
i3 = buf[5] - buf[7];
r4 = (r0 + r2) >> 1;
i4 = (i0 + i2) >> 1;
r5 = (r0 - r2) >> 1;
i5 = (i0 - i2) >> 1;
r6 = (r1 - i3) >> 1;
i6 = (i1 + r3) >> 1;
r7 = (r1 + i3) >> 1;
i7 = (i1 - r3) >> 1;
r0 = buf[ 8] + buf[10];
i0 = buf[ 9] + buf[11];
r1 = buf[ 8] - buf[10];
i1 = buf[ 9] - buf[11];
r2 = buf[12] + buf[14];
i2 = buf[13] + buf[15];
r3 = buf[12] - buf[14];
i3 = buf[13] - buf[15];
t0 = (r0 + r2) >> 1;
t1 = (i0 + i2) >> 1;
t2 = (r0 - r2) >> 1;
t3 = (i0 - i2) >> 1;
buf[ 0] = r4 + t0;
buf[ 1] = i4 + t1;
buf[ 8] = r4 - t0;
buf[ 9] = i4 - t1;
buf[ 4] = r5 + t3;
buf[ 5] = i5 - t2;
buf[12] = r5 - t3;
buf[13] = i5 + t2;
r0 = r1 - i3;
i0 = i1 + r3;
r2 = r1 + i3;
i2 = i1 - r3;
t0 = MULHIGH(SQRT1_2, r0 - i0);
t1 = MULHIGH(SQRT1_2, r0 + i0);
t2 = MULHIGH(SQRT1_2, r2 - i2);
t3 = MULHIGH(SQRT1_2, r2 + i2);
buf[ 6] = r6 - t0;
buf[ 7] = i6 - t1;
buf[14] = r6 + t0;
buf[15] = i6 + t1;
buf[ 2] = r7 + t3;
buf[ 3] = i7 - t2;
buf[10] = r7 - t3;
buf[11] = i7 + t2;
buf += 16;
}
}
/*****************************************************************************
*
* function name: Radix4FFT
* description: Radix 4 point fft core function
*
**********************************************************************************/
static void Radix4FFT(int *buf, int num, int bgn, int *twidTab)
{
int r0, r1, r2, r3;
int r4, r5, r6, r7;
int t0, t1;
int sinx, cosx;
int i, j, step;
int *xptr, *csptr;
for (num >>= 2; num != 0; num >>= 2)
{
step = 2*bgn;
xptr = buf;
for (i = num; i != 0; i--)
{
csptr = twidTab;
for (j = bgn; j != 0; j--)
{
r0 = xptr[0];
r1 = xptr[1];
xptr += step;
t0 = xptr[0];
t1 = xptr[1];
cosx = csptr[0];
sinx = csptr[1];
r2 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*br + sin*bi */
r3 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*bi - sin*br */
xptr += step;
t0 = r0 >> 2;
t1 = r1 >> 2;
r0 = t0 - r2;
r1 = t1 - r3;
r2 = t0 + r2;
r3 = t1 + r3;
t0 = xptr[0];
t1 = xptr[1];
cosx = csptr[2];
sinx = csptr[3];
r4 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */
r5 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */
xptr += step;
t0 = xptr[0];
t1 = xptr[1];
cosx = csptr[4];
sinx = csptr[5];
r6 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */
r7 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */
csptr += 6;
t0 = r4;
t1 = r5;
r4 = t0 + r6;
r5 = r7 - t1;
r6 = t0 - r6;
r7 = r7 + t1;
xptr[0] = r0 + r5;
xptr[1] = r1 + r6;
xptr -= step;
xptr[0] = r2 - r4;
xptr[1] = r3 - r7;
xptr -= step;
xptr[0] = r0 - r5;
xptr[1] = r1 - r6;
xptr -= step;
xptr[0] = r2 + r4;
xptr[1] = r3 + r7;
xptr += 2;
}
xptr += 3*step;
}
twidTab += 3*step;
bgn <<= 2;
}
}
/*********************************************************************************
*
* function name: PreMDCT
* description: prepare MDCT process for next FFT compute
*
**********************************************************************************/
static void PreMDCT(int *buf0, int num, const int *csptr)
{
int i;
int tr1, ti1, tr2, ti2;
int cosa, sina, cosb, sinb;
int *buf1;
buf1 = buf0 + num - 1;
for(i = num >> 2; i != 0; i--)
{
cosa = *csptr++;
sina = *csptr++;
cosb = *csptr++;
sinb = *csptr++;
tr1 = *(buf0 + 0);
ti2 = *(buf0 + 1);
tr2 = *(buf1 - 1);
ti1 = *(buf1 + 0);
*buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);
*buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1);
*buf1-- = MULHIGH(cosb, ti2) - MULHIGH(sinb, tr2);
*buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);
}
}
/*********************************************************************************
*
* function name: PostMDCT
* description: post MDCT process after next FFT for MDCT
*
**********************************************************************************/
static void PostMDCT(int *buf0, int num, const int *csptr)
{
int i;
int tr1, ti1, tr2, ti2;
int cosa, sina, cosb, sinb;
int *buf1;
buf1 = buf0 + num - 1;
for(i = num >> 2; i != 0; i--)
{
cosa = *csptr++;
sina = *csptr++;
cosb = *csptr++;
sinb = *csptr++;
tr1 = *(buf0 + 0);
ti1 = *(buf0 + 1);
ti2 = *(buf1 + 0);
tr2 = *(buf1 - 1);
*buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);
*buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1);
*buf0++ = MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2);
*buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);
}
}
#endif
/**********************************************************************************
*
* function name: Mdct_Long
* description: the long block mdct, include long_start block, end_long block
*
**********************************************************************************/
void Mdct_Long(int *buf)
{
PreMDCT(buf, 1024, cossintab + 128);
Shuffle(buf, 512, bitrevTab + 17);
Radix8First(buf, 512 >> 3);
Radix4FFT(buf, 512 >> 3, 8, (int *)twidTab512);
PostMDCT(buf, 1024, cossintab + 128);
}
/**********************************************************************************
*
* function name: Mdct_Short
* description: the short block mdct
*
**********************************************************************************/
void Mdct_Short(int *buf)
{
PreMDCT(buf, 128, cossintab);
Shuffle(buf, 64, bitrevTab);
Radix4First(buf, 64 >> 2);
Radix4FFT(buf, 64 >> 2, 4, (int *)twidTab64);
PostMDCT(buf, 128, cossintab);
}
/*****************************************************************************
*
* function name: shiftMdctDelayBuffer
* description: the mdct delay buffer has a size of 1600,
* so the calculation of LONG,STOP must be spilt in two
* passes with 1024 samples and a mid shift,
* the SHORT transforms can be completed in the delay buffer,
* and afterwards a shift
*
**********************************************************************************/
static void shiftMdctDelayBuffer(Word16 *mdctDelayBuffer, /*! start of mdct delay buffer */
Word16 *timeSignal, /*! pointer to new time signal samples, interleaved */
Word16 chIncrement /*! number of channels */
)
{
Word32 i;
Word16 *srBuf = mdctDelayBuffer;
Word16 *dsBuf = mdctDelayBuffer+FRAME_LEN_LONG;
for(i = 0; i < BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG; i+= 8)
{
*srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
*srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
*srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
*srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
}
srBuf = mdctDelayBuffer + BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG;
dsBuf = timeSignal;
for(i=0; i<FRAME_LEN_LONG; i+=8)
{
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
*srBuf++ = *dsBuf; dsBuf += chIncrement;
}
}
/*****************************************************************************
*
* function name: getScalefactorOfShortVectorStride
* description: Calculate max possible scale factor for input vector of shorts
* returns: Maximum scale factor
*
**********************************************************************************/
static Word16 getScalefactorOfShortVectorStride(const Word16 *vector, /*!< Pointer to input vector */
Word16 len, /*!< Length of input vector */
Word16 stride) /*!< Stride of input vector */
{
Word16 maxVal = 0;
Word16 absVal;
Word16 i;
for(i=0; i<len; i++){
absVal = abs_s(vector[i*stride]);
maxVal |= absVal;
}
return( maxVal ? norm_s(maxVal) : 15);
}
/*****************************************************************************
*
* function name: Transform_Real
* description: Calculate transform filter for input vector of shorts
* returns: TRUE if success
*
**********************************************************************************/
void Transform_Real(Word16 *mdctDelayBuffer,
Word16 *timeSignal,
Word16 chIncrement,
Word32 *realOut,
Word16 *mdctScale,
Word16 blockType
)
{
Word32 i,w;
Word32 timeSignalSample;
Word32 ws1,ws2;
Word16 *dctIn0, *dctIn1;
Word32 *outData0, *outData1;
Word32 *winPtr;
Word32 delayBufferSf,timeSignalSf,minSf;
Word32 headRoom=0;
switch(blockType){
case LONG_WINDOW:
/*
we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + 448 new timeSignal samples
and get the biggest scale factor for next calculate more precise
*/
delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
timeSignalSf = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
minSf = min(delayBufferSf,timeSignalSf);
minSf = min(minSf,14);
dctIn0 = mdctDelayBuffer;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
outData0 = realOut + FRAME_LEN_LONG/2;
/* add windows and pre add for mdct to last buffer*/
winPtr = (int *)LongWindowKBD;
for(i=0;i<FRAME_LEN_LONG/2;i++){
timeSignalSample = (*dctIn0++) << minSf;
ws1 = timeSignalSample * (*winPtr >> 16);
timeSignalSample = (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr & 0xffff);
winPtr ++;
/* shift 2 to avoid overflow next */
*outData0++ = (ws1 >> 2) - (ws2 >> 2);
}
shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
/* add windows and pre add for mdct to new buffer*/
dctIn0 = mdctDelayBuffer;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
outData0 = realOut + FRAME_LEN_LONG/2 - 1;
winPtr = (int *)LongWindowKBD;
for(i=0;i<FRAME_LEN_LONG/2;i++){
timeSignalSample = (*dctIn0++) << minSf;
ws1 = timeSignalSample * (*winPtr & 0xffff);
timeSignalSample = (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr >> 16);
winPtr++;
/* shift 2 to avoid overflow next */
*outData0-- = -((ws1 >> 2) + (ws2 >> 2));
}
Mdct_Long(realOut);
/* update scale factor */
minSf = 14 - minSf;
*mdctScale=minSf;
break;
case START_WINDOW:
/*
we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no timeSignal samples
and get the biggest scale factor for next calculate more precise
*/
minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
minSf = min(minSf,14);
dctIn0 = mdctDelayBuffer;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
outData0 = realOut + FRAME_LEN_LONG/2;
winPtr = (int *)LongWindowKBD;
/* add windows and pre add for mdct to last buffer*/
for(i=0;i<FRAME_LEN_LONG/2;i++){
timeSignalSample = (*dctIn0++) << minSf;
ws1 = timeSignalSample * (*winPtr >> 16);
timeSignalSample = (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr & 0xffff);
winPtr ++;
*outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
}
shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
outData0 = realOut + FRAME_LEN_LONG/2 - 1;
for(i=0;i<LS_TRANS;i++){
*outData0-- = -mdctDelayBuffer[i] << (15 - 2 + minSf);
}
/* add windows and pre add for mdct to new buffer*/
dctIn0 = mdctDelayBuffer + LS_TRANS;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
outData0 = realOut + FRAME_LEN_LONG/2 - 1 -LS_TRANS;
winPtr = (int *)ShortWindowSine;
for(i=0;i<FRAME_LEN_SHORT/2;i++){
timeSignalSample= (*dctIn0++) << minSf;
ws1 = timeSignalSample * (*winPtr & 0xffff);
timeSignalSample= (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr >> 16);
winPtr++;
*outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
}
Mdct_Long(realOut);
/* update scale factor */
minSf = 14 - minSf;
*mdctScale= minSf;
break;
case STOP_WINDOW:
/*
we access BLOCK_SWITCHING_OFFSET-LS_TRANS (1600-448 ) delay buffer samples + 448 new timeSignal samples
and get the biggest scale factor for next calculate more precise
*/
delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+LS_TRANS,BLOCK_SWITCHING_OFFSET-LS_TRANS,1);
timeSignalSf = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
minSf = min(delayBufferSf,timeSignalSf);
minSf = min(minSf,13);
outData0 = realOut + FRAME_LEN_LONG/2;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
for(i=0;i<LS_TRANS;i++){
*outData0++ = -(*dctIn1--) << (15 - 2 + minSf);
}
/* add windows and pre add for mdct to last buffer*/
dctIn0 = mdctDelayBuffer + LS_TRANS;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
outData0 = realOut + FRAME_LEN_LONG/2 + LS_TRANS;
winPtr = (int *)ShortWindowSine;
for(i=0;i<FRAME_LEN_SHORT/2;i++){
timeSignalSample = (*dctIn0++) << minSf;
ws1 = timeSignalSample * (*winPtr >> 16);
timeSignalSample= (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr & 0xffff);
winPtr++;
*outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
}
shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
/* add windows and pre add for mdct to new buffer*/
dctIn0 = mdctDelayBuffer;
dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
outData0 = realOut + FRAME_LEN_LONG/2 - 1;
winPtr = (int *)LongWindowKBD;
for(i=0;i<FRAME_LEN_LONG/2;i++){
timeSignalSample= (*dctIn0++) << minSf;
ws1 = timeSignalSample *(*winPtr & 0xffff);
timeSignalSample= (*dctIn1--) << minSf;
ws2 = timeSignalSample * (*winPtr >> 16);
*outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
winPtr++;
}
Mdct_Long(realOut);
minSf = 14 - minSf;
*mdctScale= minSf; /* update scale factor */
break;
case SHORT_WINDOW:
/*
we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no new timeSignal samples
and get the biggest scale factor for next calculate more precise
*/
minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+TRANSFORM_OFFSET_SHORT,9*FRAME_LEN_SHORT,1);
minSf = min(minSf,10);
for(w=0;w<TRANS_FAC;w++){
dctIn0 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT;
dctIn1 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT + FRAME_LEN_SHORT-1;
outData0 = realOut + FRAME_LEN_SHORT/2;
outData1 = realOut + FRAME_LEN_SHORT/2 - 1;
winPtr = (int *)ShortWindowSine;
for(i=0;i<FRAME_LEN_SHORT/2;i++){
timeSignalSample= *dctIn0 << minSf;
ws1 = timeSignalSample * (*winPtr >> 16);
timeSignalSample= *dctIn1 << minSf;
ws2 = timeSignalSample * (*winPtr & 0xffff);
*outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
timeSignalSample= *(dctIn0 + FRAME_LEN_SHORT) << minSf;
ws1 = timeSignalSample * (*winPtr & 0xffff);
timeSignalSample= *(dctIn1 + FRAME_LEN_SHORT) << minSf;
ws2 = timeSignalSample * (*winPtr >> 16);
*outData1-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
winPtr++;
dctIn0++;
dctIn1--;
}
Mdct_Short(realOut);
realOut += FRAME_LEN_SHORT;
}
minSf = 11 - minSf;
*mdctScale = minSf; /* update scale factor */
shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
break;
}
}

View File

@ -29,8 +29,9 @@ namespace android {
static const int32_t kNumSamplesPerFrame = 160; static const int32_t kNumSamplesPerFrame = 160;
static const int32_t kSampleRate = 8000; static const int32_t kSampleRate = 8000;
AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source) AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
: mSource(source), : mSource(source),
mMeta(meta),
mStarted(false), mStarted(false),
mBufferGroup(NULL), mBufferGroup(NULL),
mEncState(NULL), mEncState(NULL),
@ -119,28 +120,16 @@ status_t AMRNBEncoder::stop() {
sp<MetaData> AMRNBEncoder::getFormat() { sp<MetaData> AMRNBEncoder::getFormat() {
sp<MetaData> srcFormat = mSource->getFormat(); sp<MetaData> srcFormat = mSource->getFormat();
int32_t numChannels; mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
int32_t sampleRate;
CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
CHECK_EQ(numChannels, 1);
CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
CHECK_EQ(sampleRate, kSampleRate);
sp<MetaData> meta = new MetaData;
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
meta->setInt32(kKeyChannelCount, numChannels);
meta->setInt32(kKeySampleRate, sampleRate);
int64_t durationUs; int64_t durationUs;
if (srcFormat->findInt64(kKeyDuration, &durationUs)) { if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
meta->setInt64(kKeyDuration, durationUs); mMeta->setInt64(kKeyDuration, durationUs);
} }
meta->setCString(kKeyDecoderComponent, "AMRNBEncoder"); mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
return meta; return mMeta;
} }
status_t AMRNBEncoder::read( status_t AMRNBEncoder::read(

View File

@ -0,0 +1,282 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "AMRWBEncoder"
#include <utils/Log.h>
#include "AMRWBEncoder.h"
#include "voAMRWB.h"
#include "cmnMemory.h"
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
namespace android {
static const int32_t kNumSamplesPerFrame = 320;
static const int32_t kBitsPerSample = 16;
static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame;
static const int32_t kSampleRate = 16000;
static const int32_t kNumChannels = 1;
AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
: mSource(source),
mMeta(meta),
mStarted(false),
mBufferGroup(NULL),
mInputBuffer(NULL),
mEncoderHandle(NULL),
mApiHandle(NULL),
mMemOperator(NULL),
mAnchorTimeUs(0),
mNumFramesOutput(0),
mNumInputSamples(0) {
}
static VOAMRWBMODE pickModeFromBitRate(int32_t bps) {
CHECK(bps >= 0);
if (bps <= 6600) {
return VOAMRWB_MD66;
} else if (bps <= 8850) {
return VOAMRWB_MD885;
} else if (bps <= 12650) {
return VOAMRWB_MD1265;
} else if (bps <= 14250) {
return VOAMRWB_MD1425;
} else if (bps <= 15850) {
return VOAMRWB_MD1585;
} else if (bps <= 18250) {
return VOAMRWB_MD1825;
} else if (bps <= 19850) {
return VOAMRWB_MD1985;
} else if (bps <= 23050) {
return VOAMRWB_MD2305;
}
return VOAMRWB_MD2385;
}
status_t AMRWBEncoder::initCheck() {
CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
mApiHandle = new VO_AUDIO_CODECAPI;
CHECK(mApiHandle);
if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
LOGE("Failed to get api handle");
return UNKNOWN_ERROR;
}
mMemOperator = new VO_MEM_OPERATOR;
CHECK(mMemOperator != NULL);
mMemOperator->Alloc = cmnMemAlloc;
mMemOperator->Copy = cmnMemCopy;
mMemOperator->Free = cmnMemFree;
mMemOperator->Set = cmnMemSet;
mMemOperator->Check = cmnMemCheck;
VO_CODEC_INIT_USERDATA userData;
memset(&userData, 0, sizeof(userData));
userData.memflag = VO_IMF_USERMEMOPERATOR;
userData.memData = (VO_PTR) mMemOperator;
if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
LOGE("Failed to init AMRWB encoder");
return UNKNOWN_ERROR;
}
// Configure AMRWB encoder$
VOAMRWBMODE mode = pickModeFromBitRate(mBitRate);
if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) {
LOGE("Failed to set AMRWB encoder mode to %d", mode);
return UNKNOWN_ERROR;
}
VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
LOGE("Failed to set AMRWB encoder frame type to %d", type);
return UNKNOWN_ERROR;
}
return OK;
}
AMRWBEncoder::~AMRWBEncoder() {
if (mStarted) {
stop();
}
}
status_t AMRWBEncoder::start(MetaData *params) {
CHECK(!mStarted);
mBufferGroup = new MediaBufferGroup;
// The largest buffer size is header + 477 bits
mBufferGroup->add_buffer(new MediaBuffer(1024));
CHECK_EQ(OK, initCheck());
mNumFramesOutput = 0;
mSource->start();
mStarted = true;
return OK;
}
status_t AMRWBEncoder::stop() {
CHECK(mStarted);
if (mInputBuffer) {
mInputBuffer->release();
mInputBuffer = NULL;
}
delete mBufferGroup;
mBufferGroup = NULL;
CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
mEncoderHandle = NULL;
delete mApiHandle;
mApiHandle = NULL;
delete mMemOperator;
mMemOperator;
mStarted = false;
mSource->stop();
return OK;
}
sp<MetaData> AMRWBEncoder::getFormat() {
sp<MetaData> srcFormat = mSource->getFormat();
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
int64_t durationUs;
if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
mMeta->setInt64(kKeyDuration, durationUs);
}
mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder");
return mMeta;
}
status_t AMRWBEncoder::read(
MediaBuffer **out, const ReadOptions *options) {
status_t err;
*out = NULL;
int64_t seekTimeUs;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs));
while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) {
err = mSource->read(&mInputBuffer, options);
if (err != OK) {
if (mNumInputSamples == 0) {
return ERROR_END_OF_STREAM;
}
memset(&mInputFrame[mNumInputSamples],
0,
sizeof(int16_t)
* (kNumSamplesPerFrame - mNumInputSamples));
mNumInputSamples = 0;
break;
}
size_t align = mInputBuffer->range_length() % sizeof(int16_t);
CHECK_EQ(align, 0);
int64_t timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs;
}
}
size_t copy =
(kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
if (copy > mInputBuffer->range_length()) {
copy = mInputBuffer->range_length();
}
memcpy(&mInputFrame[mNumInputSamples],
(const uint8_t *)mInputBuffer->data()
+ mInputBuffer->range_offset(),
copy);
mInputBuffer->set_range(
mInputBuffer->range_offset() + copy,
mInputBuffer->range_length() - copy);
if (mInputBuffer->range_length() == 0) {
mInputBuffer->release();
mInputBuffer = NULL;
}
mNumInputSamples += copy / sizeof(int16_t);
if (mNumInputSamples >= kNumSamplesPerFrame) {
mNumInputSamples %= kNumSamplesPerFrame;
break; // Get a whole input frame 640 bytes
}
}
VO_CODECBUFFER inputData;
memset(&inputData, 0, sizeof(inputData));
inputData.Buffer = (unsigned char*) mInputFrame;
inputData.Length = kInputBufferSize;
CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
MediaBuffer *buffer;
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
uint8_t *outPtr = (uint8_t *)buffer->data();
VO_CODECBUFFER outputData;
memset(&outputData, 0, sizeof(outputData));
VO_AUDIO_OUTPUTINFO outputInfo;
memset(&outputInfo, 0, sizeof(outputInfo));
VO_U32 ret = VO_ERR_NONE;
outputData.Buffer = outPtr;
outputData.Length = buffer->size();
ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
buffer->set_range(0, outputData.Length);
++mNumFramesOutput;
// XXX: fix timestamp calculation
int64_t timestampUs = mNumFramesOutput * 20000LL;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
*out = buffer;
return OK;
}
} // namespace android

View File

@ -0,0 +1,120 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES := \
AMRWBEncoder.cpp \
src/autocorr.c \
src/az_isp.c \
src/bits.c \
src/c2t64fx.c \
src/c4t64fx.c \
src/convolve.c \
src/cor_h_x.c \
src/decim54.c \
src/deemph.c \
src/dtx.c \
src/g_pitch.c \
src/gpclip.c \
src/homing.c \
src/hp400.c \
src/hp50.c \
src/hp6k.c \
src/hp_wsp.c \
src/int_lpc.c \
src/isp_az.c \
src/isp_isf.c \
src/lag_wind.c \
src/levinson.c \
src/log2.c \
src/lp_dec2.c \
src/math_op.c \
src/oper_32b.c \
src/p_med_ol.c \
src/pit_shrp.c \
src/pitch_f4.c \
src/pred_lt4.c \
src/preemph.c \
src/q_gain2.c \
src/q_pulse.c \
src/qisf_ns.c \
src/qpisf_2s.c \
src/random.c \
src/residu.c \
src/scale.c \
src/stream.c \
src/syn_filt.c \
src/updt_tar.c \
src/util.c \
src/voAMRWBEnc.c \
src/voicefac.c \
src/wb_vad.c \
src/weight_a.c \
src/mem_align.c
ifeq ($(VOTT), v5)
LOCAL_SRC_FILES += \
src/asm/ARMV5E/convolve_opt.s \
src/asm/ARMV5E/cor_h_vec_opt.s \
src/asm/ARMV5E/Deemph_32_opt.s \
src/asm/ARMV5E/Dot_p_opt.s \
src/asm/ARMV5E/Filt_6k_7k_opt.s \
src/asm/ARMV5E/Norm_Corr_opt.s \
src/asm/ARMV5E/pred_lt4_1_opt.s \
src/asm/ARMV5E/residu_asm_opt.s \
src/asm/ARMV5E/scale_sig_opt.s \
src/asm/ARMV5E/Syn_filt_32_opt.s \
src/asm/ARMV5E/syn_filt_opt.s
endif
ifeq ($(VOTT), v7)
LOCAL_SRC_FILES += \
src/asm/ARMV7/convolve_neon.s \
src/asm/ARMV7/cor_h_vec_neon.s \
src/asm/ARMV7/Deemph_32_neon.s \
src/asm/ARMV7/Dot_p_neon.s \
src/asm/ARMV7/Filt_6k_7k_neon.s \
src/asm/ARMV7/Norm_Corr_neon.s \
src/asm/ARMV7/pred_lt4_1_neon.s \
src/asm/ARMV7/residu_asm_neon.s \
src/asm/ARMV7/scale_sig_neon.s \
src/asm/ARMV7/Syn_filt_32_neon.s \
src/asm/ARMV7/syn_filt_neon.s
endif
LOCAL_MODULE := libstagefright_amrwbenc
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES := \
frameworks/base/media/libstagefright/include \
frameworks/base/media/libstagefright/codecs/common/include \
frameworks/base/include \
$(LOCAL_PATH)/src \
$(LOCAL_PATH)/inc
LOCAL_CFLAGS := $(VO_CFLAGS)
ifeq ($(VOTT), v5)
LOCAL_CFLAGS += -DARM -DASM_OPT
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
endif
ifeq ($(VOTT), v7)
LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
endif
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,364 @@
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifdef LINUX
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "voAMRWB.h"
#include "cmnMemory.h"
#define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n"
#define INPUT_SIZE 640
#define OUTPUT_SIZE 1024
unsigned char InputBuf[INPUT_SIZE];
unsigned char OutputBuf[OUTPUT_SIZE];
void usage (void) {
printf ("AMR_WB Encoder HELP Displays this text\n");
printf ("\n");
printf ("Usage:\n");
printf ("AMRWBEnc [options] Input_file output_file \n");
printf ("\n");
printf ("Options +M* +F* +DTX \n");
printf ("Support \n");
printf ("Options +M* for seting compression bitrate mode, default is 23.85kbps\n");
printf (" +M0 = 6.6kbps \n");
printf (" +M1 = 8.85kbps \n");
printf (" +M2 = 12.65kbps \n");
printf (" +M3 = 14.25kbps \n");
printf (" +M4 = 15.58kbps \n");
printf (" +M5 = 18.25kbps \n");
printf (" +M6 = 19.85kbps \n");
printf (" +M7 = 23.05kbps \n");
printf (" +M8 = 23.85kbps \n");
printf ("\n");
printf ("Options +F* for setting output frame Type, default is RFC3267 \n");
printf ("+F0 for AMR_WB Defualt bit extern short data frame type \n");
printf ("+F1 for AMR_WB_ITU bit extern short data frame type \n");
printf ("+F2 for RFC3267\n ");
printf ("\n");
printf ("Options +DTX enable DTX mode, default is disable.\n");
printf ("File names, input raw PCM data, and output is AMR_WB bit-stream file.\n");
printf ("\n");
}
int GetNextBuf(FILE* inFile,unsigned char* dst,int size)
{
int size2 = (int)fread(dst, sizeof(signed char), size,inFile);
return size2;
}
typedef int (VO_API * VOGETAUDIOENCAPI) (VO_AUDIO_CODECAPI * pEncHandle);
int encode(
int mode,
short allow_dtx,
VOAMRWBFRAMETYPE frameType,
const char* srcfile,
const char* dstfile
)
{
int ret = 0;
int returnCode;
FILE *fsrc = NULL;
FILE *fdst = NULL;
int framenum = 0;
int eofFile = 0;
int size1 = 0;
int Relens;
VO_AUDIO_CODECAPI AudioAPI;
VO_MEM_OPERATOR moper;
VO_CODEC_INIT_USERDATA useData;
VO_HANDLE hCodec;
VO_CODECBUFFER inData;
VO_CODECBUFFER outData;
VO_AUDIO_OUTPUTINFO outFormat;
unsigned char *inBuf = InputBuf;
unsigned char *outBuf = OutputBuf;
#ifdef LINUX
void *handle = NULL;
void *pfunc;
VOGETAUDIOENCAPI pGetAPI;
#endif
clock_t start, finish;
double duration = 0.0;
if ((fsrc = fopen (srcfile, "rb")) == NULL)
{
ret = -1;
goto safe_exit;
}
if ((fdst = fopen (dstfile, "wb")) == NULL)
{
ret = -1;
goto safe_exit;
}
moper.Alloc = cmnMemAlloc;
moper.Copy = cmnMemCopy;
moper.Free = cmnMemFree;
moper.Set = cmnMemSet;
moper.Check = cmnMemCheck;
useData.memflag = VO_IMF_USERMEMOPERATOR;
useData.memData = (VO_PTR)(&moper);
#ifdef LINUX
handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW);
if(handle == 0)
{
printf("open dll error......");
return -1;
}
pfunc = dlsym(handle, "voGetAMRWBEncAPI");
if(pfunc == 0)
{
printf("open function error......");
return -1;
}
pGetAPI = (VOGETAUDIOENCAPI)pfunc;
returnCode = pGetAPI(&AudioAPI);
if(returnCode)
{
printf("get APIs error......");
return -1;
}
#else
ret = voGetAMRWBEncAPI(&AudioAPI);
if(ret)
{
ret = -1;
printf("get APIs error......");
goto safe_exit;
}
#endif
//####################################### Init Encoding Section #########################################
ret = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAMRWB, &useData);
if(ret)
{
ret = -1;
printf("APIs init error......");
goto safe_exit;
}
Relens = GetNextBuf(fsrc,InputBuf,INPUT_SIZE);
if(Relens!=INPUT_SIZE && !feof(fsrc))
{
ret = -1; //Invalid magic number
printf("get next buffer error......");
goto safe_exit;
}
//###################################### set encode Mode ##################################################
ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_FRAMETYPE, &frameType);
ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_MODE, &mode);
ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_DTX, &allow_dtx);
if(frameType == VOAMRWB_RFC3267)
{
/* write RFC3267 Header info to indicate single channel AMR file storage format */
size1 = (int)strlen(VOAMRWB_RFC3267_HEADER_INFO);
memcpy(outBuf, VOAMRWB_RFC3267_HEADER_INFO, size1);
outBuf += size1;
}
//####################################### Encoding Section #########################################
printf(" \n ---------------- Running -------------------------\n ");
do{
inData.Buffer = (unsigned char *)inBuf;
inData.Length = Relens;
outData.Buffer = outBuf;
start = clock();
/* decode one amr block */
returnCode = AudioAPI.SetInputData(hCodec,&inData);
do {
returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outFormat);
if(returnCode == 0)
{
framenum++;
printf(" Frames processed: %hd\r", framenum);
if(framenum == 1)
{
fwrite(OutputBuf, 1, outData.Length + size1, fdst);
fflush(fdst);
}
else
{
fwrite(outData.Buffer, 1, outData.Length, fdst);
fflush(fdst);
}
}
else if(returnCode == VO_ERR_LICENSE_ERROR)
{
printf("Encoder time reach upper limit......");
goto safe_exit;
}
} while(returnCode != VO_ERR_INPUT_BUFFER_SMALL);
finish = clock();
duration += finish - start;
if (!eofFile) {
Relens = GetNextBuf(fsrc, InputBuf, INPUT_SIZE);
inBuf = InputBuf;
if (feof(fsrc) && Relens == 0)
eofFile = 1;
}
} while (!eofFile && returnCode);
//####################################### End Encoding Section #########################################
safe_exit:
returnCode = AudioAPI.Uninit(hCodec);
printf( "\n%2.5f seconds\n", (double)duration/CLOCKS_PER_SEC);
if (fsrc)
fclose(fsrc);
if (fdst)
fclose(fdst);
#ifdef LINUX
dlclose(handle);
#endif
return ret;
}
int main(int argc, char **argv) // for gcc compiler;
{
int mode, r;
int arg, filename=0;
char *inFileName = NULL;
char *outFileName = NULL;
short allow_dtx;
VOAMRWBFRAMETYPE frameType;
printf("\n");
printf("************************Adaptive Multi-Rate Wide Band Encoder (AMR-WB)*******************************\n");
printf("***********************************DEFINITIONS:*******************************************************\n");
printf("AMR-WB encoder scheme is based on the principle of Algebraic Code Excited Linear Prediction algorithm\n");
printf("The AMR-WB encoder compression MONO liner PCM speech input data at 16kHz sampling rate\n");
printf("to one of nine data rate modes-6.60, 8.85, 12.65, 14.25, 15.85, 18.25, 19.25, 23.05 and 23.85kbps.\n");
printf("The encoder supports output format AMRWB ITU, AMRWB RFC3267.\n");
printf("\n");
/*Encoder Default setting */
mode = VOAMRWB_MD2385;
allow_dtx = 0;
frameType = VOAMRWB_RFC3267;
if(argc < 3){
usage();
return 0;
}else{
for (arg = 1; arg < argc; arg++) {
if (argv [arg] [0] == '+') {
if(argv[arg][1] == 'M')
{
switch(argv[arg][2])
{
case '0': mode = VOAMRWB_MD66;
break;
case '1': mode = VOAMRWB_MD885;
break;
case '2': mode = VOAMRWB_MD1265;
break;
case '3': mode = VOAMRWB_MD1425;
break;
case '4': mode = VOAMRWB_MD1585;
break;
case '5': mode = VOAMRWB_MD1825;
break;
case '6': mode = VOAMRWB_MD1985;
break;
case '7': mode = VOAMRWB_MD2305;
break;
case '8': mode = VOAMRWB_MD2385;
break;
default:
usage();
printf ("Invalid parameter '%s'.\n", argv [arg]);
break;
}
}else if(argv[arg][1] == 'F')
{
switch(argv[arg][2])
{
case '0': frameType = VOAMRWB_DEFAULT;
break;
case '1': frameType = VOAMRWB_ITU;
break;
case '2': frameType = VOAMRWB_RFC3267 ;
break;
default:
usage();
printf ("Invalid parameter '%s'.\n", argv [arg]);
break;
}
}else if(strcmp (argv[arg], "+DTX") == 0)
{
allow_dtx = 1;
}
} else {
switch (filename) {
case 0:
inFileName = argv[arg];
break;
case 1:
outFileName = argv[arg];
break;
default:
usage ();
fprintf (stderr, "Invalid parameter '%s'.\n", argv [arg]);
return 0;
}
filename++;
}
}
}
r = encode(mode, allow_dtx, frameType, inFileName, outFileName);
if(r)
{
fprintf(stderr, "error: %d\n", r);
}
return r;
}

View File

@ -0,0 +1,27 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := AMRWB_E_SAMPLE.c
LOCAL_SRC_FILES += \
../../../Common/cmnMemory.c
LOCAL_MODULE := TestvoAMRWBEnc
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/ \
$(LOCAL_PATH)/../../../Common \
$(LOCAL_PATH)/../../../Include \
LOCAL_CFLAGS := $(VO_CFLAGS)
include $(BUILD_EXECUTABLE)

View File

@ -0,0 +1,56 @@
#/*
# ** Copyright 2003-2010, VisualOn, Inc.
# **
# ** Licensed under the Apache License, Version 2.0 (the "License");
# ** you may not use this file except in compliance with the License.
# ** You may obtain a copy of the License at
# **
# ** http://www.apache.org/licenses/LICENSE-2.0
# **
# ** Unless required by applicable law or agreed to in writing, software
# ** distributed under the License is distributed on an "AS IS" BASIS,
# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# ** See the License for the specific language governing permissions and
# ** limitations under the License.
# */
# target6
# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
VOTT:= v6
# module type
# please specify the type of your module: lib or exe
VOMT:= exe
# module macros
# please append the additional macro definitions here for your module if necessary.
# e.g. -DVISUALON, macro VISUALON defined for your module
VOMM:= #ARMV5E
# please specify the name of your module
VOTARGET:= voAMRWBEnc_Test
# please modify here to be sure to see the g1.mk
include ../../../../Tools/eclair.mk
# dependent libraries.
VODEPLIBS:=-ldl
# module source
# please modify here to be sure to see the ms.mk which specifies all source info of your module
include ../ms.mk
# please specify where is the voRelease on your PC, relative path is suggested
VORELDIR:=../
# please modify here to be sure to see the doit.mk
include ../../../../Tools/doit.mk

View File

@ -0,0 +1,24 @@
#/*
# ** Copyright 2003-2010, VisualOn, Inc.
# **
# ** Licensed under the Apache License, Version 2.0 (the "License");
# ** you may not use this file except in compliance with the License.
# ** You may obtain a copy of the License at
# **
# ** http://www.apache.org/licenses/LICENSE-2.0
# **
# ** Unless required by applicable law or agreed to in writing, software
# ** distributed under the License is distributed on an "AS IS" BASIS,
# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# ** See the License for the specific language governing permissions and
# ** limitations under the License.
# */
# please list all objects needed by your target here
OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o
# please list all directories that all source files relative with your module(.h .c .cpp) locate
VOSRCDIR:=../ \
../../../../Common \
../../../../Include

View File

@ -0,0 +1,53 @@
#/*
# ** Copyright 2003-2010, VisualOn, Inc.
# **
# ** Licensed under the Apache License, Version 2.0 (the "License");
# ** you may not use this file except in compliance with the License.
# ** You may obtain a copy of the License at
# **
# ** http://www.apache.org/licenses/LICENSE-2.0
# **
# ** Unless required by applicable law or agreed to in writing, software
# ** distributed under the License is distributed on an "AS IS" BASIS,
# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# ** See the License for the specific language governing permissions and
# ** limitations under the License.
# */
# target type
# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
VOTT:= v5
# module type
# please specify the type of your module: lib or exe
VOMT:= lib
# module macros
# please append the additional macro definitions here for your module if necessary.
ifeq ($(VOTT), v5)
VOMM:=-DARM -DASM_OPT
endif
# please specify the name of your module
VOTARGET:= libvoAMRWBEncv5
# please modify here to be sure to see the g1.mk
include ../../../../../Tools/eclair.mk
# dependent libraries.
VODEPLIBS:=-ldl -lstdc++ -lcutils
# module source
# please modify here to be sure to see the ms.mk which specifies all source info of your module
include ../ms.mk
# please specify where is the voRelease on your PC, relative path is suggested
VORELDIR:=../../../../../../Release
# please modify here to be sure to see the doit.mk
include ../../../../../Tools/doit.mk

Some files were not shown because too many files have changed in this diff Show More