Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first commit

  • Loading branch information...
commit 3218842a8c8ddddd746dd862d9dbcb18846a93a6 0 parents
@teknoraver authored
Showing with 39,167 additions and 0 deletions.
  1. +1 −0  CHANGELOG
  2. +7 −0 COPYRIGHT
  3. +43 −0 Makefile
  4. +40 −0 aacplusenc.1
  5. +762 −0 aacplusenc.c
  6. +60 −0 adts.h
  7. +54 −0 au_channel.h
  8. +79 −0 configure
  9. +194 −0 debian/changelog
  10. +1 −0  debian/compat
  11. +14 −0 debian/control
  12. +30 −0 debian/rules
  13. +45 −0 libaacenc/Makefile
  14. +44 −0 libaacenc/aac_ram.c
  15. +26 −0 libaacenc/aac_ram.h
  16. +1,903 −0 libaacenc/aac_rom.c
  17. +104 −0 libaacenc/aac_rom.h
  18. +476 −0 libaacenc/aacenc.c
  19. +83 −0 libaacenc/aacenc.h
  20. +1,604 −0 libaacenc/adj_thr.c
  21. +36 −0 libaacenc/adj_thr.h
  22. +42 −0 libaacenc/adj_thr_data.h
  23. +101 −0 libaacenc/band_nrg.c
  24. +24 −0 libaacenc/band_nrg.h
  25. +1,485 −0 libaacenc/bit_cnt.c
  26. +84 −0 libaacenc/bit_cnt.h
  27. +958 −0 libaacenc/bitenc.c
  28. +30 −0 libaacenc/bitenc.h
  29. +468 −0 libaacenc/block_switch.c
  30. +40 −0 libaacenc/block_switch.h
  31. +163 −0 libaacenc/channel_map.c
  32. +20 −0 libaacenc/channel_map.h
  33. +38 −0 libaacenc/counters.h
  34. +798 −0 libaacenc/dyn_bits.c
  35. +61 −0 libaacenc/dyn_bits.h
  36. +291 −0 libaacenc/grp_data.c
  37. +24 −0 libaacenc/grp_data.h
  38. +119 −0 libaacenc/interface.c
  39. +77 −0 libaacenc/interface.h
  40. +163 −0 libaacenc/line_pe.c
  41. +41 −0 libaacenc/line_pe.h
  42. +11 −0 libaacenc/minmax.h
  43. +148 −0 libaacenc/ms_stereo.c
  44. +26 −0 libaacenc/ms_stereo.h
  45. +74 −0 libaacenc/pre_echo_control.c
  46. +19 −0 libaacenc/pre_echo_control.h
  47. +647 −0 libaacenc/psy_configuration.c
  48. +81 −0 libaacenc/psy_configuration.h
  49. +66 −0 libaacenc/psy_const.h
  50. +44 −0 libaacenc/psy_data.h
  51. +975 −0 libaacenc/psy_main.c
  52. +49 −0 libaacenc/psy_main.h
  53. +111 −0 libaacenc/qc_data.h
  54. +798 −0 libaacenc/qc_main.c
  55. +41 −0 libaacenc/qc_main.h
  56. +218 −0 libaacenc/quantize.c
  57. +26 −0 libaacenc/quantize.h
  58. +1,330 −0 libaacenc/sf_estim.c
  59. +24 −0 libaacenc/sf_estim.h
  60. +49 −0 libaacenc/spreading.c
  61. +12 −0 libaacenc/spreading.h
  62. +291 −0 libaacenc/stat_bits.c
  63. +16 −0 libaacenc/stat_bits.h
  64. +422 −0 libaacenc/stprepro.c
  65. +66 −0 libaacenc/stprepro.h
  66. +1,257 −0 libaacenc/tns.c
  67. +90 −0 libaacenc/tns.h
  68. +51 −0 libaacenc/tns_func.h
  69. +118 −0 libaacenc/tns_param.c
  70. +29 −0 libaacenc/tns_param.h
  71. +475 −0 libaacenc/transform.c
  72. +12 −0 libaacenc/transform.h
  73. +70 −0 libbitbuf/FFR_bitbuffer.h
  74. +20 −0 libbitbuf/Makefile
  75. +363 −0 libbitbuf/bitbuffer.c
  76. +28 −0 libfr/FloatFR.h
  77. +20 −0 libfr/Makefile
  78. +1,400 −0 libfr/cfftn.c
  79. +26 −0 libfr/cfftn.h
  80. +38 −0 libfr/counters.h
  81. +70 −0 libfr/transcendent.c
  82. +20 −0 libresamp/Makefile
  83. +212 −0 libresamp/iir32resample.c
  84. +19 −0 libresamp/iir32resample.h
  85. +327 −0 libresamp/resampler.c
  86. +54 −0 libresamp/resampler.h
  87. +37 −0 libsbrenc/Makefile
  88. +1,290 −0 libsbrenc/bit_sbr.c
  89. +39 −0 libsbrenc/bit_sbr.h
  90. +26 −0 libsbrenc/cmondata.h
  91. +769 −0 libsbrenc/code_env.c
  92. +72 −0 libsbrenc/code_env.h
  93. +200 −0 libsbrenc/env_bit.c
  94. +52 −0 libsbrenc/env_bit.h
  95. +1,785 −0 libsbrenc/env_est.c
  96. +69 −0 libsbrenc/env_est.h
  97. +1,775 −0 libsbrenc/fram_gen.c
  98. +124 −0 libsbrenc/fram_gen.h
  99. +849 −0 libsbrenc/freq_sca.c
  100. +43 −0 libsbrenc/freq_sca.h
  101. +428 −0 libsbrenc/hybrid.c
  102. +56 −0 libsbrenc/hybrid.h
  103. +598 −0 libsbrenc/invf_est.c
  104. +96 −0 libsbrenc/invf_est.h
  105. +1,390 −0 libsbrenc/mh_det.c
  106. +80 −0 libsbrenc/mh_det.h
  107. +614 −0 libsbrenc/nf_est.c
  108. +73 −0 libsbrenc/nf_est.h
  109. +526 −0 libsbrenc/ps_bitenc.c
  110. +26 −0 libsbrenc/ps_bitenc.h
  111. +707 −0 libsbrenc/ps_enc.c
  112. +104 −0 libsbrenc/ps_enc.h
  113. +1,282 −0 libsbrenc/qmf_enc.c
  114. +60 −0 libsbrenc/qmf_enc.h
  115. +173 −0 libsbrenc/sbr.h
  116. +185 −0 libsbrenc/sbr_def.h
  117. +1,103 −0 libsbrenc/sbr_main.c
  118. +129 −0 libsbrenc/sbr_main.h
  119. +174 −0 libsbrenc/sbr_misc.c
  120. +15 −0 libsbrenc/sbr_misc.h
  121. +159 −0 libsbrenc/sbr_ram.c
  122. +31 −0 libsbrenc/sbr_ram.h
  123. +1,458 −0 libsbrenc/sbr_rom.c
  124. +56 −0 libsbrenc/sbr_rom.h
  125. +868 −0 libsbrenc/ton_corr.c
  126. +112 −0 libsbrenc/ton_corr.h
  127. +595 −0 libsbrenc/tran_det.c
  128. +63 −0 libsbrenc/tran_det.h
