commit 0e9ca200fbd11d508a39ff3af3512f29ea1337a3 Author: Milan Nikolic Date: Tue Mar 6 04:50:55 2018 +0100 Initial commit diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..9bb5af5 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,22 @@ +version: "{build}" + +clone_depth: 1 + +clone_folder: c:\gopath\src\github.com\gen2brain\aac-go + +environment: + GOPATH: c:\gopath + MSYS_PATH: c:\msys64 + CGO_ENABLED: 1 + GOARCH: 386 + CC: i686-w64-mingw32-gcc + +install: + - echo %GOPATH% + - echo %MSYS_PATH% + - set PATH=%GOPATH%\bin;c:\go\bin;%MSYS_PATH%\usr\bin;%MSYS_PATH%\mingw32\bin;%PATH% + - go version + - go env + +build_script: + - bash -lc "cd /c/gopath/src/github.com/gen2brain/aac-go && go build" diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a0f05f9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.9.x + +script: + - go test -v ./ diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..28cd2c5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Milan Nikolic diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5ec4bf0 --- /dev/null +++ b/COPYING @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only to +those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or +contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such +litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a +copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating +that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must include a +readable copy of the attribution notices contained within such NOTICE file, +excluding those notices that do not pertain to any part of the Derivative +Works, in at least one of the following places: within a NOTICE text file +distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a +display generated by the Derivative Works, if and wherever such third-party +notices normally appear. The contents of the NOTICE file are for +informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that +such additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated in +this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to +the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, except +as required for reasonable and customary use in describing the origin of +the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any +warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or +FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for +determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or +inability to use the Work (including but not limited to damages for loss of +goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the +Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability +obligations and/or rights consistent with this License. However, in +accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if +You agree to indemnify, defend, and hold each Contributor harmless for any +liability incurred by, or claims asserted against, such Contributor by +reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a07230e --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +## aac-go +[![TravisCI Build Status](https://travis-ci.org/gen2brain/aac-go.svg?branch=master)](https://travis-ci.org/gen2brain/aac-go) +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/wfkqlac5ffwk5xgb?svg=true)](https://ci.appveyor.com/project/gen2brain/aac-go) +[![GoDoc](https://godoc.org/github.com/gen2brain/aac-go?status.svg)](https://godoc.org/github.com/gen2brain/aac-go) +[![Go Report Card](https://goreportcard.com/badge/github.com/gen2brain/aac-go?branch=master)](https://goreportcard.com/report/github.com/gen2brain/aac-go) + +`aac-go` provides AAC codec encoder based on [VisualOn AAC encoder library](https://github.com/mstorsjo/vo-aacenc) library. + +### Installation + + go get -u github.com/gen2brain/aac-go + +### Example + +```go +package main + +import ( + "bytes" + "io/ioutil" + "os" + + "github.com/gen2brain/aac-go" + "github.com/youpy/go-wav" +) + +func main() { + file, err := os.Open("test.wav") + if err != nil { + panic(err) + } + + wreader := wav.NewReader(file) + f, err := wreader.Format() + if err != nil { + panic(err) + } + + buf := bytes.NewBuffer(make([]byte, 0)) + + opts := &aac.Options{} + opts.SampleRate = int(f.SampleRate) + opts.NumChannels = int(f.NumChannels) + + enc, err := aac.NewEncoder(buf, opts) + if err != nil { + panic(err) + } + + err = enc.Encode(wreader) + if err != nil { + panic(err) + } + + err = enc.Close() + if err != nil { + panic(err) + } + + err = ioutil.WriteFile("test.aac", buf.Bytes(), 0644) + if err != nil { + panic(err) + } +} +``` + +## More + +For H.264 encoder see [x264-go](https://github.com/gen2brain/x264-go). diff --git a/aacenc/aacenc.go b/aacenc/aacenc.go new file mode 100644 index 0000000..e37e438 --- /dev/null +++ b/aacenc/aacenc.go @@ -0,0 +1,316 @@ +// Package aacenc implements cgo bindings for [VisualOn AAC encoder library](https://github.com/mstorsjo/vo-aacenc) library. +package aacenc + +//#include "voAAC.h" +import "C" + +import ( + "errors" + "unsafe" +) + +// Constants. +const ( + // AAC Param ID + VoPidAacMdoule = 0x42211000 + VoPidAacEncparam = VoPidAacMdoule | 0x0040 + + // AAC decoder error ID + VoErrAacMdoule = 0x82210000 + VoErrAacUnsfileformat = (VoErrAacMdoule | 0xF001) + VoErrAacUnsprofile = (VoErrAacMdoule | 0xF002) + + // The base param ID for AUDIO codec + VoPidAudioBase = 0x42000000 + // The format data of audio in track + VoPidAudioFormat = (VoPidAudioBase | 0x0001) + // The sample rate of audio + VoPidAudioSampleRate = (VoPidAudioBase | 0x0002) + // The channel of audio + VoPidAudioChannels = (VoPidAudioBase | 0x0003) + // The bit rate of audio + VoPidAudioBitrate = (VoPidAudioBase | 0x0004) + // The channel mode of audio + VoPidAudioChannelmode = (VoPidAudioBase | 0x0005) + + // The base of common param ID + VoPidCommonBase = 0x40000000 + // Query the memory needed; Reserved + VoPidCommonQueryMem = (VoPidCommonBase | 0) + // Set or get the input buffer type + VoPidCommonInputType = (VoPidCommonBase | 0) + // Query it has resource to be used + VoPidCommonHasResource = (VoPidCommonBase | 0) + // Decoder track header data + VoPidCommonHeadData = (VoPidCommonBase | 0) + // VoPidCommonFlush as defined in include/voIndex.h:182 + VoPidCommonFlush = (VoPidCommonBase | 0) +) + +// Error codes. +const ( + VoErrNone = 0x00000000 + VoErrFinish = 0x00000001 + VoErrFailed = 0x80000001 + VoErrOutofMemory = 0x80000002 + VoErrNotImplement = 0x80000003 + VoErrInvalidArg = 0x80000004 + VoErrInputBufferSmall = 0x80000005 + VoErrOutputBufferSmall = 0x80000006 + VoErrWrongStatus = 0x80000007 + VoErrWrongParamId = 0x80000008 + VoErrLicenseError = 0x80000009 + + VoErrAudioBase = 0x82000000 + VoErrAudioUnsChannel = VoErrAudioBase | 0x0001 + VoErrAudioUnsSampleRate = VoErrAudioBase | 0x0002 + VoErrAudioUnsFeature = VoErrAudioBase | 0x0003 +) + +// Enumeration used to define the possible audio coding formats. +const ( + // Placeholder value when coding is N/A + VoAudioCodingUnused int32 = iota + // Any variant of PCM coding + VoAudioCodingPcm + // Any variant of ADPCM encoded data + VoAudioCodingAdpcm + // Any variant of AMR encoded data + VoAudioCodingAmrnb + // Any variant of AMR encoded data + VoAudioCodingAmrwb + // Any variant of AMR encoded data + VoAudioCodingAmrwbp + // Any variant of QCELP 13kbps encoded data + VoAudioCodingQcelp13 + // Any variant of EVRC encoded data + VoAudioCodingEvrc + // Any variant of AAC encoded data, 0xA106 - ISO/MPEG-4 AAC, 0xFF - AAC + VoAudioCodingAac + // Any variant of AC3 encoded data + VoAudioCodingAc3 + // Any variant of FLAC encoded data + VoAudioCodingFlac + // Any variant of MP1 encoded data + VoAudioCodingMp1 + // Any variant of MP3 encoded data + VoAudioCodingMp3 + // Any variant of OGG encoded data + VoAudioCodingOgg + // Any variant of WMA encoded data + VoAudioCodingWma + // Any variant of RA encoded data + VoAudioCodingRa + // Any variant of MIDI encoded data + VoAudioCodingMidi + // Any variant of dra encoded data + VoAudioCodingDra + // Any variant of dra encoded data + VoAudioCodingG729 +) + +// The frame type that the decoder supports. +const ( + // Contains only raw aac data in a frame + VoAacRawdata int32 = iota + // Contains ADTS header + raw AAC data in a frame + VoAacAdts +) + +// The channel type value. +const ( + // Center channel + VoChannelCenter int32 = 1 + // Front left channel + VoChannelFrontLeft = 1 << 1 + // Front right channel + VoChannelFrontRight = 1 << 2 + // Side left channel + VoChannelSideLeft = 1 << 3 + // Side right channel + VoChannelSideRight = 1 << 4 + // Back left channel + VoChannelBackLeft = 1 << 5 + // Back right channel + VoChannelBackRight = 1 << 6 + // Back center channel + VoChannelBackCenter = 1 << 7 + // Low-frequency effects bass channel + VoChannelLfeBass = 1 << 8 + // Include all channels (default) + VoChannelAll = 0xffff +) + +// Input stream format, Frame or Stream. +const ( + // Input contains completely frame(s) data + VoInputFrame int32 = iota + 1 + // Input is stream data. + VoInputStream +) + +// VoAudioFormat - general audio format info. +type VoAudioFormat struct { + // Sample rate + SampleRate int + // Channel count + Channels int + // Bits per sample + SampleBits int +} + +// cptr return C pointer. +func (v *VoAudioFormat) cptr() *C.VO_AUDIO_FORMAT { + return (*C.VO_AUDIO_FORMAT)(unsafe.Pointer(v)) +} + +// VoAudioOutputinfo - general audio output info. +type VoAudioOutputinfo struct { + // Sample rate + Format VoAudioFormat + // Channel count + InputUsed uint + // Reserved + Reserve uint +} + +// cptr return C pointer. +func (v *VoAudioOutputinfo) cptr() *C.VO_AUDIO_OUTPUTINFO { + return (*C.VO_AUDIO_OUTPUTINFO)(unsafe.Pointer(v)) +} + +// VoCodecBuffer - general data buffer, used as input or output. +type VoCodecBuffer struct { + // Buffer pointer + Buffer unsafe.Pointer + // Buffer size in byte + Length uint64 + // The time of the buffer + Time int64 +} + +// cptr return C pointer. +func (v *VoCodecBuffer) cptr() *C.VO_CODECBUFFER { + return (*C.VO_CODECBUFFER)(unsafe.Pointer(v)) +} + +// AacencParam - the structure for AAC encoder input parameter. +type AacencParam struct { + // Audio file sample rate + SampleRate int32 + // Encoder bit rate in bits/sec + BitRate int32 + // Number of channels on input (1,2) + NChannels int16 + // Whether write adts header + AdtsUsed int16 +} + +var handle C.VO_HANDLE + +// Errors. +var ( + ErrFinish = errors.New("aac: error finish") + ErrFailed = errors.New("aac: process data failed") + ErrOutOfMemory = errors.New("aac: out of memory") + ErrNotImplement = errors.New("aac: feature not implemented") + ErrInvalidArg = errors.New("aac: invalid argument") + ErrInputBufferSmall = errors.New("aac: input buffer data too small") + ErrOutputBufferSmall = errors.New("aac: output buffer size too small") + ErrWrongStatus = errors.New("aac: wrong encoder run-time status") + ErrWrongParamId = errors.New("aac: wrong parameter id") + ErrLicenseError = errors.New("aac: license error") + + ErrAudioBase = errors.New("aac: error audio base") + ErrAudioUnsChannel = errors.New("aac: unsupported number of channel") + ErrAudioUnsSampleRate = errors.New("aac: unsupported sample rate") + ErrAudioUnsFeature = errors.New("aac: unsupported feature") +) + +// ErrorFromResult returns error for result code +func ErrorFromResult(r uint) error { + switch r { + case VoErrNone: + return nil + case VoErrFinish: + return ErrFinish + case VoErrFailed: + return ErrFailed + case VoErrOutofMemory: + return ErrOutOfMemory + case VoErrNotImplement: + return ErrNotImplement + case VoErrInvalidArg: + return ErrInvalidArg + case VoErrInputBufferSmall: + return ErrInputBufferSmall + case VoErrOutputBufferSmall: + return ErrOutputBufferSmall + case VoErrWrongStatus: + return ErrWrongStatus + case VoErrWrongParamId: + return ErrWrongParamId + case VoErrLicenseError: + return ErrLicenseError + case VoErrAudioBase: + return ErrAudioBase + case VoErrAudioUnsChannel: + return ErrAudioUnsChannel + case VoErrAudioUnsSampleRate: + return ErrAudioUnsSampleRate + case VoErrAudioUnsFeature: + return ErrAudioUnsFeature + default: + return nil + } +} + +// Init - init the audio codec module and return codec handle. +func Init(vtype int32) uint { + cvtype := (C.VO_AUDIO_CODINGTYPE)(vtype) + ret := C.voAACEncInit(&handle, cvtype, nil) + v := (uint)(ret) + return v +} + +// SetInputData - set input audio data. +func SetInputData(pinput *VoCodecBuffer) uint { + cpinput := pinput.cptr() + ret := C.voAACEncSetInputData(handle, cpinput) + v := (uint)(ret) + return v +} + +// GetOutputData - get the outut audio data. +func GetOutputData(poutbuffer *VoCodecBuffer, poutinfo *VoAudioOutputinfo) uint { + cpoutbuffer := poutbuffer.cptr() + cpoutinfo := poutinfo.cptr() + ret := C.voAACEncGetOutputData(handle, cpoutbuffer, cpoutinfo) + v := (uint)(ret) + return v +} + +// SetParam - set the parameter for the specified param ID. +func SetParam(uparamid int, pdata unsafe.Pointer) uint { + cuparamid := (C.VO_S32)(uparamid) + cpdata := (C.VO_PTR)(pdata) + ret := C.voAACEncSetParam(handle, cuparamid, cpdata) + v := (uint)(ret) + return v +} + +// GetParam - get the parameter for the specified param ID. +func GetParam(uparamid int, pdata unsafe.Pointer) uint { + cuparamid := (C.VO_S32)(uparamid) + cpdata := (C.VO_PTR)(pdata) + ret := C.voAACEncGetParam(handle, cuparamid, cpdata) + v := (uint)(ret) + return v +} + +// Uninit - uninit the Codec. +func Uninit() uint { + ret := C.voAACEncUninit(handle) + v := (uint)(ret) + return v +} diff --git a/aacenc/aacenc_cgo.go b/aacenc/aacenc_cgo.go new file mode 100644 index 0000000..816e074 --- /dev/null +++ b/aacenc/aacenc_cgo.go @@ -0,0 +1,36 @@ +package aacenc + +/* +#include "external/aacenc/src/cmnMemory.c" +#include "external/aacenc/src/basicop2.c" +#include "external/aacenc/src/oper_32b.c" +#include "external/aacenc/src/aac_rom.c" +#include "external/aacenc/src/aacenc.c" +#include "external/aacenc/src/aacenc_core.c" +#include "external/aacenc/src/adj_thr.c" +#include "external/aacenc/src/band_nrg.c" +#include "external/aacenc/src/bit_cnt.c" +#include "external/aacenc/src/bitbuffer.c" +#include "external/aacenc/src/bitenc.c" +#include "external/aacenc/src/block_switch.c" +#include "external/aacenc/src/channel_map.c" +#include "external/aacenc/src/dyn_bits.c" +#include "external/aacenc/src/grp_data.c" +#include "external/aacenc/src/interface.c" +#include "external/aacenc/src/line_pe.c" +#include "external/aacenc/src/memalign.c" +#include "external/aacenc/src/ms_stereo.c" +#include "external/aacenc/src/pre_echo_control.c" +#include "external/aacenc/src/psy_configuration.c" +#include "external/aacenc/src/psy_main.c" +#include "external/aacenc/src/qc_main.c" +#include "external/aacenc/src/quantize.c" +#include "external/aacenc/src/sf_estim.c" +#include "external/aacenc/src/spreading.c" +#include "external/aacenc/src/stat_bits.c" +#include "external/aacenc/src/tns.c" +#include "external/aacenc/src/transform.c" + +#cgo CFLAGS: -std=gnu99 -Iexternal/aacenc/include -DUSE_DEFAULT_MEM +*/ +import "C" diff --git a/aacenc/external/aacenc/COPYING b/aacenc/external/aacenc/COPYING new file mode 100644 index 0000000..5ec4bf0 --- /dev/null +++ b/aacenc/external/aacenc/COPYING @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only to +those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or +contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such +litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a +copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating +that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must include a +readable copy of the attribution notices contained within such NOTICE file, +excluding those notices that do not pertain to any part of the Derivative +Works, in at least one of the following places: within a NOTICE text file +distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a +display generated by the Derivative Works, if and wherever such third-party +notices normally appear. The contents of the NOTICE file are for +informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that +such additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated in +this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to +the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, except +as required for reasonable and customary use in describing the origin of +the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any +warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or +FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for +determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or +inability to use the Work (including but not limited to damages for loss of +goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the +Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability +obligations and/or rights consistent with this License. However, in +accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if +You agree to indemnify, defend, and hold each Contributor harmless for any +liability incurred by, or claims asserted against, such Contributor by +reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/aacenc/external/aacenc/README b/aacenc/external/aacenc/README new file mode 100644 index 0000000..e474d4c --- /dev/null +++ b/aacenc/external/aacenc/README @@ -0,0 +1,7 @@ +VisualOn AAC encoder library + +This library contains an encoder implementation of the Advanced Audio +Coding (AAC) audio codec. The library is based on a codec implementation +by VisualOn as part of the Stagefright framework from the Google +Android project. + diff --git a/aacenc/external/aacenc/include/voAAC.h b/aacenc/external/aacenc/include/voAAC.h new file mode 100644 index 0000000..7a639ce --- /dev/null +++ b/aacenc/external/aacenc/include/voAAC.h @@ -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: voAAC.h + + Content: AAC codec APIs & data types + +*******************************************************************************/ + +#ifndef __voAAC_H__ +#define __voAAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voAudio.h" + +/*! + * the frame type that the decoder supports + */ +typedef enum { + VOAAC_RAWDATA = 0, /*!InputUsed is total used input data size in byte. + * \retval VO_ERR_NONE Succeeded. + * VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought. Continue to input + * data before next call. + */ + VO_U32 (VO_API * GetOutputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pOutBuffer, VO_AUDIO_OUTPUTINFO * pOutInfo); + + /** + * Set the parameter for the specified param ID. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \param uParamID [IN] The param ID. + * \param pData [IN] The param value. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * SetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData); + + /** + * Get the parameter for the specified param ID. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \param uParamID [IN] The param ID. + * \param pData [IN] The param value. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * GetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData); + + /** + * Uninit the Codec. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * Uninit) (VO_HANDLE hCodec); +} VO_AUDIO_CODECAPI; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voAudio_H__ diff --git a/aacenc/external/aacenc/include/voIndex.h b/aacenc/external/aacenc/include/voIndex.h new file mode 100644 index 0000000..320a2f8 --- /dev/null +++ b/aacenc/external/aacenc/include/voIndex.h @@ -0,0 +1,193 @@ +/* + ** 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: voIndex.h + + Content: module and ID definition + +*******************************************************************************/ + +#ifndef __voIndex_H__ +#define __voIndex_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voType.h" + +/* Define the module ID */ +#define _MAKE_SOURCE_ID(id, name) \ +VO_INDEX_SRC_##name = _VO_INDEX_SOURCE | id, + +#define _MAKE_CODEC_ID(id, name) \ +VO_INDEX_DEC_##name = _VO_INDEX_DEC | id, \ +VO_INDEX_ENC_##name = _VO_INDEX_ENC | id, + +#define _MAKE_EFFECT_ID(id, name) \ +VO_INDEX_EFT_##name = _VO_INDEX_EFFECT | id, + +#define _MAKE_SINK_ID(id, name) \ +VO_INDEX_SNK_##name = _VO_INDEX_SINK | id, + +#define _MAKE_FILTER_ID(id, name) \ +VO_INDEX_FLT_##name = _VO_INDEX_FILTER | id, + +#define _MAKE_OMX_ID(id, name) \ +VO_INDEX_OMX_##name = _VO_INDEX_OMX | id, + +#define _MAKE_MFW_ID(id, name) \ +VO_INDEX_MFW_##name = _VO_INDEX_MFW | id, + +enum +{ + _VO_INDEX_SOURCE = 0x01000000, + _VO_INDEX_DEC = 0x02000000, + _VO_INDEX_ENC = 0x03000000, + _VO_INDEX_EFFECT = 0x04000000, + _VO_INDEX_SINK = 0x05000000, + _VO_INDEX_FILTER = 0x06000000, + _VO_INDEX_OMX = 0x07000000, + _VO_INDEX_MFW = 0x08000000, + + // define file parser modules + _MAKE_SOURCE_ID (0x010000, MP4) + _MAKE_SOURCE_ID (0x020000, AVI) + _MAKE_SOURCE_ID (0x030000, ASF) + _MAKE_SOURCE_ID (0x040000, REAL) + _MAKE_SOURCE_ID (0x050000, AUDIO) + _MAKE_SOURCE_ID (0x060000, FLASH) + _MAKE_SOURCE_ID (0x070000, OGG) + _MAKE_SOURCE_ID (0x080000, MKV) + + // define network source modules + _MAKE_SOURCE_ID (0x110000, RTSP) + _MAKE_SOURCE_ID (0x120000, HTTP) + + // define CMMB source modules + _MAKE_SOURCE_ID (0x200000, CMMB) + _MAKE_SOURCE_ID (0x210000, CMMB_INNO) + _MAKE_SOURCE_ID (0x220000, CMMB_TELE) + _MAKE_SOURCE_ID (0x230000, CMMB_SIANO) + + // define DVBT source modules + _MAKE_SOURCE_ID (0x300000, DVBT) + _MAKE_SOURCE_ID (0x310000, DVBT_DIBCOM) + + // define other source modules + _MAKE_SOURCE_ID (0x400000, ID3) + + // define video codec modules + _MAKE_CODEC_ID (0x010000, H264) + _MAKE_CODEC_ID (0x020000, MPEG4) + _MAKE_CODEC_ID (0x030000, H263) + _MAKE_CODEC_ID (0x040000, S263) + _MAKE_CODEC_ID (0x050000, RV) + _MAKE_CODEC_ID (0x060000, WMV) + _MAKE_CODEC_ID (0x070000, DIVX3) + _MAKE_CODEC_ID (0x080000, MJPEG) + _MAKE_CODEC_ID (0x090000, MPEG2) + _MAKE_CODEC_ID (0x0A0000, VP6) + + // define audio codec modules + _MAKE_CODEC_ID (0x210000, AAC) + _MAKE_CODEC_ID (0x220000, MP3) + _MAKE_CODEC_ID (0x230000, WMA) + _MAKE_CODEC_ID (0x240000, RA) + _MAKE_CODEC_ID (0x250000, AMRNB) + _MAKE_CODEC_ID (0x260000, AMRWB) + _MAKE_CODEC_ID (0x270000, AMRWBP) + _MAKE_CODEC_ID (0x280000, QCELP) + _MAKE_CODEC_ID (0x290000, EVRC) + _MAKE_CODEC_ID (0x2A0000, ADPCM) + _MAKE_CODEC_ID (0x2B0000, MIDI) + _MAKE_CODEC_ID (0x2C0000, AC3) + _MAKE_CODEC_ID (0x2D0000, FLAC) + _MAKE_CODEC_ID (0x2E0000, DRA) + _MAKE_CODEC_ID (0x2F0000, OGG) + _MAKE_CODEC_ID (0x300000, G729) + + // define image codec modules + _MAKE_CODEC_ID (0x410000, JPEG) + _MAKE_CODEC_ID (0x420000, GIF) + _MAKE_CODEC_ID (0x430000, PNG) + _MAKE_CODEC_ID (0x440000, TIF) + + // define effect modules + _MAKE_EFFECT_ID (0x010000, EQ) + + // define sink modules + _MAKE_SINK_ID (0x010000, VIDEO) + _MAKE_SINK_ID (0x020000, AUDIO) + _MAKE_SINK_ID (0x030000, CCRRR) + _MAKE_SINK_ID (0x040000, CCRRV) + + _MAKE_SINK_ID (0x110000, MP4) + _MAKE_SINK_ID (0x120000, AVI) + _MAKE_SINK_ID (0x130000, AFW) + + // define media frame module ID + _MAKE_MFW_ID (0x010000, VOMMPLAY) + _MAKE_MFW_ID (0x020000, VOMMREC) + _MAKE_MFW_ID (0x030000, VOME) +}; + + +/* define the error ID */ +#define VO_ERR_NONE 0x00000000 +#define VO_ERR_FINISH 0x00000001 +#define VO_ERR_BASE 0X80000000 +#define VO_ERR_FAILED 0x80000001 +#define VO_ERR_OUTOF_MEMORY 0x80000002 +#define VO_ERR_NOT_IMPLEMENT 0x80000003 +#define VO_ERR_INVALID_ARG 0x80000004 +#define VO_ERR_INPUT_BUFFER_SMALL 0x80000005 +#define VO_ERR_OUTPUT_BUFFER_SMALL 0x80000006 +#define VO_ERR_WRONG_STATUS 0x80000007 +#define VO_ERR_WRONG_PARAM_ID 0x80000008 +#define VO_ERR_LICENSE_ERROR 0x80000009 + +/* xxx is the module ID +#define VO_ERR_FAILED 0x8xxx0001 +#define VO_ERR_OUTOF_MEMORY 0x8xxx0002 +#define VO_ERR_NOT_IMPLEMENT 0x8xxx0003 +#define VO_ERR_INVALID_ARG 0x8xxx0004 +#define VO_ERR_INPUT_BUFFER_SMALL 0x8xxx0005 +#define VO_ERR_OUTPUT_BUFFER_SMALL 0x8xxx0006 +#define VO_ERR_WRONG_STATUS 0x8xxx0007 +#define VO_ERR_WRONG_PARAM_ID 0x8xxx0008 +#define VO_ERR_LICENSE_ERROR 0x8xxx0009 +// Module own error ID +#define VO_ERR_Module 0x8xxx0X00 +*/ + +#define VO_PID_COMMON_BASE 0x40000000 /*!< The base of common param ID */ +#define VO_PID_COMMON_QUERYMEM (VO_PID_COMMON_BASE | 0X0001) /*!< Query the memory needed; Reserved. */ +#define VO_PID_COMMON_INPUTTYPE (VO_PID_COMMON_BASE | 0X0002) /*!< Set or get the input buffer type. VO_INPUT_TYPE */ +#define VO_PID_COMMON_HASRESOURCE (VO_PID_COMMON_BASE | 0X0003) /*!< Query it has resource to be used. VO_U32 *, 1 have, 0 No */ +#define VO_PID_COMMON_HEADDATA (VO_PID_COMMON_BASE | 0X0004) /*!< Decoder track header data. VO_CODECBUFFER * */ +#define VO_PID_COMMON_FLUSH (VO_PID_COMMON_BASE | 0X0005) /*!< Flush the codec buffer. VO_U32 *, 1 Flush, 0 No * */ + +/* +// Module Param ID +#define VO_ID_Mdoule 0x0xxx1000 +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voIndex_H__ diff --git a/aacenc/external/aacenc/include/voMem.h b/aacenc/external/aacenc/include/voMem.h new file mode 100644 index 0000000..8dfb634 --- /dev/null +++ b/aacenc/external/aacenc/include/voMem.h @@ -0,0 +1,65 @@ +/* + ** 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: voMem.h + + Content: memory functions & data structures + +*******************************************************************************/ + +#ifndef __voMem_H__ +#define __voMem_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voIndex.h" + +typedef struct +{ + VO_S32 Size; /*!< Buffer stride */ + VO_S32 Flag; + VO_PTR VBuffer; /*!< user data pointer */ + VO_PTR PBuffer; /*!< user data pointer */ +} +VO_MEM_INFO; + +typedef struct VO_MEM_OPERATOR +{ + VO_U32 (VO_API * Alloc) (VO_S32 uID, VO_MEM_INFO * pMemInfo); + VO_U32 (VO_API * Free) (VO_S32 uID, VO_PTR pBuff); + VO_U32 (VO_API * Set) (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize); + VO_U32 (VO_API * Copy) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + VO_U32 (VO_API * Check) (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize); + VO_S32 (VO_API * Compare) (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize); + VO_U32 (VO_API * Move) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); +} VO_MEM_OPERATOR; + +#define voMemAlloc(pBuff, pMemOP, ID, nSize) \ +{ \ + VO_MEM_INFO voMemInfo; \ + voMemInfo.Size=nSize; \ + pMemOP->Alloc(ID, &voMemInfo); \ + pBuff=(VO_PBYTE)voMemInfo.VBuffer; \ +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voMem_H__ diff --git a/aacenc/external/aacenc/include/voType.h b/aacenc/external/aacenc/include/voType.h new file mode 100644 index 0000000..da208d4 --- /dev/null +++ b/aacenc/external/aacenc/include/voType.h @@ -0,0 +1,197 @@ +/* + ** 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: voType.h + + Content: data type definition + +*******************************************************************************/ +#ifndef __voType_H__ +#define __voType_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 +# define VO_API __cdecl +# define VO_CBI __stdcall +#else +# define VO_API +# define VO_CBI +#endif //_WIN32 + +/** VO_IN is used to identify inputs to an VO function. This designation + will also be used in the case of a pointer that points to a parameter + that is used as an output. */ +#ifndef VO_IN +#define VO_IN +#endif + +/** VO_OUT is used to identify outputs from an VO function. This + designation will also be used in the case of a pointer that points + to a parameter that is used as an input. */ +#ifndef VO_OUT +#define VO_OUT +#endif + +/** VO_INOUT is used to identify parameters that may be either inputs or + outputs from an VO function at the same time. This designation will + also be used in the case of a pointer that points to a parameter that + is used both as an input and an output. */ +#ifndef VO_INOUT +#define VO_INOUT +#endif + +#define VO_MAX_ENUM_VALUE 0X7FFFFFFF + +/** VO_VOID */ +typedef void VO_VOID; + +/** VO_U8 is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char VO_U8; + +/** VO_BYTE is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char VO_BYTE; + +/** VO_S8 is an 8 bit signed quantity that is byte aligned */ +typedef signed char VO_S8; + +/** VO_CHAR is an 8 bit signed quantity that is byte aligned */ +typedef char VO_CHAR; + +/** VO_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */ +typedef unsigned short VO_U16; + +/** VO_S16 is a 16 bit signed quantity that is 16 bit word aligned */ +typedef signed short VO_S16; + +/** VO_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ +typedef unsigned long VO_U32; + +/** VO_S32 is a 32 bit signed quantity that is 32 bit word aligned */ +typedef signed long VO_S32; + +/* Users with compilers that cannot accept the "long long" designation should + define the VO_SKIP64BIT macro. It should be noted that this may cause + some components to fail to compile if the component was written to require + 64 bit integral types. However, these components would NOT compile anyway + since the compiler does not support the way the component was written. +*/ +#ifndef VO_SKIP64BIT +#ifdef _MSC_VER +/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned __int64 VO_U64; +/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed __int64 VO_S64; +#else // WIN32 +/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long VO_U64; +/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long VO_S64; +#endif // WIN32 +#endif // VO_SKIP64BIT + +/** The VO_BOOL type is intended to be used to represent a true or a false + value when passing parameters to and from the VO core and components. The + VO_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary. + */ +typedef enum VO_BOOL { + VO_FALSE = 0, + VO_TRUE = !VO_FALSE, + VO_BOOL_MAX = VO_MAX_ENUM_VALUE +} VO_BOOL; + +/** The VO_PTR type is intended to be used to pass pointers between the VO + applications and the VO Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* VO_PTR; + +/** The VO_HANDLE type is intended to be used to pass pointers between the VO + applications and the VO Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* VO_HANDLE; + +/** The VO_STRING type is intended to be used to pass "C" type strings between + the application and the core and component. The VO_STRING type is a 32 + bit pointer to a zero terminated string. The pointer is word aligned and + the string is byte aligned. + */ +typedef char* VO_PCHAR; + +/** The VO_PBYTE type is intended to be used to pass arrays of bytes such as + buffers between the application and the component and core. The VO_PBYTE + type is a 32 bit pointer to a zero terminated string. The pointer is word + aligned and the string is byte aligned. + */ +typedef unsigned char* VO_PBYTE; + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/** + * Input stream format, Frame or Stream.. + */ +typedef enum { + VO_INPUT_FRAME = 1, /*!< Input contains completely frame(s) data. */ + VO_INPUT_STREAM, /*!< Input is stream data. */ + VO_INPUT_STREAM_MAX = VO_MAX_ENUM_VALUE +} VO_INPUT_TYPE; + + +/** + * General data buffer, used as input or output. + */ +typedef struct { + VO_PBYTE Buffer; /*!< Buffer pointer */ + VO_U32 Length; /*!< Buffer size in byte */ + VO_S64 Time; /*!< The time of the buffer */ +} VO_CODECBUFFER; + + +/** + * The init memdata flag. + */ +typedef enum{ + VO_IMF_USERMEMOPERATOR =0, /*!< memData is the pointer of memoperator function*/ + VO_IMF_PREALLOCATEDBUFFER =1, /*!< memData is preallocated memory*/ + VO_IMF_MAX = VO_MAX_ENUM_VALUE +}VO_INIT_MEM_FlAG; + + +/** + * The init memory structure.. + */ +typedef struct{ + VO_INIT_MEM_FlAG memflag; /*!memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) + { +#ifdef USE_DEFAULT_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_DEFAULT_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 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) +{ + UNUSED(hCodec); + UNUSED(uParamID); + UNUSED(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; +} diff --git a/aacenc/external/aacenc/src/aacenc_core.c b/aacenc/external/aacenc/src/aacenc_core.c new file mode 100644 index 0000000..de452d4 --- /dev/null +++ b/aacenc/external/aacenc/src/aacenc_core.c @@ -0,0 +1,238 @@ +/* + ** 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 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) */ + VO_U32 *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; + } + } +} diff --git a/aacenc/external/aacenc/src/aacenc_core.h b/aacenc/external/aacenc/src/aacenc_core.h new file mode 100644 index 0000000..bb75b6d --- /dev/null +++ b/aacenc/external/aacenc/src/aacenc_core.h @@ -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 */ + VO_U32 *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_ */ diff --git a/aacenc/external/aacenc/src/adj_thr.c b/aacenc/external/aacenc/src/adj_thr.c new file mode 100644 index 0000000..9bc775d --- /dev/null +++ b/aacenc/external/aacenc/src/adj_thr.c @@ -0,0 +1,1230 @@ +/* + ** 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.c + + Content: Threshold compensation functions + +*******************************************************************************/ + +/* Include system headers before local headers - the local headers + * redefine __inline, which can mess up definitions in libc headers if + * they happen to use __inline. */ +#include +#include "basic_op.h" +#include "oper_32b.h" +#include "adj_thr_data.h" +#include "adj_thr.h" +#include "qc_data.h" +#include "line_pe.h" + + +#define minSnrLimit 0x6666 /* 1 dB */ +#define PEBITS_COEF 0x170a /* 0.18*(1 << 15)*/ + +#define HOLE_THR_LONG 0x2873 /* 0.316*(1 << 15) */ +#define HOLE_THR_SHORT 0x4000 /* 0.5 *(1 << 15) */ + +#define MS_THRSPREAD_COEF 0x7333 /* 0.9 * (1 << 15) */ + +#define MIN_SNR_COEF 0x651f /* 3.16* (1 << (15 - 2)) */ + +/* values for avoid hole flag */ +enum _avoid_hole_state { + NO_AH =0, + AH_INACTIVE =1, + AH_ACTIVE =2 +}; + +/******************************************************************************** +* +* function name:bits2pe +* description: convert from bits to pe +* pe = 1.18*desiredBits +* +**********************************************************************************/ +Word16 bits2pe(const Word16 bits) { + return (bits + ((PEBITS_COEF * bits) >> 15)); +} + +/******************************************************************************** +* +* function name:calcThreshExp +* description: loudness calculation (threshold to the power of redExp) +* thr(n)^0.25 +* +**********************************************************************************/ +static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word16 ch, sfb, sfbGrp; + Word32 *pthrExp = NULL, *psfbThre; + for (ch=0; chsfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) + pthrExp = &(thrExp[ch][sfbGrp]); + psfbThre = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS); + pthrExp++; psfbThre++; + } + } +} + +/******************************************************************************** +* +* function name:adaptMinSnr +* description: reduce minSnr requirements for bands with relative low energies +* +**********************************************************************************/ +static void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + MINSNR_ADAPT_PARAM *msaParam, + const Word16 nChannels) +{ + Word16 ch, sfb, sfbOffs; + Word32 nSfb, avgEn; + Word16 log_avgEn = 0; + Word32 startRatio_x_avgEn = 0; + + + for (ch=0; chsfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]); + nSfb = nSfb + 1; + } + } + + if (nSfb > 0) { + avgEn = avgEn / nSfb; + + log_avgEn = iLog4(avgEn); + startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn); + } + + + /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) { + Word16 dbRatio, minSnrRed; + Word32 snrRed; + Word16 newMinSnr; + + dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb]; + dbRatio = dbRatio + (dbRatio << 1); + + minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2); + minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80, + 3: 0.00375(redRatioFac)*80 + 20: 0.25(maxRed) * 80 */ + + snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16)); + /* + snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4) + */ + + newMinSnr = round16(pow2_xy(snrRed,80*4)); + + psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit); + } + } + } + } + +} + + +/******************************************************************************** +* +* function name:initAvoidHoleFlag +* description: determine bands where avoid hole is not necessary resp. possible +* +**********************************************************************************/ +static void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT* psyOutElement, + const Word16 nChannels, + AH_PARAM *ahParam) +{ + Word16 ch, sfb, sfbGrp, shift; + Word32 threshold; + Word32* psfbSpreadEn; + + for (ch=0; chwindowSequence != SHORT_WINDOW) { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */ + ++psfbSpreadEn; + } + } + } + else { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */ + ++psfbSpreadEn; + } + } + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for(ch=0; chwindowSequence != SHORT_WINDOW) + threshold = HOLE_THR_LONG; + else + threshold = HOLE_THR_SHORT; + + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn; + + if (sfb > 0) + sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1]; + else + sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp]; + + if (sfb < (psyOutChan->maxSfbPerGroup-1)) + sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1]; + else + sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb]; + avgEn = (sfbEnm1 + sfbEnp1) >> 1; + sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; + + if (sfbEn > avgEn && avgEn > 0) { + Word32 tmpMinSnr; + shift = norm_l(sfbEn); + tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift ); + tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG); + tmpMinSnr = max(tmpMinSnr, threshold); + *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr); + } + /* valley ? */ + + if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) { + Word32 tmpMinSnr; + Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr); + + if(minSnrEn < sfbEn) { + shift = norm_l(sfbEn); + tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<> 2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2); + } + psfbMinSnr++; + } + } + } + } + + /* stereo: adapt the minimum requirements sfbMinSnr of mid and + side channels */ + + if (nChannels == 2) { + PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0]; + PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1]; + for (sfb=0; sfbsfbCnt; sfb++) { + if (psyOutElement->toolsInfo.msMask[sfb]) { + Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb]; + Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb]; + Word32 maxSfbEn = max(sfbEnM, sfbEnS); + Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1; + + if(maxThr >= sfbEnM) { + psyOutChanM->sfbMinSnr[sfb] = MAX_16; + } + else { + shift = norm_l(sfbEnM); + psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb], + round16(Div_32(maxThr<= sfbEnS) { + psyOutChanS->sfbMinSnr[sfb] = MAX_16; + } + else { + shift = norm_l(sfbEnS); + psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb], + round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit); + } + + + if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb]) + psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF); + + if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb]) + psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF); + } + } + } + + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + for(ch=0; chsfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + Word16 *pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) || + (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) || + (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) { + *pahFlag++ = NO_AH; + } + else { + *pahFlag++ = AH_INACTIVE; + } + } + for (sfb=psyOutChan->maxSfbPerGroup; sfbsfbPerGroup; sfb++) { + *pahFlag++ = NO_AH; + } + } + } +} + +/******************************************************************************** +* +* function name:calcPeNoAH +* description: sum the pe data only for bands where avoid hole is inactive +* +**********************************************************************************/ +static void calcPeNoAH(Word16 *pe, + Word16 *constPart, + Word16 *nActiveLines, + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word16 ch, sfb, sfbGrp; + int ipe, iconstPart, inActiveLines; + + ipe = 0; + iconstPart = 0; + inActiveLines = 0; + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) { + ipe = ipe + peChanData->sfbPe[sfbGrp+sfb]; + iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb]; + inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; + } + } + } + } + + *pe = saturate(ipe); + *constPart = saturate(iconstPart); + *nActiveLines = saturate(inActiveLines); +} + +/******************************************************************************** +* +* function name:reduceThresholds +* description: apply reduction formula +* +**********************************************************************************/ +static void reduceThresholds(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word32 redVal) +{ + Word32 sfbThrReduced; + Word32 *psfbEn, *psfbThr; + Word16 ch, sfb, sfbGrp; + + for(ch=0; chsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + psfbEn = psyOutChan->sfbEnergy + sfbGrp; + psfbThr = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if (*psfbEn > *psfbThr) { + /* threshold reduction formula */ + Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal; + tmp = fixmul(tmp, tmp); + sfbThrReduced = fixmul(tmp, tmp); + /* avoid holes */ + tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); + + if ((sfbThrReduced > tmp) && + (ahFlag[ch][sfbGrp+sfb] != NO_AH)){ + sfbThrReduced = max(tmp, *psfbThr); + ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; + } + *psfbThr = sfbThrReduced; + } + + psfbEn++; psfbThr++; + } + } + } +} + + +/******************************************************************************** +* +* function name:correctThresh +* description: if pe difference deltaPe between desired pe and real pe is small enough, +* the difference can be distributed among the scale factor bands. +* +**********************************************************************************/ +static void correctThresh(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PE_DATA *peData, + Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word32 redVal, + const Word16 nChannels, + const Word32 deltaPe) +{ + Word16 ch, sfb, sfbGrp,shift; + PSY_OUT_CHANNEL *psyOutChan; + PE_CHANNEL_DATA *peChanData; + Word32 deltaSfbPe; + Word32 normFactor; + Word32 *psfbPeFactors; + Word16 *psfbNActiveLines, *pahFlag; + Word32 sfbEn, sfbThr; + Word32 sfbThrReduced; + + /* for each sfb calc relative factors for pe changes */ + normFactor = 1; + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; + psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; + pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal; + + if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) && (redThrExp >= *psfbNActiveLines)) { + + *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp); + normFactor = L_add(normFactor, *psfbPeFactors); + } + else { + *psfbPeFactors = 0; + } + psfbPeFactors++; + pahFlag++; psfbNActiveLines++; + } + } + } + + + /* calculate new thresholds */ + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; + psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; + pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + /* pe difference for this sfb */ + deltaSfbPe = *psfbPeFactors * deltaPe; + + /* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */ + if (*psfbNActiveLines > 0 && (normFactor* (*psfbNActiveLines)) != 0) { + /* new threshold */ + Word32 thrFactor; + sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; + sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb]; + + if(deltaSfbPe >= 0){ + /* + reduce threshold + */ + thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines))); + + sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor)); + } + else { + /* + increase threshold + */ + thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines))); + + + if(thrFactor > sfbThr) { + shift = norm_l(thrFactor); + sfbThrReduced = Div_32( sfbThr << shift, thrFactor<sfbMinSnr[sfbGrp+sfb]); + + if ((sfbThrReduced > sfbEn) && + (*pahFlag == AH_INACTIVE)) { + sfbThrReduced = max(sfbEn, sfbThr); + *pahFlag = AH_ACTIVE; + } + + psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced; + } + + pahFlag++; psfbNActiveLines++; psfbPeFactors++; + } + } + } +} + + +/******************************************************************************** +* +* function name:reduceMinSnr +* description: if the desired pe can not be reached, reduce pe by reducing minSnr +* +**********************************************************************************/ +static void reduceMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word16 desiredPe) +{ + Word16 ch, sfb, sfbSubWin; + Word16 deltaPe; + + /* start at highest freq down to 0 */ + sfbSubWin = psyOutChannel[0].maxSfbPerGroup; + while (peData->pe > desiredPe && sfbSubWin > 0) { + + sfbSubWin = sfbSubWin - 1; + /* loop over all subwindows */ + for (sfb=sfbSubWin; sfbpeChannelData; + PSY_OUT_CHANNEL* psyOutCh = psyOutChannel; + for (ch=0; chsfbMinSnr[sfb] < minSnrLimit) { + psyOutCh->sfbMinSnr[sfb] = minSnrLimit; + psyOutCh->sfbThreshold[sfb] = + L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]); + + /* calc new pe */ + deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) - + peChan->sfbPe[sfb]; + peData->pe = peData->pe + deltaPe; + peChan->pe = peChan->pe + deltaPe; + } + peChan += 1; psyOutCh += 1; + } + /* stop if enough has been saved */ + + if (peData->pe <= desiredPe) + break; + } + } +} + +/******************************************************************************** +* +* function name:allowMoreHoles +* description: if the desired pe can not be reached, some more scalefactor bands +* have to be quantized to zero +* +**********************************************************************************/ +static void allowMoreHoles(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + const AH_PARAM *ahParam, + const Word16 nChannels, + const Word16 desiredPe) +{ + Word16 ch, sfb; + Word16 actPe, shift; + + actPe = peData->pe; + + /* for MS allow hole in the channel with less energy */ + + if (nChannels==2 && + psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) { + PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0]; + PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1]; + for (sfb=0; sfbsfbCnt; sfb++) { + Word32 minEn; + + if (psyOutElement->toolsInfo.msMask[sfb]) { + /* allow hole in side channel ? */ + minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16); + + if (ahFlag[1][sfb] != NO_AH && + minEn > psyOutChanR->sfbEnergy[sfb]) { + ahFlag[1][sfb] = NO_AH; + psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[1].sfbPe[sfb]; + } + /* allow hole in mid channel ? */ + else { + minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16); + + if (ahFlag[0][sfb]!= NO_AH && + minEn > psyOutChanL->sfbEnergy[sfb]) { + ahFlag[0][sfb] = NO_AH; + psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[0].sfbPe[sfb]; + } + } + + if (actPe < desiredPe) + break; + } + } + } + + /* subsequently erase bands */ + if (actPe > desiredPe) { + Word16 startSfb[2]; + Word32 avgEn, minEn; + Word16 ahCnt; + Word16 enIdx; + Word16 enDiff; + Word32 en[4]; + Word16 minSfb, maxSfb; + Flag done; + + /* do not go below startSfb */ + for (ch=0; chstartSfbL; + else + startSfb[ch] = ahParam->startSfbS; + } + + avgEn = 0; + minEn = MAX_32; + ahCnt = 0; + for (ch=0; chsfbCnt; sfb++) { + + if ((ahFlag[ch][sfb] != NO_AH) && + (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) { + minEn = min(minEn, psyOutChan->sfbEnergy[sfb]); + avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]); + ahCnt++; + } + } + } + + if(ahCnt) { + Word32 iahCnt; + shift = norm_l(ahCnt); + iahCnt = Div_32( 1 << shift, ahCnt << shift ); + avgEn = fixmul(avgEn, iahCnt); + if (avgEn < minEn) + avgEn = minEn; + } + + enDiff = iLog4(avgEn) - iLog4(minEn); + /* calc some energy borders between minEn and avgEn */ + for (enIdx=0; enIdx<4; enIdx++) { + Word32 enFac; + enFac = ((6-(enIdx << 1)) * enDiff); + en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4)); + } + + /* start with lowest energy border at highest sfb */ + maxSfb = psyOutChannel[0].sfbCnt - 1; + minSfb = startSfb[0]; + + if (nChannels == 2) { + maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1)); + minSfb = min(minSfb, startSfb[1]); + } + + sfb = maxSfb; + enIdx = 0; + done = 0; + while (!done) { + + for (ch=0; ch=startSfb[ch] && sfbsfbCnt) { + /* sfb energy below border ? */ + + if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){ + /* allow hole */ + ahFlag[ch][sfb] = NO_AH; + psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[ch].sfbPe[sfb]; + } + + if (actPe < desiredPe) { + done = 1; + break; + } + } + } + sfb = sfb - 1; + + if (sfb < minSfb) { + /* restart with next energy border */ + sfb = maxSfb; + enIdx = enIdx + 1; + + if (enIdx - 4 >= 0) + done = 1; + } + } + } +} + +/******************************************************************************** +* +* function name:adaptThresholdsToPe +* description: two guesses for the reduction value and one final correction of the +* thresholds +* +**********************************************************************************/ +static void adaptThresholdsToPe(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + PE_DATA *peData, + const Word16 nChannels, + const Word16 desiredPe, + AH_PARAM *ahParam, + MINSNR_ADAPT_PARAM *msaParam) +{ + Word16 noRedPe, redPe, redPeNoAH; + Word16 constPart, constPartNoAH; + Word16 nActiveLines, nActiveLinesNoAH; + Word16 desiredPeNoAH; + Word32 redVal, avgThrExp; + Word32 iter; + + calcThreshExp(peData->thrExp, psyOutChannel, nChannels); + + adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels); + + initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam); + + noRedPe = peData->pe; + constPart = peData->constPart; + nActiveLines = peData->nActiveLines; + + /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */ + avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2)); + + /* r1 = 2^((a-per)/4*b) - t^0.25 */ + redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp; + + /* reduce thresholds */ + reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); + + /* pe after first guess */ + calcSfbPe(peData, psyOutChannel, nChannels); + redPe = peData->pe; + + iter = 0; + do { + /* pe for bands where avoid hole is inactive */ + calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, + peData, peData->ahFlag, psyOutChannel, nChannels); + + desiredPeNoAH = desiredPe -(redPe - redPeNoAH); + + if (desiredPeNoAH < 0) { + desiredPeNoAH = 0; + } + + /* second guess */ + + if (nActiveLinesNoAH > 0) { + + avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2)); + + redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp; + + /* reduce thresholds */ + reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); + } + + calcSfbPe(peData, psyOutChannel, nChannels); + redPe = peData->pe; + + iter = iter+1; + + } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2)); + + + if ((100 * redPe < 115 * desiredPe)) { + correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal, + nChannels, desiredPe - redPe); + } + else { + Word16 desiredPe105 = (105 * desiredPe) / 100; + reduceMinSnr(psyOutChannel, peData, peData->ahFlag, + nChannels, desiredPe105); + allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag, + ahParam, nChannels, desiredPe105); + } +} + + +/***************************************************************************** +* +* function name: calcBitSave +* description: Calculates percentage of bit save, see figure below +* returns: +* input: parameters and bitres-fullness +* output: percentage of bit save +* +*****************************************************************************/ +static Word16 calcBitSave(Word16 fillLevel, + const Word16 clipLow, + const Word16 clipHigh, + const Word16 minBitSave, + const Word16 maxBitSave) +{ + Word16 bitsave = 0; + + fillLevel = max(fillLevel, clipLow); + fillLevel = min(fillLevel, clipHigh); + + if(clipHigh-clipLow) + bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/ + (clipHigh-clipLow))); + + return (bitsave); +} + + + +/***************************************************************************** +* +* function name: calcBitSpend +* description: Calculates percentage of bit spend, see figure below +* returns: +* input: parameters and bitres-fullness +* output: percentage of bit spend +* +*****************************************************************************/ +static Word16 calcBitSpend(Word16 fillLevel, + const Word16 clipLow, + const Word16 clipHigh, + const Word16 minBitSpend, + const Word16 maxBitSpend) +{ + Word16 bitspend = 1; + + fillLevel = max(fillLevel, clipLow); + fillLevel = min(fillLevel, clipHigh); + + if(clipHigh-clipLow) + bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) / + (clipHigh-clipLow))); + + return (bitspend); +} + + +/***************************************************************************** +* +* function name: adjustPeMinMax() +* description: adjusts peMin and peMax parameters over time +* returns: +* input: current pe, peMin, peMax +* output: adjusted peMin/peMax +* +*****************************************************************************/ +static void adjustPeMinMax(const Word16 currPe, + Word16 *peMin, + Word16 *peMax) +{ + Word16 minFacHi, maxFacHi, minFacLo, maxFacLo; + Word16 diff; + Word16 minDiff = extract_l(currPe / 6); + minFacHi = 30; + maxFacHi = 100; + minFacLo = 14; + maxFacLo = 7; + + diff = currPe - *peMax ; + + if (diff > 0) { + *peMin = *peMin + ((diff * minFacHi) / 100); + *peMax = *peMax + ((diff * maxFacHi) / 100); + } else { + diff = *peMin - currPe; + + if (diff > 0) { + *peMin = *peMin - ((diff * minFacLo) / 100); + *peMax = *peMax - ((diff * maxFacLo) / 100); + } else { + *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100); + *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100); + } + } + + + if ((*peMax - *peMin) < minDiff) { + Word16 partLo, partHi; + + partLo = max(0, (currPe - *peMin)); + partHi = max(0, (*peMax - currPe)); + + *peMax = currPe + ((partHi * minDiff) / (partLo + partHi)); + *peMin = currPe - ((partLo * minDiff) / (partLo + partHi)); + *peMin = max(0, *peMin); + } +} + + +/***************************************************************************** +* +* function name: BitresCalcBitFac +* description: calculates factor of spending bits for one frame +* 1.0 : take all frame dynpart bits +* >1.0 : take all frame dynpart bits + bitres +* <1.0 : put bits in bitreservoir +* returns: BitFac*100 +* input: bitres-fullness, pe, blockType, parameter-settings +* output: +* +*****************************************************************************/ +static Word16 bitresCalcBitFac( const Word16 bitresBits, + const Word16 maxBitresBits, + const Word16 pe, + const Word16 windowSequence, + const Word16 avgBits, + const Word16 maxBitFac, + ADJ_THR_STATE *AdjThr, + ATS_ELEMENT *adjThrChan) +{ + BRES_PARAM *bresParam; + Word16 pex; + Word16 fillLevel; + Word16 bitSave, bitSpend, bitresFac; + + fillLevel = extract_l((100* bitresBits) / maxBitresBits); + + if (windowSequence != SHORT_WINDOW) + bresParam = &(AdjThr->bresParamLong); + else + bresParam = &(AdjThr->bresParamShort); + + pex = max(pe, adjThrChan->peMin); + pex = min(pex,adjThrChan->peMax); + + bitSave = calcBitSave(fillLevel, + bresParam->clipSaveLow, bresParam->clipSaveHigh, + bresParam->minBitSave, bresParam->maxBitSave); + + bitSpend = calcBitSpend(fillLevel, + bresParam->clipSpendLow, bresParam->clipSpendHigh, + bresParam->minBitSpend, bresParam->maxBitSpend); + + if(adjThrChan->peMax != adjThrChan->peMin) + bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) / + (adjThrChan->peMax - adjThrChan->peMin)); + else + bitresFac = 0x7fff; + + bitresFac = min(bitresFac, + (100-30 + extract_l((100 * bitresBits) / avgBits))); + + bitresFac = min(bitresFac, maxBitFac); + + adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); + + return bitresFac; +} + +/***************************************************************************** +* +* function name: AdjThrInit +* description: init thresholds parameter +* +*****************************************************************************/ +void AdjThrInit(ADJ_THR_STATE *hAdjThr, + const Word32 meanPe, + Word32 chBitrate) +{ + ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + + /* common for all elements: */ + /* parameters for bitres control */ + hAdjThr->bresParamLong.clipSaveLow = 20; + hAdjThr->bresParamLong.clipSaveHigh = 95; + hAdjThr->bresParamLong.minBitSave = -5; + hAdjThr->bresParamLong.maxBitSave = 30; + hAdjThr->bresParamLong.clipSpendLow = 20; + hAdjThr->bresParamLong.clipSpendHigh = 95; + hAdjThr->bresParamLong.minBitSpend = -10; + hAdjThr->bresParamLong.maxBitSpend = 40; + + hAdjThr->bresParamShort.clipSaveLow = 20; + hAdjThr->bresParamShort.clipSaveHigh = 75; + hAdjThr->bresParamShort.minBitSave = 0; + hAdjThr->bresParamShort.maxBitSave = 20; + hAdjThr->bresParamShort.clipSpendLow = 20; + hAdjThr->bresParamShort.clipSpendHigh = 75; + hAdjThr->bresParamShort.minBitSpend = -5; + hAdjThr->bresParamShort.maxBitSpend = 50; + + /* specific for each element: */ + + /* parameters for bitres control */ + atsElem->peMin = extract_l(((80*meanPe) / 100)); + atsElem->peMax = extract_l(((120*meanPe) / 100)); + + /* additional pe offset to correct pe2bits for low bitrates */ + atsElem->peOffset = 0; + if (chBitrate < 32000) { + atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000))); + } + + /* avoid hole parameters */ + if (chBitrate > 20000) { + atsElem->ahParam.modifyMinSnr = TRUE; + atsElem->ahParam.startSfbL = 15; + atsElem->ahParam.startSfbS = 3; + } + else { + atsElem->ahParam.modifyMinSnr = FALSE; + atsElem->ahParam.startSfbL = 0; + atsElem->ahParam.startSfbS = 0; + } + + /* minSnr adaptation */ + /* maximum reduction of minSnr goes down to minSnr^maxRed */ + msaParam->maxRed = 0x20000000; /* *0.25f */ + /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ + msaParam->startRatio = 0x0ccccccd; /* 10 */ + /* maximum minSnr reduction to minSnr^maxRed is reached for + avgEn/sfbEn >= maxRatio */ + msaParam->maxRatio = 0x0020c49c; /* 1000 */ + /* helper variables to interpolate minSnr reduction for + avgEn/sfbEn between startRatio and maxRatio */ + + msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */ + + msaParam->redOffs = 0x30000000; /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */ + + + /* pe correction */ + atsElem->peLast = 0; + atsElem->dynBitsLast = 0; + atsElem->peCorrectionFactor = 100; /* 1.0 */ + +} + +/***************************************************************************** +* +* function name: calcPeCorrection +* description: calculates the desired perceptual entropy factor +* It is between 0.85 and 1.15 +* +*****************************************************************************/ +static void calcPeCorrection(Word16 *correctionFac, + const Word16 peAct, + const Word16 peLast, + const Word16 bitsLast) +{ + Word32 peAct100 = 100 * peAct; + Word32 peLast100 = 100 * peLast; + Word16 peBitsLast = bits2pe(bitsLast); + + if ((bitsLast > 0) && + (peAct100 < (150 * peLast)) && (peAct100 > (70 * peLast)) && + ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100)) + { + Word16 newFac = (100 * peLast) / peBitsLast; + /* dead zone */ + + if (newFac < 100) { + newFac = min(((110 * newFac) / 100), 100); + newFac = max(newFac, 85); + } + else { + newFac = max(((90 * newFac) / 100), 100); + newFac = min(newFac, 115); + } + + if ((newFac > 100 && *correctionFac < 100) || + (newFac < 100 && *correctionFac > 100)) { + *correctionFac = 100; + } + /* faster adaptation towards 1.0, slower in the other direction */ + + if ((*correctionFac < 100 && newFac < *correctionFac) || + (*correctionFac > 100 && newFac > *correctionFac)) + *correctionFac = (85 * *correctionFac + 15 * newFac) / 100; + else + *correctionFac = (70 * *correctionFac + 30 * newFac) / 100; + *correctionFac = min(*correctionFac, 115); + *correctionFac = max(*correctionFac, 85); + } + else { + *correctionFac = 100; + } +} + +/******************************************************************************** +* +* function name: AdjustThresholds +* description: Adjust thresholds to the desired bitrate +* +**********************************************************************************/ +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) +{ + PE_DATA peData; + Word16 noRedPe, grantedPe, grantedPeCorr; + Word16 curWindowSequence; + Word16 bitFactor; + Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed)); + Word16 bitresBits = elBits->bitResLevel; + Word16 maxBitresBits = elBits->maxBits; + Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed); + Word16 ch; + memset(&peData, 0, sizeof(peData)); + + prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset); + + /* pe without reduction */ + calcSfbPe(&peData, psyOutChannel, nChannels); + noRedPe = peData.pe; + + + curWindowSequence = LONG_WINDOW; + + if (nChannels == 2) { + + if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) || + (psyOutChannel[1].windowSequence == SHORT_WINDOW)) { + curWindowSequence = SHORT_WINDOW; + } + } + else { + curWindowSequence = psyOutChannel[0].windowSequence; + } + + + /* bit factor */ + bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits, + curWindowSequence, avgBits, maxBitFac, + adjThrState, + AdjThrStateElement); + + /* desired pe */ + grantedPe = ((bitFactor * bits2pe(avgBits)) / 100); + + /* correction of pe value */ + calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor), + min(grantedPe, noRedPe), + AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast); + grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100; + + + if (grantedPeCorr < noRedPe && noRedPe > peData.offset) { + /* calc threshold necessary for desired pe */ + adaptThresholdsToPe(psyOutChannel, + psyOutElement, + logSfbEnergy, + &peData, + nChannels, + grantedPeCorr, + &AdjThrStateElement->ahParam, + &AdjThrStateElement->minSnrAdaptParam); + } + + /* calculate relative distribution */ + for (ch=0; ch 0) { + Word32 temp = 1000 - (nChannels * 200); + chBitDistribution[ch] = chBitDistribution[ch] + + (temp * peData.peChannelData[ch].pe) / peOffsDiff; + } + } + + /* store pe */ + qcOE->pe = noRedPe; + + /* update last pe */ + AdjThrStateElement->peLast = grantedPe; +} + +/******************************************************************************** +* +* function name: AdjThrUpdate +* description: save dynBitsUsed for correction of bits2pe relation +* +**********************************************************************************/ +void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement, + const Word16 dynBitsUsed) +{ + AdjThrStateElement->dynBitsLast = dynBitsUsed; +} + + diff --git a/aacenc/external/aacenc/src/adj_thr.h b/aacenc/external/aacenc/src/adj_thr.h new file mode 100644 index 0000000..0f4bb5e --- /dev/null +++ b/aacenc/external/aacenc/src/adj_thr.h @@ -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 diff --git a/aacenc/external/aacenc/src/adj_thr_data.h b/aacenc/external/aacenc/src/adj_thr_data.h new file mode 100644 index 0000000..30132d8 --- /dev/null +++ b/aacenc/external/aacenc/src/adj_thr_data.h @@ -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 diff --git a/aacenc/external/aacenc/src/band_nrg.c b/aacenc/external/aacenc/src/band_nrg.c new file mode 100644 index 0000000..e4034b8 --- /dev/null +++ b/aacenc/external/aacenc/src/band_nrg.c @@ -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> 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 diff --git a/aacenc/external/aacenc/src/band_nrg.h b/aacenc/external/aacenc/src/band_nrg.h new file mode 100644 index 0000000..65453c0 --- /dev/null +++ b/aacenc/external/aacenc/src/band_nrg.h @@ -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 diff --git a/aacenc/external/aacenc/src/basic_op.h b/aacenc/external/aacenc/src/basic_op.h new file mode 100644 index 0000000..ea21035 --- /dev/null +++ b/aacenc/external/aacenc/src/basic_op.h @@ -0,0 +1,1178 @@ +/* + ** 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: basicop2.h + + Content: Constants , Globals and Basic arithmetic operators. + +*******************************************************************************/ + +#ifndef __BASIC_OP_H +#define __BASIC_OP_H + +#include "typedef.h" + +#define MAX_32 (Word32)0x7fffffffL +#define MIN_32 (Word32)0x80000000L + +#define MAX_16 (Word16)0x7fff +#define MIN_16 (Word16)0x8000 +#define ABS(a) ((a) >= 0) ? (a) : (-(a)) + +/* Short abs, 1 */ +#define abs_s(x) (((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16) + +/* 16 bit var1 -> MSB, 2 */ +#define L_deposit_h(x) (((Word32)(x)) << 16) + + +/* 16 bit var1 -> LSB, 2 */ +#define L_deposit_l(x) ((Word32)(x)) + + +/* Long abs, 3 */ +#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32) + + +/* Short negate, 1 */ +#define negate(var1) (((var1) == MIN_16) ? MAX_16 : (-(var1))) + + +/* Long negate, 2 */ +#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1))) + + +#define MULHIGH(A,B) (int)(((Word64)(A)*(Word64)(B)) >> 32) +#define fixmul(a, b) (int)((((Word64)(a)*(Word64)(b)) >> 32) << 1) + + +#if (SATRUATE_IS_INLINE) +__inline Word32 saturate(Word32 L_var1); +#else +Word16 saturate(Word32 L_var1); +#endif + +/* Short shift left, 1 */ +#if (SHL_IS_INLINE) +__inline Word32 shl (Word32 var1, Word32 var2); +#else +Word16 shl (Word16 var1, Word16 var2); +#endif + +/* Short shift right, 1 */ +#if (SHR_IS_INLINE) +__inline Word32 shr (Word32 var1, Word32 var2); +#else +Word16 shr (Word16 var1, Word16 var2); +#endif + +#if (L_MULT_IS_INLINE) +__inline Word32 L_mult(Word32 var1, Word32 var2); +#else +Word32 L_mult(Word16 var1, Word16 var2); +#endif + +/* Msu, 1 */ +#if (L_MSU_IS_INLINE) +__inline Word32 L_msu (Word32 L_var3, Word32 var1, Word32 var2); +#else +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Long sub, 2 */ +#if (L_SUB_IS_INLINE) +__inline Word32 L_sub(Word32 L_var1, Word32 L_var2); +#else +Word32 L_sub(Word32 L_var1, Word32 L_var2); +#endif + +/* Long shift left, 2 */ +#if (L_SHL_IS_INLINE) +__inline Word32 L_shl (Word32 L_var1, Word32 var2); +#else +Word32 L_shl (Word32 L_var1, Word16 var2); +#endif + +/* Long shift right, 2*/ +#if (L_SHR_IS_INLINE) +__inline Word32 L_shr (Word32 L_var1, Word32 var2); +#else +Word32 L_shr (Word32 L_var1, Word16 var2); +#endif + +/* Short add, 1 */ +#if (ADD_IS_INLINE) +__inline Word32 add (Word32 var1, Word32 var2); +#else +Word16 add (Word16 var1, Word16 var2); +#endif + +/* Short sub, 1 */ +#if (SUB_IS_INLINE) +__inline Word32 sub(Word32 var1, Word32 var2); +#else +Word16 sub(Word16 var1, Word16 var2); +#endif + +/* Short division, 18 */ +#if (DIV_S_IS_INLINE) +__inline Word32 div_s (Word32 var1, Word32 var2); +#else +Word16 div_s (Word16 var1, Word16 var2); +#endif + +/* Short mult, 1 */ +#if (MULT_IS_INLINE) +__inline Word32 mult (Word32 var1, Word32 var2); +#else +Word16 mult (Word16 var1, Word16 var2); +#endif + +/* Short norm, 15 */ +#if (NORM_S_IS_INLINE) +__inline Word32 norm_s (Word32 var1); +#else +Word16 norm_s (Word16 var1); +#endif + +/* Long norm, 30 */ +#if (NORM_L_IS_INLINE) +__inline Word32 norm_l (Word32 L_var1); +#else +Word16 norm_l (Word32 L_var1); +#endif + +/* Round, 1 */ +#if (ROUND_IS_INLINE) +__inline Word32 round16(Word32 L_var1); +#else +Word16 round16(Word32 L_var1); +#endif + +/* Mac, 1 */ +#if (L_MAC_IS_INLINE) +__inline Word32 L_mac (Word32 L_var3, Word32 var1, Word32 var2); +#else +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +#if (L_ADD_IS_INLINE) +__inline Word32 L_add (Word32 L_var1, Word32 L_var2); +#else +Word32 L_add (Word32 L_var1, Word32 L_var2); +#endif + +/* Extract high, 1 */ +#if (EXTRACT_H_IS_INLINE) +__inline Word32 extract_h (Word32 L_var1); +#else +Word16 extract_h (Word32 L_var1); +#endif + +/* Extract low, 1 */ +#if (EXTRACT_L_IS_INLINE) +__inline Word32 extract_l(Word32 L_var1); +#else +Word16 extract_l(Word32 L_var1); +#endif + +/* Mult with round, 2 */ +#if (MULT_R_IS_INLINE) +__inline Word32 mult_r(Word32 var1, Word32 var2); +#else +Word16 mult_r(Word16 var1, Word16 var2); +#endif + +/* Shift right with round, 2 */ +#if (SHR_R_IS_INLINE) +__inline Word32 shr_r (Word32 var1, Word32 var2); +#else +Word16 shr_r (Word16 var1, Word16 var2); +#endif + +/* Mac with rounding,2 */ +#if (MAC_R_IS_INLINE) +__inline Word32 mac_r (Word32 L_var3, Word32 var1, Word32 var2); +#else +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Msu with rounding,2 */ +#if (MSU_R_IS_INLINE) +__inline Word32 msu_r (Word32 L_var3, Word32 var1, Word32 var2); +#else +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Long shift right with round, 3 */ +#if (L_SHR_R_IS_INLINE) +__inline Word32 L_shr_r (Word32 L_var1, Word32 var2); +#else +Word32 L_shr_r (Word32 L_var1, Word16 var2); +#endif + +#if ARMV4_INASM +__inline Word32 ASM_L_shr(Word32 L_var1, Word32 var2) +{ + return L_var1 >> var2; +} + +__inline Word32 ASM_L_shl(Word32 L_var1, Word32 var2) +{ + Word32 result; + asm ( + "MOV %[result], %[L_var1], ASL %[var2] \n" + "TEQ %[L_var1], %[result], ASR %[var2]\n" + "EORNE %[result], %[mask], %[L_var1], ASR #31\n" + :[result]"=&r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fffffff) + :"cc" + ); + return result; +} + +__inline Word32 ASM_shr(Word32 L_var1, Word32 var2) +{ + Word32 result; + asm ( + "CMP %[var2], #15\n" + "MOVLT %[result], %[L_var1], ASR %[var2]\n" + "MOVGE %[result], %[L_var1], ASR #15\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + :"cc" + ); + return result; +} + +__inline Word32 ASM_shl(Word32 L_var1, Word32 var2) +{ +#if ARMV6_SAT + Word32 result; + asm ( + "CMP %[var2], #16\n" + "MOVLT %[result], %[L_var1], ASL %[var2]\n" + "MOVGE %[result], %[L_var1], ASL #16\n" + "SSAT %[result], #16, %[result]\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + :"cc" + ); + return result; +#else + Word32 result; + Word32 tmp; + asm ( + "CMP %[var2], #16\n" + "MOVLT %[result], %[L_var1], ASL %[var2]\n" + "MOVGE %[result], %[L_var1], ASL #16\n" + "MOV %[tmp], %[result], ASR #15\n" + "TEQ %[tmp], %[result], ASR #31 \n" + "EORNE %[result], %[mask], %[result],ASR #31" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fff) + :"cc" + ); + return result; +#endif +} +#endif + +/*___________________________________________________________________________ + | | + | definitions for inline basic arithmetic operators | + |___________________________________________________________________________| +*/ +#if (SATRUATE_IS_INLINE) +__inline Word32 saturate(Word32 L_var1) +{ +#if ARMV6_SAT + Word32 result; + asm ( + "SSAT %[result], #16, %[L_var1]" + : [result]"=r"(result) + : [L_var1]"r"(L_var1) + ); + return result; +#elif ARMV5TE_SAT + Word32 result; + Word32 tmp; + asm volatile ( + "MOV %[tmp], %[L_var1],ASR#15\n" + "TEQ %[tmp], %[L_var1],ASR#31\n" + "EORNE %[result], %[mask],%[L_var1],ASR#31\n" + "MOVEQ %[result], %[L_var1]\n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[L_var1]"r"(L_var1), [mask]"r"(0x7fff) + :"cc" + ); + + return result; +#else + Word32 var_out; + + //var_out = (L_var1 > (Word32)0X00007fffL) ? (MAX_16) : ((L_var1 < (Word32)0xffff8000L) ? (MIN_16) : ((Word16)L_var1)); + + if (L_var1 > 0X00007fffL) + { + var_out = MAX_16; + } + else if (L_var1 < (Word32) 0xffff8000L) + { + var_out = MIN_16; + } + else + { + var_out = extract_l(L_var1); + } + + return (var_out); +#endif +} +#endif + +/* Short shift left, 1 */ +#if (SHL_IS_INLINE) +__inline Word32 shl (Word32 var1, Word32 var2) +{ +#if ARMV5TE_SHL + if(var2>=0) + { + return ASM_shl( var1, var2); + } + else + { + return ASM_shr( var1, -var2); + } +#else + Word32 var_out; + Word32 result; + + if (var2 < 0) + { + var_out = shr (var1, (Word16)-var2); + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16); + } + else + { + var_out = extract_l(result); + } + } + return (var_out); +#endif +} +#endif + +/* Short shift right, 1 */ +#if (SHR_IS_INLINE) +__inline Word32 shr (Word32 var1, Word32 var2) +{ +#if ARMV5TE_SHR + if(var2>=0) + { + return ASM_shr( var1, var2); + } + else + { + return ASM_shl( var1, -var2); + } +#else + Word32 var_out; + + if (var2 < 0) + { + var_out = shl (var1, (Word16)-var2); + } + else + { + if (var2 >= 15) + { + var_out = (Word16)((var1 < 0) ? -1 : 0); + } + else + { + if (var1 < 0) + { + var_out = (Word16)(~((~var1) >> var2)); + } + else + { + var_out = (Word16)(var1 >> var2); + } + } + } + + return (var_out); +#endif +} +#endif + + +#if (L_MULT_IS_INLINE) +__inline Word32 L_mult(Word32 var1, Word32 var2) +{ +#if ARMV5TE_L_MULT + Word32 result; + asm ( + "SMULBB %[result], %[var1], %[var2] \n" + "QADD %[result], %[result], %[result] \n" + :[result]"=r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out <<= 1; + } + else + { + L_var_out = MAX_32; + } + return (L_var_out); +#endif +} +#endif + +#if (L_MSU_IS_INLINE) +__inline Word32 L_msu (Word32 L_var3, Word32 var1, Word32 var2) +{ +#if ARMV5TE_L_MSU + Word32 result; + asm ( + "SMULBB %[result], %[var1], %[var2] \n" + "QDSUB %[result], %[L_var3], %[result]\n" + :[result]"=&r"(result) + :[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_sub(L_var3, L_product); + return (L_var_out); +#endif +} +#endif + +#if (L_SUB_IS_INLINE) +__inline Word32 L_sub(Word32 L_var1, Word32 L_var2) +{ +#if ARMV5TE_L_SUB + Word32 result; + asm ( + "QSUB %[result], %[L_var1], %[L_var2]\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + } + } + + return (L_var_out); +#endif +} +#endif + +#if (L_SHL_IS_INLINE) +__inline Word32 L_shl(Word32 L_var1, Word32 var2) +{ +#if ARMV5TE_L_SHL + if(var2>=0) + { + return ASM_L_shl( L_var1, var2); + } + else + { + return ASM_L_shr( L_var1, -var2); + } +#else + if (var2 <= 0) + { + L_var1 = L_shr(L_var1, (Word16)-var2); + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + return MAX_32; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + return MIN_32; + } + } + L_var1 <<= 1; + } + } + return (L_var1); +#endif +} +#endif + +#if (L_SHR_IS_INLINE) +__inline Word32 L_shr (Word32 L_var1, Word32 var2) +{ +#if ARMV5TE_L_SHR + if(var2>=0) + { + return ASM_L_shr( L_var1, var2); + } + else + { + return ASM_L_shl( L_var1, -var2); + } +#else + Word32 L_var_out; + + if (var2 < 0) + { + L_var_out = L_shl (L_var1, (Word16)-var2); + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } + return (L_var_out); +#endif +} +#endif + +/* Short add, 1 */ +#if (ADD_IS_INLINE) +__inline Word32 add (Word32 var1, Word32 var2) +{ +#if ARMV5TE_ADD + Word32 result; + Word32 tmp; + asm ( + "ADD %[result], %[var1], %[var2] \n" + "MOV %[tmp], %[result], ASR #15 \n" + "TEQ %[tmp], %[result], ASR #31 \n" + "EORNE %[result], %[mask], %[result], ASR #31" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) + :"cc" + ); + return result; +#else + Word32 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate(L_sum); + + return (var_out); +#endif +} +#endif + +/* Short sub, 1 */ +#if (SUB_IS_INLINE) +__inline Word32 sub(Word32 var1, Word32 var2) +{ +#if ARMV5TE_SUB + Word32 result; + Word32 tmp; + asm ( + "SUB %[result], %[var1], %[var2] \n" + "MOV %[tmp], %[var1], ASR #15 \n" + "TEQ %[tmp], %[var1], ASR #31 \n" + "EORNE %[result], %[mask], %[result], ASR #31 \n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) + :"cc" + ); + return result; +#else + Word32 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate(L_diff); + + return (var_out); +#endif +} +#endif + +/* Short division, 18 */ +#if (DIV_S_IS_INLINE) +__inline Word32 div_s (Word32 var1, Word32 var2) +{ + Word32 var_out = 0; + Word32 iteration; + Word32 L_num; + Word32 L_denom; + + var_out = MAX_16; + if (var1!= var2)//var1!= var2 + { + var_out = 0; + L_num = (Word32) var1; + + L_denom = (Word32) var2; + + //return (L_num<<15)/var2; + + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) + { + L_num -= L_denom; + var_out++; + } + } + } + return (var_out); +} +#endif + +/* Short mult, 1 */ +#if (MULT_IS_INLINE) +__inline Word32 mult (Word32 var1, Word32 var2) +{ +#if ARMV5TE_MULT && ARMV6_SAT + Word32 result; + asm ( + "SMULBB %[result], %[var1], %[var2] \n" + "SSAT %[result], #16, %[result], ASR #15 \n" + :[result]"=r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#elif ARMV5TE_MULT + Word32 result, tmp; + asm ( + "SMULBB %[tmp], %[var1], %[var2] \n" + "MOV %[result], %[tmp], ASR #15\n" + "MOV %[tmp], %[result], ASR #15\n" + "TEQ %[tmp], %[result], ASR #31\n" + "EORNE %[result], %[mask], %[result], ASR #31 \n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) + :"cc" + ); + return result; +#else + Word32 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + var_out = saturate(L_product); + + return (var_out); +#endif +} +#endif + + +/* Short norm, 15 */ +#if (NORM_S_IS_INLINE) +__inline Word32 norm_s (Word32 var1) +{ +#if ARMV5TE_NORM_S + Word32 result; + Word32 tmp; + asm ( + "RSBS %[tmp], %[var1], #0 \n" + "CLZLT %[result], %[var1]\n" + "CLZGT %[result], %[tmp]\n" + "SUBNE %[result], %[result], #17\n" + "MOVEQ %[result], #0\n" + "CMP %[var1], #-1\n" + "MOVEQ %[result], #15\n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1) + :"cc" + ); + return result; +#else + Word32 var_out; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == -1) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = (Word16)~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + return (var_out); +#endif +} +#endif + +/* Long norm, 30 */ +#if (NORM_L_IS_INLINE) +__inline Word32 norm_l (Word32 L_var1) +{ +#if ARMV5TE_NORM_L + Word32 result; + asm volatile( + "CMP %[L_var1], #0\n" + "CLZNE %[result], %[L_var1]\n" + "SUBNE %[result], %[result], #1\n" + "MOVEQ %[result], #0\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1) + :"cc" + ); + return result; +#else + //Word16 var_out; + + //if (L_var1 == 0) + //{ + // var_out = 0; + //} + //else + //{ + // if (L_var1 == (Word32) 0xffffffffL) + // { + // var_out = 31; + // } + // else + // { + // if (L_var1 < 0) + // { + // L_var1 = ~L_var1; + // } + // for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + // { + // L_var1 <<= 1; + // } + // } + //} + //return (var_out); + Word16 a16; + Word16 r = 0 ; + + + if ( L_var1 < 0 ) { + L_var1 = ~L_var1; + } + + if (0 == (L_var1 & 0x7fff8000)) { + a16 = extract_l(L_var1); + r += 16; + + if (0 == (a16 & 0x7f80)) { + r += 8; + + if (0 == (a16 & 0x0078)) { + r += 4; + + if (0 == (a16 & 0x0006)) { + r += 2; + + if (0 == (a16 & 0x0001)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0004)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x0060)) { + r += 2; + + if (0 == (a16 & 0x0010)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0040)) { + r += 1; + } + } + } + } + else { + + if (0 == (a16 & 0x7800)) { + r += 4; + + if (0 == (a16 & 0x0600)) { + r += 2; + + if (0 == (a16 & 0x0100)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0400)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x6000)) { + r += 2; + + if (0 == (a16 & 0x1000)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x4000)) { + r += 1; + } + } + } + } + } + else { + a16 = extract_h(L_var1); + + if (0 == (a16 & 0x7f80)) { + r += 8; + + if (0 == (a16 & 0x0078)) { + r += 4 ; + + if (0 == (a16 & 0x0006)) { + r += 2; + + if (0 == (a16 & 0x0001)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0004)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x0060)) { + r += 2; + + if (0 == (a16 & 0x0010)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0040)) { + r += 1; + } + } + } + } + else { + + if (0 == (a16 & 0x7800)) { + r += 4; + + if (0 == (a16 & 0x0600)) { + r += 2; + + if (0 == (a16 & 0x0100)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0400)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x6000)) { + r += 2; + + if (0 == (a16 & 0x1000)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x4000)) { + return 1; + } + } + } + } + } + + return r ; +#endif +} +#endif + +/* Round, 1 */ +#if (ROUND_IS_INLINE) +__inline Word32 round16(Word32 L_var1) +{ +#if ARMV5TE_ROUND + Word32 result; + asm ( + "QADD %[result], %[L_var1], %[bias]\n" + "MOV %[result], %[result], ASR #16 \n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [bias]"r"(0x8000) + ); + return result; +#else + Word32 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + return (var_out); +#endif +} +#endif + +/* Mac, 1 */ +#if (L_MAC_IS_INLINE) +__inline Word32 L_mac (Word32 L_var3, Word32 var1, Word32 var2) +{ +#if ARMV5TE_L_MAC + Word32 result; + asm ( + "SMULBB %[result], %[var1], %[var2]\n" + "QDADD %[result], %[L_var3], %[result]\n" + :[result]"=&r"(result) + : [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_add (L_var3, L_product); + return (L_var_out); +#endif +} +#endif + +#if (L_ADD_IS_INLINE) +__inline Word32 L_add (Word32 L_var1, Word32 L_var2) +{ +#if ARMV5TE_L_ADD + Word32 result; + asm ( + "QADD %[result], %[L_var1], %[L_var2]\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + } + } + return (L_var_out); +#endif +} +#endif + + + +#if (MULT_R_IS_INLINE) +__inline Word32 mult_r (Word32 var1, Word32 var2) +{ + Word32 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32)var1 *(Word32)var2; /* product */ + L_product_arr += (Word32)0x00004000L; /* round */ + L_product_arr >>= 15; /* shift */ + + var_out = saturate(L_product_arr); + + return (var_out); +} +#endif + +#if (SHR_R_IS_INLINE) +__inline Word32 shr_r (Word32 var1, Word32 var2) +{ + Word32 var_out; + + if (var2 > 15) + { + var_out = 0; + } + else + { + var_out = shr(var1, var2); + + if (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } + + return (var_out); +} +#endif + +#if (MAC_R_IS_INLINE) +__inline Word32 mac_r (Word32 L_var3, Word32 var1, Word32 var2) +{ + Word32 var_out; + + L_var3 = L_mac (L_var3, var1, var2); + var_out = (Word16)((L_var3 + 0x8000L) >> 16); + + return (var_out); +} +#endif + +#if (MSU_R_IS_INLINE) +__inline Word32 msu_r (Word32 L_var3, Word32 var1, Word32 var2) +{ + Word32 var_out; + + L_var3 = L_msu (L_var3, var1, var2); + var_out = (Word16)((L_var3 + 0x8000L) >> 16); + + return (var_out); +} +#endif + +#if (L_SHR_R_IS_INLINE) +__inline Word32 L_shr_r (Word32 L_var1, Word32 var2) +{ + Word32 L_var_out; + + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr(L_var1, var2); + + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + + return (L_var_out); +} +#endif + +#if (EXTRACT_H_IS_INLINE) +__inline Word32 extract_h (Word32 L_var1) +{ + Word32 var_out; + + var_out = (L_var1 >> 16); + + return (var_out); +} +#endif + +#if (EXTRACT_L_IS_INLINE) +__inline Word32 extract_l(Word32 L_var1) +{ + return (Word16) L_var1; +} +#endif + +#endif diff --git a/aacenc/external/aacenc/src/basicop2.c b/aacenc/external/aacenc/src/basicop2.c new file mode 100644 index 0000000..d43bbd9 --- /dev/null +++ b/aacenc/external/aacenc/src/basicop2.c @@ -0,0 +1,1624 @@ +/* + ** 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: basicop2.c + + Content: Basic arithmetic operators. + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +/*___________________________________________________________________________ + | | + | Function Name : saturate | + | | + | Purpose : | + | | + | Limit the 32 bit input to the range of a 16 bit word. | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SATRUATE_IS_INLINE) +Word16 saturate(Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 > 0X00007fffL) + { + var_out = MAX_16; + } + else if (L_var1 < (Word32) 0xffff8000L) + { + var_out = MIN_16; + } + else + { + var_out = extract_l(L_var1); + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : add | + | | + | Purpose : | + | | + | Performs the addition (var1+var2) with overflow control and saturation;| + | the 16 bit result is set at +32767 when overflow occurs or at -32768 | + | when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!ADD_IS_INLINE) +Word16 add (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32)var1 + (Word32)var2; + var_out = saturate(L_sum); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : sub | + | | + | Purpose : | + | | + | Performs the subtraction (var1+var2) with overflow control and satu- | + | ration; the 16 bit result is set at +32767 when overflow occurs or at | + | -32768 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!SUB_IS_INLINE) +Word16 sub(Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate(L_diff); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : abs_s | + | | + | Purpose : | + | | + | Absolute value of var1; abs_s(-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word16 abs_s (Word16 var1) +//{ +// Word16 var_out; +// +// if (var1 == MIN_16) +// { +// var_out = MAX_16; +// } +// else +// { +// if (var1 < 0) +// { +// var_out = (Word16)-var1; +// } +// else +// { +// var_out = var1; +// } +// } +// +// return (var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : shl | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| + | the var2 LSB of the result. If var2 is negative, arithmetically shift | + | var1 right by -var2 with sign extension. Saturate the result in case of | + | underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SHL_IS_INLINE) +Word16 shl (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 result; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shr (var1, (Word16)-var2); + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + //Overflow = 1; + var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16); + } + else + { + var_out = extract_l(result); + } + } + + return (var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : shr | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift var1 left by | + | -var2 with sign extension. Saturate the result in case of underflows or | + | overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SHR_IS_INLINE) +Word16 shr (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shl (var1, (Word16)-var2); + } + else + { + if (var2 >= 15) + { + var_out = (Word16)((var1 < 0) ? -1 : 0); + } + else + { + if (var1 < 0) + { + var_out = (Word16)(~((~var1) >> var2)); + } + else + { + var_out = (Word16)(var1 >> var2); + } + } + } + + return (var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : mult | + | | + | Purpose : | + | | + | Performs the multiplication of var1 by var2 and gives a 16 bit result | + | which is scaled i.e.: | + | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | + | mult(-32768,-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MULT_IS_INLINE) +Word16 mult (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + + var_out = saturate(L_product); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_mult | + | | + | Purpose : | + | | + | L_mult is the 32 bit result of the multiplication of var1 times var2 | + | with one shift left i.e.: | + | L_mult(var1,var2) = L_shl((var1 times var2),1) and | + | L_mult(-32768,-32768) = 2147483647. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_MULT_IS_INLINE) +Word32 L_mult(Word16 var1, Word16 var2) +{ + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out <<= 1; + } + else + { + L_var_out = MAX_32; + } + + return (L_var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : negate | + | | + | Purpose : | + | | + | Negate var1 with saturation, saturate in the case where input is -32768:| + | negate(var1) = sub(0,var1). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word16 negate (Word16 var1) +//{ +// Word16 var_out; +// +// var_out = (Word16)((var1 == MIN_16) ? MAX_16 : -var1); +// +// return (var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : extract_h | + | | + | Purpose : | + | | + | Return the 16 MSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!EXTRACT_H_IS_INLINE) +Word16 extract_h (Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) (L_var1 >> 16); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : extract_l | + | | + | Purpose : | + | | + | Return the 16 LSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!EXTRACT_L_IS_INLINE) +Word16 extract_l(Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) L_var1; + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : round | + | | + | Purpose : | + | | + | Round the lower 16 bits of the 32 bit input number into the MS 16 bits | + | with saturation. Shift the resulting bits right by 16 and return the 16 | + | bit number: | + | round(L_var1) = extract_h(L_add(L_var1,32768)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!ROUND_IS_INLINE) +Word16 round16(Word32 L_var1) +{ + Word16 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + + return (var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : L_mac | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation, return a 32 bit result: | + | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_MSU_IS_INLINE) +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_add (L_var3, L_product); + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_msu | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation, return a 32 bit result: | + | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_MSU_IS_INLINE) +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_sub (L_var3, L_product); + + return (L_var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : L_add | + | | + | Purpose : | + | | + | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_ADD_IS_INLINE) +Word32 L_add (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + //Overflow = 1; + } + } + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_sub | + | | + | Purpose : | + | | + | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_SUB_IS_INLINE) +Word32 L_sub(Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + //Overflow = 1; + } + } + + return (L_var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : L_negate | + | | + | Purpose : | + | | + | Negate the 32 bit variable L_var1 with saturation; saturate in the case | + | where input is -2147483648 (0x8000 0000). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +//Word32 L_negate (Word32 L_var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : mult_r | + | | + | Purpose : | + | | + | Same as mult with rounding, i.e.: | + | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | + | mult_r(-32768,-32768) = 32767. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MULT_R_IS_INLINE) +Word16 mult_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32) var1 *(Word32) var2; /* product */ + L_product_arr += (Word32) 0x00004000L; /* round */ + L_product_arr &= (Word32) 0xffff8000L; + L_product_arr >>= 15; /* shift */ + + if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */ + { + L_product_arr |= (Word32) 0xffff0000L; + } + var_out = saturate(L_product_arr); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_shl | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | + | fill the var2 LSB of the result. If var2 is negative, arithmetically | + | shift L_var1 right by -var2 with sign extension. Saturate the result in | + | case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_SHL_IS_INLINE) +Word32 L_shl (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out = 0L; + + if (var2 <= 0) + { + L_var1 = L_shr(L_var1, (Word16)-var2); + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + return MAX_32; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + return MIN_32; + } + } + L_var1 <<= 1; + } + } + return (L_var1); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_shr | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift L_var1 left | + | by -var2 and zero fill the -var2 LSB of the result. Saturate the result | + | in case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_SHR_IS_INLINE) +Word32 L_shr (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 < 0) + { + L_var_out = L_shl (L_var1, (Word16)-var2); + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : shr_r | + | | + | Purpose : | + | | + | Same as shr(var1,var2) but with rounding. Saturate the result in case of| + | underflows or overflows : | + | - If var2 is greater than zero : | + | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) | + | is equal to zero | + | then | + | shr_r(var1,var2) = shr(var1,var2) | + | else | + | shr_r(var1,var2) = add(shr(var1,var2),1) | + | - If var2 is less than or equal to zero : | + | shr_r(var1,var2) = shr(var1,var2). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!SHR_R_IS_INLINE) +Word16 shr_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 > 15) + { + var_out = 0; + } + else + { + var_out = shr (var1, var2); + + if (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : mac_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation. Round the LS 16 bits of the result | + | into the MS 16 bits with saturation and shift the result right by 16. | + | Return a 16 bit result. | + | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MAC_R_IS_INLINE) +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_mac (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : msu_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation. Round the LS 16 bits of the res- | + | ult into the MS 16 bits with saturation and shift the result right by | + | 16. Return a 16 bit result. | + | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MSU_R_IS_INLINE) +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_msu (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_h | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The | + | 16 LS bits of the output are zeroed. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff 0000. | + |___________________________________________________________________________| +*/ +//Word32 L_deposit_h (Word16 var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (Word32) var1 << 16; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_l | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | + | 16 MS bits of the output are sign extended. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word32 L_deposit_l (Word16 var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (Word32) var1; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : L_shr_r | + | | + | Purpose : | + | | + | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in | + | case of underflows or overflows : | + | - If var2 is greater than zero : | + | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))| + | is equal to zero | + | then | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) | + | else | + | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) | + | - If var2 is less than or equal to zero : | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_SHR_R_IS_INLINE) +Word32 L_shr_r (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr (L_var1, var2); + + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_abs | + | | + | Purpose : | + | | + | Absolute value of L_var1; Saturate in case where the input is | + | -214783648 | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +//Word32 L_abs (Word32 L_var1) +//{ +// Word32 L_var_out; +// +// if (L_var1 == MIN_32) +// { +// L_var_out = MAX_32; +// } +// else +// { +// if (L_var1 < 0) +// { +// L_var_out = -L_var1; +// } +// else +// { +// L_var_out = L_var1; +// } +// } +// +// return (L_var_out); +//} + +/*___________________________________________________________________________ + | | + | Function Name : norm_s | + | | + | Purpose : | + | | + | Produces the number of left shift needed to normalize the 16 bit varia- | + | ble var1 for positive values on the interval with minimum of 16384 and | + | maximum of 32767, and for negative values on the interval with minimum | + | of -32768 and maximum of -16384; in order to normalize the result, the | + | following operation must be done : | + | norm_var1 = shl(var1,norm_s(var1)). | + | | + | Complexity weight : 15 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 000f. | + |___________________________________________________________________________| +*/ + +#if (!NORM_S_IS_INLINE) +Word16 norm_s (Word16 var1) +{ + Word16 var_out; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == -1) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = (Word16)~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : div_s | + | | + | Purpose : | + | | + | Produces a result which is the fractional integer division of var1 by | + | var2; var1 and var2 must be positive and var2 must be greater or equal | + | to var1; the result is positive (leading bit equal to 0) and truncated | + | to 16 bits. | + | If var1 = var2 then div(var1,var2) = 32767. | + | | + | Complexity weight : 18 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + | It's a Q15 value (point between b15 and b14). | + |___________________________________________________________________________| +*/ + +#if (!DIV_S_IS_INLINE) +Word16 div_s (Word16 var1, Word16 var2) +{ + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == var2) + { + var_out = MAX_16; + } + else + { + L_num = L_deposit_l (var1); + L_denom = L_deposit_l (var2); + + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) + { + L_num = L_sub(L_num, L_denom); + var_out = add (var_out, 1); + } + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : norm_l | + | | + | Purpose : | + | | + | Produces the number of left shifts needed to normalize the 32 bit varia-| + | ble L_var1 for positive values on the interval with minimum of | + | 1073741824 and maximum of 2147483647, and for negative values on the in-| + | terval with minimum of -2147483648 and maximum of -1073741824; in order | + | to normalize the result, the following operation must be done : | + | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | + | | + | Complexity weight : 30 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 001f. | + |___________________________________________________________________________| +*/ + +#if (!NORM_L_IS_INLINE) +Word16 norm_l (Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 == 0) + { + var_out = 0; + } + else + { + if (L_var1 == (Word32) 0xffffffffL) + { + var_out = 31; + } + else + { + if (L_var1 < 0) + { + L_var1 = ~L_var1; + } + for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + { + L_var1 <<= 1; + } + } + } + + return (var_out); +} +#endif + diff --git a/aacenc/external/aacenc/src/bit_cnt.c b/aacenc/external/aacenc/src/bit_cnt.c new file mode 100644 index 0000000..9fe511c --- /dev/null +++ b/aacenc/external/aacenc/src/bit_cnt.c @@ -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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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; + UWord16 codeWord, codeLength; + Word16 sign, signLength; + + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for(i=0; i= 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); +} diff --git a/aacenc/external/aacenc/src/bit_cnt.h b/aacenc/external/aacenc/src/bit_cnt.h new file mode 100644 index 0000000..266a219 --- /dev/null +++ b/aacenc/external/aacenc/src/bit_cnt.h @@ -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 diff --git a/aacenc/external/aacenc/src/bitbuffer.c b/aacenc/external/aacenc/src/bitbuffer.c new file mode 100644 index 0000000..15eebd0 --- /dev/null +++ b/aacenc/external/aacenc/src/bitbuffer.c @@ -0,0 +1,150 @@ +/* + ** 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: 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, + UWord32 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 &= ~(0xffffffff << noBitsToWrite); // Mask out everything except the lowest noBitsToWrite bits + 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; +} diff --git a/aacenc/external/aacenc/src/bitbuffer.h b/aacenc/external/aacenc/src/bitbuffer.h new file mode 100644 index 0000000..7c79f07 --- /dev/null +++ b/aacenc/external/aacenc/src/bitbuffer.h @@ -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, + UWord32 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 */ diff --git a/aacenc/external/aacenc/src/bitenc.c b/aacenc/external/aacenc/src/bitenc.c new file mode 100644 index 0000000..9c81204 --- /dev/null +++ b/aacenc/external/aacenc/src/bitenc.c @@ -0,0 +1,693 @@ +/* + ** 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" + +#define UNUSED(x) (void)(x) + +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; inoOfSections; i++) { + psectioninfo = &(sectionData->sectionInfo[i]); + /* + huffencode spectral data for this section + */ + for(sfb=psectioninfo->sfbStart; + sfbsfbStart+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;inoOfSections;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;inoOfSections;i++){ + psectioninfo = &(sectionData->sectionInfo[i]); + if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){ + for (j=psectioninfo->sfbStart; + jsfbStart+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 3 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + for(k=0; 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; kfirstScf], 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;iqcElement.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); +} diff --git a/aacenc/external/aacenc/src/bitenc.h b/aacenc/external/aacenc/src/bitenc.h new file mode 100644 index 0000000..6a58aeb --- /dev/null +++ b/aacenc/external/aacenc/src/bitenc.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/block_switch.c b/aacenc/external/aacenc/src/block_switch.c new file mode 100644 index 0000000..11bc7e7 --- /dev/null +++ b/aacenc/external/aacenc/src/block_switch.c @@ -0,0 +1,404 @@ +/* + ** 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 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 +*/ +const 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; igroupLen[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; igroupLen[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; wwindowNrg[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; waccWindowNrg); + 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, tidx; + 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> 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 + +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; igroupLen[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; igroupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + else { + + if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; + for (i=0; igroupLen[i] = blockSwitchingControlLeft->groupLen[i]; + } + } + else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; + for (i=0; igroupLen[i] = blockSwitchingControlRight->groupLen[i]; + } + } + } + } /*endif Mono or Stereo */ + + return(TRUE); +} diff --git a/aacenc/external/aacenc/src/block_switch.h b/aacenc/external/aacenc/src/block_switch.h new file mode 100644 index 0000000..a4d3e8f --- /dev/null +++ b/aacenc/external/aacenc/src/block_switch.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/channel_map.c b/aacenc/external/aacenc/src/channel_map.c new file mode 100644 index 0000000..f6552ed --- /dev/null +++ b/aacenc/external/aacenc/src/channel_map.c @@ -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; +} diff --git a/aacenc/external/aacenc/src/channel_map.h b/aacenc/external/aacenc/src/channel_map.h new file mode 100644 index 0000000..c361feb --- /dev/null +++ b/aacenc/external/aacenc/src/channel_map.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/cmnMemory.c b/aacenc/external/aacenc/src/cmnMemory.c new file mode 100644 index 0000000..5bb6cc4 --- /dev/null +++ b/aacenc/external/aacenc/src/cmnMemory.c @@ -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: cmnMemory.c + + Content: sample code for memory operator implementation + +*******************************************************************************/ +#include "cmnMemory.h" + +#include +#include + +//VO_MEM_OPERATOR g_memOP; + +#define UNUSED(x) (void)(x) + +VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) +{ + UNUSED(uID); + + if (!pMemInfo) + return VO_ERR_INVALID_ARG; + + pMemInfo->VBuffer = malloc (pMemInfo->Size); + return 0; +} + +VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) +{ + UNUSED(uID); + + free (pMem); + return 0; +} + +VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) +{ + UNUSED(uID); + + memset (pBuff, uValue, uSize); + return 0; +} + +VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + UNUSED(uID); + + memcpy (pDest, pSource, uSize); + return 0; +} + +VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) +{ + UNUSED(uID); + UNUSED(pBuffer); + UNUSED(uSize); + + return 0; +} + +VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) +{ + UNUSED(uID); + + return memcmp(pBuffer1, pBuffer2, uSize); +} + +VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + UNUSED(uID); + + memmove (pDest, pSource, uSize); + return 0; +} + diff --git a/aacenc/external/aacenc/src/cmnMemory.h b/aacenc/external/aacenc/src/cmnMemory.h new file mode 100644 index 0000000..e175103 --- /dev/null +++ b/aacenc/external/aacenc/src/cmnMemory.h @@ -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: cmnMemory.h + + Content: memory operator implementation header file + +*******************************************************************************/ + +#ifndef __cmnMemory_H__ +#define __cmnMemory_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voMem.h" + +//extern VO_MEM_OPERATOR g_memOP; + +/** + * Allocate memory + * \param uID [in] module ID + * \param uSize [in] size of memory + * \return value is the allocated memory address. NULL is failed. + */ +VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo); + +/** + * Free up memory + * \param uID [in] module ID + * \param pMem [in] address of memory + * \return value 0, if succeeded. + */ +VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pBuffer); + +/** + * memory set function + * \param uID [in] module ID + * \param pBuff [in/out] address of memory + * \param uValue [in] the value to be set + * \param uSize [in] the size to be set + * \return value 0, if succeeded. + */ +VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize); + +/** + * memory copy function + * \param uID [in] module ID + * \param pDest [in/out] address of destination memory + * \param pSource [in] address of source memory + * \param uSize [in] the size to be copied + * \return value 0, if succeeded. + */ +VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + +/** + * memory check function + * \param uID [in] module ID + * \param pBuff [in] address of buffer to be checked + * \param uSize [in] the size to be checked + * \return value 0, if succeeded. + */ +VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize); + +/** + * memory compare function + * \param uID [in] module ID + * \param pBuffer1 [in] address of buffer 1 to be compared + * \param pBuffer2 [in] address of buffer 2 to be compared + * \param uSize [in] the size to be compared + * \return value: same as standard C run-time memcmp() function. + */ +VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize); + +/** + * memory move function + * \param uID [in] module ID + * \param pDest [in/out] address of destination memory + * \param pSource [in] address of source memory + * \param uSize [in] the size to be moved + * \return value 0, if succeeded. + */ +VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __cmnMemory_H__ + + diff --git a/aacenc/external/aacenc/src/config.h b/aacenc/external/aacenc/src/config.h new file mode 100644 index 0000000..b0b4c26 --- /dev/null +++ b/aacenc/external/aacenc/src/config.h @@ -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 diff --git a/aacenc/external/aacenc/src/dyn_bits.c b/aacenc/external/aacenc/src/dyn_bits.c new file mode 100644 index 0000000..4d763d0 --- /dev/null +++ b/aacenc/external/aacenc/src/dyn_bits.c @@ -0,0 +1,544 @@ +/* + ** 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 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; icodeBook != 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].sfbCntnoOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* + loop trough groups + */ + for (grpNdx=0; grpNdxsfbCnt; 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; imaxSfbPerGroup; 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; inoOfSections; 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; inoOfSections; 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); +} + diff --git a/aacenc/external/aacenc/src/dyn_bits.h b/aacenc/external/aacenc/src/dyn_bits.h new file mode 100644 index 0000000..d3a8a67 --- /dev/null +++ b/aacenc/external/aacenc/src/dyn_bits.h @@ -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 diff --git a/aacenc/external/aacenc/src/grp_data.c b/aacenc/external/aacenc/src/grp_data.c new file mode 100644 index 0000000..7861e1c --- /dev/null +++ b/aacenc/external/aacenc/src/grp_data.c @@ -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=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; jsfbShort[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; jsfbShort[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; jsfbShort[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; jsfbShort[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;imaxSfbPerGroup = 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; jsfbMinSnr; + for(j=0;jgroupingMask = mask; + + if (windowSequence != SHORT_WINDOW) { + psyOutCh->sfbEnSumLR = sfbEnergySumLR.sfbLong; + psyOutCh->sfbEnSumMS = sfbEnergySumMS.sfbLong; + } + else { + Word32 i; + Word32 accuSumMS=0; + Word32 accuSumLR=0; + const Word32 *pSumMS = sfbEnergySumMS.sfbShort; + const 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; + } +} diff --git a/aacenc/external/aacenc/src/interface.h b/aacenc/external/aacenc/src/interface.h new file mode 100644 index 0000000..a42e6a9 --- /dev/null +++ b/aacenc/external/aacenc/src/interface.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/line_pe.c b/aacenc/external/aacenc/src/line_pe.c new file mode 100644 index 0000000..480dc28 --- /dev/null +++ b/aacenc/external/aacenc/src/line_pe.c @@ -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; chpeChannelData[ch]; + for(sfbGrp=0;sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; 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; chpeChannelData[ch]; + const Word32 *sfbEnergy = psyOutChan->sfbEnergy; + const Word32 *sfbThreshold = psyOutChan->sfbThreshold; + + pe = 0; + constPart = 0; + nActiveLines = 0; + + for(sfbGrp=0; sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; 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); + } +} diff --git a/aacenc/external/aacenc/src/line_pe.h b/aacenc/external/aacenc/src/line_pe.h new file mode 100644 index 0000000..116d5a8 --- /dev/null +++ b/aacenc/external/aacenc/src/line_pe.h @@ -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 diff --git a/aacenc/external/aacenc/src/memalign.c b/aacenc/external/aacenc/src/memalign.c new file mode 100644 index 0000000..bb266dc --- /dev/null +++ b/aacenc/external/aacenc/src/memalign.c @@ -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: mem_align.c + + Content: Memory alloc alignments functions + +*******************************************************************************/ + + +#include "memalign.h" +#ifdef _MSC_VER +#include +#else +#include +#endif + +/***************************************************************************** +* +* 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 *) ((intptr_t) (tmp + alignment - 1) & + (~((intptr_t) (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); +} + + + diff --git a/aacenc/external/aacenc/src/memalign.h b/aacenc/external/aacenc/src/memalign.h new file mode 100644 index 0000000..30bbf45 --- /dev/null +++ b/aacenc/external/aacenc/src/memalign.h @@ -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__ */ + + + diff --git a/aacenc/external/aacenc/src/ms_stereo.c b/aacenc/external/aacenc/src/ms_stereo.c new file mode 100644 index 0000000..1e4b227 --- /dev/null +++ b/aacenc/external/aacenc/src/ms_stereo.c @@ -0,0 +1,138 @@ +/* + ** 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 sfb,sfboffs, j; + Word32 msMaskTrueSomewhere = 0; + Word32 msMaskFalseSomewhere = 0; + + for (sfb=0; sfb> 8) + 1); + + temp = pnms - pnlr; + if( temp > 0 ){ + + msMask[idx] = 1; + msMaskTrueSomewhere = 1; + + for (j=sfbOffset[idx]; 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; + } + } + +} diff --git a/aacenc/external/aacenc/src/ms_stereo.h b/aacenc/external/aacenc/src/ms_stereo.h new file mode 100644 index 0000000..3c03dea --- /dev/null +++ b/aacenc/external/aacenc/src/ms_stereo.h @@ -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 diff --git a/aacenc/external/aacenc/src/oper_32b.c b/aacenc/external/aacenc/src/oper_32b.c new file mode 100644 index 0000000..4fd16a1 --- /dev/null +++ b/aacenc/external/aacenc/src/oper_32b.c @@ -0,0 +1,363 @@ +/* + ** 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" + +#define UNUSED(x) (void)(x) + +/***************************************************************************** + * * + * 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; + UNUSED(accuracy); + + 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) +{ + UWord32 iPart; + UWord32 fPart; + Word32 res; + Word32 tmp; + + tmp = -x; + iPart = tmp / y; + fPart = tmp - iPart*y; + iPart = min(iPart,INT_BITS-1); + + res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart; + + return(res); +} diff --git a/aacenc/external/aacenc/src/oper_32b.h b/aacenc/external/aacenc/src/oper_32b.h new file mode 100644 index 0000000..6e5844f --- /dev/null +++ b/aacenc/external/aacenc/src/oper_32b.h @@ -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<> 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 diff --git a/aacenc/external/aacenc/src/pre_echo_control.c b/aacenc/external/aacenc/src/pre_echo_control.c new file mode 100644 index 0000000..1406e11 --- /dev/null +++ b/aacenc/external/aacenc/src/pre_echo_control.c @@ -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 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; + } + + } + } +} + diff --git a/aacenc/external/aacenc/src/pre_echo_control.h b/aacenc/external/aacenc/src/pre_echo_control.h new file mode 100644 index 0000000..e719ba7 --- /dev/null +++ b/aacenc/external/aacenc/src/pre_echo_control.h @@ -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 + diff --git a/aacenc/external/aacenc/src/psy_configuration.c b/aacenc/external/aacenc/src/psy_configuration.c new file mode 100644 index 0000000..dd40f9b --- /dev/null +++ b/aacenc/external/aacenc/src/psy_configuration.c @@ -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, + const Word16 *pbOffset, + Word16 *pbBarcVal, + Word32 *pbThresholdQuiet) { + Word16 i; + Word16 barcThrQuiet; + + for(i=0; i0) + 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 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, + const Word16 *pbOffset, + Word16 numLines, + Word32 samplingFrequency, + Word16 *pbBval) +{ + Word16 i; + Word16 pbBval0, pbBval1; + + pbBval0 = 0; + + for(i=0; i> 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 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); +} + diff --git a/aacenc/external/aacenc/src/psy_configuration.h b/aacenc/external/aacenc/src/psy_configuration.h new file mode 100644 index 0000000..f6981fa --- /dev/null +++ b/aacenc/external/aacenc/src/psy_configuration.h @@ -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 */ + const 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 */ + const 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 */ + + + diff --git a/aacenc/external/aacenc/src/psy_const.h b/aacenc/external/aacenc/src/psy_const.h new file mode 100644 index 0000000..19fb9b2 --- /dev/null +++ b/aacenc/external/aacenc/src/psy_const.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/psy_data.h b/aacenc/external/aacenc/src/psy_data.h new file mode 100644 index 0000000..3ea6a84 --- /dev/null +++ b/aacenc/external/aacenc/src/psy_data.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/psy_main.c b/aacenc/external/aacenc/src/psy_main.c new file mode 100644 index 0000000..6f0679c --- /dev/null +++ b/aacenc/external/aacenc/src/psy_main.c @@ -0,0 +1,815 @@ +/* + ** 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" + +#define UNUSED(x) (void)(x) + +/* 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; ipsyData[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; nchpsyData[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) +{ + UNUSED(hPsyOut); + UNUSED(pMemOP); + + 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; chChannelIndex[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 0) { + Word32 *Spectrum = psyData[ch].mdctSpectrum; + for(line=0; line> scaleDiff; + Spectrum++; + } + } + psyData[ch].mdctScale = maxScale; + } + + for (ch=0; chsfbCnt-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; chsfbCnt, + 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;chsfbCnt, + 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; imdctSpectrum, + 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; isfbEnergySum.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; + const Word32 *data1; + + for(w = 0; w < TRANS_FAC; w++) { + Word32 i, tdata; + + /* low pass */ + data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine; + for(i=hPsyConfShort->lowpassLine; imdctSpectrum+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; wsfbOffset, + 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; +} diff --git a/aacenc/external/aacenc/src/psy_main.h b/aacenc/external/aacenc/src/psy_main.h new file mode 100644 index 0000000..2ccac60 --- /dev/null +++ b/aacenc/external/aacenc/src/psy_main.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/qc_data.h b/aacenc/external/aacenc/src/qc_data.h new file mode 100644 index 0000000..109922d --- /dev/null +++ b/aacenc/external/aacenc/src/qc_data.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/qc_main.c b/aacenc/external/aacenc/src/qc_main.c new file mode 100644 index 0000000..e5d78aa --- /dev/null +++ b/aacenc/external/aacenc/src/qc_main.c @@ -0,0 +1,578 @@ +/* + ** 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" + +#define UNUSED(x) (void)(x) + +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; iqcChannel[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; iqcChannel[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) +{ + UNUSED(hQC); + UNUSED(pMemOP); +} + +/********************************************************************************* +* +* 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;sfbOffsbitResTot = 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; +} diff --git a/aacenc/external/aacenc/src/qc_main.h b/aacenc/external/aacenc/src/qc_main.h new file mode 100644 index 0000000..8f83973 --- /dev/null +++ b/aacenc/external/aacenc/src/qc_main.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/quantize.c b/aacenc/external/aacenc/src/quantize.c new file mode 100644 index 0000000..0d0f550 --- /dev/null +++ b/aacenc/external/aacenc/src/quantize.c @@ -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<> (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; + const Word16 *pquat; + /* gain&3 */ + + pquat = quantBorders[m]; + + g += 16; + + if(g >= 0) + { + for (line=0; line> 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 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> (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> 2) + 4; + Word32 g2 = (g << 1) + 1; + const 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> 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> 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; + + sfbw = sfbw1 = 0; + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; 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> 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) +{ + Word16 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;jsfbCnt;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 scfAct)) { + sfb = sfb + 1; + } + stopSfb = sfb; + + possibleRegionFound = 0; + + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb=startSfb; sfbmdctSpectrum + + 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 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; isfbCnt; 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;isfbCnt;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; isfbCnt; 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; isfbCnt; 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; isfbCnt; i++) { + + if (scf[i] == MIN_16) { + scf[i] = lastSf; + /* set band explicitely to zero */ + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[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; isfbCnt; i++) { + scf[i] = 0; + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[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=0; i--) { + pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i], + L_mpy_ls(pbSpreadedEnergy[i+1], maskLowFactor[i])); + } +} diff --git a/aacenc/external/aacenc/src/spreading.h b/aacenc/external/aacenc/src/spreading.h new file mode 100644 index 0000000..0c96fc7 --- /dev/null +++ b/aacenc/external/aacenc/src/spreading.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/stat_bits.c b/aacenc/external/aacenc/src/stat_bits.c new file mode 100644 index 0000000..c2bd8bd --- /dev/null +++ b/aacenc/external/aacenc/src/stat_bits.c @@ -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; sfbOfftnsActive[i]!=0) { + tnsPresent = 1; + } + } + + if (tnsPresent) { + /* there is data to be written*/ + /*count += 1; */ + for (i=0; itnsActive[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; korder[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; korder[i]; k++) { + + if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) { + coefBits = 3; + break; + } + } + } + for (k=0; korder[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; +} + diff --git a/aacenc/external/aacenc/src/stat_bits.h b/aacenc/external/aacenc/src/stat_bits.h new file mode 100644 index 0000000..9cddc1d --- /dev/null +++ b/aacenc/external/aacenc/src/stat_bits.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/tns.c b/aacenc/external/aacenc/src/tns.c new file mode 100644 index 0000000..0ee4b01 --- /dev/null +++ b/aacenc/external/aacenc/src/tns.c @@ -0,0 +1,908 @@ +/* + ** 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 UNUSED(x) (void)(x) + +#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 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 __unused;*/ + 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 __unused;*/ + 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; itnsActive[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: 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=lpcStartLine; i--){ + pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1; + } + /* filter up */ + for (i=(lpcStartLine + 1); i> 1; + } + + /* weight and normalize */ + for (i=lpcStartLine; i= 0) + { + for (i=lpcStartLine; i> maxShift; + } + } + else + { + maxShift = -maxShift; + for (i=lpcStartLine; i> 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> scf)); + } + corr[i] = accu; + } +} +#endif + +/***************************************************************************** +* +* function name: AutoToParcor +* description: conversion autocorrelation to reflection coefficients +* returns: prediction gain +* input: input values, no. of output values (=order), +* ptr. to workbuffer (required size: 2*order) +* output: 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 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> 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> 2); + } + } +} diff --git a/aacenc/external/aacenc/src/tns.h b/aacenc/external/aacenc/src/tns.h new file mode 100644 index 0000000..40cfaee --- /dev/null +++ b/aacenc/external/aacenc/src/tns.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/tns_func.h b/aacenc/external/aacenc/src/tns_func.h new file mode 100644 index 0000000..02df24d --- /dev/null +++ b/aacenc/external/aacenc/src/tns_func.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/tns_param.h b/aacenc/external/aacenc/src/tns_param.h new file mode 100644 index 0000000..0aa33c3 --- /dev/null +++ b/aacenc/external/aacenc/src/tns_param.h @@ -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 */ diff --git a/aacenc/external/aacenc/src/transform.c b/aacenc/external/aacenc/src/transform.c new file mode 100644 index 0000000..0080810 --- /dev/null +++ b/aacenc/external/aacenc/src/transform.c @@ -0,0 +1,677 @@ +/* + ** 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); + } +} +#else +void Radix4First(int *buf, int num); +void Radix8First(int *buf, int num); +void Radix4FFT(int *buf, int num, int bgn, int *twidTab); +void PreMDCT(int *buf0, int num, const int *csptr); +void PostMDCT(int *buf0, int num, const int *csptr); +#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> 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> 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> 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> 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> 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> 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> 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; + } +} + diff --git a/aacenc/external/aacenc/src/transform.h b/aacenc/external/aacenc/src/transform.h new file mode 100644 index 0000000..311cef5 --- /dev/null +++ b/aacenc/external/aacenc/src/transform.h @@ -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 diff --git a/aacenc/external/aacenc/src/typedef.h b/aacenc/external/aacenc/src/typedef.h new file mode 100644 index 0000000..b1f8225 --- /dev/null +++ b/aacenc/external/aacenc/src/typedef.h @@ -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 diff --git a/aacenc/external/aacenc/src/typedefs.h b/aacenc/external/aacenc/src/typedefs.h new file mode 100644 index 0000000..29ff1e9 --- /dev/null +++ b/aacenc/external/aacenc/src/typedefs.h @@ -0,0 +1,187 @@ +/* + ** 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 + +#define __inline static __inline + +#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 int Word32; +typedef unsigned int UWord32; + + + +#ifndef _MSC_VER +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 +#if ARMV6_INASM + #undef ARMV5TE_ADD + #define ARMV5TE_ADD 0 + #undef ARMV5TE_SUB + #define ARMV5TE_SUB 0 + #define ARMV6_SAT 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 TnsEncode ADD_PREFIX(TnsEncode) +#define GetSRIndex ADD_PREFIX(GetSRIndex) +#define WriteBitstream ADD_PREFIX(WriteBitstream) + +#define mem_malloc ADD_PREFIX(mem_malloc) +#define mem_free ADD_PREFIX(mem_free) + +#endif diff --git a/encode.go b/encode.go new file mode 100644 index 0000000..78bac4a --- /dev/null +++ b/encode.go @@ -0,0 +1,116 @@ +// Package aac provides AAC codec encoder based on [VisualOn AAC encoder library](https://github.com/mstorsjo/vo-aacenc) library. +package aac + +import "C" + +import ( + "io" + "unsafe" + + "github.com/gen2brain/aac-go/aacenc" +) + +// Options represent encoding options. +type Options struct { + // Audio file sample rate + SampleRate int + // Encoder bit rate in bits/sec + BitRate int + // Number of channels on input (1,2) + NumChannels int +} + +// Encoder type. +type Encoder struct { + w io.Writer + + insize int + inbuf []byte + outbuf []byte +} + +// NewEncoder returns new AAC encoder. +func NewEncoder(w io.Writer, opts *Options) (e *Encoder, err error) { + e = &Encoder{} + e.w = w + + if opts.BitRate == 0 { + opts.BitRate = 64000 + } + + ret := aacenc.Init(aacenc.VoAudioCodingAac) + err = aacenc.ErrorFromResult(ret) + if err != nil { + return + } + + var params aacenc.AacencParam + params.SampleRate = int32(opts.SampleRate) + params.BitRate = int32(opts.BitRate) + params.NChannels = int16(opts.NumChannels) + params.AdtsUsed = 1 + + ret = aacenc.SetParam(aacenc.VoPidAacEncparam, unsafe.Pointer(¶ms)) + err = aacenc.ErrorFromResult(ret) + if err != nil { + return + } + + e.insize = int(opts.NumChannels) * 2 * 1024 + + e.inbuf = make([]byte, e.insize) + e.outbuf = make([]byte, 20480) + + return +} + +// Encode encodes data from reader. +func (e *Encoder) Encode(r io.Reader) (err error) { + for { + n, err := r.Read(e.inbuf) + if err != nil { + if err != io.EOF { + return err + } + break + } + + if n < e.insize { + break + } + + var outinfo aacenc.VoAudioOutputinfo + var input, output aacenc.VoCodecBuffer + + input.Buffer = C.CBytes(e.inbuf) + input.Length = uint64(n) + + ret := aacenc.SetInputData(&input) + err = aacenc.ErrorFromResult(ret) + if err != nil { + return err + } + + output.Buffer = C.CBytes(e.outbuf) + output.Length = uint64(len(e.outbuf)) + + ret = aacenc.GetOutputData(&output, &outinfo) + err = aacenc.ErrorFromResult(ret) + if err != nil { + return err + } + + _, err = e.w.Write(C.GoBytes(output.Buffer, C.int(output.Length))) + if err != nil { + return err + } + } + + return nil +} + +// Close closes encoder. +func (e *Encoder) Close() error { + ret := aacenc.Uninit() + return aacenc.ErrorFromResult(ret) +} diff --git a/encode_test.go b/encode_test.go new file mode 100644 index 0000000..b0ba769 --- /dev/null +++ b/encode_test.go @@ -0,0 +1,50 @@ +package aac + +import ( + "bytes" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/youpy/go-wav" +) + +func TestEncode(t *testing.T) { + file, err := os.Open(filepath.Join("testdata", "test.wav")) + if err != nil { + t.Fatal(err) + } + + wr := wav.NewReader(file) + f, err := wr.Format() + if err != nil { + t.Fatal(err) + } + + buf := bytes.NewBuffer(make([]byte, 0)) + + opts := &Options{} + opts.SampleRate = int(f.SampleRate) + opts.NumChannels = int(f.NumChannels) + + enc, err := NewEncoder(buf, opts) + if err != nil { + t.Fatal(err) + } + + err = enc.Encode(wr) + if err != nil { + t.Error(err) + } + + err = enc.Close() + if err != nil { + t.Error(err) + } + + err = ioutil.WriteFile(filepath.Join(os.TempDir(), "test.aac"), buf.Bytes(), 0644) + if err != nil { + t.Error(err) + } +} diff --git a/examples/basic/basic.go b/examples/basic/basic.go new file mode 100644 index 0000000..28eca98 --- /dev/null +++ b/examples/basic/basic.go @@ -0,0 +1,49 @@ +package main + +import ( + "bytes" + "io/ioutil" + "os" + + "github.com/gen2brain/aac-go" + "github.com/youpy/go-wav" +) + +func main() { + file, err := os.Open("test.wav") + if err != nil { + panic(err) + } + + wreader := wav.NewReader(file) + f, err := wreader.Format() + if err != nil { + panic(err) + } + + buf := bytes.NewBuffer(make([]byte, 0)) + + opts := &aac.Options{} + opts.SampleRate = int(f.SampleRate) + opts.NumChannels = int(f.NumChannels) + + enc, err := aac.NewEncoder(buf, opts) + if err != nil { + panic(err) + } + + err = enc.Encode(wreader) + if err != nil { + panic(err) + } + + err = enc.Close() + if err != nil { + panic(err) + } + + err = ioutil.WriteFile("test.aac", buf.Bytes(), 0644) + if err != nil { + panic(err) + } +} diff --git a/testdata/test.wav b/testdata/test.wav new file mode 100644 index 0000000..cc6c9bd Binary files /dev/null and b/testdata/test.wav differ