1  CHANGELOG
7 COPYRIGHT
@@ -0,0 +1,7 @@
+AAC encoder and SBR algorithm
+Copyright (c) Coding Technologies 2003
+All Rights Reserved
+
+Wav and ADTS header handling routines
+Copyright (c) Matteo Croce 2006-2007
+All Rights Reserved
43 Makefile
@@ -0,0 +1,43 @@
+include config.mak
+TOPDIR=$(CURDIR)
+export CFLAGS=-Wall -pedantic -O3 -ftree-vectorize -I$(TOPDIR)/libaacenc -I$(TOPDIR)/libbitbuf -I$(TOPDIR)/libfr -I$(TOPDIR)/libsbrenc -I$(TOPDIR)/libresamp $(EXTRACFLAGS)
+SUBDIRS=libaacenc libbitbuf libfr libsbrenc libresamp
+LIBS=libaacenc/libaacenc.a libbitbuf/libbitbuf.a libfr/libfr.a libsbrenc/libsbrenc.a libresamp/libresamp.a
+TARGET=aacplusenc
+
+LDFLAGS=-lm
+LDFLAGS+=-L$(TOPDIR)/libaacenc -L$(TOPDIR)/libbitbuf -L$(TOPDIR)/libfr -L$(TOPDIR)/libsbrenc -L$(TOPDIR)/libresamp
+LDFLAGS+=-laacenc -lbitbuf -lfr -lsbrenc -lresamp
+
+ifdef FFTW3
+ LDFLAGS+=-lfftw3f
+endif
+
+
+INSTDIR=/usr/local
+
+%.a:
+ $(MAKE) -C $$(dirname $*)
+
+all: config.h $(TARGET)
+
+$(TARGET): $(LIBS) au_channel.h adts.h aacplusenc.c
+ for i in $(LIBS) ; do \
+ $(MAKE) $$i ;\
+ done
+ $(CC) $(CFLAGS) -o $(TARGET) aacplusenc.c $(LDFLAGS)
+
+.PHONY: clean
+clean:
+ rm -f $(ofiles) $(TARGET) config.* test-*
+ for i in $(SUBDIRS) ; do \
+ $(MAKE) -C $$i clean ;\
+ done
+
+install: all
+ mkdir -p $(INSTDIR)/bin
+ cp aacplusenc $(INSTDIR)/bin
+ strip -s -R.comment $(INSTDIR)/bin/aacplusenc
+
+config.mak:
+ ./configure
40 aacplusenc.1
@@ -0,0 +1,40 @@
+.TH "AACPLUSENC" "1" "19 January 2008" "Matteo Croce" "Debian GNU/Linux"
+.SH "NAME"
+aacplusenc \- AAC+ encoder
+.SH "SYNOPSIS"
+.B aacplusenc
+.I inputfile.wav outputfile.aac bitrate
+.PP
+.SH "DESCRIPTION"
+\fBaacplusenc\fP is an \fIHE\-AACv2\fP encoder.
+
+It accepts as input a \fIWAV\fP file and outputs an \fIAAC\fP file, with \fIRAW ADTS\fP header.
+.PP
+.SH "OPTIONS"
+.TP 8
+.B inputfile.wav
+The file to encode
+.TP 8
+.B outputfile.aac
+The desired filename of the encoded file
+.TP 8
+.B bitrate
+The encoding bitrate, in kbps
+.TP 8
+both inputfile and outputfile can be \fI"\-"\fP to specify stdin and stdout respectively
+.SH "NOTES"
+On 64 bit platform there are issues with Parametric Stereo (PS) an algorithm to give
+better quality on stereo tracks.
+.PP
+As PS is enabled for bitrates lower than 45 kbps, a 64 bit build of \fBaacplusenc\fP can only encode
+mono tracks or stereo tracks encoded with bitrates of 45 kbps and over
+.SH "AUTHOR"
+\fBaacplusenc\fP is written by Matteo Croce <\fIrootkit85@yahoo.it\fP> and its based on 3GPP sources.
+
+Get the latest version from \fIhttp://teknoraver.campuslife.it/software/mp4tools/\fP
+
+The 3GPP project used by \fBaacplusenc\fP: for more info visit \fIhttp://www.3gpp.org/ftp/Specs/archive/26_series/26.410/\fP
+
+AAC+ is licensed by Coding Technologies, for info read: \fIhttp://codingtechnologies.com/products/aacPlus.htm\fP
+
+This manpage was written by Matteo Croce <\fIrootkit85@yahoo.it\fP> and licensed under the terms of the GNU General Public License.
762 aacplusenc.c
@@ -0,0 +1,762 @@
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "FloatFR.h"
+#include "au_channel.h"
+#include "aacenc.h"
+#include "iir32resample.h"
+#include "resampler.h"
+
+#include "sbr_main.h"
+#include "aac_ram.h"
+#include "aac_rom.h"
+#include "adts.h"
+#include "cfftn.h"
+#include "config.h"
+
+/* dynamic buffer of SBR that can be reused for resampling */
+extern float sbr_envRBuffer[];
+
+#define CORE_DELAY (1600)
+#define INPUT_DELAY ((CORE_DELAY)*2 +6*64-2048+1) /* ((1600 (core codec)*2 (multi rate) + 6*64 (sbr dec delay) - 2048 (sbr enc delay) + magic*/
+#define MAX_DS_FILTER_DELAY 16 /* the additional max resampler filter delay (source fs)*/
+
+#define CORE_INPUT_OFFSET_PS (0) /* (96-64) makes AAC still some 64 core samples too early wrt SBR ... maybe -32 would be even more correct, but 1024-32 would need additional SBR bitstream delay by one frame */
+
+#define bEncodeMono (inputInfo.nChannels == 1)
+
+/*
+
+ input buffer (1ch)
+
+ |------------ 1537 -------------|-----|---------- 2048 -------------|
+ (core2sbr delay ) ds (read, core and ds area)
+*/
+static float inputBuffer[(AACENC_BLOCKSIZE*2 + MAX_DS_FILTER_DELAY + INPUT_DELAY)*MAX_CHANNELS];
+char outputBuffer[ADTS_HEADER_SIZE+(6144/8)*MAX_CHANNELS];
+
+static IIR21_RESAMPLER IIR21_reSampler[MAX_CHANNELS];
+
+int main(int argc, char *argv[])
+{
+ AACENC_CONFIG config;
+
+ WavInfo inputInfo;
+ FILE *inputFile;
+
+ FILE *fOut=NULL;
+ FILE *hADTSFile;
+
+ int error;
+
+ int bitrate;
+ int nChannelsAAC, nChannelsSBR;
+ unsigned int sampleRateAAC;
+ int frmCnt;
+ int bandwidth = 0;
+
+ unsigned int numAncDataBytes=0;
+ unsigned char ancDataBytes[MAX_PAYLOAD_SIZE];
+ unsigned int ancDataLength = 0;
+
+ /*!< required only for interfacing with audio output library, thus not counted into RAM requirements */
+ short TimeDataPcm[AACENC_BLOCKSIZE*2*MAX_CHANNELS];
+
+ int numSamplesRead;
+ int bDoIIR2Downsample = 0;
+ int bDingleRate = 0;
+ int useParametricStereo = 0;
+ int coreWriteOffset = 0;
+ int coreReadOffset = 0;
+ int envWriteOffset = 0;
+ int envReadOffset = 0;
+ int writeOffset=INPUT_DELAY*MAX_CHANNELS;
+ int percent = -1;
+
+ struct AAC_ENCODER *aacEnc = 0;
+
+ int bDoUpsample = 0;
+ int upsampleReadOffset = 0;
+
+ int inSamples;
+ int bDoIIR32Resample = 0;
+ int nSamplesPerChannel;
+ const int nRuns = 4;
+ float *resamplerScratch = sbr_envRBuffer;
+
+ HANDLE_SBR_ENCODER hEnvEnc=NULL;
+
+ /* initialize the 3GPP instrumenting tool */
+
+
+ fprintf(stderr,
+ "\n"
+ "*************************************************************\n"
+ "* Enhanced aacPlus Encoder\n"
+ "* Build %s, %s\n"
+ "* Matteo Croce <rootkit85@yahoo.it>\n"
+ "*************************************************************\n\n", __DATE__, __TIME__);
+
+
+ /*
+ * parse command line arguments
+ */
+ if (argc != 4) {
+ fprintf(stderr, "\nUsage: %s <source.wav> <destination.aac> <bitrate>\n", argv[0]);
+ fprintf(stderr, "\nUse - as filename for stdin and/or stdout.\n");
+ fprintf(stderr, "\nExample: %s song.wav song.aac 32\n", argv[0]);
+ return 0;
+ }
+
+ bitrate = atoi(argv[3]) * 1000;;
+
+ fflush(stderr);
+
+ /*
+ open audio input file
+ */
+
+ inputFile = AuChannelOpen (argv[1], &inputInfo);
+
+ if(!inputFile) {
+ fprintf(stderr,"could not open %s\n",argv[1]);
+ exit(10);
+ }
+
+
+
+
+ /*
+ set up basic parameters for aacPlus codec
+ */
+
+ AacInitDefaultConfig(&config);
+
+
+ nChannelsAAC = nChannelsSBR = inputInfo.nChannels;
+
+
+ if ( (inputInfo.nChannels == 2) && (bitrate >= 16000) && (bitrate < 44001) )
+ useParametricStereo = 1;
+
+
+ if (useParametricStereo)
+ {
+
+ nChannelsAAC = 1;
+ nChannelsSBR = 2;
+ }
+
+
+ if ( ((inputInfo.sampleRate == 48000) && (nChannelsAAC == 2) && (bitrate < 24000))
+ || ((inputInfo.sampleRate == 48000) && (nChannelsAAC == 1) && (bitrate < 12000))
+
+ ) {
+
+
+ bDoIIR32Resample = 1;
+ }
+
+
+ if (inputInfo.sampleRate == 16000) {
+
+
+ bDoUpsample = 1;
+ inputInfo.sampleRate = 32000;
+ bDingleRate = 1;
+ }
+
+
+ sampleRateAAC = inputInfo.sampleRate;
+
+
+ if (bDoIIR32Resample)
+ {
+
+ sampleRateAAC = 32000;
+ }
+
+
+ config.bitRate = bitrate;
+ config.nChannelsIn=inputInfo.nChannels;
+ config.nChannelsOut=nChannelsAAC;
+
+
+ config.bandWidth=bandwidth;
+
+
+
+ /*
+ set up SBR configuration
+ */
+
+
+ if(!IsSbrSettingAvail (bitrate, nChannelsAAC, sampleRateAAC, &sampleRateAAC)) {
+ fprintf(stderr,"No valid SBR configuration found for:\n\t\t\tbitrate=%d\n\t\t\tchannels=%d\n\t\t\tsamplerate=%d\n", bitrate, nChannelsAAC, sampleRateAAC);
+ exit(10);
+ }
+
+ {
+ sbrConfiguration sbrConfig;
+
+
+ envReadOffset = 0;
+
+
+ coreWriteOffset = 0;
+
+
+ if(useParametricStereo)
+ {
+
+ envReadOffset = (MAX_DS_FILTER_DELAY + INPUT_DELAY)*MAX_CHANNELS;
+ coreWriteOffset = CORE_INPUT_OFFSET_PS;
+ writeOffset = envReadOffset;
+ }
+
+
+ InitializeSbrDefaults (&sbrConfig);
+
+
+
+ sbrConfig.usePs = useParametricStereo;
+
+
+ AdjustSbrSettings(&sbrConfig,
+ bitrate,
+ nChannelsAAC,
+ sampleRateAAC,
+ AACENC_TRANS_FAC,
+ 24000);
+
+
+ EnvOpen (&hEnvEnc,
+ inputBuffer + coreWriteOffset,
+ &sbrConfig,
+ &config.bandWidth);
+
+ /* set IIR 2:1 downsampling */
+
+ bDoIIR2Downsample = (bDoUpsample) ? 0 : 1;
+
+
+ if (useParametricStereo)
+ {
+
+ bDoIIR2Downsample = 0;
+ }
+
+ }
+
+
+
+ /*
+ set up mode-dependant 1:2 upsampling
+ */
+
+
+ if (bDoUpsample) {
+
+
+ if (inputInfo.nChannels>1) {
+
+
+
+ fprintf( stderr, "\n Stereo @ 16kHz input sample rate is not supported\n");
+ return -1;
+ }
+
+
+ InitIIR21_Resampler(&(IIR21_reSampler[0]));
+
+#if (MAX_CHANNELS==2)
+
+ InitIIR21_Resampler(&(IIR21_reSampler[1]));
+#endif
+
+ assert(IIR21_reSampler[0].delay <=MAX_DS_FILTER_DELAY);
+
+
+ if (useParametricStereo) {
+
+
+ writeOffset += AACENC_BLOCKSIZE * MAX_CHANNELS;
+
+
+ upsampleReadOffset = writeOffset;
+ envWriteOffset = envReadOffset;
+ }
+ else
+ {
+
+ writeOffset += AACENC_BLOCKSIZE * MAX_CHANNELS;
+
+
+ coreReadOffset = writeOffset;
+
+
+ upsampleReadOffset = writeOffset - (((INPUT_DELAY-IIR21_reSampler[0].delay) >> 1) * MAX_CHANNELS);
+
+
+ envWriteOffset = ((INPUT_DELAY-IIR21_reSampler[0].delay) & 0x1) * MAX_CHANNELS;
+
+
+ envReadOffset = 0;
+ }
+ }
+ else {
+
+ /*
+ set up 2:1 downsampling
+ */
+
+
+ if (bDoIIR2Downsample){
+
+
+ InitIIR21_Resampler(&(IIR21_reSampler[0]));
+
+#if (MAX_CHANNELS==2)
+
+ InitIIR21_Resampler(&(IIR21_reSampler[1]));
+#endif
+
+ assert(IIR21_reSampler[0].delay <=MAX_DS_FILTER_DELAY);
+
+
+ writeOffset += IIR21_reSampler[0].delay*MAX_CHANNELS;
+ }
+ }
+
+
+ if (bDoIIR32Resample)
+ {
+
+ IIR32Init();
+ }
+
+ /*
+ set up AAC encoder, now that samling rate is known
+ */
+
+ config.sampleRate = sampleRateAAC;
+
+
+ error = AacEncOpen( &aacEnc,
+ config);
+
+
+ if (error){
+ fprintf(stderr,"\n Initialisation of AAC failed !\n");
+
+
+ AacEncClose(aacEnc);
+
+ AuChannelClose (inputFile);
+
+
+ if (fOut) fclose(fOut);
+
+
+
+
+ return 1;
+ }
+
+ if (strcmp(argv[2],"-")==0)
+ hADTSFile=stdout;
+ else
+ hADTSFile = fopen(argv[2], "wb");
+
+ if(!hADTSFile) {
+ fprintf(stderr, "\nFailed to create ADTS file\n") ;
+ exit(10);
+ }
+
+ /*
+ Be verbose
+ */
+
+
+ fprintf(stderr,"input file %s: \nsr = %d, nc = %d\n\n", argv[1], inputInfo.sampleRate, inputInfo.nChannels);
+ fprintf(stderr,"output file %s: \nbr = %d sr-OUT = %d nc-OUT = %d\n\n", argv[2], bitrate, sampleRateAAC*2, nChannelsSBR);
+ fflush(stderr);
+
+ init_plans();
+
+ frmCnt = 0;
+
+
+ memset(TimeDataPcm,0,sizeof(TimeDataPcm));
+
+
+ /*
+ set up input samples block size feed
+ */
+
+
+ if (bDoIIR32Resample) {
+
+
+ inSamples = IIR32GetResamplerFeed(AACENC_BLOCKSIZE * inputInfo.nChannels * 2) / nRuns;
+
+ assert(inSamples <= AACENC_BLOCKSIZE * 2);
+ }
+ else {
+
+
+ inSamples = AACENC_BLOCKSIZE * inputInfo.nChannels * 2;
+
+
+ if (bDoUpsample) {
+
+ inSamples = inSamples>>1;
+ }
+ }
+
+
+ /* create the ADTS header */
+ adts_hdr(outputBuffer, &config);
+
+ /*
+ The frame loop
+ */
+
+ while (1)
+ {
+ int i, ch, outSamples, numOutBytes, newpercent = -1;
+
+
+
+
+ /*
+ File input read, resample and downmix
+ */
+
+
+ if (bDoIIR32Resample) {
+
+ /* resampling from 48 kHz to 32 kHz prior to encoding */
+
+ int stopLoop = 0;
+ int nSamplesProcessed = 0;
+ int r;
+
+ const int nDSOutBlockSize = AACENC_BLOCKSIZE * 2 / nRuns;
+ int stride = inputInfo.nChannels;
+#if (MAX_CHANNELS==2)
+ if (inputInfo.nChannels==1)
+ stride = 2;
+#endif
+
+ /* counting previous operations */
+
+
+ for (r=0; r<nRuns; r++) {
+
+
+ if ( AuChannelReadShort(inputFile, TimeDataPcm,
+ inSamples, &numSamplesRead)) {
+
+ stopLoop = 1;
+ break;
+ }
+
+ /* copy from short to float input buffer */
+ /* resamplerScratch[]
+ TimeDataPcm[]
+ */
+
+ for (i=0; i<numSamplesRead; i++) {
+
+
+ resamplerScratch[i] = (float) TimeDataPcm[i];
+ }
+
+
+ switch (inputInfo.nChannels) {
+ case 1:
+
+ nSamplesPerChannel = numSamplesRead;
+ break;
+ case 2:
+
+ nSamplesPerChannel = numSamplesRead >> 1;
+ break;
+ default:
+
+ nSamplesPerChannel = numSamplesRead / inputInfo.nChannels;
+ }
+
+ /* supposed to return exact number samples to encode one block of audio */
+
+ nSamplesProcessed += IIR32Resample( resamplerScratch,
+ &inputBuffer[writeOffset + r*nDSOutBlockSize*stride],
+ nSamplesPerChannel,
+ nDSOutBlockSize,
+ inputInfo.nChannels);
+
+ if (inputInfo.nChannels==1 && stride==2) {
+ /* reordering necessary since the encoder takes interleaved data */
+ for (i=nDSOutBlockSize-1; i>=0; i--) {
+ inputBuffer[writeOffset+r*nDSOutBlockSize*2+2*i] =
+ inputBuffer[writeOffset+r*nDSOutBlockSize*2+i];
+ }
+ }
+ }
+
+
+ if (stopLoop)
+ break;
+
+
+ numSamplesRead = nSamplesProcessed;
+
+ }
+ else {
+
+ /* no resampling prior to encoding required */
+
+
+ /* read from file */
+
+ if ( AuChannelReadShort(inputFile, TimeDataPcm,
+ inSamples, &numSamplesRead)) {
+ break;
+ }
+
+
+ /* copy from short to float input buffer */
+
+ if ( inputInfo.nChannels == nChannelsSBR ) {
+ /* inputBuffer[i+writeOffset]
+ TimeDataPcm[i]
+ */
+
+ for (i=0; i<numSamplesRead; i++) {
+
+
+ inputBuffer[i+writeOffset] = (float) TimeDataPcm[i];
+ }
+ }
+
+
+#if (MAX_CHANNELS==2)
+
+ /* copy from short to float input buffer, reordering necessary since the encoder takes interleaved data */
+
+ if(inputInfo.nChannels == 1) {
+ int i;
+
+ /* inputBuffer[writeOffset+MAX_CHANNELS*i]
+ inputBuffer[writeOffset+i]
+ */
+
+ for (i=0; i<numSamplesRead; i++) {
+
+
+ inputBuffer[writeOffset+2*i] = (float) TimeDataPcm[i];
+ }
+ }
+
+ /* copy from short to float input buffer, downmix stereo input signal to mono, reordering necessary since the encoder takes interleaved data */
+
+ if( (inputInfo.nChannels == 2) && bEncodeMono) {
+ int i;
+
+ /* inputBuffer[writeOffset+2*i]
+ inputBuffer[writeOffset+2*i+1]
+ */
+
+ for(i=0;i<numSamplesRead/2;i++){
+
+
+ inputBuffer[writeOffset+2*i] = ((float) TimeDataPcm[2*i] + (float) TimeDataPcm[2*i+1])*0.5f;
+ }
+ }
+
+#endif
+
+ } /*end if (bDoIIR32Resample) */
+
+
+
+ if (bDoUpsample) {
+
+
+ for(ch=0;ch < inputInfo.nChannels;ch++){
+
+
+ IIR21_Upsample( &(IIR21_reSampler[ch]),
+ inputBuffer+upsampleReadOffset+ch,
+ numSamplesRead/inputInfo.nChannels,
+ MAX_CHANNELS,
+ inputBuffer+envWriteOffset+ch,
+ &outSamples,
+ MAX_CHANNELS);
+
+ }
+ }
+
+
+ /*
+ encode one SBR frame
+ */
+
+
+ EnvEncodeFrame (hEnvEnc,
+ inputBuffer + envReadOffset,
+ inputBuffer + coreWriteOffset,
+ MAX_CHANNELS,
+ &numAncDataBytes,
+ ancDataBytes);
+
+
+ /*
+ 2:1 downsampling for AAC core
+ */
+
+
+ if (bDoIIR2Downsample) {
+
+
+ for( ch=0; ch<nChannelsAAC; ch++ ) {
+
+
+ IIR21_Downsample(&(IIR21_reSampler[ch]),
+ inputBuffer+writeOffset+ch,
+ numSamplesRead/inputInfo.nChannels,
+ MAX_CHANNELS,
+ inputBuffer+ch,
+ &outSamples,
+ MAX_CHANNELS);
+
+ }
+ }
+
+
+ /* SBR side info data is passed as ancillary data */
+
+ if(numAncDataBytes == 0)
+ {
+
+ numAncDataBytes=ancDataLength;
+ }
+
+
+ /*
+ encode one AAC frame
+ */
+
+
+
+ if (hEnvEnc && useParametricStereo) {
+
+
+ AacEncEncode(aacEnc,
+ inputBuffer,
+ 1, /* stride */
+ ancDataBytes,
+ &numAncDataBytes,
+ (unsigned*)(outputBuffer + ADTS_HEADER_SIZE),
+ &numOutBytes);
+
+
+ if(hEnvEnc)
+ {
+
+ memcpy( inputBuffer,inputBuffer+AACENC_BLOCKSIZE,CORE_INPUT_OFFSET_PS*sizeof(float));
+ }
+ }
+ else
+ {
+
+ AacEncEncode(aacEnc,
+ inputBuffer+coreReadOffset,
+ MAX_CHANNELS,
+ ancDataBytes,
+ &numAncDataBytes,
+ (unsigned*)(outputBuffer + ADTS_HEADER_SIZE),
+ &numOutBytes);
+
+
+
+ if(hEnvEnc) {
+
+
+ if (bDoUpsample) {
+
+ memmove( &inputBuffer[envReadOffset],
+ &inputBuffer[envReadOffset+AACENC_BLOCKSIZE*MAX_CHANNELS*2],
+ (envWriteOffset-envReadOffset)*sizeof(float));
+
+
+ memmove( &inputBuffer[upsampleReadOffset],
+ &inputBuffer[upsampleReadOffset+AACENC_BLOCKSIZE*MAX_CHANNELS],
+ (writeOffset-upsampleReadOffset)*sizeof(float));
+ }
+ else {
+
+ memmove( inputBuffer,inputBuffer+AACENC_BLOCKSIZE*2*MAX_CHANNELS,writeOffset*sizeof(float));
+ }
+ }
+ }
+
+
+ /*
+ Write one frame of encoded audio to file
+ */
+
+
+ if (numOutBytes) {
+
+ adts_hdr_up(outputBuffer, numOutBytes);
+ fwrite(outputBuffer, 1, numOutBytes + ADTS_HEADER_SIZE, hADTSFile);
+ }
+
+
+ frmCnt++;
+
+
+
+ /* 3GPP instrumenting tool: measure worst case work load at end of each decoding loop */
+
+
+ newpercent = frmCnt * AACENC_BLOCKSIZE * inputInfo.nChannels / (inputInfo.nSamples / ( 4 * 100 ));
+ if(newpercent != percent) {
+ percent = newpercent;
+ fprintf(stderr,"[%d%%]\r", newpercent);
+ fflush(stderr);
+ }
+ }
+ fprintf(stderr,"\n"); fflush(stderr);
+
+
+ /*
+ Close encoder
+ */
+
+
+
+
+ AacEncClose(aacEnc);
+
+ AuChannelClose (inputFile);
+
+ destroy_plans();
+
+ if(hEnvEnc)
+ {
+
+ EnvClose(hEnvEnc);
+ }
+
+ /* 3GPP instrumenting tool: print output data */
+
+
+ fprintf(stderr,"\nencoding finished\n");
+ fflush(stderr);
+
+ return 0;
+}
60 adts.h
@@ -0,0 +1,60 @@
+/*
+ adts
+
+ Copyright (C) Matteo Croce
+
+ */
+
+#define ADTS_HEADER_SIZE 7
+
+#include "aacenc.h"
+
+const int aac_sampling_freq[16] = {96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ 0, 0, 0, 0}; /* filling */
+const int id = 0, profile = 1;
+
+void adts_hdr(char *adts, AACENC_CONFIG *config) {
+ int srate_idx = 15, i;
+
+ /* sync word, 12 bits */
+ adts[0] = (char)0xff;
+ adts[1] = (char)0xf0;
+
+ /* ID, 1 bit */
+ adts[1] |= id << 3;
+ /* layer: 2 bits = 00 */
+
+ /* protection absent: 1 bit = 1 (ASSUMPTION!) */
+ adts[1] |= 1;
+
+ /* profile, 2 bits */
+ adts[2] = profile << 6;
+
+ for (i = 0; i < 16; i++)
+ if (config->sampleRate >= (aac_sampling_freq[i] - 1000)) {
+ srate_idx = i;
+ break;
+ }
+
+ /* sampling frequency index, 4 bits */
+ adts[2] |= srate_idx << 2;
+
+ /* private, 1 bit = 0 (ASSUMPTION!) */
+
+ /* channels, 3 bits */
+ adts[2] |= (config->nChannelsOut & 4) >> 2;
+ adts[3] = (config->nChannelsOut & 3) << 6;
+
+ /* adts buffer fullness, 11 bits, 0x7ff = VBR (ASSUMPTION!) */
+ adts[6] = (char)0xfc;
+}
+
+void adts_hdr_up(char *adts, int size)
+{
+ /* frame length, 13 bits */
+ int len = size + 7;
+ adts[3] = (adts[3] & 0xc0) | (len >> 11);
+ adts[4] = (len >> 3) & 0xff;
+ adts[5] = (len & 7) << 5 | (char)0x1f;
+}
54 au_channel.h
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#define b2l(A) ((((unsigned short)(A) & 0xff00) >> 8) | (((unsigned short)(A) & 0x00ff) << 8))
+
+#define WAV_HEADER_SIZE 44
+
+typedef struct {
+ int sampleRate;
+ int nChannels;
+ long nSamples;
+} WavInfo;
+
+FILE* AuChannelOpen (const char* filename, WavInfo* info)
+{
+ unsigned char header[WAV_HEADER_SIZE];
+ FILE *handle;
+
+ if (!strcmp(filename,"-"))
+ handle = stdin;
+ else
+ handle = fopen(filename, "rb");
+
+ if(!handle)
+ return NULL;
+
+ if(fread(header, 1, WAV_HEADER_SIZE, handle) != WAV_HEADER_SIZE)
+ return 0;
+
+ info->nSamples = (header[4] | (header[5] << 8) | (header[6] << 16) | (header[7] << 24)) + 8;
+ info->nChannels = header[22] | header[23] << 8;
+ info->sampleRate = header[24] | header[25] << 8 | header[26] << 12 | header[27] << 16;
+ return handle;
+}
+
+void AuChannelClose (FILE *audioChannel)
+{
+ fclose(audioChannel);
+}
+
+size_t AuChannelReadShort(FILE *audioChannel, short *samples, int nSamples, int *readed)
+{
+ *readed = fread(samples, 2, nSamples, audioChannel);
+#ifdef _BE_ARCH
+ {
+ int i;
+ for(i = 0; i < *readed; i++)
+ samples[i] = b2l(samples[i]);
+ }
+#endif
+ return *readed <= 0;
+}
79 configure
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+>config.mak
+cat >config.h <<'EOF'
+#ifndef _CONFIG_H
+#define _CONFIG_H
+EOF
+
+echo -n 'Checking for libfftw3f...'
+
+gcc -o test-fft -Wall -x c -lfftw3f -I/usr/local/include -L/usr/local/lib - <<'EOF'
+#include <fftw3.h>
+
+#define N 128
+
+int main(int argc, char *argv[])
+{
+ fftwf_complex *data;
+ fftwf_plan p;
+
+ data = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * N);
+ p = fftwf_plan_dft_1d(N, data, data, FFTW_FORWARD, FFTW_ESTIMATE);
+
+ fftwf_execute(p);
+
+ fftwf_destroy_plan(p);
+ fftwf_free(data);
+ return 0;
+}
+EOF
+
+if ./test-fft
+then
+ echo OK
+ echo '#define _FFTW3' >> config.h
+ echo 'export FFTW3=1' >> config.mak
+fi
+
+echo -n 'Detecting endianness...'
+
+gcc -o test-endian -Wall -x c - <<'EOF'
+#include <stdint.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ uint32_t dword = 0x11223344;
+ uint8_t *byte = (uint8_t*)&dword;
+
+ if(byte[0] == 0x44 && byte[1] == 0x33 && byte[2] == 0x22 && byte[3] == 0x11) {
+ printf("EL");
+ return 0;
+ }
+
+ if(byte[0] == 0x11 && byte[1] == 0x22 && byte[2] == 0x33 && byte[3] == 0x44) {
+ printf("BE");
+ return 0;
+ }
+ return 1;
+}
+EOF
+
+if ./test-endian > /dev/null
+then
+ ENDIAN=$(./test-endian)
+ if [ $ENDIAN = EL ]
+ then
+ echo 'Little Endian'
+ echo '#define _EL_ARCH' >> config.h
+ elif [ $ENDIAN = BE ]
+ then
+ echo 'Big Endian'
+ echo '#define _BE_ARCH' >> config.h
+ fi
+fi
+
+echo '#endif' >> config.h
+
+echo 'Now run make'
194 debian/changelog
@@ -0,0 +1,194 @@
+aacplusenc (0.17.4) jaunty; urgency=low
+
+ * Fix ppc encoding
+ * Jaunty upload
+
+ -- Matteo Croce <rootkit85@yahoo.it> Mon, 18 May 2009 18:08:17 +0200
+
+aacplusenc (0.17.3) intrepid; urgency=low
+
+ * Fix possibly corrupted ADTS header
+ * Intrepid upload
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 29 Oct 2008 23:50:12 +0100
+
+aacplusenc (0.17.2) intrepid; urgency=low
+
+ * Intrepid upload
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sat, 13 Sep 2008 01:22:11 +0200
+
+aacplusenc (0.17.1) hardy; urgency=low
+
+ * Updated homepage URL
+
+ -- Matteo Croce <rootkit85@yahoo.it> Thu, 17 Jul 2008 16:44:46 +0200
+
+aacplusenc (0.17) hardy; urgency=high
+
+ * Fixed 64 bit encoding
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 04 Jun 2008 00:42:44 +0200
+
+aacplusenc (0.16.3) hardy; urgency=low
+
+ * Fix type in au_channel.h
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sun, 17 Feb 2008 15:55:51 +0100
+
+aacplusenc (0.16.2) hardy; urgency=low
+
+ * Added compile time checks for endiannes and FFTW3
+
+ -- Matteo Croce <rootkit85@yahoo.it> Thu, 14 Feb 2008 16:32:42 +0100
+
+aacplusenc (0.16.1) hardy; urgency=low
+
+ * Fix BSD build
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 12 Feb 2008 17:39:16 +0100
+
+aacplusenc (0.16) hardy; urgency=low
+
+ * Added support for bitrate up to 64 and 63 kbit for 44.1 and 48 kHz
+
+ -- Matteo Croce <rootkit85@yahoo.it> Thu, 31 Jan 2008 18:48:17 +0100
+
+aacplusenc (0.15) hardy; urgency=low
+
+ * Full 64 bit support
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 23 Jan 2008 20:14:58 +0100
+
+aacplusenc (0.14.2) hardy; urgency=low
+
+ * Rebuild ubuntu package with sane dpkg-deb arguments
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 23 Jan 2008 16:01:31 +0100
+
+aacplusenc (0.14.1) hardy; urgency=low
+
+ * Fix endiannes under BSD
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 23 Jan 2008 01:20:42 +0100
+
+aacplusenc (0.14) hardy; urgency=low
+
+ * Small speedup (~9%)
+ * Better packaging
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 22 Jan 2008 03:26:28 +0100
+
+aacplusenc (0.13.2) hardy; urgency=low
+
+ * Fix manpage path
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sun, 20 Jan 2008 04:18:55 +0100
+
+aacplusenc (0.13.1-1~gutsy1) gutsy; urgency=low
+
+ * Gutsy upload
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sun, 20 Jan 2008 00:15:31 +0100
+
+aacplusenc (0.13.1) hardy; urgency=low
+
+ * Added changelog
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sat, 19 Jan 2008 23:56:44 +0100
+
+aacplusenc (0.13) gutsy; urgency=low
+
+ * All channels/samplerates/bitrates combinations works now
+ * A 64 bit build can encode a mono track, or an high bitrate one (> 44kbit)
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 15 Jan 2008 01:23:42 +0100
+
+aacplusenc (0.12.1) gutsy; urgency=low
+
+ * Fix Win32 build
+
+ -- Matteo Croce <rootkit85@yahoo.it> Mon, 17 Dec 2007 17:36:39 +0100
+
+aacplusenc (0.12) gutsy; urgency=low
+
+ * Fixed encodings higher tha 44 kbit/s
+
+ -- Matteo Croce <rootkit85@yahoo.it> Thu, 06 Dec 2007 02:16:07 +0100
+
+aacplusenc (0.11) gutsy; urgency=low
+
+ * Enable 64 bit builds, but only for mono encodings
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 04 Dec 2007 17:53:59 +0100
+
+aacplusenc (0.10) gutsy; urgency=low
+
+ * Good speed increase (25-33%) against older version
+ * Keep legacy builtin FFT, enable it with the NOFFTW3 make flag
+
+ -- Matteo Croce <rootkit85@yahoo.it> Sat, 01 Dec 2007 18:10:30 +0100
+
+aacplusenc (0.9) gutsy; urgency=low
+
+ * Trashed the builtin FFT and used the GPL one FFTW3 which is faster
+
+ -- Matteo Croce <rootkit85@yahoo.it> Fri, 30 Nov 2007 02:16:58 +0100
+
+aacplusenc (0.8) gutsy; urgency=low
+
+ * removed the last m/s parameter. Stereo or mono encoding
+ is done according to source number of channels
+ * now the target bitrate is expressed in kbit, not bits
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 20 Nov 2007 18:35:37 +0100
+
+aacplusenc (0.7) gutsy; urgency=low
+
+ * Adding safety code to avoid encoder runtime-assertion
+
+ -- Matteo Croce <rootkit85@yahoo.it> Fri, 19 Oct 2007 02:09:05 +0200
+
+aacplusenc (0.6) feisty; urgency=low
+
+ * fixed percentage display
+ * copied missing b2l macro from old libaudio/au_channel.h
+ * removed unneeded libaudio and fixed CFLAGS, one -ftree-vectorize should be
+ enough in Makefile
+
+ -- Bernhard Geier <bernhard.geier@gmx.de> Thu, 19 Apr 2007 23:38:24 +0200
+
+aacplusenc (0.5) feisty; urgency=low
+
+ * Ported the I/O read/write to fread/fwrite
+ * Reduced I/O calls, it encodes much faster now
+ * Removed unused au_channel functions
+ * Added percent indicator, needed to use aacplusenc as backend
+
+ -- Matteo Croce <rootkit85@yahoo.it> Mon, 19 Mar 2007 17:40:13 +0100
+
+aacplusenc (0.4) unstable; urgency=low
+
+ * New bitrate tables from 3gpp.org
+
+ -- Matteo Croce <rootkit85@yahoo.it> Thu, 14 Dec 2006 00:26:01 +0100
+
+mp4tools (0.3) unstable; urgency=low
+
+ * Removed libisomediafile, now aacplusenc saves raw ADTS streams
+ * Removed unused downsampling library
+ * Now encoding parameters are taken from the WAV header
+
+ -- Matteo Croce <rootkit85@yahoo.it> Wed, 7 Jun 2006 20:28:35 +0200
+
+mp4tools (0.2) unstable; urgency=low
+
+ * Replaced real's encoder with an opensource, better one
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 6 Jun 2006 18:44:48 +0200
+
+mp4tools (0.1) unstable; urgency=low
+
+ * Initial release
+
+ -- Matteo Croce <rootkit85@yahoo.it> Tue, 23 May 2006 15:02:07 +0200
1  debian/compat
@@ -0,0 +1 @@
+4
14 debian/control
@@ -0,0 +1,14 @@
+Source: aacplusenc
+Build-Depends: debhelper, fftw3-dev
+Section: sound
+Priority: optional
+Standards-Version: 3.7.3
+Homepage: http://teknoraver.net/software/mp4tools/
+Maintainer: Matteo Croce <rootkit85@yahoo.it>
+
+Package: aacplusenc
+Architecture: any
+Section: sound
+Priority: optional
+Depends: ${shlibs:Depends}
+Description: High-Efficency AAC (AAC+) Encoder
30 debian/rules
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+
+version := $(shell awk '/Package/{print$$2}' debian/control)
+
+build:
+ $(MAKE) -j$(shell grep -c ^processor /proc/cpuinfo)
+
+binary: binary-arch
+
+binary-arch: build install
+
+binary-indep:
+
+install: build
+ $(MAKE) INSTDIR=$(CURDIR)/debian/${version}/usr install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installman aacplusenc.1
+ dh_strip
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_compress
+ dh_builddeb -- -Zbzip2
+
+clean:
+ $(MAKE) clean
+ dh_clean
45 libaacenc/Makefile
@@ -0,0 +1,45 @@
+####################################################################
+#
+# Makefile for aac encoder - library
+#
+####################################################################
+################## user section: insert objlist here #######
+LIB = libaacenc.a
+
+SRCS = adj_thr.c \
+ band_nrg.c \
+ block_switch.c \
+ grp_data.c \
+ interface.c \
+ ms_stereo.c \
+ pre_echo_control.c \
+ psy_configuration.c \
+ psy_main.c \
+ spreading.c \
+ tns.c \
+ tns_param.c \
+ transform.c \
+ adj_thr.c \
+ dyn_bits.c \
+ line_pe.c \
+ qc_main.c \
+ quantize.c \
+ sf_estim.c \
+ stat_bits.c \
+ bit_cnt.c \
+ bitenc.c \
+ aacenc.c \
+ stprepro.c \
+ channel_map.c \
+ aac_ram.c \
+ aac_rom.c
+
+OBJS = $(SRCS:.c=.o)
+
+$(LIB): $(OBJS)
+ ar r $@ $(OBJS)
+
+all: $(LIB)
+
+clean:
+ rm -f $(OBJS) $(LIB)
44 libaacenc/aac_ram.c
@@ -0,0 +1,44 @@
+/*
+ memory requirement in dynamic and static RAM
+*/
+
+#include <stdio.h>
+#include "aac_ram.h"
+#include "aacenc.h"
+#include "psy_const.h"
+#include "FloatFR.h"
+#include "sbr_ram.h"
+
+/*
+ Static memory areas, must not be overwritten in other sections of the encoder
+*/
+
+/* aac Encoder mdct delay buffer */
+float mdctDelayBuffer[MAX_CHANNELS*BLOCK_SWITCHING_OFFSET];
+
+/*
+ these tables are initialized once at application start
+ and are not touched thereafter
+*/
+
+int sideInfoTabLong[MAX_SFB_LONG + 1];
+int sideInfoTabShort[MAX_SFB_SHORT + 1];
+
+/*
+ Dynamic memory areas, might be reused in other algorithm sections,
+*/
+
+
+/* quantized spectrum */
+short *quantSpec = (short*)PsBuf3;
+
+/* scratch space for quantization */
+float *expSpec = sbr_envIBuffer; /* FRAME_LEN_LONG values */
+short *quantSpecTmp = (short*) &sbr_envIBuffer[FRAME_LEN_LONG];
+
+/* scalefactors */
+short *scf= (short*) &sbr_envIBuffer[2*FRAME_LEN_LONG]; /*[MAX_CHANNELS*MAX_GROUPED_SFB];*/
+
+/* max spectral values pre sfb */
+unsigned short *maxValueInSfb = (unsigned short*) &sbr_envIBuffer[2*FRAME_LEN_LONG+MAX_CHANNELS*MAX_GROUPED_SFB]; /* [MAX_CHANNELS*MAX_GROUPED_SFB]; */
+
26 libaacenc/aac_ram.h
@@ -0,0 +1,26 @@
+/*
+ memory requirement in dynamic and static RAM
+*/
+
+#ifndef AAC_RAM_H
+#define AAC_RAM_H
+
+#include "psy_const.h"
+
+extern float mdctDelayBuffer[MAX_CHANNELS*BLOCK_SWITCHING_OFFSET];
+
+extern int sideInfoTabLong[MAX_SFB_LONG + 1];
+extern int sideInfoTabShort[MAX_SFB_SHORT + 1];
+
+extern short *quantSpec;
+extern float *expSpec;
+extern short *quantSpecTmp;
+
+extern short *scf;
+extern unsigned short *maxValueInSfb;
+
+/* dynamic buffers of SBR that can be reused by the core */
+extern float sbr_envRBuffer[];
+extern float sbr_envIBuffer[];
+
+#endif
1,903 libaacenc/aac_rom.c
1,903 additions, 0 deletions not shown
104 libaacenc/aac_rom.h
@@ -0,0 +1,104 @@
+/*
+ Declaration of constant tables
+*/
+#ifndef AAC_ROM_H
+#define AAC_ROM_H
+
+#include "psy_const.h"
+#include "tns_param.h"
+
+#define LD_FFT_TWIDDLE_TABLE_SIZE 9
+#define FFT_TWIDDLE_TABLE_SIZE (1 << LD_FFT_TWIDDLE_TABLE_SIZE)
+
+
+/*
+ mdct
+*/
+extern const float LongWindowSine [FRAME_LEN_LONG];
+extern const float ShortWindowSine [FRAME_LEN_SHORT];
+extern const float LongWindowKBD [FRAME_LEN_LONG];
+extern const float fftTwiddleTab[FFT_TWIDDLE_TABLE_SIZE+1];
+
+
+
+/*
+ quantizer
+*/
+extern const float quantTableQ[16];
+extern const float quantTableE[17];
+extern const float invQuantTableQ[16];
+extern const float invQuantTableE[17];
+#define MAX_POW4_3_TABLE 64
+extern const float pow4_3_tab[MAX_POW4_3_TABLE];
+
+
+
+/*
+ huffman
+*/
+extern const unsigned short huff_ltab1_2[3][3][3][3];
+extern const unsigned short huff_ltab3_4[3][3][3][3];
+extern const unsigned short huff_ltab5_6[9][9];
+extern const unsigned short huff_ltab7_8[8][8];
+extern const unsigned short huff_ltab9_10[13][13];
+extern const unsigned short huff_ltab11[17][17];
+extern const unsigned short huff_ltabscf[121];
+extern const unsigned short huff_ctab1[3][3][3][3];
+extern const unsigned short huff_ctab2[3][3][3][3];
+extern const unsigned short huff_ctab3[3][3][3][3];
+extern const unsigned short huff_ctab4[3][3][3][3];
+extern const unsigned short huff_ctab5[9][9];
+extern const unsigned short huff_ctab6[9][9];
+extern const unsigned short huff_ctab7[8][8];
+extern const unsigned short huff_ctab8[8][8];
+extern const unsigned short huff_ctab9[13][13];
+extern const unsigned short huff_ctab10[13][13];
+extern const unsigned short huff_ctab11[17][17];
+extern const unsigned long huff_ctabscf[121];
+
+
+
+/*
+ misc
+*/
+
+extern const unsigned char sfb_11025_long_1024[];
+extern const unsigned char sfb_11025_short_128[];
+extern const unsigned char sfb_12000_long_1024[];
+extern const unsigned char sfb_12000_short_128[];
+extern const unsigned char sfb_16000_long_1024[];
+extern const unsigned char sfb_16000_short_128[];
+extern const unsigned char sfb_22050_long_1024[];
+extern const unsigned char sfb_22050_short_128[];
+extern const unsigned char sfb_24000_long_1024[];
+extern const unsigned char sfb_24000_short_128[];
+
+/*
+ TNS
+ */
+
+extern const TNS_MAX_TAB_ENTRY tnsMaxBandsTab[9];
+extern const TNS_CONFIG_TABULATED p_8000_mono_long;
+extern const TNS_CONFIG_TABULATED p_8000_mono_short;
+extern const TNS_CONFIG_TABULATED p_8000_stereo_long;
+extern const TNS_CONFIG_TABULATED p_8000_stereo_short;
+extern const TNS_CONFIG_TABULATED p_16000_mono_long;
+extern const TNS_CONFIG_TABULATED p_16000_mono_short;
+extern const TNS_CONFIG_TABULATED p_16000_stereo_long;
+extern const TNS_CONFIG_TABULATED p_16000_stereo_short;
+extern const TNS_CONFIG_TABULATED p_24000_mono_long;
+extern const TNS_CONFIG_TABULATED p_24000_mono_short;
+extern const TNS_CONFIG_TABULATED p_24000_stereo_long;
+extern const TNS_CONFIG_TABULATED p_24000_stereo_short;
+extern const TNS_CONFIG_TABULATED p_32000_mono_long;
+extern const TNS_CONFIG_TABULATED p_32000_mono_short;
+extern const TNS_CONFIG_TABULATED p_32000_stereo_long;
+extern const TNS_CONFIG_TABULATED p_32000_stereo_short;
+extern const TNS_INFO_TAB tnsInfoTab[4];
+
+extern const float tnsCoeff3[8];
+extern const float tnsCoeff3Borders[8];
+extern const float tnsCoeff4[16];
+extern const float tnsCoeff4Borders[16];
+
+#endif
476 libaacenc/aacenc.c
@@ -0,0 +1,476 @@
+/*
+ fast aac coder interface library functions
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "aacenc.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 "stprepro.h"
+#include "minmax.h"
+
+#include "counters.h" /* the 3GPP instrumenting tool */
+
+struct AAC_ENCODER {
+
+ AACENC_CONFIG config;
+
+ ELEMENT_INFO elInfo;
+
+ QC_STATE qcKernel;
+ QC_OUT qcOut;
+
+ PSY_OUT psyOut;
+ PSY_KERNEL psyKernel;
+
+ struct BITSTREAMENCODER_INIT bseInit;
+
+ struct STEREO_PREPRO stereoPrePro;
+
+ struct BIT_BUF bitStream;
+ HANDLE_BIT_BUF hBitStream;
+
+ /* lifetime vars */
+ int downmix;
+ int downmixFac;
+ int dualMono;
+ int bandwidth90dB;
+};
+
+
+/*
+ static AAC encoder instance for one encoder
+ all other major static and dynamic memory areas are located
+ in module aac_ram.c and aac_rom.c
+*/
+static struct AAC_ENCODER aacEncoder;
+
+
+/*-----------------------------------------------------------------------------
+
+ functionname: AacInitDefaultConfig
+ description: gives reasonable default configuration
+ returns: ---
+
+ ------------------------------------------------------------------------------*/
+void AacInitDefaultConfig(AACENC_CONFIG *config)
+{
+ COUNT_sub_start("AacInitDefaultConfig");
+
+ /* make the pre initialization of the structs flexible */
+ FUNC(2); LOOP(1); PTR_INIT(1); MOVE(1); STORE(sizeof(AACENC_CONFIG));
+ memset(config, 0, sizeof(AACENC_CONFIG));
+
+ /* default configurations */
+ INDIRECT(2); MOVE(2);
+ config->bitRate = 48000;
+ config->bandWidth = 0;
+
+ COUNT_sub_end();
+}
+
+/*---------------------------------------------------------------------------
+
+ functionname: AacEncOpen
+ description: allocate and initialize a new encoder instance
+ returns: 0 if success
+
+ ---------------------------------------------------------------------------*/
+
+int
+AacEncOpen ( struct AAC_ENCODER** phAacEnc, /* pointer to an encoder handle, initialized on return */
+ const AACENC_CONFIG config /* pre-initialized config struct */
+ )
+{
+ int error = 0;
+ int profile = 1;
+ ELEMENT_INFO* elInfo = NULL;
+ struct AAC_ENCODER *hAacEnc ;
+
+ COUNT_sub_start("AacEncOpen");
+
+ MOVE(2); /* counting previous operations */
+
+ PTR_INIT(1);
+ hAacEnc = &aacEncoder;
+
+ BRANCH(1);
+ if (phAacEnc==0) {
+ MOVE(1);
+ error=1;
+ }
+
+ BRANCH(1);
+ if (!error) {
+ /* sanity checks on config structure */
+ PTR_INIT(1); ADD(7); LOGIC(9); DIV(1);
+ error = (&config == 0 || phAacEnc == 0 ||
+ config.nChannelsIn < 1 || config.nChannelsIn > MAX_CHANNELS ||
+ config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS ||
+ config.nChannelsIn < config.nChannelsOut ||
+ (config.bitRate!=0 && (config.bitRate / config.nChannelsOut < 8000 ||
+ config.bitRate / config.nChannelsOut > 160000)));
+ }
+
+ /* check sample rate */
+ BRANCH(1);
+ if (!error) {
+
+ BRANCH(2);
+ switch (config.sampleRate) {
+ case 8000: case 11025: case 12000:
+ case 16000: case 22050: case 24000:
+ case 32000: case 44100: case 48000:
+ break;
+
+ default:
+ MOVE(1);
+ error = 1; break;
+ }
+ }
+
+
+ /* check if bit rate is not too high for sample rate */
+ BRANCH(1);
+ if (!error) {
+
+ MULT(2); ADD(1); BRANCH(1);
+ if (config.bitRate > ((float)(MAX_CHANNEL_BITS-744)/FRAME_LEN_LONG*
+ config.sampleRate*config.nChannelsOut))
+ {
+ MOVE(1);
+ error=1;
+ }
+ }
+
+
+ BRANCH(1);
+ if (!error) {
+ INDIRECT(1); MOVE(1);
+ hAacEnc->config = config;
+ }
+
+
+ BRANCH(1);
+ if (!error) {
+ INDIRECT(2); PTR_INIT(1); FUNC(2);
+ error = InitElementInfo (config.nChannelsOut,
+ &hAacEnc->elInfo);
+ }
+
+ BRANCH(1);
+ if (!error) {
+ INDIRECT(1); PTR_INIT(1);
+ elInfo = &hAacEnc->elInfo;
+ }
+
+ /* allocate the Psy aud Psy Out structure */
+ BRANCH(1);
+ if (!error) {
+
+ INDIRECT(3); PTR_INIT(2); FUNC(2); FUNC(1); LOGIC(1);
+ error = (PsyNew(&hAacEnc->psyKernel, elInfo->nChannelsInEl) ||
+ PsyOutNew(&hAacEnc->psyOut));
+ }
+
+ BRANCH(1);
+ if (!error) {
+ int tnsMask=3;
+
+ MOVE(1); /* counting previous operation */
+
+ INDIRECT(2); MOVE(1);
+ hAacEnc->bandwidth90dB = (int)hAacEnc->config.bandWidth;
+
+ INDIRECT(4); PTR_INIT(1); FUNC(6);
+ error = psyMainInit(&hAacEnc->psyKernel,
+ config.sampleRate,
+ config.bitRate,
+ elInfo->nChannelsInEl,
+ tnsMask,
+ hAacEnc->bandwidth90dB);
+ }
+
+
+ /* allocate the Q&C Out structure */
+ BRANCH(1);
+ if (!error) {
+ INDIRECT(2); PTR_INIT(1); FUNC(2);
+ error = QCOutNew(&hAacEnc->qcOut,
+ elInfo->nChannelsInEl);
+ }
+
+ /* allocate the Q&C kernel */
+ BRANCH(1);
+ if (!error) {
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ error = QCNew(&hAacEnc->qcKernel);
+ }
+
+ BRANCH(1);
+ if (!error) {
+ struct QC_INIT qcInit;
+
+ INDIRECT(1); PTR_INIT(1); MOVE(1);
+ qcInit.elInfo = &hAacEnc->elInfo;
+
+ INDIRECT(1); MULT(1); STORE(1);
+ qcInit.maxBits = MAX_CHANNEL_BITS * elInfo->nChannelsInEl;
+
+ MOVE(1);
+ qcInit.bitRes = qcInit.maxBits;
+
+ MULT(1); DIV(1); STORE(1);
+ qcInit.averageBits = (config.bitRate * FRAME_LEN_LONG) / config.sampleRate;
+
+ MOVE(1);
+ qcInit.padding.paddingRest = config.sampleRate;
+
+ INDIRECT(1); MULT(2); DIV(1);
+ qcInit.meanPe = 10.0f * FRAME_LEN_LONG * hAacEnc->bandwidth90dB/(config.sampleRate/2.0f);
+
+ MULT(1); DIV(1); BRANCH(1); STORE(1);
+ qcInit.maxBitFac = (float)((MAX_CHANNEL_BITS-744)*elInfo->nChannelsInEl) /
+ (float)(qcInit.averageBits?qcInit.averageBits:1);
+
+ MOVE(1);
+ qcInit.bitrate = config.bitRate;
+
+ INDIRECT(1); PTR_INIT(2); FUNC(2);
+ error = QCInit(&hAacEnc->qcKernel, &qcInit);
+ }
+
+ /* init bitstream encoder */
+ BRANCH(1);
+ if (!error) {
+
+ INDIRECT(5); MOVE(4);
+ hAacEnc->bseInit.nChannels = elInfo->nChannelsInEl;
+ hAacEnc->bseInit.bitrate = config.bitRate;
+ hAacEnc->bseInit.sampleRate = config.sampleRate;
+ hAacEnc->bseInit.profile = profile;
+ }
+
+
+ /* common things */
+ BRANCH(1);
+ if (!error) {
+
+ INDIRECT(1); ADD(2); LOGIC(1); STORE(1);
+ hAacEnc->downmix = (config.nChannelsIn==2 && config.nChannelsOut==1);
+
+ INDIRECT(1); BRANCH(1); MOVE(1);
+ hAacEnc->downmixFac = (hAacEnc->downmix) ? config.nChannelsIn : 1;
+ }
+
+
+
+ BRANCH(1);
+ if(!error) {
+
+ /*
+ decide if stereo preprocessing should be activated
+ */
+
+ ADD(3); DIV(1); MULT(1); LOGIC(2); BRANCH(1);
+ if ( elInfo->elType == ID_CPE &&
+ (config.sampleRate <= 24000 && (config.bitRate/elInfo->nChannelsInEl*2) < 60000) ) {
+
+ float scfUsedRatio = (float) hAacEnc->psyKernel.psyConfLong.sfbActive / hAacEnc->psyKernel.psyConfLong.sfbCnt ;
+
+ DIV(1); /* counting previous operation */
+
+ FUNC(5);
+ error = InitStereoPreProcessing(&(hAacEnc->stereoPrePro),
+ elInfo->nChannelsInEl,
+ config.bitRate,
+ config.sampleRate,
+ scfUsedRatio);
+ }
+ }
+
+ BRANCH(1);
+ if (error) {
+
+ FUNC(1);
+ AacEncClose(hAacEnc);
+
+ MOVE(1);
+ hAacEnc=0;
+ }
+
+ MOVE(1);
+ *phAacEnc = hAacEnc;
+
+ COUNT_sub_end();
+
+ return error;
+}
+
+
+int AacEncEncode(struct AAC_ENCODER *aacEnc, /*!< an encoder handle */
+ float *timeSignal, /*!< BLOCKSIZE*nChannels audio samples */
+ unsigned int timeInStride,
+ const unsigned char *ancBytes, /*!< pointer to ancillary data bytes */
+ unsigned int *numAncBytes, /*!< number of ancillary Data Bytes */
+ unsigned int *outBytes, /*!< pointer to output buffer */
+ int *numOutBytes /*!< number of bytes in output buffer */
+ )
+{
+ ELEMENT_INFO* elInfo = &aacEnc->elInfo;
+ int globUsedBits;
+ int ancDataBytes, ancDataBytesLeft;
+
+ COUNT_sub_start("AacEncEncode");
+
+ INDIRECT(2); PTR_INIT(1); FUNC(3);
+ aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream,
+ (unsigned char*) outBytes,
+ (MAX_CHANNEL_BITS/8)*MAX_CHANNELS);
+
+ INDIRECT(1); PTR_INIT(1); /* counting previous operation */
+
+ MOVE(2);
+ ancDataBytes = ancDataBytesLeft = *numAncBytes;
+
+
+ /* advance psychoacoustic */
+
+ LOGIC(1); BRANCH(1);
+ if (elInfo->elType == ID_CPE) {
+
+ PTR_INIT(1); FUNC(5);
+ ApplyStereoPreProcess(&aacEnc->stereoPrePro,
+ timeInStride,
+ elInfo,
+ timeSignal,
+ FRAME_LEN_LONG);
+ }
+
+ INDIRECT(5); PTR_INIT(4); FUNC(9);
+ psyMain(timeInStride,
+ 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);
+
+
+ INDIRECT(3); PTR_INIT(1); FUNC(3);
+ AdjustBitrate(&aacEnc->qcKernel,
+ aacEnc->config.bitRate,
+ aacEnc->config.sampleRate);
+
+ PTR_INIT(4); /*
+ aacEnc->qcKernel.elementBits
+ aacEnc->qcKernel.adjThr.adjThrStateElem,
+ aacEnc->psyOut.psyOutElement,
+ aacEnc->qcOut.qcElement
+ */
+
+ ADD(1); BRANCH(1); MOVE(1); /* min() */ INDIRECT(2); PTR_INIT(3); FUNC(9);
+ QCMain( &aacEnc->qcKernel,
+ elInfo->nChannelsInEl,
+ &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,
+ min(ancDataBytesLeft,ancDataBytes));
+
+
+ LOGIC(1); BRANCH(1);
+ if ( elInfo->elType == ID_CPE ) {
+
+ INDIRECT(1); PTR_INIT(2); FUNC(4);
+ UpdateStereoPreProcess(&aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
+ &aacEnc->qcOut.qcElement,
+ &aacEnc->stereoPrePro,
+ aacEnc->psyOut.psyOutElement.weightMsLrPeRatio);
+ }
+
+ ADD(1);
+ ancDataBytesLeft-=ancDataBytes;
+
+
+ INDIRECT(2); PTR_INIT(2); FUNC(2);
+ FinalizeBitConsumption( &aacEnc->qcKernel,
+ &aacEnc->qcOut);
+
+ INDIRECT(3); PTR_INIT(3); FUNC(7);
+ WriteBitstream( aacEnc->hBitStream,
+ *elInfo,
+ &aacEnc->qcOut,
+ &aacEnc->psyOut,
+ &globUsedBits,
+ ancBytes);
+
+ INDIRECT(2); PTR_INIT(2); FUNC(2);
+ UpdateBitres(&aacEnc->qcKernel,
+ &aacEnc->qcOut);
+
+ /* write out the bitstream */
+ INDIRECT(1); FUNC(1); DIV(1); STORE(1);
+ *numOutBytes = GetBitsAvail(aacEnc->hBitStream)/8;
+
+ /* assert this frame is not too large */
+ assert(*numOutBytes*8 <= MAX_CHANNEL_BITS * elInfo->nChannelsInEl);
+
+ COUNT_sub_end();
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------
+
+ functionname:AacEncClose
+ description: deallocate an encoder instance
+
+ ---------------------------------------------------------------------------*/
+
+void AacEncClose (struct AAC_ENCODER* hAacEnc)
+{
+ int error=0;
+
+ COUNT_sub_start("AacEncClose");
+
+ MOVE(1); /* counting previous operation */
+
+ BRANCH(1);
+ if (hAacEnc) {
+
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ QCDelete(&hAacEnc->qcKernel);
+
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ QCOutDelete(&hAacEnc->qcOut);
+
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ error = PsyDelete(&hAacEnc->psyKernel);
+
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ error = PsyOutDelete(&hAacEnc->psyOut);
+
+ INDIRECT(1); PTR_INIT(1); FUNC(1);
+ DeleteBitBuffer(&hAacEnc->hBitStream);
+
+ PTR_INIT(1);
+ hAacEnc=0;
+ }
+
+ COUNT_sub_end();
+}
83 libaacenc/aacenc.h
@@ -0,0 +1,83 @@
+/*
+ fast aac coder interface library functions
+*/
+
+#ifndef _aacenc_h_
+#define _aacenc_h_
+
+/* here we distinguish between stereo and the mono only encoder */
+#ifdef MONO_ONLY
+#define MAX_CHANNELS 1
+#else
+#define MAX_CHANNELS 2
+#endif
+
+#define AACENC_BLOCKSIZE 1024 /*! encoder only takes BLOCKSIZE samples at a time */
+#define AACENC_TRANS_FAC 8 /*! encoder short long ratio */
+#define AACENC_PCM_LEVEL 1.0 /*! encoder pcm 0db refernence */
+
+
+/*-------------------------- defines --------------------------------------*/
+
+#define BUFFERSIZE 1024 /* anc data */
+
+/*-------------------- structure definitions ------------------------------*/
+
+typedef struct {
+ int sampleRate; /* audio file sample rate */
+ int bitRate; /* encoder bit rate in bits/sec */
+ int nChannelsIn; /* number of channels on input (1,2) */
+ int nChannelsOut; /* number of channels on output (1,2) */
+ int bandWidth; /* core coder audio bandwidth in Hz */
+} AACENC_CONFIG;
+
+struct AAC_ENCODER;
+
+/*
+ * p u b l i c a n c i l l a r y
+ *
+ */
+
+
+/*-----------------------------------------------------------------------------
+
+ 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
+
+ ---------------------------------------------------------------------------*/
+
+int AacEncOpen
+( struct AAC_ENCODER** phAacEnc, /* pointer to an encoder handle, initialized on return */
+ const AACENC_CONFIG config /* pre-initialized config struct */
+);
+
+int AacEncEncode(struct AAC_ENCODER *hAacEnc,
+ float *timeSignal,
+ unsigned int timeInStride,
+ const unsigned char *ancBytes, /*!< pointer to ancillary data bytes */
+ unsigned int *numAncBytes, /*!< number of ancillary Data Bytes, send as fill element */
+ unsigned int *outBytes, /*!< pointer to output buffer */
+ int *numOutBytes /*!< number of bytes in output buffer */
+ );
+
+
+/*---------------------------------------------------------------------------
+
+ functionname:AacEncClose
+ description: deallocate an encoder instance
+
+ ---------------------------------------------------------------------------*/
+
+void AacEncClose (struct AAC_ENCODER* hAacEnc); /* an encoder handle */
+
+#endif /* _aacenc_h_ */
1,604 libaacenc/adj_thr.c
@@ -0,0 +1,1604 @@
+/*
+ adjust thresholds
+*/
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+
+#include "adj_thr_data.h"
+#include "adj_thr.h"
+#include "qc_data.h"
+#include "line_pe.h"
+#include "minmax.h"
+
+#include "counters.h" /* the 3GPP instrumenting tool */
+
+#define redExp 0.25f
+#define invRedExp (1.0f/redExp)
+#define minSnrLimit 0.8f /* 1dB */
+
+/* values for avoid hole flag */
+enum _avoid_hole_state {
+ NO_AH =0,
+ AH_INACTIVE =1,
+ AH_ACTIVE =2
+};
+
+
+typedef struct {
+ PE_CHANNEL_DATA peChannelData[MAX_CHANNELS];
+ float pe;
+ float constPart;
+ float nActiveLines;
+ float offset;
+} PE_DATA;
+
+
+/* convert from bits to pe */
+float bits2pe(const float bits) {
+
+ COUNT_sub_start("bits2pe");
+ MULT(1); /* counting post-operation */
+ COUNT_sub_end();
+
+ return (bits * 1.18f);
+}
+
+/* loudness calculation (threshold to the power of redExp) */
+static void calcThreshExp(float thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const int nChannels)
+{
+ int ch, sfb,sfbGrp;
+
+ COUNT_sub_start("calcThreshExp");
+
+ LOOP(1);
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ PTR_INIT(1); /* counting operation above */
+
+ INDIRECT(2); LOOP(1);
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup) {
+
+ PTR_INIT(2); /* pointer for thrExp[][],
+ psyOutChan->sfbThreshold[]
+ */
+ INDIRECT(1); LOOP(1);
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ TRANS(1); STORE(1);
+ thrExp[ch][sfbGrp+sfb] = (float) pow(psyOutChan->sfbThreshold[sfbGrp+sfb], redExp);
+ }
+ }
+ }
+
+ COUNT_sub_end();
+}
+
+/* reduce minSnr requirements for bands with relative low energies */
+static void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ MINSNR_ADAPT_PARAM *msaParam,
+ const int nChannels)
+{
+ int ch, sfb, sfbOffs, nSfb;
+ float avgEn, dbRatio, minSnrRed;
+
+ COUNT_sub_start("adaptMinSnr");
+
+ LOOP(1);
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch];
+
+ PTR_INIT(1); /* counting operation above */
+
+ /* calc average energy per scalefactor band */
+ MOVE(2);
+ avgEn = 0.0f;
+ nSfb = 0;
+
+ INDIRECT(2); LOOP(1);
+ for (sfbOffs=0;
+ sfbOffs<psyOutChan->sfbCnt;
+ sfbOffs+=psyOutChan->sfbPerGroup) {
+
+ PTR_INIT(1); /* pointer for psyOutChan->sfbEnergy[] */
+ INDIRECT(1); LOOP(1);
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ ADD(1);
+ avgEn += psyOutChan->sfbEnergy[sfbOffs+sfb];
+
+ ADD(1);
+ nSfb++;
+ }
+ }
+
+ BRANCH(1);
+ if (nSfb > 0) {
+
+ DIV(1);
+ avgEn /= nSfb;
+ }
+
+ /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
+ INDIRECT(2); LOOP(1);
+ for (sfbOffs=0;
+ sfbOffs<psyOutChan->sfbCnt;
+ sfbOffs+=psyOutChan->sfbPerGroup) {
+
+ PTR_INIT(2); /* pointer for psyOutChan->sfbEnergy[],
+ psyOutChan->sfbMinSnr[]
+ */
+ INDIRECT(1); LOOP(1);
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ INDIRECT(1); MULT(1); ADD(1); BRANCH(1);
+ if (msaParam->startRatio*psyOutChan->sfbEnergy[sfbOffs+sfb] < avgEn) {
+
+ ADD(2); DIV(1); TRANS(1); MULT(1);
+ dbRatio = (float) (10.0*log10((FLT_MIN+avgEn) /
+ (FLT_MIN+psyOutChan->sfbEnergy[sfbOffs+sfb])));
+
+ INDIRECT(1); MULT(1); ADD(1);
+ minSnrRed = msaParam->redOffs + msaParam->redRatioFac * dbRatio;
+
+ INDIRECT(1); ADD(1); BRANCH(1); MOVE(1);
+ minSnrRed = max(minSnrRed, msaParam->maxRed);
+
+ TRANS(1); STORE(1);
+ psyOutChan->sfbMinSnr[sfbOffs+sfb] =
+ (float)pow(psyOutChan->sfbMinSnr[sfbOffs+sfb], minSnrRed);
+
+ ADD(1); BRANCH(1); MOVE(1);
+ psyOutChan->sfbMinSnr[sfbOffs+sfb] =
+ min(minSnrLimit, psyOutChan->sfbMinSnr[sfbOffs+sfb]);
+ }
+ }
+ }
+
+ }
+
+ COUNT_sub_end();
+}
+
+/* determine bands where avoid hole is not necessary resp. possible */
+static void initAvoidHoleFlag(int ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT* psyOutElement,
+ const int nChannels,
+ AH_PARAM *ahParam)
+{
+ int ch, sfb,sfbGrp;
+ float sfbEn;
+ float scaleSprEn;
+
+ COUNT_sub_start("initAvoidHoleFlag");
+
+ /* decrease spreaded energy by 3dB for long blocks, resp. 2dB for shorts
+ (avoid more holes in long blocks) */
+ LOOP(1);
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ PTR_INIT(1); /* counting operation above */
+
+ INDIRECT(1); ADD(1); BRANCH(1);
+ if (psyOutChan->windowSequence != SHORT_WINDOW) {
+
+ MOVE(1);
+ scaleSprEn = 0.5f;
+ }
+ else {
+
+ MOVE(1);
+ scaleSprEn = 0.63f;
+ }
+
+ INDIRECT(2); LOOP(1);
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+
+ PTR_INIT(1); /* pointer for psyOutChan->sfbSpreadedEnergy[] */
+ LOOP(1);
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ MULT(1); STORE(1);
+ psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] *= scaleSprEn;
+ }
+ }
+ }
+
+
+ /* increase minSnr for local peaks, decrease it for valleys */
+
+ INDIRECT(1); BRANCH(1);
+ if (ahParam->modifyMinSnr) {
+
+ LOOP(1);
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ PTR_INIT(1); /* counting operation above */
+
+ INDIRECT(2); LOOP(1);
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+
+ PTR_INIT(3); /* pointers for psyOutChan->sfbEnergy[sfbGrp],
+ psyOutChan->sfbEnergy[sfbGrp+sfb],
+ psyOutChan->sfbMinSnr[]
+ */
+ INDIRECT(1); LOOP(1);
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ float sfbEnm1, sfbEnp1, avgEn;
+
+ BRANCH(1); MOVE(1);
+ if (sfb > 0)
+ sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1];
+ else
+ sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp];
+
+ INDIRECT(1); ADD(2); BRANCH(1); MOVE(1);
+ if (sfb < psyOutChan->maxSfbPerGroup-1)
+ sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1];
+ else
+ sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb];
+
+ ADD(1); MULT(1);
+ avgEn = (sfbEnm1 + sfbEnp1)/(float)2.0f;
+
+ MOVE(1);
+ sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];
+
+ /* peak ? */
+ ADD(1); BRANCH(1);
+ if (sfbEn > avgEn) {
+ float tmpMinSnr = max((float)0.8f*avgEn/sfbEn,
+ (float)0.316f);
+
+ MULT(1); DIV(1); ADD(