diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-02-15 02:44:20 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-02-15 02:44:20 +0100 |
commit | 22f1fce330059ef8a383cf327a023d6a9da5ad3e (patch) | |
tree | 6893f158dcaaaa1b9f1317923c32a841ba31f768 | |
parent | 891bb2592944aa2be2d81e1583e73e632e70537f (diff) | |
download | fdk-aac-22f1fce330059ef8a383cf327a023d6a9da5ad3e.tar.gz fdk-aac-22f1fce330059ef8a383cf327a023d6a9da5ad3e.tar.bz2 fdk-aac-22f1fce330059ef8a383cf327a023d6a9da5ad3e.zip |
Include toolame-dab as library
78 files changed, 16763 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 38fc7c0..13c9f54 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,6 +19,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/libPCMutils/include libfdk_aac_la_LINK = $(LINK) $(libfdk_aac_la_LDFLAGS) +libtoolame_dab_la_LINK = $(LINK) $(libtoolame_dab_la_LDFLAGS) # Mention a dummy pure C file to trigger generation of the $(LINK) variable nodist_EXTRA_libfdk_aac_la_SOURCES = dummy.c @@ -30,14 +31,56 @@ fdk_aacinclude_HEADERS = \ $(top_srcdir)/libAACenc/include/aacenc_lib.h \ $(top_srcdir)/libAACdec/include/aacdecoder_lib.h +toolame_dabincludedir = $(includedir)/libtoolame-dab +toolame_dabinclude_HEADERS = \ + $(top_srcdir)/libtoolame-dab/absthr.h \ + $(top_srcdir)/libtoolame-dab/ath.h \ + $(top_srcdir)/libtoolame-dab/audio_read.h \ + $(top_srcdir)/libtoolame-dab/availbits.h \ + $(top_srcdir)/libtoolame-dab/bitstream.h \ + $(top_srcdir)/libtoolame-dab/common.h \ + $(top_srcdir)/libtoolame-dab/crc.h \ + $(top_srcdir)/libtoolame-dab/critband.h \ + $(top_srcdir)/libtoolame-dab/encode.h \ + $(top_srcdir)/libtoolame-dab/encode_new.h \ + $(top_srcdir)/libtoolame-dab/encoder.h \ + $(top_srcdir)/libtoolame-dab/enwindow.h \ + $(top_srcdir)/libtoolame-dab/fft.h \ + $(top_srcdir)/libtoolame-dab/freqtable.h \ + $(top_srcdir)/libtoolame-dab/ieeefloat.h \ + $(top_srcdir)/libtoolame-dab/mem.h \ + $(top_srcdir)/libtoolame-dab/musicin.h \ + $(top_srcdir)/libtoolame-dab/options.h \ + $(top_srcdir)/libtoolame-dab/portableio.h \ + $(top_srcdir)/libtoolame-dab/psycho_0.h \ + $(top_srcdir)/libtoolame-dab/psycho_1.h \ + $(top_srcdir)/libtoolame-dab/psycho_1_priv.h \ + $(top_srcdir)/libtoolame-dab/psycho_2.h \ + $(top_srcdir)/libtoolame-dab/psycho_3.h \ + $(top_srcdir)/libtoolame-dab/psycho_3priv.h \ + $(top_srcdir)/libtoolame-dab/psycho_4.h \ + $(top_srcdir)/libtoolame-dab/psycho_n1.h \ + $(top_srcdir)/libtoolame-dab/subband.h \ + $(top_srcdir)/libtoolame-dab/tables.h \ + $(top_srcdir)/libtoolame-dab/toolame.h \ + $(top_srcdir)/libtoolame-dab/utils.h \ + $(top_srcdir)/libtoolame-dab/xpad.h \ + $(top_srcdir)/libtoolame-dab/zmqoutput.h \ + $(top_srcdir)/libtoolame-dab/vlc_input.h + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = fdk-aac-dabplus.pc -lib_LTLIBRARIES = libfdk-aac.la +lib_LTLIBRARIES = libfdk-aac.la libtoolame-dab.la + +libtoolame_dab_la_CXXFLAGS = -fomit-frame-pointer +libtoolame_dab_la_LDFLAGS = -version-info @LIBTOOLAME_DAB_VERSION@ \ + -no-undefined \ + -export-symbols $(top_srcdir)/libtoolame-dab.sym libfdk_aac_la_CXXFLAGS = -fno-exceptions -fno-rtti -Wno-narrowing libfdk_aac_la_LDFLAGS = -version-info @FDK_AAC_VERSION@ -no-undefined \ - -export-symbols $(top_srcdir)/fdk-aac.sym + -export-symbols $(top_srcdir)/fdk-aac.sym #aac_enc_LDADD = libfdk-aac.la #aac_enc_SOURCES = src/aac-enc.c \ @@ -51,7 +94,8 @@ endif dabplus_enc_LDFLAGS = -no-install -dabplus_enc_LDADD = libfdk-aac.la -lfec -lzmq -lasound \ +dabplus_enc_LDADD = libfdk-aac.la libtoolame-dab.la \ + -lfec -lzmq -lasound \ -lrt $(dabplus_enc_LDADD_JACK) \ $(LIBVLC_LIBS) dabplus_enc_CPPFLAGS = $(AM_CPPFLAGS) $(GITVERSION_FLAGS) -ggdb -O2 @@ -230,6 +274,34 @@ libfdk_aac_la_SOURCES = \ $(SBRDEC_SRC) $(SBRENC_SRC) \ $(PCMUTILS_SRC) $(FDK_SRC) $(SYS_SRC) +libtoolame_dab_la_SOURCES = \ + libtoolame-dab/common.c \ + libtoolame-dab/encode.c \ + libtoolame-dab/ieeefloat.c \ + libtoolame-dab/toolame.c \ + libtoolame-dab/portableio.c \ + libtoolame-dab/psycho_n1.c \ + libtoolame-dab/psycho_0.c \ + libtoolame-dab/psycho_1.c \ + libtoolame-dab/psycho_2.c \ + libtoolame-dab/psycho_3.c \ + libtoolame-dab/psycho_4.c \ + libtoolame-dab/fft.c \ + libtoolame-dab/subband.c \ + libtoolame-dab/audio_read.c \ + libtoolame-dab/bitstream.c \ + libtoolame-dab/mem.c \ + libtoolame-dab/crc.c \ + libtoolame-dab/tables.c \ + libtoolame-dab/availbits.c \ + libtoolame-dab/ath.c \ + libtoolame-dab/encode_new.c \ + libtoolame-dab/zmqoutput.c \ + libtoolame-dab/utils.c \ + libtoolame-dab/xpad.c \ + libtoolame-dab/vlc_input.c + + EXTRA_DIST = \ $(top_srcdir)/bootstrap \ $(top_srcdir)/NOTICE \ diff --git a/configure.ac b/configure.ac index 8aa842f..95b8029 100644 --- a/configure.ac +++ b/configure.ac @@ -74,9 +74,11 @@ dnl soname version to use dnl goes by ‘current[:revision[:age]]’ with the soname ending up as dnl current.age.revision FDK_AAC_VERSION=0:4:0 +LIBTOOLAME_DAB_VERSION=0:1:0 AS_IF([test x$enable_shared = xyes], [LIBS_PRIVATE=$LIBS], [LIBS_PUBLIC=$LIBS]) AC_SUBST(FDK_AAC_VERSION) +AC_SUBST(LIBTOOLAME_DAB_VERSION) AC_SUBST(LIBS_PUBLIC) AC_SUBST(LIBS_PRIVATE) diff --git a/libtoolame-dab.sym b/libtoolame-dab.sym new file mode 100644 index 0000000..9fa2b97 --- /dev/null +++ b/libtoolame-dab.sym @@ -0,0 +1 @@ +toolame_encode_frame diff --git a/libtoolame-dab/HISTORY b/libtoolame-dab/HISTORY new file mode 100644 index 0000000..ba53e4a --- /dev/null +++ b/libtoolame-dab/HISTORY @@ -0,0 +1,127 @@ +v0.1a - initial release (7 Nov 1998) + +v0.1b - released 1 Oct 99 + - filter subband and window subband from Lame3.x added + - cleaned up some memory stuff in psy.c + - a fast mode switch (-f) which turns off psychoacoustics + -instead of having the psymodel calculate SNR + just use a bunch of preset values. I just made up + some SNR values based upon my test file. These + could probably be tuned so that there's a set of SNR + values for rock, pop, classical, voice etc. + +v0.1d - released 14 Oct 99 + - cleaned up some code + - removed decoding source code (use mpg123 instead :) + - renamed subs.c to fft.c (which is mostly what it does :) + - moved the filter/window_subband into subband.c + - split encode.c into generic code (encode), LayerI code (encodeI) + and layerII code (encodeII) + - no longer use obtain_parameters(). interactive input is a pain + +v0.1e - released 15 Oct 99 + - cleaned up some code + - defaults to 192kbps, psy model 1 with extension mp2 (see encoder.h) + - added (-a) downmix to mono option (code in encode.c/get_audio() ) + - transplanted FHT-based fft() from LAME. + - II_f_f_t() now calls fht(). heaps faster. (in tonal.c used by psymodel 1) + This could be neater though. + - PDS's II_scale_factor_calc() put in encodeII.c + +v0.1f - released 16 Oct 99 + - PDS's updated scale_factor_calc + - integrated a few functions in tonal.c/II_psycho_one() which gave about a 15% + speedup when using psymodel 1 + +v0.1g - released + - tweaked tonal.c/threshold() 10-15% improvement in this routine. + +v0.2a - released 24 october 1999 + - changed base source code from mpegaudio.tar to the dist10/lsf/encoder. This new code includes lower sampling frequency (LSF) extensions. + - added in most of the changes already done. + - LSF mode is faulty. Seg faults after about 190 frames here. LSF mode works if you turn off psy models though (-f) + +v0.2b - released 30 October 1999 + - added a "-q n" mode. will only calculate the psy model every n frames. + "-q 0" is equivalent to "-f". + - reimplemented "downmix to mono" -a switch + - WAV file support from Nick Burch <gagravarr@SoftHome.net> + - some code cleanup - removed more LayerI & III stuff. + +v0.2c - skipped this release + +v0.2d - released 6 November 1999 + - used Mathew Hendry's enhanced fht() with table lookup (20% faster) + - made add_db an inline function and tweaked it (25% faster) + - code cleanup - renamed psy.c->psycho_II.c, tonal.c->psycho_I.c, other misc stuff + - added a "no padding" (-r) switch. Needed by the rfa.org (thanks to Federico Grau) + - tweaked threshold 33% speedup. + +v0.2e - released 14 December 1999 + - Some minor speedups from PDS in encode.c + - Changed // comments to /* */ style + - Merged some functions in subband.c + - Cleaned up file input parsing a little. + - Now reads PCM from /dev/stdin if this is specified as input filename (kludgy but works for me) + - Started putting tables into exe. (only enwindow done so far) + +v0.2f - released 15 April 2000 + - mainly cosmetic changes in the source and code layout + - removed a lot of unused functions, and split common.c into more logical subumits. + - about 15-20% faster when using psymodel I. (merged some functions in psycho_i.c) + +v0.2g - released 22 April 2000 + - added a VBR mode. See README.VBR + - cleaned up more code. + +v0.2h - stdio/stdout now parse a little better using '-' + - tables now included in the exe thanks to Oliver Lietz <lietz@nanocosmos.de> + (I haven't had a chance to test it much though) + - including the tables in the exe seems to have boosted speed quite a bit (25%?) + - re-implemented byte-swapping in get_audio.c (command line switch -x ) + +v0.2i - Released 13 July 2001 + - DAB extensions from Phillipe Jouguet <philippe.jouguet@vdldiffusion.com> + - Added a switch to swap the input channels (can someone confirm that toolame + swaps them incorrectly by default) + +v0.2j - Released 13 February 2003 + - Definitely LGPL + - VBR mode is stable for all sampling frequencies. (See README.VBR for details) + - speedups and cleanups from + Phillipe Jouguet - philippe.jouguet at vdl.fr + (spelling, LSF using psyII, WAVE reading) + Henrik Herranen - leopold at vlsi.fi + (WAVE reading) + Andreas Neukoetter - anti at webhome.de + (verbosity patch '-t' switch for transcode plugin) + Sami Sallinen - sami.sallinen at g-cluster.com + filter_subband loop unroll + psycho_i fix for "% 1408" calcs) + +v0.2k - Released 16 February 2003 + - Nicolas Croiset + unlimited file read size for stdin + fixed bitstream ending so that mp2 files can be concatenated + DAB options now comes with a size argument + (finally?) fixed the core dump in psycho_1 + - Ricardo Schelp ricardoschelp at arnet.com.ar + combined window/filter subband routine. nice speed increase. + +v0.2l - Released 3 March 2003 + - Added new psychomodels + -1 use precomputed values + 0 very low complexity + 1 same old psy model 1 + 2 same old psy model 2 + 3 psy model 1 rewritten from scratch + 4 rewritten psy model 2 + - Rewrote the bitstream encoding routines + - Sped up the sin/cos/atan stuff in psymodel 4 (using tables now) + +v0.2l with ZMQ output - February 2014 + - added outputzmq.{h, c} + Matthias P. Braendli + - integrate into FDK-AAC-DABplus in February 2016 + +mike (mikecheng at NOT planckenergy.com) [remove the NOT] diff --git a/libtoolame-dab/LGPL.txt b/libtoolame-dab/LGPL.txt new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/libtoolame-dab/LGPL.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/libtoolame-dab/README.md b/libtoolame-dab/README.md new file mode 100644 index 0000000..234cd01 --- /dev/null +++ b/libtoolame-dab/README.md @@ -0,0 +1,114 @@ +tooLAME - an optimized mpeg 1/2 layer 2 audio encoder, in form +of a library to be used with the encoder for the ODR-mmbTools + +Copyright (C) 2002, 2003 Michael Cheng [mikecheng at NOT planckenergy.com] remove the NOT +http://www.planckenergy.com/ + +Copyright (C) 2014, 2015, 2016 Matthias P. Braendli [matthias.braendli@mpb.li] +http://opendigitalradio.org/ + +All changes to the ISO source are licensed under the LGPL +(see LGPL.txt for details) + +tooLAME is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +tooLAME is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with tooLAME; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +********************* +INTRODUCTION +********************* + +tooLAME is an optimized Mpeg Audio 1/2 Layer 2 encoder. It is based heavily on + - the ISO dist10 code + - improvement to algorithms as part of the LAME project (www.sulaco.org/mp3) + - work by Mike Cheng and other contributors (see CONTRIBUTORS) + +********************* +CONTRIBUTORS +********************* + +Dist10 code writers +LAME specific contributions + fht routines from Ron Mayer <mayer at acuson.com> + fht tweaking by Mathew Hendry <math at vissci.com> + window_subband & filter_subband from LAME circa v3.30 + (multiple LAME authors) + (before Takehiro's window/filter/mdct combination) + +Oliver Lietz <lietz at nanocosmos.de> + Tables now included in the exe! (yay! :) + +Patrick de Smet <pds at telin.rug.ac.be> + scale_factor calc speedup. + subband_quantization speedup + +Federico Grau <grauf at rfa.org> +Bill Eldridge <bill at hk.rfa.org> + option for "no padding" + +Nick Burch <gagravarr at SoftHome.net> + WAV file reading + os/2 Makefile mods. + +Phillipe Jouguet <philippe.jouguet at vdldiffusion.com> + DAB extensions + spelling, LSF using psyII, WAVE reading + +Henrik Herranen - leopold at vlsi.fi + (WAVE reading) + +Andreas Neukoetter - anti at webhome.de + (verbosity patch '-t' switch for transcode plugin) + +Sami Sallinen - sami.sallinen at g-cluster.com + (filter_subband loop unroll + psycho_i fix for "% 1408" calcs) + +Mike Cheng <mikecheng at NOT planckenergy.com> (remove the NOT) + Most of the rest + +Matthias P. Braendli <matthias@mpb.li> + PAD insertion for DLS and slides + Integration into FDK-AAC-DABplus + +********************* +REFERENCE PAPERS +********************* +(Specifically LayerII Papers) + +Kumar, M & Zubair, M., A high performance software implementation of mpeg audio +encoder, 1996, ICASSP Conf Proceedings (I think) + +Fischer, K.A., Calculation of the psychoacoustic simultaneous masked threshold +based on MPEG/Audio Encoder Model One, ICSI Technical Report, 1997 +ftp://ftp.icsi.berkeley.edu/pub/real/kyrill/PsychoMpegOne.tar.Z + +Hyen-O et al, New Implementation techniques of a real-time mpeg-2 audio encoding +system. p2287, ICASSP 99. + +Imai, T., et al, MPEG-1 Audio real-time encoding system, IEEE Trans on Consumer +Electronics, v44, n3 1998. p888 + +Teh, D., et al, Efficient bit allocation algorithm for ISO/MPEG audio encoder, +Electronics Letters, v34, n8, p721 + +Murphy, C & Anandakumar, K, Real-time MPEG-1 audio coding and decoding on a DSP +Chip, IEEE Trans on Consumer Electronics, v43, n1, 1997 p40 + +Hans, M & Bhaskaran, V., A compliant MPEG-1 layer II audio decoder with 16-B +arithmetic operations, IEEE Signal Proc Letters v4 n5 1997 p121 + +[mikecheng at NOT planckenergy.com] remove the NOT +and +[matthias.braendli@mpb.li] diff --git a/libtoolame-dab/absthr.h b/libtoolame-dab/absthr.h new file mode 100644 index 0000000..bc124e1 --- /dev/null +++ b/libtoolame-dab/absthr.h @@ -0,0 +1,2057 @@ +static const double absthr_table[4][HBLKSIZE] = { + {10156347392.00, + 33708348.00, + 3987838.75, + 1269806.88, + 614805.19, + 372166.75, + 256884.33, + 192636.06, + 153016.27, + 126980.66, + 108576.95, + 95003.05, + 84671.56, + 76513.41, + 70103.16, + 64824.27, + 60358.38, + 56720.18, + 53424.14, + 50668.45, + 48276.70, + 46103.89, + 44232.10, + 42534.13, + 40995.63, + 39603.86, + 38347.55, + 37131.08, + 36036.08, + 35054.00, + 34098.68, + 33169.40, + 32339.82, + 31530.99, + 30742.39, + 29973.51, + 29291.23, + 28624.48, + 27972.91, + 27336.16, + 26652.48, + 26045.79, + 25452.92, + 24873.54, + 24307.35, + 23754.04, + 23159.95, + 22632.76, + 21514.81, + 21514.81, + 20452.08, + 20452.08, + 19397.13, + 19397.13, + 18354.29, + 18354.29, + 17327.57, + 17327.57, + 16320.66, + 16320.66, + 15336.90, + 15336.90, + 14412.44, + 14412.44, + 13481.48, + 13481.48, + 12610.65, + 12610.65, + 11796.08, + 11796.08, + 10983.42, + 10983.42, + 10250.32, + 10250.32, + 9544.16, + 9544.16, + 8907.13, + 8907.13, + 8312.61, + 8312.61, + 7775.67, + 7775.67, + 7273.40, + 7273.40, + 6834.99, + 6834.99, + 6452.64, + 6452.64, + 6105.73, + 6105.73, + 5804.14, + 5804.14, + 5542.91, + 5542.91, + 5330.13, + 5330.13, + 5031.96, + 5031.96, + 5031.96, + 5031.96, + 4872.34, + 4872.34, + 4872.34, + 4872.34, + 4861.13, + 4861.13, + 4861.13, + 4861.13, + 4985.83, + 4985.83, + 4985.83, + 4985.83, + 5257.00, + 5257.00, + 5257.00, + 5257.00, + 5685.09, + 5685.09, + 5685.09, + 5685.09, + 6262.35, + 6262.35, + 6262.35, + 6262.35, + 6994.19, + 6994.19, + 6994.19, + 6994.19, + 7902.01, + 7902.01, + 7902.01, + 7902.01, + 8968.87, + 8968.87, + 8968.87, + 8968.87, + 10156.35, + 10156.35, + 10156.35, + 10156.35, + 11474.60, + 11474.60, + 11474.60, + 11474.60, + 12874.71, + 12874.71, + 12874.71, + 12874.71, + 14280.31, + 14280.31, + 14280.31, + 14280.31, + 15694.14, + 15694.14, + 15694.14, + 15694.14, + 17050.52, + 17050.52, + 17050.52, + 17050.52, + 18312.08, + 18312.08, + 18312.08, + 18312.08, + 19486.67, + 19486.67, + 19486.67, + 19486.67, + 20546.49, + 20546.49, + 20546.49, + 20546.49, + 21514.81, + 21514.81, + 21514.81, + 21514.81, + 22373.69, + 22373.69, + 22373.69, + 22373.69, + 23159.95, + 23159.95, + 23159.95, + 23159.95, + 23918.70, + 23918.70, + 23918.70, + 23918.70, + 24645.50, + 24645.50, + 24645.50, + 24645.50, + 26105.83, + 26105.83, + 26105.83, + 26105.83, + 26105.83, + 26105.83, + 26105.83, + 26105.83, + 27716.45, + 27716.45, + 27716.45, + 27716.45, + 27716.45, + 27716.45, + 27716.45, + 27716.45, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 31676.53, + 31676.53, + 31676.53, + 31676.53, + 31676.53, + 31676.53, + 31676.53, + 31676.53, + 34256.07, + 34256.07, + 34256.07, + 34256.07, + 34256.07, + 34256.07, + 34256.07, + 34256.07, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 41184.86, + 41184.86, + 41184.86, + 41184.86, + 41184.86, + 41184.86, + 41184.86, + 41184.86, + 45997.86, + 45997.86, + 45997.86, + 45997.86, + 45997.86, + 45997.86, + 45997.86, + 45997.86, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 59120.43, + 59120.43, + 59120.43, + 59120.43, + 59120.43, + 59120.43, + 59120.43, + 59120.43, + 68192.65, + 68192.65, + 68192.65, + 68192.65, + 68192.65, + 68192.65, + 68192.65, + 68192.65, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 94784.55, + 94784.55, + 94784.55, + 94784.55, + 94784.55, + 94784.55, + 94784.55, + 94784.55, + 114482.10, + 114482.10, + 114482.10, + 114482.10, + 114482.10, + 114482.10, + 114482.10, + 114482.10, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 174476.75, + 174476.75, + 174476.75, + 174476.75, + 174476.75, + 174476.75, + 174476.75, + 174476.75, + 220667.11, + 220667.11, + 220667.11, + 220667.11, + 220667.11, + 220667.11, + 220667.11, + 220667.11, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 374746.47, + 374746.47, + 374746.47, + 374746.47, + 374746.47, + 374746.47, + 374746.47, + 374746.47, + 503196.50, + 503196.50, + 503196.50, + 503196.50, + 503196.50, + 503196.50, + 503196.50, + 503196.50, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 965467.38, + 965467.38, + 965467.38, + 965467.38, + 965467.38, + 965467.38, + 965467.38, + 965467.38, + 1382730.50, + 1382730.50, + 1382730.50, + 1382730.50, + 1382730.50, + 1382730.50, + 1382730.50, + 1382730.50, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 3053076.00, + 3053076.00, + 3053076.00, + 3053076.00, + 3053076.00, + 3053076.00, + 3053076.00, + 3053076.00, + 4717778.50, + 4717778.50, + 4717778.50, + 4717778.50, + 4717778.50, + 4717778.50, + 4717778.50, + 4717778.50, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 12210618.00, + 12210618.00, + 12210618.00, + 12210618.00, + 12210618.00, + 12210618.00, + 12210618.00, + 12210618.00, + 20499234.00, + 20499234.00, + 20499234.00, + 20499234.00, + 20499234.00, + 20499234.00, + 20499234.00, + 20499234.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 63494696.00, + 63494696.00, + 63494696.00, + 63494696.00, + 63494696.00, + 63494696.00, + 63494696.00, + 63494696.00, + 117418800.00, + 117418800.00, + 117418800.00, + 117418800.00, + 117418800.00, + 117418800.00, + 117418800.00, + 117418800.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 443340800.00, + 443340800.00, + 443340800.00, + 443340800.00, + 443340800.00, + 443340800.00, + 443340800.00, + 443340800.00, + 911459584.00, + 911459584.00, + 911459584.00, + 911459584.00, + 911459584.00, + 911459584.00, + 911459584.00, + 911459584.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 1935251712.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00}, + + {488357088.00, + 5898447.00, + 1131716.50, + 466377.53, + 265911.78, + 180192.88, + 135125.59, + 108078.07, + 90518.55, + 78295.64, + 69141.30, + 62335.81, + 56981.98, + 52569.95, + 49061.14, + 45997.86, + 43524.88, + 41279.80, + 39331.23, + 37647.63, + 36119.16, + 34732.62, + 33399.32, + 32265.44, + 31170.05, + 30111.86, + 29156.65, + 28231.74, + 27336.16, + 26469.00, + 25629.35, + 24816.33, + 24029.10, + 23266.85, + 22476.96, + 21713.89, + 20976.72, + 20264.58, + 19531.59, + 18781.82, + 18102.46, + 17367.51, + 16700.81, + 16022.77, + 15336.90, + 14680.39, + 14051.98, + 13419.54, + 12238.76, + 12238.76, + 11136.21, + 11136.21, + 10109.68, + 10109.68, + 9177.78, + 9177.78, + 8331.78, + 8331.78, + 7598.67, + 7598.67, + 6962.06, + 6962.06, + 6408.22, + 6408.22, + 5953.02, + 5953.02, + 5581.33, + 5581.33, + 5293.44, + 5293.44, + 5078.52, + 5078.52, + 4928.76, + 4928.76, + 4861.13, + 4861.13, + 4849.95, + 4849.95, + 4917.42, + 4917.42, + 5043.56, + 5043.56, + 5232.84, + 5232.84, + 5504.75, + 5504.75, + 5844.37, + 5844.37, + 6262.35, + 6262.35, + 6756.75, + 6756.75, + 7323.82, + 7323.82, + 7975.13, + 7975.13, + 9500.31, + 9500.31, + 9500.31, + 9500.31, + 11239.26, + 11239.26, + 11239.26, + 11239.26, + 13174.60, + 13174.60, + 13174.60, + 13174.60, + 15126.47, + 15126.47, + 15126.47, + 15126.47, + 17011.30, + 17011.30, + 17011.30, + 17011.30, + 18738.62, + 18738.62, + 18738.62, + 18738.62, + 20264.58, + 20264.58, + 20264.58, + 20264.58, + 21614.12, + 21614.12, + 21614.12, + 21614.12, + 22789.65, + 22789.65, + 22789.65, + 22789.65, + 23808.80, + 23808.80, + 23808.80, + 23808.80, + 24816.33, + 24816.33, + 24816.33, + 24816.33, + 25807.00, + 25807.00, + 25807.00, + 25807.00, + 26837.22, + 26837.22, + 26837.22, + 26837.22, + 27972.91, + 27972.91, + 27972.91, + 27972.91, + 29223.86, + 29223.86, + 29223.86, + 29223.86, + 30671.68, + 30671.68, + 30671.68, + 30671.68, + 32265.44, + 32265.44, + 32265.44, + 32265.44, + 34098.68, + 34098.68, + 34098.68, + 34098.68, + 36119.16, + 36119.16, + 36119.16, + 36119.16, + 38524.55, + 38524.55, + 38524.55, + 38524.55, + 41279.80, + 41279.80, + 41279.80, + 41279.80, + 44436.27, + 44436.27, + 44436.27, + 44436.27, + 48054.89, + 48054.89, + 48054.89, + 48054.89, + 52328.41, + 52328.41, + 52328.41, + 52328.41, + 62912.59, + 62912.59, + 62912.59, + 62912.59, + 62912.59, + 62912.59, + 62912.59, + 62912.59, + 77756.66, + 77756.66, + 77756.66, + 77756.66, + 77756.66, + 77756.66, + 77756.66, + 77756.66, + 98568.38, + 98568.38, + 98568.38, + 98568.38, + 98568.38, + 98568.38, + 98568.38, + 98568.38, + 128451.02, + 128451.02, + 128451.02, + 128451.02, + 128451.02, + 128451.02, + 128451.02, + 128451.02, + 172877.14, + 172877.14, + 172877.14, + 172877.14, + 172877.14, + 172877.14, + 172877.14, + 172877.14, + 240291.06, + 240291.06, + 240291.06, + 240291.06, + 240291.06, + 240291.06, + 240291.06, + 240291.06, + 346527.44, + 346527.44, + 346527.44, + 346527.44, + 346527.44, + 346527.44, + 346527.44, + 346527.44, + 517294.19, + 517294.19, + 517294.19, + 517294.19, + 517294.19, + 517294.19, + 517294.19, + 517294.19, + 806747.31, + 806747.31, + 806747.31, + 806747.31, + 806747.31, + 806747.31, + 806747.31, + 806747.31, + 1308391.13, + 1308391.13, + 1308391.13, + 1308391.13, + 1308391.13, + 1308391.13, + 1308391.13, + 1308391.13, + 2227088.75, + 2227088.75, + 2227088.75, + 2227088.75, + 2227088.75, + 2227088.75, + 2227088.75, + 2227088.75, + 3969516.00, + 3969516.00, + 3969516.00, + 3969516.00, + 3969516.00, + 3969516.00, + 3969516.00, + 3969516.00, + 7442819.50, + 7442819.50, + 7442819.50, + 7442819.50, + 7442819.50, + 7442819.50, + 7442819.50, + 7442819.50, + 14714232.00, + 14714232.00, + 14714232.00, + 14714232.00, + 14714232.00, + 14714232.00, + 14714232.00, + 14714232.00, + 30742394.00, + 30742394.00, + 30742394.00, + 30742394.00, + 30742394.00, + 30742394.00, + 30742394.00, + 30742394.00, + 68349824.00, + 68349824.00, + 68349824.00, + 68349824.00, + 68349824.00, + 68349824.00, + 68349824.00, + 68349824.00, + 161338400.00, + 161338400.00, + 161338400.00, + 161338400.00, + 161338400.00, + 161338400.00, + 161338400.00, + 161338400.00, + 407134048.00, + 407134048.00, + 407134048.00, + 407134048.00, + 407134048.00, + 407134048.00, + 407134048.00, + 407134048.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 1100874368.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 3196962048.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 10016993280.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 34020253696.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 124950298624.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00}, + + {247592464.00, + 3987838.75, + 852584.69, + 372166.75, + 220667.11, + 153016.27, + 116879.30, + 95003.05, + 80489.19, + 70103.16, + 62479.50, + 56720.18, + 52087.99, + 48276.70, + 45158.30, + 42534.13, + 40247.38, + 38347.55, + 36537.39, + 35054.00, + 33630.83, + 32339.82, + 31098.37, + 29973.51, + 28955.93, + 27972.91, + 26961.10, + 26045.79, + 25161.56, + 24307.35, + 23428.13, + 22632.76, + 21814.11, + 20976.72, + 20171.47, + 19397.13, + 18609.62, + 17813.02, + 17089.82, + 16320.66, + 15586.10, + 14884.61, + 14182.00, + 13481.48, + 12845.10, + 12210.62, + 11580.77, + 10983.42, + 9902.33, + 9902.33, + 8907.13, + 8907.13, + 8030.41, + 8030.41, + 7273.40, + 7273.40, + 6633.42, + 6633.42, + 6105.73, + 6105.73, + 5672.02, + 5672.02, + 5330.13, + 5330.13, + 5090.23, + 5090.23, + 4928.76, + 4928.76, + 4849.95, + 4849.95, + 4861.13, + 4861.13, + 4940.12, + 4940.12, + 5101.97, + 5101.97, + 5354.73, + 5354.73, + 5685.09, + 5685.09, + 6091.69, + 6091.69, + 6602.94, + 6602.94, + 7206.72, + 7206.72, + 7902.01, + 7902.01, + 8684.36, + 8684.36, + 9544.16, + 9544.16, + 10489.08, + 10489.08, + 11474.60, + 11474.60, + 13574.93, + 13574.93, + 13574.93, + 13574.93, + 15694.14, + 15694.14, + 15694.14, + 15694.14, + 17690.40, + 17690.40, + 17690.40, + 17690.40, + 19486.67, + 19486.67, + 19486.67, + 19486.67, + 21025.08, + 21025.08, + 21025.08, + 21025.08, + 22373.69, + 22373.69, + 22373.69, + 22373.69, + 23536.27, + 23536.27, + 23536.27, + 23536.27, + 24645.50, + 24645.50, + 24645.50, + 24645.50, + 25747.65, + 25747.65, + 25747.65, + 25747.65, + 26899.09, + 26899.09, + 26899.09, + 26899.09, + 28102.02, + 28102.02, + 28102.02, + 28102.02, + 29494.26, + 29494.26, + 29494.26, + 29494.26, + 31098.37, + 31098.37, + 31098.37, + 31098.37, + 32865.30, + 32865.30, + 32865.30, + 32865.30, + 34973.38, + 34973.38, + 34973.38, + 34973.38, + 37388.46, + 37388.46, + 37388.46, + 37388.46, + 40154.81, + 40154.81, + 40154.81, + 40154.81, + 43424.77, + 43424.77, + 43424.77, + 43424.77, + 47286.54, + 47286.54, + 47286.54, + 47286.54, + 51848.66, + 51848.66, + 51848.66, + 51848.66, + 57113.34, + 57113.34, + 57113.34, + 57113.34, + 63348.68, + 63348.68, + 63348.68, + 63348.68, + 70914.91, + 70914.91, + 70914.91, + 70914.91, + 79935.11, + 79935.11, + 79935.11, + 79935.11, + 103929.20, + 103929.20, + 103929.20, + 103929.20, + 103929.20, + 103929.20, + 103929.20, + 103929.20, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 140196.64, + 195766.14, + 195766.14, + 195766.14, + 195766.14, + 195766.14, + 195766.14, + 195766.14, + 195766.14, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 284929.63, + 433249.00, + 433249.00, + 433249.00, + 433249.00, + 433249.00, + 433249.00, + 433249.00, + 433249.00, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 688236.44, + 1150105.38, + 1150105.38, + 1150105.38, + 1150105.38, + 1150105.38, + 1150105.38, + 1150105.38, + 1150105.38, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 2026457.63, + 3782140.25, + 3782140.25, + 3782140.25, + 3782140.25, + 3782140.25, + 3782140.25, + 3782140.25, + 3782140.25, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 7477175.00, + 15766581.00, + 15766581.00, + 15766581.00, + 15766581.00, + 15766581.00, + 15766581.00, + 15766581.00, + 15766581.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 35541636.00, + 86047336.00, + 86047336.00, + 86047336.00, + 86047336.00, + 86047336.00, + 86047336.00, + 86047336.00, + 86047336.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 224252560.00, + 632029568.00, + 632029568.00, + 632029568.00, + 632029568.00, + 632029568.00, + 632029568.00, + 632029568.00, + 632029568.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 1939713920.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 6497371136.00, + 23863681024.00, + 23863681024.00, + 23863681024.00, + 23863681024.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 96324681728.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00, + 60776765194240.00}, + + {15000.00, + 15000.00, + 15000.00, + 15000.00, + 15000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 5000.00, + 15000.00, + 15000.00, + 15000.00, + 15000.00, + 115000.00, + 215000.00, + 315000.00, + 415000.00, + 515000.00, + 615000.00, + 715000.00} +}; diff --git a/libtoolame-dab/ath.c b/libtoolame-dab/ath.c new file mode 100644 index 0000000..8544752 --- /dev/null +++ b/libtoolame-dab/ath.c @@ -0,0 +1,79 @@ +#include <stdio.h> +#include <math.h> +#include "common.h" +#include "ath.h" + + /* freq in hz */ +FLOAT8 ATH_dB(FLOAT8 f, FLOAT8 value) +{ + /* from Painter & Spanias + modified by Gabriel Bouvigne to better fit the reality + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + 0.6* 0.001 * pow(f,4.0); + + + In the past LAME was using the Painter &Spanias formula. + But we had some recurrent problems with HF content. + We measured real ATH values, and found the older formula + to be inacurate in the higher part. So we made this new + formula and this solved most of HF problematic testcases. + The tradeoff is that in VBR mode it increases a lot the + bitrate.*/ + + +/*this curve can be udjusted according to the VBR scale: +it adjusts from something close to Painter & Spanias +on V9 up to Bouvigne's formula for V0. This way the VBR +bitrate is more balanced according to the -V value.*/ + + FLOAT8 ath; + FLOAT8 valueold = 0.0; + + if (f < -.3) + f=3410; + + f /= 1000; // convert to khz + f = MAX(0.01, f); + f = MIN(18.0, f); + + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + (0.6+0.04*valueold)* 0.001 * pow(f,4.0); + + /* MFC Feb 2003 + I've changed the fudge technique on the code. + The "-l [float]" value raises/lowers the ATH by this many dB */ + return (ath + value); +} + + +/* Convert ATH values from dB into energy values as required by the psycho model */ +float ATH_energy(float freq, float value) { + float db; + db = ATH_dB(freq, 0) + value; // Originally: ATH_dB(freq,value) + /* The values in the standard, and from the ATH formula are in dB. + In the psycho model we are working in the energy domain. Hence the values that + are in the absthr_X tables are not in dB. This function converts from dB into the energy domain. + As noted on the LAME mailing list from years ago (MFC FIX find the reference), the + absolute threhsold of hearing values in the tables in the standard are dodgy - the + ATH in the tables do not correspond to any previously known values of the ATH. + From ISO 11172 Tables D.4.x + "A value of 0dB represents a level in the absolute threshold calculation of + 96dB below the energy of a sine wave of amplitude 32760." + But I still don't know why the factor of 41.837375 is the value that it is. MFC Feb 2003 */ + return(pow(10.0, (db+41.837375)*0.1)); +} + + +/* Convert a frequency (in Hz) to a bark value + Taken from LAME. MFC Feb 2003 + see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT8 freq2bark(FLOAT8 freq) +{ + if (freq<0) freq=0; + freq = freq * 0.001; + return 13.0*atan(.76*freq) + 3.5*atan(freq*freq/(7.5*7.5)); +} diff --git a/libtoolame-dab/ath.h b/libtoolame-dab/ath.h new file mode 100644 index 0000000..297f91f --- /dev/null +++ b/libtoolame-dab/ath.h @@ -0,0 +1,3 @@ +FLOAT8 ATH_dB(FLOAT8 f, FLOAT8 value); +FLOAT8 ATH_energy(FLOAT8 f, FLOAT8 value); +FLOAT8 freq2bark(FLOAT8 freq); diff --git a/libtoolame-dab/audio_read.c b/libtoolame-dab/audio_read.c new file mode 100644 index 0000000..3649ef4 --- /dev/null +++ b/libtoolame-dab/audio_read.c @@ -0,0 +1,689 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "common.h" +#include "encoder.h" +#include "options.h" +#include "portableio.h" +#if defined(JACK_INPUT) +#include <pthread.h> +#include <jack/jack.h> +#include <jack/ringbuffer.h> +#endif +#include "audio_read.h" +#include "vlc_input.h" + +#if defined(JACK_INPUT) +jack_port_t *input_port_left; +jack_port_t *input_port_right; +jack_client_t *client; +pthread_mutex_t encode_thread_lock = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER; + +/* shutdown can tell get_audio to stop */ +typedef struct _thread_info { + volatile int connected; +} jack_thread_info_t; + +jack_thread_info_t thread_info; +const size_t sample_size = sizeof(jack_default_audio_sample_t); + +#define DEFAULT_RB_SIZE 16384 /* ringbuffer size in frames */ +jack_ringbuffer_t *rb; + +/* setup_jack() + * + * PURPOSE: connect to jack, setup the ports, the ringbuffer + * + * frame_header is needed (fill information about sampling rate) + */ + +void setup_jack(frame_header *header, const char* jackname) { + const char *client_name = jackname; + const char *server_name = NULL; + jack_options_t options = JackNullOption; + jack_status_t status; + + /* open a client connection to the JACK server */ + + client = jack_client_open(client_name, options, &status, server_name); + if (client == NULL) { + fprintf(stderr, "jack_client_open() failed, " + "status = 0x%2.0x\n", status); + if (status & JackServerFailed) { + fprintf(stderr, "Unable to connect to JACK server\n"); + } + exit(1); + } + if (status & JackServerStarted) { + fprintf(stderr, "JACK server started\n"); + } + if (status & JackNameNotUnique) { + client_name = jack_get_client_name(client); + fprintf(stderr, "unique name `%s' assigned\n", client_name); + } + + thread_info.connected = 1; + + /* tell the JACK server to call `process()' whenever + there is work to be done. + */ + + jack_set_process_callback(client, process, &thread_info); + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. + */ + + jack_on_shutdown(client, jack_shutdown, &thread_info); + + /* display the current sample rate. + */ + + printf ("engine sample rate: %" PRIu32 "\n", + jack_get_sample_rate(client)); + + if ((header->sampling_frequency = SmpFrqIndex((long) jack_get_sample_rate(client), &header->version)) < 0) { + fprintf (stderr, "invalid sample rate\n"); + exit(1); + } + + /* create two ports */ + + input_port_left = jack_port_register(client, "input0", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0); + input_port_right = jack_port_register(client, "input1", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0); + + if ((input_port_left == NULL) || (input_port_right == NULL)) { + fprintf(stderr, "no more JACK ports available\n"); + exit(1); + } + + + /* setup the ringbuffer */ + rb = jack_ringbuffer_create(2 * sample_size * DEFAULT_RB_SIZE); + fprintf(stderr, "jack sample_size: %zu\n", sample_size); + + + /* take the mutex */ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_mutex_lock(&encode_thread_lock); + + /* Tell the JACK server that we are ready to roll. Our + * process() callback will start running now. */ + + if (jack_activate(client)) { + fprintf (stderr, "cannot activate client"); + exit(1); + } +} + +/** + * The process callback for this JACK application is called in a + * special realtime thread once for each audio cycle. + * + * It fills the ringbuffer + */ +int process(jack_nframes_t nframes, void *arg) { + int i; + int samp; + //jack_thread_info_t *info = (jack_thread_info_t *) arg; + + jack_default_audio_sample_t *in_left, *in_right; + in_left = jack_port_get_buffer(input_port_left, nframes); + in_right = jack_port_get_buffer(input_port_right, nframes); + + /* Sndfile requires interleaved data. It is simpler here to + * just queue interleaved samples to a single ringbuffer. */ + //fprintf(stderr, "process()\n"); + for (i = 0; i < nframes; i++) { + /* + jack_ringbuffer_write(rb, (void *)(in_left + i), sample_size); + jack_ringbuffer_write(rb, (void *)(in_right + i), sample_size); + */ + /* convert to shorts, then insert into ringbuffer */ + samp = lrintf(in_left[i] * 1.0 * 0x7FFF); + jack_ringbuffer_write(rb, (char*)&samp, 2); + samp = lrintf(in_right[i] * 1.0 * 0x7FFF); + jack_ringbuffer_write(rb, (char*)&samp, 2); + + } + //fprintf(stderr, "PROCESS()\n"); + + /* tell read_samples that we've got new data */ + pthread_cond_signal(&data_ready); + + return 0; +} + +/** + * JACK calls this shutdown_callback if the server ever shuts down or + * decides to disconnect the client. + */ +void jack_shutdown(void *arg) +{ + jack_thread_info_t *info = (jack_thread_info_t *) arg; + + info->connected = 0; + /* tell read_samples to move on */ + + pthread_cond_signal(&data_ready); +} +#endif // defined(JACK_INPUT) + +/************************************************************************ + * + * read_samples() + * + * PURPOSE: reads the PCM samples from a file to the buffer + * + * SEMANTICS: + * Reads #samples_read# number of shorts from #musicin# filepointer + * into #sample_buffer[]#. Returns the number of samples read. + * + ************************************************************************/ + +unsigned long read_samples (music_in_t* musicin, short sample_buffer[2304], + unsigned long num_samples, unsigned long frame_size) +{ + unsigned long samples_read; + static unsigned long samples_to_read; + static char init = TRUE; + + void* jack_sample_buffer; + + if (init) { + samples_to_read = num_samples; + init = FALSE; + } + if (samples_to_read >= frame_size) + samples_read = frame_size; + else + samples_read = samples_to_read; + + if (0) { } +#if defined(JACK_INPUT) + else if (glopts.input_select == INPUT_SELECT_JACK) { + int f = 2; + while (jack_ringbuffer_read_space(rb) < f * samples_read) { + /* wait until process() signals more data */ + pthread_cond_wait(&data_ready, &encode_thread_lock); + + if (thread_info.connected == 0) { + pthread_mutex_unlock(&encode_thread_lock); + jack_client_close(client); + jack_ringbuffer_free(rb); + return 0; + } + } + + jack_sample_buffer = malloc(f * (int)samples_read); + int bytes_read = jack_ringbuffer_read(rb, jack_sample_buffer, f * (int)samples_read); + //fprintf(stderr, " read_bytes / f = %d, should be %d\n", (int)bytes_read/f, samples_read); + samples_read = bytes_read / f; + if (bytes_read % f != 0) { + fprintf(stderr, "cannot divide bytes_read by f: %d mod f = %d", bytes_read, bytes_read % f); + } + //fprintf(stderr, " #%d(%d) \n", (int)bytes_read, samples_read); + //f2les_array(jack_sample_buffer, sample_buffer, samples_read, 1); + + memcpy(sample_buffer, jack_sample_buffer, bytes_read); + + free(jack_sample_buffer); + + } +#endif // defined(JACK_INPUT) + else if (glopts.input_select == INPUT_SELECT_WAV) { + if ((samples_read = + fread (sample_buffer, sizeof (short), (int) samples_read, + musicin->wav_input)) == 0) + fprintf (stderr, "Hit end of WAV audio data\n"); + } + else if (glopts.input_select == INPUT_SELECT_VLC) { +#if defined(VLC_INPUT) + ssize_t bytes_read = vlc_in_read(sample_buffer, sizeof(short) * (int)samples_read); + if (bytes_read == -1) { + fprintf (stderr, "VLC input error\n"); + samples_read = 0; + } + else { + samples_read = bytes_read / sizeof(short); + } +#else + samples_read = 0; +#endif + } + + /* + Samples are big-endian. If this is a little-endian machine + we must swap + */ + if (NativeByteOrder == order_unknown) { + NativeByteOrder = DetermineByteOrder (); + if (NativeByteOrder == order_unknown) { + fprintf (stderr, "byte order not determined\n"); + exit (1); + } + } + if (NativeByteOrder != order_littleEndian || (glopts.byteswap == TRUE)) + SwapBytesInWords (sample_buffer, samples_read); + + if (num_samples != MAX_U_32_NUM) + samples_to_read -= samples_read; + + if (samples_read < frame_size && samples_read > 0) { + /* fill out frame with zeros */ + for (; samples_read < frame_size; sample_buffer[samples_read++] = 0); + samples_to_read = 0; + samples_read = frame_size; + } + return (samples_read); +} + +/************************************************************************ + * + * get_audio() + * + * PURPOSE: reads a frame of audio data from a file to the buffer, + * aligns the data for future processing, and separates the + * left and right channels + * + * + ************************************************************************/ + unsigned long +get_audio (music_in_t* musicin, short buffer[2][1152], unsigned long num_samples, + int nch, frame_header *header) +{ + int j; + short insamp[2304]; + unsigned long samples_read; + + if (nch == 2) { /* stereo */ + samples_read = + read_samples (musicin, insamp, num_samples, (unsigned long) 2304); + if (glopts.channelswap == TRUE) { + for (j = 0; j < 1152; j++) { + buffer[1][j] = insamp[2 * j]; + buffer[0][j] = insamp[2 * j + 1]; + } + } else { + for (j = 0; j < 1152; j++) { + buffer[0][j] = insamp[2 * j]; + buffer[1][j] = insamp[2 * j + 1]; + } + } + } else if (glopts.downmix == TRUE) { + samples_read = + read_samples (musicin, insamp, num_samples, (unsigned long) 2304); + for (j = 0; j < 1152; j++) { + buffer[0][j] = 0.5 * (insamp[2 * j] + insamp[2 * j + 1]); + } + } else { /* mono */ + samples_read = + read_samples (musicin, insamp, num_samples, (unsigned long) 1152); + for (j = 0; j < 1152; j++) { + buffer[0][j] = insamp[j]; + /* buffer[1][j] = 0; don't bother zeroing this buffer. MFC Nov 99 */ + } + } + return (samples_read); +} + + +/***************************************************************************** + * + * Routines to determine byte order and swap bytes + * + *****************************************************************************/ + +enum byte_order DetermineByteOrder (void) +{ + char s[sizeof (long) + 1]; + union { + long longval; + char charval[sizeof (long)]; + } probe; + probe.longval = 0x41424344L; /* ABCD in ASCII */ + strncpy (s, probe.charval, sizeof (long)); + s[sizeof (long)] = '\0'; + /* fprintf( stderr, "byte order is %s\n", s ); */ + if (strcmp (s, "ABCD") == 0) + return order_bigEndian; + else if (strcmp (s, "DCBA") == 0) + return order_littleEndian; + else + return order_unknown; +} + +void SwapBytesInWords (short *loc, int words) +{ + int i; + short thisval; + char *dst, *src; + src = (char *) &thisval; + for (i = 0; i < words; i++) { + thisval = *loc; + dst = (char *) loc++; + dst[0] = src[1]; + dst[1] = src[0]; + } +} + +/***************************************************************************** + * + * Read Audio Interchange File Format (AIFF) headers. + * + *****************************************************************************/ + +int aiff_read_headers (FILE * file_ptr, IFF_AIFF * aiff_ptr) +{ + int chunkSize, subSize, sound_position; + + if (fseek (file_ptr, 0, SEEK_SET) != 0) + return -1; + + if (Read32BitsHighLow (file_ptr) != IFF_ID_FORM) + return -1; + + chunkSize = Read32BitsHighLow (file_ptr); + + if (Read32BitsHighLow (file_ptr) != IFF_ID_AIFF) + return -1; + + sound_position = 0; + while (chunkSize > 0) { + chunkSize -= 4; + switch (Read32BitsHighLow (file_ptr)) { + + case IFF_ID_COMM: + chunkSize -= subSize = Read32BitsHighLow (file_ptr); + aiff_ptr->numChannels = Read16BitsHighLow (file_ptr); + subSize -= 2; + aiff_ptr->numSampleFrames = Read32BitsHighLow (file_ptr); + subSize -= 4; + aiff_ptr->sampleSize = Read16BitsHighLow (file_ptr); + subSize -= 2; + aiff_ptr->sampleRate = ReadIeeeExtendedHighLow (file_ptr); + subSize -= 10; + while (subSize > 0) { + getc (file_ptr); + subSize -= 1; + } + break; + + case IFF_ID_SSND: + chunkSize -= subSize = Read32BitsHighLow (file_ptr); + aiff_ptr->blkAlgn.offset = Read32BitsHighLow (file_ptr); + subSize -= 4; + aiff_ptr->blkAlgn.blockSize = Read32BitsHighLow (file_ptr); + subSize -= 4; + sound_position = ftell (file_ptr) + aiff_ptr->blkAlgn.offset; + if (fseek (file_ptr, (long) subSize, SEEK_CUR) != 0) + return -1; + aiff_ptr->sampleType = IFF_ID_SSND; + break; + + default: + chunkSize -= subSize = Read32BitsHighLow (file_ptr); + while (subSize > 0) { + getc (file_ptr); + subSize -= 1; + } + break; + } + } + return sound_position; +} + +/***************************************************************************** + * + * Seek past some Audio Interchange File Format (AIFF) headers to sound data. + * + *****************************************************************************/ + +int aiff_seek_to_sound_data (FILE * file_ptr) +{ + if (fseek + (file_ptr, AIFF_FORM_HEADER_SIZE + AIFF_SSND_HEADER_SIZE, + SEEK_SET) != 0) + return (-1); + return (0); +} + +/************************************************************ + * parse_input_file() + * Determine the type of sound file. (stdin, wav, aiff, raw pcm) + * Determine Sampling Frequency + * number of samples + * whether the new sample is stereo or mono. + * + * If file is coming from /dev/stdin assume it is raw PCM. (it's what I use. YMMV) + * + * This is just a hacked together function. The aiff parsing comes from the ISO code. + * The WAV code comes from Nick Burch + * The ugly /dev/stdin hack comes from me. + * MFC Dec 99 + **************************************************************/ + void +parse_input_file (FILE * musicin, char inPath[MAX_NAME_SIZE], frame_header *header, + unsigned long *num_samples) +{ + + IFF_AIFF pcm_aiff_data; + long soundPosition; + + unsigned char wave_header_buffer[40]; //HH fixed + int wave_header_read = 0; + int wave_header_stereo = -1; + int wave_header_16bit = -1; + unsigned long samplerate; + + /*************************** STDIN ********************************/ + /* check if we're reading from stdin. Assume it's a raw PCM file. */ + /* Of course, you could be piping a WAV file into stdin. Not done in this code */ + /* this code is probably very dodgy and was written to suit my needs. MFC Dec 99 */ + if ((strcmp (inPath, "/dev/stdin") == 0)) { + fprintf (stderr, "Reading from stdin\n"); + fprintf (stderr, "Remember to set samplerate with '-s'.\n"); + *num_samples = MAX_U_32_NUM; /* huge sound file */ + return; + } + + if (fseek (musicin, 0L, SEEK_SET) == -1) { + fprintf (stderr, "Input is not seekable, assuming pipe with raw PCM\n"); + fprintf (stderr, "Remember to set samplerate with '-s'.\n"); + *num_samples = MAX_U_32_NUM; /* huge sound file */ + return; + } + + /**************************** AIFF ********************************/ + if ((soundPosition = aiff_read_headers (musicin, &pcm_aiff_data)) != -1) { + fprintf (stderr, ">>> Using Audio IFF sound file headers\n"); + aiff_check (inPath, &pcm_aiff_data, &header->version); + if (fseek (musicin, soundPosition, SEEK_SET) != 0) { + fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", + inPath); + exit (1); + } + fprintf (stderr, "Parsing AIFF audio file \n"); + header->sampling_frequency = + SmpFrqIndex ((long) pcm_aiff_data.sampleRate, &header->version); + fprintf (stderr, ">>> %f Hz sampling frequency selected\n", + pcm_aiff_data.sampleRate); + + /* Determine number of samples in sound file */ + *num_samples = pcm_aiff_data.numChannels * pcm_aiff_data.numSampleFrames; + + if (pcm_aiff_data.numChannels == 1) { + header->mode = MPG_MD_MONO; + header->mode_ext = 0; + } + return; + } + + /**************************** WAVE *********************************/ + /* Nick Burch <The_Leveller@newmail.net> */ + /*********************************/ + /* Wave File Headers: (Dec) */ + /* 8-11 = "WAVE" */ + /* 22 = Stereo / Mono */ + /* 01 = mono, 02 = stereo */ + /* 24 = Sampling Frequency */ + /* 32 = Data Rate */ + /* 01 = x1 (8bit Mono) */ + /* 02 = x2 (8bit Stereo or */ + /* 16bit Mono) */ + /* 04 = x4 (16bit Stereo) */ + /*********************************/ + + fseek (musicin, 0, SEEK_SET); + fread (wave_header_buffer, 1, 40, musicin); + + if (wave_header_buffer[8] == 'W' && wave_header_buffer[9] == 'A' + && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') { + fprintf (stderr, "Parsing Wave File Header\n"); + if (NativeByteOrder == order_unknown) { + NativeByteOrder = DetermineByteOrder (); + if (NativeByteOrder == order_unknown) { + fprintf (stderr, "byte order not determined\n"); + exit (1); + } + } + if (NativeByteOrder == order_littleEndian) { + samplerate = wave_header_buffer[24] + + (wave_header_buffer[25] << 8) + + (wave_header_buffer[26] << 16) + + (wave_header_buffer[27] << 24); + } else { + samplerate = wave_header_buffer[27] + + (wave_header_buffer[26] << 8) + + (wave_header_buffer[25] << 16) + + (wave_header_buffer[24] << 24); + } + /* Wave File */ + wave_header_read = 1; + switch (samplerate) { + case 44100: + case 48000: + case 32000: + case 24000: + case 22050: + case 16000: + fprintf (stderr, ">>> %ld Hz sampling freq selected\n", samplerate); + break; + default: + /* Unknown Unsupported Frequency */ + fprintf (stderr, ">>> Unknown samp freq %ld Hz in Wave Header\n", + samplerate); + fprintf (stderr, ">>> Default 44.1 kHz samp freq selected\n"); + samplerate = 44100; + } + + if ((header->sampling_frequency = + SmpFrqIndex ((long) samplerate, &header->version)) < 0) { + fprintf (stderr, "invalid sample rate\n"); + exit (0); + } + + if ((long) wave_header_buffer[22] == 1) { + fprintf (stderr, ">>> Input Wave File is Mono\n"); + wave_header_stereo = 0; + header->mode = MPG_MD_MONO; + header->mode_ext = 0; + } + if ((long) wave_header_buffer[22] == 2) { + fprintf (stderr, ">>> Input Wave File is Stereo\n"); + wave_header_stereo = 1; + } + if ((long) wave_header_buffer[32] == 1) { + fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); + wave_header_16bit = 0; + fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); + exit (1); + } + if ((long) wave_header_buffer[32] == 2) { + if (wave_header_stereo == 1) { + fprintf (stderr, ">>> Input Wave File is 8 Bit\n"); + wave_header_16bit = 0; + fprintf (stderr, "Input File must be 16 Bit! Please Re-sample"); + exit (1); + } else { + /* fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); */ + wave_header_16bit = 1; + } + } + if ((long) wave_header_buffer[32] == 4) { + /* fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); */ + wave_header_16bit = 1; + } + /* should probably use the wave header to determine size here FIXME MFC Feb 2003 */ + *num_samples = MAX_U_32_NUM; + if (fseek (musicin, 44, SEEK_SET) != 0) { /* there's a way of calculating the size of the + wave header. i'll just jump 44 to start with */ + fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", + inPath); + exit (1); + } + return; + } + + /*************************** PCM **************************/ + fprintf (stderr, "No header found. Assuming Raw PCM sound file\n"); + /* Raw PCM. No header. Reset the input file to read from the start */ + fseek (musicin, 0, SEEK_SET); + /* Assume it is a huge sound file since there's no real info available */ + /* FIXME: Could always fstat the file? Probably not worth it. MFC Feb 2003 */ + *num_samples = MAX_U_32_NUM; +} + + + +/************************************************************************ + * + * aiff_check + * + * PURPOSE: Checks AIFF header information to make sure it is valid. + * Exits if not. + * + ************************************************************************/ + +void aiff_check (char *file_name, IFF_AIFF * pcm_aiff_data, int *version) +{ + if (pcm_aiff_data->sampleType != IFF_ID_SSND) { + fprintf (stderr, "Sound data is not PCM in \"%s\".\n", file_name); + exit (1); + } + + if (SmpFrqIndex ((long) pcm_aiff_data->sampleRate, version) < 0) { + fprintf (stderr, "in \"%s\".\n", file_name); + exit (1); + } + + if (pcm_aiff_data->sampleSize != sizeof (short) * BITS_IN_A_BYTE) { + fprintf (stderr, "Sound data is not %zu bits in \"%s\".\n", + sizeof (short) * BITS_IN_A_BYTE, file_name); + exit (1); + } + + if (pcm_aiff_data->numChannels != MONO + && pcm_aiff_data->numChannels != STEREO) { + fprintf (stderr, "Sound data is not mono or stereo in \"%s\".\n", + file_name); + exit (1); + } + + if (pcm_aiff_data->blkAlgn.blockSize != 0) { + fprintf (stderr, "Block size is not %d bytes in \"%s\".\n", 0, file_name); + exit (1); + } + + if (pcm_aiff_data->blkAlgn.offset != 0) { + fprintf (stderr, "Block offset is not %d bytes in \"%s\".\n", 0, + file_name); + exit (1); + } +} diff --git a/libtoolame-dab/audio_read.h b/libtoolame-dab/audio_read.h new file mode 100644 index 0000000..215e89d --- /dev/null +++ b/libtoolame-dab/audio_read.h @@ -0,0 +1,48 @@ +/* AIFF Definitions */ + +#define IFF_ID_FORM 0x464f524d /* "FORM" */ +#define IFF_ID_AIFF 0x41494646 /* "AIFF" */ +#define IFF_ID_COMM 0x434f4d4d /* "COMM" */ +#define IFF_ID_SSND 0x53534e44 /* "SSND" */ +#define IFF_ID_MPEG 0x4d504547 /* "MPEG" */ + +#define AIFF_FORM_HEADER_SIZE 12 +#define AIFF_SSND_HEADER_SIZE 16 + + +typedef struct blockAlign_struct +{ + unsigned long offset; + unsigned long blockSize; +} +blockAlign; + +typedef struct IFF_AIFF_struct +{ + short numChannels; + unsigned long numSampleFrames; + short sampleSize; + double sampleRate; + unsigned long sampleType; + blockAlign blkAlgn; +} +IFF_AIFF; + +#if defined(JACK_INPUT) +void setup_jack(frame_header *header, const char* jackname); +int process(jack_nframes_t nframes, void *arg); +#endif +void jack_shutdown(void *arg); + +void parse_input_file (FILE *musicin, char *, frame_header *header, unsigned long *num_samples); +void aiff_check (char *file_name, IFF_AIFF * pcm_aiff_data, int *version); + +int aiff_read_headers (FILE *, IFF_AIFF *); +int aiff_seek_to_sound_data (FILE *); +enum byte_order DetermineByteOrder (void); +void SwapBytesInWords (short *loc, int words); + unsigned long read_samples (music_in_t*, short[2304], unsigned long, + unsigned long); + unsigned long get_audio (music_in_t*, short[2][1152], unsigned long, + int, frame_header *header); + diff --git a/libtoolame-dab/availbits.c b/libtoolame-dab/availbits.c new file mode 100644 index 0000000..809c28e --- /dev/null +++ b/libtoolame-dab/availbits.c @@ -0,0 +1,67 @@ +/* + * toolame - an optimized mpeg 1/2 layer 2 audio encoder + * Copyright (C) 2001 Michael Cheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdio.h> +#include "common.h" +#include "encoder.h" +#include "musicin.h" +#include "options.h" +#include "availbits.h" + + +struct slotinfo { + double average; + double frac; + int whole; + double lag; + int extra; +} slots; + +/* function returns the number of available bits */ +int available_bits (frame_header *header, options * glopts) +{ + int adb; + + slots.extra = 0; /* be default, no extra slots */ + + slots.average = + (1152.0 / s_freq[header->version][header->sampling_frequency]) * + ((double) bitrate[header->version][header->bitrate_index] / 8.0); + + slots.whole = (int) slots.average; + slots.frac = slots.average - (double) slots.whole; + + /* never allow padding for a VBR frame. + Don't ask me why, I've forgotten why I set this */ + if (slots.frac != 0 && glopts->usepadbit && glopts->vbr == FALSE) { + if (slots.lag > (slots.frac - 1.0)) { /* no padding for this frame */ + slots.lag -= slots.frac; + slots.extra = 0; + header->padding = 0; + } else { /* padding */ + + slots.extra = 1; + header->padding = 1; + slots.lag += (1 - slots.frac); + } + } + + adb = (slots.whole + slots.extra) * 8; + + return adb; +} diff --git a/libtoolame-dab/availbits.h b/libtoolame-dab/availbits.h new file mode 100644 index 0000000..1341cda --- /dev/null +++ b/libtoolame-dab/availbits.h @@ -0,0 +1,2 @@ + +int available_bits (frame_header *header, options * glopts); diff --git a/libtoolame-dab/bitstream.c b/libtoolame-dab/bitstream.c new file mode 100644 index 0000000..3417c89 --- /dev/null +++ b/libtoolame-dab/bitstream.c @@ -0,0 +1,303 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "zmqoutput.h" +#include "common.h" +#include "mem.h" +#include "bitstream.h" + +/***************************************************************************** + * + * bit_stream.c package + * Author: Jean-Georges Fritsch, C-Cube Microsystems + * Changes + * Apr 2000 - removed all the file input routines. MFC + *****************************************************************************/ + +/******************************************************************** + This package provides functions to write (exclusive or read) + information from (exclusive or to) the bit stream. + + If the bit stream is opened in read mode only the get functions are + available. If the bit stream is opened in write mode only the put + functions are available. + ********************************************************************/ + +/*open_bit_stream_w(); open the device to write the bit stream into it */ +/*close_bit_stream(); close the device containing the bit stream */ +/*alloc_buffer(); open and initialize the buffer; */ +/*desalloc_buffer(); empty and close the buffer */ +/*back_track_buffer(); goes back N bits in the buffer */ +/*put1bit(); write 1 bit from the bit stream */ +/*put1bit(); write 1 bit from the bit stream */ +/*putbits(); write N bits from the bit stream */ +/*byte_ali_putbits(); write byte aligned the next N bits into the bit stream*/ +/*unsigned long sstell(); return the current bit stream length (in bits) */ +/*int end_bs(); return 1 if the end of bit stream reached otherwise 0 */ +/*int seek_sync(); return 1 if a sync word was found in the bit stream */ +/* otherwise returns 0 */ + +/* refill the buffer from the input device when the buffer becomes empty */ + +/* You must have one frame in memory if you are in DAB mode */ +/* in conformity of the norme ETS 300 401 http://www.etsi.org */ +/* see toollame.c */ +int minimum = MINIMUM; +int refill_buffer (Bit_stream_struc * bs) +{ + register int i = bs->buf_size - 2 - bs->buf_byte_idx; + register unsigned long n = 1; + register int index = 0; + char val[2]; + + while ((i >= 0) && (!bs->eob)) { + + if (bs->format == BINARY) + n = fread (&bs->buf[i--], sizeof (unsigned char), 1, bs->pt); + + else { + while ((index < 2) && n) { + n = fread (&val[index], sizeof (char), 1, bs->pt); + switch (val[index]) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + index++; + break; + default: + break; + } + } + + if (val[0] <= 0x39) + bs->buf[i] = (val[0] - 0x30) << 4; + else + bs->buf[i] = (val[0] - 0x37) << 4; + if (val[1] <= 0x39) + bs->buf[i--] |= (val[1] - 0x30); + else + bs->buf[i--] |= (val[1] - 0x37); + index = 0; + } + + if (!n) { + bs->eob = i + 1; + } + + } + return 0; +} + +/* empty the buffer to the output device when the buffer becomes full */ +void empty_buffer (Bit_stream_struc * bs, int minimum) +{ + int i; + + if (bs->pt) { + for (i = bs->buf_size - 1; i >= minimum; i--) + fwrite (&bs->buf[i], sizeof (unsigned char), 1, bs->pt); + + fflush (bs->pt); /* NEW SS to assist in debugging */ + } + else if (bs->zmq_sock) { + for (i = bs->buf_size - 1; i >= minimum; i--) + zmqoutput_write_byte(bs, bs->buf[i]); + } + + for (i = minimum - 1; i >= 0; i--) + bs->buf[bs->buf_size - minimum + i] = bs->buf[i]; + + bs->buf_byte_idx = bs->buf_size - 1 - minimum; + bs->buf_bit_idx = 8; + +} + + +/* open the device to write the bit stream into it */ +void open_bit_stream_w (Bit_stream_struc * bs, char *bs_filenam, int size) +{ + bs->zmq_sock = NULL; + + if (bs_filenam[0] == '-') + bs->pt = stdout; + else if (strncmp(bs_filenam, "tcp://", 4) == 0) { + if (zmqoutput_open(bs, bs_filenam) != 0) { + fprintf(stderr, "Could not initialise ZMQ\n"); + exit(1); + } + bs->pt = NULL; // we're not using file output + } + else if ((bs->pt = fopen (bs_filenam, "wb")) == NULL) { + fprintf (stderr, "Could not create \"%s\".\n", bs_filenam); + exit (1); + } + alloc_buffer (bs, size); + bs->buf_byte_idx = size - 1; + bs->buf_bit_idx = 8; + bs->totbit = 0; + bs->mode = WRITE_MODE; + bs->eob = FALSE; + bs->eobs = FALSE; +} + +/*close the device containing the bit stream after a write process*/ +void close_bit_stream_w (Bit_stream_struc * bs) +{ + putbits (bs, 0, 7); + empty_buffer (bs, bs->buf_byte_idx + 1); + if (bs->pt) fclose(bs->pt); + zmqoutput_close(bs); + desalloc_buffer (bs); +} + +/*open and initialize the buffer; */ +void alloc_buffer (Bit_stream_struc * bs, int size) +{ + bs->buf = + (unsigned char *) mem_alloc (size * sizeof (unsigned char), "buffer"); + bs->buf_size = size; +} + +/*empty and close the buffer */ +void desalloc_buffer (Bit_stream_struc * bs) +{ + free (bs->buf); +} + +int putmask[9] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff }; +int clearmask[9] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x0 }; + +void back_track_buffer (Bit_stream_struc * bs, int N) + /* goes back N bits in the buffer */ +{ + int tmp = N - (N / 8) * 8; + register int i; + + bs->totbit -= N; + for (i = bs->buf_byte_idx; i < bs->buf_byte_idx + N / 8 - 1; i++) + bs->buf[i] = 0; + bs->buf_byte_idx += N / 8; + if ((tmp + bs->buf_bit_idx) <= 8) { + bs->buf_bit_idx += tmp; + } else { + bs->buf_byte_idx++; + bs->buf_bit_idx += (tmp - 8); + } + bs->buf[bs->buf_byte_idx] &= clearmask[bs->buf_bit_idx]; +} + +int mask[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; + +/*write 1 bit from the bit stream */ +void put1bit (Bit_stream_struc * bs, int bit) +{ + bs->totbit++; + + bs->buf[bs->buf_byte_idx] |= (bit & 0x1) << (bs->buf_bit_idx - 1); + bs->buf_bit_idx--; + if (!bs->buf_bit_idx) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx--; + if (bs->buf_byte_idx < 0) + empty_buffer (bs, minimum); + bs->buf[bs->buf_byte_idx] = 0; + } +} + +/*write N bits into the bit stream */ +void putbits (Bit_stream_struc * bs, unsigned int val, int N) +{ + register int j = N; + register int k, tmp; + + /* if (N > MAX_LENGTH) + fprintf(stderr, "Cannot read or write more than %d bits at a time.\n", MAX_LENGTH); ignore check!! MFC Apr 00 */ + + bs->totbit += N; + while (j > 0) { + k = MIN (j, bs->buf_bit_idx); + tmp = val >> (j - k); + bs->buf[bs->buf_byte_idx] |= (tmp & putmask[k]) << (bs->buf_bit_idx - k); + bs->buf_bit_idx -= k; + if (!bs->buf_bit_idx) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx--; + if (bs->buf_byte_idx < 0) + empty_buffer (bs, minimum); + bs->buf[bs->buf_byte_idx] = 0; + } + j -= k; + } +} + +/*write N bits byte aligned into the bit stream */ +void byte_ali_putbits (Bit_stream_struc * bs, unsigned int val, int N) +{ + unsigned long aligning; + + if (N > MAX_LENGTH) + fprintf (stderr, "Cannot read or write more than %d bits at a time.\n", + MAX_LENGTH); + aligning = sstell (bs) % 8; + if (aligning) + putbits (bs, (unsigned int) 0, (int) (8 - aligning)); + + putbits (bs, val, N); +} + +/*return the current bit stream length (in bits)*/ +unsigned long sstell (Bit_stream_struc * bs) +{ + return (bs->totbit); +} + +/*return the status of the bit stream*/ +/* returns 1 if end of bit stream was reached */ +/* returns 0 if end of bit stream was not reached */ +int end_bs (Bit_stream_struc * bs) +{ + return (bs->eobs); +} + +/***************************************************************************** + * + * End of bit_stream.c package + * + *****************************************************************************/ + +#define BUFSIZE 4096 +static unsigned long offset, totbit = 0; +static unsigned int buf[BUFSIZE]; + +/*return the current bit stream length (in bits)*/ +unsigned long hsstell () +{ + return (totbit); +} + +/* int putmask[9]={0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff}; */ +//extern int putmask[9]; MFC Feb 2003 Redundant redeclaration + +/*write N bits into the bit stream */ +void hputbuf (unsigned int val, int N) +{ + if (N != 8) { + fprintf (stderr, "Not Supported yet!!\n"); + exit (-3); + } + buf[offset % BUFSIZE] = val; + offset++; +} diff --git a/libtoolame-dab/bitstream.h b/libtoolame-dab/bitstream.h new file mode 100644 index 0000000..f7759d8 --- /dev/null +++ b/libtoolame-dab/bitstream.h @@ -0,0 +1,21 @@ +int refill_buffer (Bit_stream_struc *); +void empty_buffer (Bit_stream_struc *, int); +void open_bit_stream_w (Bit_stream_struc *, char *, int); +void close_bit_stream_w (Bit_stream_struc *); +void alloc_buffer (Bit_stream_struc *, int); +void desalloc_buffer (Bit_stream_struc *); +void back_track_buffer (Bit_stream_struc *, int); +unsigned int get1bit (Bit_stream_struc *); +void put1bit (Bit_stream_struc *, int); +unsigned long look_ahead (Bit_stream_struc *, int); +unsigned long getbits (Bit_stream_struc *, int); +extern void putbits (Bit_stream_struc *, unsigned int, int); +void byte_ali_putbits (Bit_stream_struc *, unsigned int, int); +unsigned long byte_ali_getbits (Bit_stream_struc *, int); +unsigned long sstell (Bit_stream_struc *); +int end_bs (Bit_stream_struc *); +int seek_sync (Bit_stream_struc *, long, int); +unsigned int hget1bit (void); /* MI */ +unsigned long hgetbits (int); +unsigned long hsstell (void); +void hputbuf (unsigned int, int); diff --git a/libtoolame-dab/common.c b/libtoolame-dab/common.c new file mode 100644 index 0000000..e1c5407 --- /dev/null +++ b/libtoolame-dab/common.c @@ -0,0 +1,188 @@ + +/*********************************************************************** +* +* Global Include Files +* +***********************************************************************/ +#include <stdio.h> +#include <string.h> /* 1995-07-11 shn */ +#include <ctype.h> +#include <stdlib.h> +#include "common.h" +#include "options.h" +#include "encode_new.h" +#include "tables.h" + +/*********************************************************************** +* +* Global Variable Definitions +* +***********************************************************************/ + +char *mode_names[4] = { "stereo", "j-stereo", "dual-ch", "single-ch" }; +char *version_names[2] = { "MPEG-2 LSF", "MPEG-1" }; + +/* 1: MPEG-1, 0: MPEG-2 LSF, 1995-07-11 shn */ +double s_freq[2][4] = { {22.05, 24, 16, 0}, {44.1, 48, 32, 0} }; + +/* 1: MPEG-1, 0: MPEG-2 LSF, 1995-07-11 shn */ +int bitrate[2][15] = { + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384} +}; + +double multiple[64] = { + 2.00000000000000, 1.58740105196820, 1.25992104989487, + 1.00000000000000, 0.79370052598410, 0.62996052494744, 0.50000000000000, + 0.39685026299205, 0.31498026247372, 0.25000000000000, 0.19842513149602, + 0.15749013123686, 0.12500000000000, 0.09921256574801, 0.07874506561843, + 0.06250000000000, 0.04960628287401, 0.03937253280921, 0.03125000000000, + 0.02480314143700, 0.01968626640461, 0.01562500000000, 0.01240157071850, + 0.00984313320230, 0.00781250000000, 0.00620078535925, 0.00492156660115, + 0.00390625000000, 0.00310039267963, 0.00246078330058, 0.00195312500000, + 0.00155019633981, 0.00123039165029, 0.00097656250000, 0.00077509816991, + 0.00061519582514, 0.00048828125000, 0.00038754908495, 0.00030759791257, + 0.00024414062500, 0.00019377454248, 0.00015379895629, 0.00012207031250, + 0.00009688727124, 0.00007689947814, 0.00006103515625, 0.00004844363562, + 0.00003844973907, 0.00003051757813, 0.00002422181781, 0.00001922486954, + 0.00001525878906, 0.00001211090890, 0.00000961243477, 0.00000762939453, + 0.00000605545445, 0.00000480621738, 0.00000381469727, 0.00000302772723, + 0.00000240310869, 0.00000190734863, 0.00000151386361, 0.00000120155435, + 1E-20 +}; + +enum byte_order NativeByteOrder = order_unknown; + +/*********************************************************************** +* +* Global Function Definitions +* +***********************************************************************/ + + + +int js_bound (int m_ext) +{ + /* layer 2 only */ + static int jsb_table[4] = { 4, 8, 12, 16 }; + + if (m_ext < 0 || m_ext > 3) { + fprintf (stderr, "js_bound bad modext (%d)\n", m_ext); + exit (1); + } + return (jsb_table[m_ext]); +} + +void hdr_to_frps (frame_info * frame) +/* interpret data in hdr str to fields in frame */ +{ + frame_header *hdr = frame->header; /* (or pass in as arg?) */ + + frame->actual_mode = hdr->mode; + frame->nch = (hdr->mode == MPG_MD_MONO) ? 1 : 2; + + frame->sblimit = pick_table (frame); + /* MFC FIX this up */ + encode_init(frame); + + if (hdr->mode == MPG_MD_JOINT_STEREO) + frame->jsbound = js_bound (hdr->mode_ext); + else + frame->jsbound = frame->sblimit; + /* alloc, tab_num set in pick_table */ +} + +int BitrateIndex (int bRate, /* legal rates from 32 to 448 */ + int version /* MPEG-1 or MPEG-2 LSF */ ) +/* convert bitrate in kbps to index */ +{ + int index = 0; + int found = 0; + + while (!found && index < 15) { + if (bitrate[version][index] == bRate) + found = 1; + else + ++index; + } + if (found) + return (index); + else { + fprintf (stderr, + "BitrateIndex: %d is not a legal bitrate for version %i\n", + bRate, version); + exit (-1); /* Error! */ + } +} + +int SmpFrqIndex (long sRate, int *version) +/* convert samp frq in Hz to index */ +/* legal rates 16000, 22050, 24000, 32000, 44100, 48000 */ +{ + if (sRate == 44100L) { + *version = MPEG_AUDIO_ID; + return (0); + } else if (sRate == 48000L) { + *version = MPEG_AUDIO_ID; + return (1); + } else if (sRate == 32000L) { + *version = MPEG_AUDIO_ID; + return (2); + } else if (sRate == 24000L) { + *version = MPEG_PHASE2_LSF; + return (1); + } else if (sRate == 22050L) { + *version = MPEG_PHASE2_LSF; + return (0); + } else if (sRate == 16000L) { + *version = MPEG_PHASE2_LSF; + return (2); + } else { + fprintf (stderr, "SmpFrqIndex: %ld is not a legal sample rate\n", sRate); + return (-1); /* Error! */ + } +} + + + + + +/******************************************************************** +new_ext() +Puts a new extension name on a file name <filename>. +Removes the last extension name, if any. +1992-08-19, 1995-06-12 shn +***********************************************************************/ +void new_ext (char *filename, char *extname, char *newname) +{ + int found, dotpos; + + /* First, strip the extension */ + dotpos = strlen (filename); + found = 0; + do { + switch (filename[dotpos]) { + case '.': + found = 1; + break; + case '\\': + case '/': + case ':': + found = -1; + break; + default: + dotpos--; + if (dotpos < 0) + found = -1; + break; + } + } + while (found == 0); + if (found == -1) + strcpy (newname, filename); + if (found == 1) { + strncpy (newname, filename, dotpos); + newname[dotpos] = '\0'; + } + strcat (newname, extname); +} diff --git a/libtoolame-dab/common.h b/libtoolame-dab/common.h new file mode 100644 index 0000000..8551483 --- /dev/null +++ b/libtoolame-dab/common.h @@ -0,0 +1,203 @@ +#ifndef COMMON_DOT_H +#define COMMON_DOT_H + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#define FLOAT float + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define NULL_CHAR '\0' + +#define MAX_U_32_NUM 0xFFFFFFFF +#ifndef PI +#define PI 3.14159265358979 +#endif +#define PI2 PI/2 +#define PI4 PI/4 +#define PI64 PI/64 +#define LN_TO_LOG10 0.2302585093 + +#define VOL_REF_NUM 0 +#define MPEG_AUDIO_ID 1 +#define MPEG_PHASE2_LSF 0 /* 1995-07-11 SHN */ +#define MAC_WINDOW_SIZE 24 + +#define MONO 1 +#define STEREO 2 +#define BITS_IN_A_BYTE 8 +#define WORD 16 +#define MAX_NAME_SIZE 255 +#define SBLIMIT 32 +#define SSLIMIT 18 +#define FFT_SIZE 1024 +#define HAN_SIZE 512 +#define SCALE_BLOCK 12 +#define SCALE_RANGE 64 +#define SCALE 32768 +#define CRC16_POLYNOMIAL 0x8005 +#define CRC8_POLYNOMIAL 0x1D + +/* MPEG Header Definitions - Mode Values */ + +#define MPG_MD_STEREO 0 +#define MPG_MD_JOINT_STEREO 1 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + +/* Mode Extension */ + +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 + + +/* "bit_stream.h" Definitions */ + +#define MINIMUM 4 /* Minimum size of the buffer in bytes */ +#define MAX_LENGTH 32 /* Maximum length of word written or + read from bit stream */ +#define READ_MODE 0 +#define WRITE_MODE 1 +#define ALIGNING 8 +#define BINARY 0 +#define ASCII 1 + +#define BUFFER_SIZE 4096 + +#define FLOAT8 float +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + +#include "utils.h" +#include <stdio.h> +#include <stdlib.h> +#if defined(JACK_INPUT) +# include <jack/jack.h> +#endif + +/* Structure for Reading Layer II Allocation Tables from File */ + +typedef struct +{ + unsigned int steps; + unsigned int bits; + unsigned int group; + unsigned int quant; +} +sb_alloc, *alloc_ptr; + +typedef sb_alloc al_table[SBLIMIT][16]; + +/* Header Information Structure */ + +typedef struct +{ + int version; + int lay; + int error_protection; + int dab_extension; + int dab_length; + int bitrate_index; + int sampling_frequency; + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; +} +frame_header; + +/* Parent Structure Interpreting some Frame Parameters in Header */ + +typedef struct +{ + frame_header *header; /* raw header information */ + int actual_mode; /* when writing IS, may forget if 0 chs */ + al_table *alloc; /* bit allocation table read in */ + int tab_num; /* number of table as loaded */ + int nch; /* num channels: 1 for mono, 2 for stereo */ + int jsbound; /* first band of joint stereo coding */ + int sblimit; /* total number of sub bands */ +} +frame_info; + +typedef struct bit_stream_struc +{ + FILE *pt; /* pointer to bit stream device */ + void *zmq_sock; /* zmq socket */ + int zmq_framesize; /* zmq frame size */ + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + long totbit; /* bit counter of bit stream */ + int buf_byte_idx; /* pointer to top byte in buffer */ + int buf_bit_idx; /* pointer to top bit of top byte in buffer */ + int mode; /* bit stream open in read or write mode */ + int eob; /* end of buffer index */ + int eobs; /* end of bit stream flag */ + char format; + + /* format of file in rd mode (BINARY/ASCII) */ +} +Bit_stream_struc; + + +enum byte_order +{ order_unknown, order_bigEndian, order_littleEndian }; +extern enum byte_order NativeByteOrder; + + +typedef struct music_in_s +{ + /* Data for the wav input */ + FILE* wav_input; + +#if defined(JACK_INPUT) + /* Data for the jack input */ + jack_client_t* jack_client; +#endif + const char* jack_name; +} music_in_t; + +/* "bit_stream.h" Type Definitions */ + + + + +/*********************************************************************** +* +* Global Variable External Declarations +* +***********************************************************************/ + +extern char *mode_names[4]; +extern char *version_names[2]; +extern double s_freq[2][4]; +extern int bitrate[2][15]; +extern double multiple[64]; + +int js_bound (int); +void hdr_to_frps (frame_info *); +int BitrateIndex (int, int); +int SmpFrqIndex (long, int *); +void new_ext (char *filename, char *extname, char *newname); + +#endif diff --git a/libtoolame-dab/crc.c b/libtoolame-dab/crc.c new file mode 100644 index 0000000..b83ac03 --- /dev/null +++ b/libtoolame-dab/crc.c @@ -0,0 +1,113 @@ +#include <stdio.h> +#include <string.h> +#include "common.h" +#include "crc.h" + +/***************************************************************************** +* +* CRC error protection package +* +*****************************************************************************/ + +void CRC_calc (frame_info * frame, unsigned int bit_alloc[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], unsigned int *crc) +{ + int i, k; + frame_header *header = frame->header; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + + *crc = 0xffff; /* changed from '0' 92-08-11 shn */ + update_CRC (header->bitrate_index, 4, crc); + update_CRC (header->sampling_frequency, 2, crc); + update_CRC (header->padding, 1, crc); + update_CRC (header->extension, 1, crc); + update_CRC (header->mode, 2, crc); + update_CRC (header->mode_ext, 2, crc); + update_CRC (header->copyright, 1, crc); + update_CRC (header->original, 1, crc); + update_CRC (header->emphasis, 2, crc); + + for (i = 0; i < sblimit; i++) + for (k = 0; k < ((i < jsbound) ? nch : 1); k++) + update_CRC (bit_alloc[k][i], (*alloc)[i][0].bits, crc); + + for (i = 0; i < sblimit; i++) + for (k = 0; k < nch; k++) + if (bit_alloc[k][i]) + update_CRC (scfsi[k][i], 2, crc); +} + +void update_CRC (unsigned int data, unsigned int length, unsigned int *crc) +{ + unsigned int masking, carry; + + masking = 1 << length; + + while ((masking >>= 1)) { + carry = *crc & 0x8000; + *crc <<= 1; + if (!carry ^ !(data & masking)) + *crc ^= CRC16_POLYNOMIAL; + } + *crc &= 0xffff; +} + +void +CRC_calcDAB (frame_info * frame, + unsigned int bit_alloc[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int scalar[2][3][SBLIMIT], unsigned int *crc, + int packed) +{ + int i, j, k; + int nch = frame->nch; + int nb_scalar; + int f[5] = { 0, 4, 8, 16, 30 }; + int first, last; + + first = f[packed]; + last = f[packed + 1]; + if (last > frame->sblimit) + last = frame->sblimit; + + nb_scalar = 0; + *crc = 0x0; + for (i = first; i < last; i++) + for (k = 0; k < nch; k++) + if (bit_alloc[k][i]) /* above jsbound, bit_alloc[0][i] == ba[1][i] */ + switch (scfsi[k][i]) { + case 0: + for (j = 0; j < 3; j++) { + nb_scalar++; + update_CRCDAB (scalar[k][j][i] >> 3, 3, crc); + } + break; + case 1: + case 3: + nb_scalar += 2; + update_CRCDAB (scalar[k][0][i] >> 3, 3, crc); + update_CRCDAB (scalar[k][2][i] >> 3, 3, crc); + break; + case 2: + nb_scalar++; + update_CRCDAB (scalar[k][0][i] >> 3, 3, crc); + } +} + +void update_CRCDAB (unsigned int data, unsigned int length, unsigned int *crc) +{ + unsigned int masking, carry; + + masking = 1 << length; + + while ((masking >>= 1)) { + carry = *crc & 0x80; + *crc <<= 1; + if (!carry ^ !(data & masking)) + *crc ^= CRC8_POLYNOMIAL; + } + *crc &= 0xff; +} diff --git a/libtoolame-dab/crc.h b/libtoolame-dab/crc.h new file mode 100644 index 0000000..33b8bf1 --- /dev/null +++ b/libtoolame-dab/crc.h @@ -0,0 +1,11 @@ +void CRC_calc (frame_info *, unsigned int[2][SBLIMIT], + unsigned int[2][SBLIMIT], unsigned int *); +void update_CRC (unsigned int, unsigned int, unsigned int *); + +void CRC_calcDAB (frame_info * frame, + unsigned int bit_alloc[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int scalar[2][3][SBLIMIT], + unsigned int *crc, int i); + +void update_CRCDAB (unsigned int, unsigned int, unsigned int *); diff --git a/libtoolame-dab/critband.h b/libtoolame-dab/critband.h new file mode 100644 index 0000000..74e98f3 --- /dev/null +++ b/libtoolame-dab/critband.h @@ -0,0 +1,179 @@ +const int SecondCriticalBand[7][28] = { + { +/* 2cb0, 27 entries */ + 27, + 1, + 2, + 3, + 5, + 7, + 10, + 13, + 16, + 19, + 22, + 26, + 30, + 35, + 40, + 46, + 54, + 64, + 76, + 90, + 104, + 124, + 148, + 176, + 216, + 264, + 360, + 464}, + { +/* 2cb1, 27 entries */ + 27, + 1, + 2, + 3, + 5, + 7, + 9, + 12, + 14, + 17, + 20, + 24, + 27, + 32, + 37, + 42, + 50, + 58, + 70, + 82, + 100, + 116, + 136, + 164, + 200, + 248, + 328, + 432}, + { +/* 2cb2, 25 entries */ + 25, + 1, + 3, + 6, + 10, + 13, + 17, + 21, + 25, + 30, + 35, + 41, + 47, + 54, + 64, + 74, + 88, + 104, + 124, + 148, + 176, + 208, + 248, + 296, + 368, + 480, + 0, 0}, + { +/* 2cb3, 0 entries (all dummies) */ + 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0}, + { +/* 2cb4, 24 entries */ + 24, + 1, + 5, + 9, + 14, + 19, + 25, + 30, + 36, + 43, + 50, + 58, + 68, + 78, + 92, + 108, + 124, + 148, + 176, + 208, + 248, + 296, + 352, + 424, + 480, + 0, 0, 0}, + { +/* 2cb5, 24 entries */ + 24, + 1, + 4, + 9, + 13, + 18, + 23, + 28, + 33, + 39, + 46, + 54, + 62, + 72, + 84, + 100, + 116, + 136, + 164, + 192, + 232, + 272, + 328, + 392, + 480, + 0, 0, 0}, + { +/* 2cb6, 22 entries */ + 22, + 1, + 6, + 13, + 20, + 27, + 34, + 42, + 50, + 60, + 70, + 80, + 94, + 108, + 124, + 148, + 172, + 208, + 248, + 288, + 344, + 408, + 480, + 0, 0, 0, 0, 0} +}; diff --git a/libtoolame-dab/encode.c b/libtoolame-dab/encode.c new file mode 100644 index 0000000..fa9bd4a --- /dev/null +++ b/libtoolame-dab/encode.c @@ -0,0 +1,1224 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "common.h" +#include "encoder.h" +#include "bitstream.h" +#include "availbits.h" +#include "encode.h" + +int vbrstats[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* This segment contains all the core routines of the encoder, + except for the psychoacoustic models. + + The user can select either one of the two psychoacoustic + models. Model I is a simple tonal and noise masking threshold + generator, and Model II is a more sophisticated cochlear masking + threshold generator. Model I is recommended for lower complexity + applications whereas Model II gives better subjective quality at low + bit rates. */ + +/************************************************************************ +* encode_info() +* +* PURPOSE: Puts the syncword and header information on the output +* bitstream. +* +************************************************************************/ + +void encode_info (frame_info * frame, Bit_stream_struc * bs) +{ + frame_header *header = frame->header; + + putbits (bs, 0xfff, 12); /* syncword 12 bits */ + put1bit (bs, header->version); /* ID 1 bit */ + putbits (bs, 4 - header->lay, 2); /* layer 2 bits */ + put1bit (bs, !header->error_protection); /* bit set => no err prot */ + putbits (bs, header->bitrate_index, 4); + putbits (bs, header->sampling_frequency, 2); + put1bit (bs, header->padding); + put1bit (bs, header->extension); /* private_bit */ + putbits (bs, header->mode, 2); + putbits (bs, header->mode_ext, 2); + put1bit (bs, header->copyright); + put1bit (bs, header->original); + putbits (bs, header->emphasis, 2); +} + +/************************************************************************ +* +* combine_LR (Layer II) +* +* PURPOSE:Combines left and right channels into a mono channel +* +* SEMANTICS: The average of left and right subband samples is put into +* #joint_sample# +* +* +************************************************************************/ + +void combine_LR (double sb_sample[2][3][SCALE_BLOCK][SBLIMIT], + double joint_sample[3][SCALE_BLOCK][SBLIMIT], int sblimit) +{ /* make a filtered mono for joint stereo */ + int sb, smp, sufr; + + for (sb = 0; sb < sblimit; ++sb) + for (smp = 0; smp < SCALE_BLOCK; ++smp) + for (sufr = 0; sufr < 3; ++sufr) + joint_sample[sufr][smp][sb] = + .5 * (sb_sample[0][sufr][smp][sb] + sb_sample[1][sufr][smp][sb]); +} + +/************************************************************************ +* +* scale_factor_calc (Layer II) +* +* PURPOSE:For each subband, calculate the scale factor for each set +* of the 12 subband samples +* +* SEMANTICS: Pick the scalefactor #multiple[]# just larger than the +* absolute value of the peak subband sample of 12 samples, +* and store the corresponding scalefactor index in #scalar#. +* +* Layer II has three sets of 12-subband samples for a given +* subband. +* +************************************************************************/ + +#define PDS1 +#ifdef PDS1 +void scale_factor_calc (double sb_sample[][3][SCALE_BLOCK][SBLIMIT], + unsigned int scalar[][3][SBLIMIT], int nch, + int sblimit) +{ + /* Optimized to use binary search instead of linear scan through the + scalefactor table; guarantees to find scalefactor in only 5 + jumps/comparisons and not in {0 (lin. best) to 63 (lin. worst)}. + Scalefactors for subbands > sblimit are no longer computed. + Uses a single sblimit-loop. + Patrick De Smet Oct 1999. + */ + int k, t; + /* Using '--' loops to avoid possible "cmp value + bne/beq" compiler */ + /* inefficiencies. Below loops should compile to "bne/beq" only code */ + for (k = nch; k--;) + for (t = 3; t--;) { + int i; + for (i = sblimit; i--;) { + int j; + unsigned int l; + register double temp; + unsigned int scale_fac; + /* Determination of max. over each set of 12 subband samples: */ + /* PDS TODO: maybe this could/should ??!! be integrated into */ + /* the subband filtering routines? */ + register double cur_max = fabs (sb_sample[k][t][SCALE_BLOCK - 1][i]); + for (j = SCALE_BLOCK - 1; j--;) { + if ((temp = fabs (sb_sample[k][t][j][i])) > cur_max) + cur_max = temp; + } + /* PDS: binary search in the scalefactor table: */ + /* This is the real speed up: */ + for (l = 16, scale_fac = 32; l; l >>= 1) { + if (cur_max <= multiple[scale_fac]) + scale_fac += l; + else + scale_fac -= l; + } + if (cur_max > multiple[scale_fac]) + scale_fac--; + scalar[k][t][i] = scale_fac; + } + } +} +#else +void scale_factor_calc (sb_sample, scalar, nch, sblimit) + double sb_sample[][3][SCALE_BLOCK][SBLIMIT]; + unsigned int scalar[][3][SBLIMIT]; + int nch, sblimit; +{ + int i, j, k, t; + double s[SBLIMIT]; + + for (k = 0; k < nch; k++) + for (t = 0; t < 3; t++) { + for (i = 0; i < sblimit; i++) + for (j = 1, s[i] = fabs (sb_sample[k][t][0][i]); j < SCALE_BLOCK; j++) + if (fabs (sb_sample[k][t][j][i]) > s[i]) + s[i] = fabs (sb_sample[k][t][j][i]); + + for (i = 0; i < sblimit; i++) + for (j = SCALE_RANGE - 2, scalar[k][t][i] = 0; j >= 0; j--) /* $A 6/16/92 */ + if (s[i] <= multiple[j]) { + scalar[k][t][i] = j; + break; + } + for (i = sblimit; i < SBLIMIT; i++) + scalar[k][t][i] = SCALE_RANGE - 1; + } +} + +#endif +/************************************************************************ +* +* pick_scale (Layer II) +* +* PURPOSE:For each subband, puts the smallest scalefactor of the 3 +* associated with a frame into #max_sc#. This is used +* used by Psychoacoustic Model I. +* (I would recommend changin max_sc to min_sc) +* +************************************************************************/ + +void pick_scale (unsigned int scalar[2][3][SBLIMIT], frame_info * frame, + double max_sc[2][SBLIMIT]) +{ + int i, j, k, max; + int nch = frame->nch; + int sblimit = frame->sblimit; + + for (k = 0; k < nch; k++) + for (i = 0; i < sblimit; max_sc[k][i] = multiple[max], i++) + for (j = 1, max = scalar[k][0][i]; j < 3; j++) + if (max > scalar[k][j][i]) + max = scalar[k][j][i]; + for (i = sblimit; i < SBLIMIT; i++) + max_sc[0][i] = max_sc[1][i] = 1E-20; +} + +/************************************************************************ +* +* transmission_pattern (Layer II only) +* +* PURPOSE:For a given subband, determines whether to send 1, 2, or +* all 3 of the scalefactors, and fills in the scalefactor +* select information accordingly +* +* SEMANTICS: The subbands and channels are classified based on how much +* the scalefactors changes over its three values (corresponding +* to the 3 sets of 12 samples per subband). The classification +* will send 1 or 2 scalefactors instead of three if the scalefactors +* do not change much. The scalefactor select information, +* #scfsi#, is filled in accordingly. +* +************************************************************************/ + +void transmission_pattern (unsigned int scalar[2][3][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + frame_info * frame) +{ + int nch = frame->nch; + int sblimit = frame->sblimit; + int dscf[2]; + int class[2], i, j, k; + static int pattern[5][5] = { {0x123, 0x122, 0x122, 0x133, 0x123}, + {0x113, 0x111, 0x111, 0x444, 0x113}, + {0x111, 0x111, 0x111, 0x333, 0x113}, + {0x222, 0x222, 0x222, 0x333, 0x123}, + {0x123, 0x122, 0x122, 0x133, 0x123} + }; + + for (k = 0; k < nch; k++) + for (i = 0; i < sblimit; i++) { + dscf[0] = (scalar[k][0][i] - scalar[k][1][i]); + dscf[1] = (scalar[k][1][i] - scalar[k][2][i]); + for (j = 0; j < 2; j++) { + if (dscf[j] <= -3) + class[j] = 0; + else if (dscf[j] > -3 && dscf[j] < 0) + class[j] = 1; + else if (dscf[j] == 0) + class[j] = 2; + else if (dscf[j] > 0 && dscf[j] < 3) + class[j] = 3; + else + class[j] = 4; + } + switch (pattern[class[0]][class[1]]) { + case 0x123: + scfsi[k][i] = 0; + break; + case 0x122: + scfsi[k][i] = 3; + scalar[k][2][i] = scalar[k][1][i]; + break; + case 0x133: + scfsi[k][i] = 3; + scalar[k][1][i] = scalar[k][2][i]; + break; + case 0x113: + scfsi[k][i] = 1; + scalar[k][1][i] = scalar[k][0][i]; + break; + case 0x111: + scfsi[k][i] = 2; + scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; + break; + case 0x222: + scfsi[k][i] = 2; + scalar[k][0][i] = scalar[k][2][i] = scalar[k][1][i]; + break; + case 0x333: + scfsi[k][i] = 2; + scalar[k][0][i] = scalar[k][1][i] = scalar[k][2][i]; + break; + case 0x444: + scfsi[k][i] = 2; + if (scalar[k][0][i] > scalar[k][2][i]) + scalar[k][0][i] = scalar[k][2][i]; + scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; + } + } +} + +/************************************************************************ +* +* encode_scale (Layer II) +* +* PURPOSE:The encoded scalar factor information is arranged and +* queued into the output fifo to be transmitted. +* +* For Layer II, the three scale factors associated with +* a given subband and channel are transmitted in accordance +* with the scfsi, which is transmitted first. +* +************************************************************************/ + +void +encode_scale (unsigned int bit_alloc[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int scalar[2][3][SBLIMIT], frame_info * frame, + Bit_stream_struc * bs) +{ + int nch = frame->nch; + int sblimit = frame->sblimit; + int i, j, k; + + for (i = 0; i < sblimit; i++) + for (k = 0; k < nch; k++) + if (bit_alloc[k][i]) + putbits (bs, scfsi[k][i], 2); + + for (i = 0; i < sblimit; i++) + for (k = 0; k < nch; k++) + if (bit_alloc[k][i]) /* above jsbound, bit_alloc[0][i] == ba[1][i] */ + switch (scfsi[k][i]) { + case 0: + for (j = 0; j < 3; j++) + putbits (bs, scalar[k][j][i], 6); + break; + case 1: + case 3: + putbits (bs, scalar[k][0][i], 6); + putbits (bs, scalar[k][2][i], 6); + break; + case 2: + putbits (bs, scalar[k][0][i], 6); + } +} + +/*=======================================================================\ +| | +| The following routines are done after the masking threshold | +| has been calculated by the fft analysis routines in the Psychoacoustic | +| model. Using the MNR calculated, the actual number of bits allocated | +| to each subband is found iteratively. | +| | +\=======================================================================*/ + +/************************************************************************ +* +* bits_for_nonoise (Layer II) +* +* PURPOSE:Returns the number of bits required to produce a +* mask-to-noise ratio better or equal to the noise/no_noise threshold. +* +* SEMANTICS: +* bbal = # bits needed for encoding bit allocation +* bsel = # bits needed for encoding scalefactor select information +* banc = # bits needed for ancillary data (header info included) +* +* For each subband and channel, will add bits until one of the +* following occurs: +* - Hit maximum number of bits we can allocate for that subband +* - MNR is better than or equal to the minimum masking level +* (NOISY_MIN_MNR) +* Then the bits required for scalefactors, scfsi, bit allocation, +* and the subband samples are tallied (#req_bits#) and returned. +* +* (NOISY_MIN_MNR) is the smallest MNR a subband can have before it is +* counted as 'noisy' by the logic which chooses the number of JS +* subbands. +* +* Joint stereo is supported. +* +************************************************************************/ + +static double snr[18] = { 0.00, 7.00, 11.00, 16.00, 20.84, + 25.28, 31.59, 37.75, 43.84, + 49.89, 55.93, 61.96, 67.98, 74.01, + 80.03, 86.05, 92.01, 98.01 +}; + +int bits_for_nonoise (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], frame_info * frame) +{ + int sb, ch, ba; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + int req_bits = 0, bbal = 0, berr = 0, banc = 32; + int maxAlloc, sel_bits, sc_bits, smp_bits; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + /* added 92-08-11 shn */ + if (frame->header->error_protection) + berr = 16; + else + berr = 0; + + for (sb = 0; sb < jsbound; ++sb) + bbal += nch * (*alloc)[sb][0].bits; + for (sb = jsbound; sb < sblimit; ++sb) + bbal += (*alloc)[sb][0].bits; + req_bits = banc + bbal + berr; + + for (sb = 0; sb < sblimit; ++sb) + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ++ch) { + maxAlloc = (1 << (*alloc)[sb][0].bits) - 1; + sel_bits = sc_bits = smp_bits = 0; + for (ba = 0; ba < maxAlloc - 1; ++ba) + if ((-perm_smr[ch][sb] + + snr[(*alloc)[sb][ba].quant + ((ba > 0) ? 1 : 0)]) >= + NOISY_MIN_MNR) + break; /* we found enough bits */ + if (nch == 2 && sb >= jsbound) /* check other JS channel */ + for (; ba < maxAlloc - 1; ++ba) + if ((-perm_smr[1 - ch][sb] + + snr[(*alloc)[sb][ba].quant + ((ba > 0) ? 1 : 0)]) >= + NOISY_MIN_MNR) + break; + if (ba > 0) { + smp_bits = + SCALE_BLOCK * ((*alloc)[sb][ba].group * (*alloc)[sb][ba].bits); + /* scale factor bits required for subband */ + sel_bits = 2; + sc_bits = 6 * sfsPerScfsi[scfsi[ch][sb]]; + if (nch == 2 && sb >= jsbound) { + /* each new js sb has L+R scfsis */ + sel_bits += 2; + sc_bits += 6 * sfsPerScfsi[scfsi[1 - ch][sb]]; + } + req_bits += smp_bits + sel_bits + sc_bits; + } + } + return req_bits; +} + +int VBR_bits_for_nonoise (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + frame_info * frame, int vbrlevel) +{ + int sb, ch, ba; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + int req_bits = 0, bbal = 0, berr = 0, banc = 32; + int maxAlloc, sel_bits, sc_bits, smp_bits; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + /* added 92-08-11 shn */ + if (frame->header->error_protection) + berr = 16; + else + berr = 0; + + for (sb = 0; sb < jsbound; ++sb) + bbal += nch * (*alloc)[sb][0].bits; + for (sb = jsbound; sb < sblimit; ++sb) + bbal += (*alloc)[sb][0].bits; + req_bits = banc + bbal + berr; + + for (sb = 0; sb < sblimit; ++sb) + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ++ch) { + maxAlloc = (1 << (*alloc)[sb][0].bits) - 1; + sel_bits = sc_bits = smp_bits = 0; + for (ba = 0; ba < maxAlloc - 1; ++ba) + /* The change between this function and the normal one is that the MIN_MNR is increased by the vbrlevel */ + if ((-perm_smr[ch][sb] + + snr[(*alloc)[sb][ba].quant + ((ba > 0) ? 1 : 0)]) >= + NOISY_MIN_MNR + vbrlevel) + break; /* we found enough bits */ + if (nch == 2 && sb >= jsbound) /* check other JS channel */ + for (; ba < maxAlloc - 1; ++ba) + if ((-perm_smr[1 - ch][sb] + + snr[(*alloc)[sb][ba].quant + ((ba > 0) ? 1 : 0)]) >= + NOISY_MIN_MNR + vbrlevel) + break; + if (ba > 0) { + smp_bits = + SCALE_BLOCK * ((*alloc)[sb][ba].group * (*alloc)[sb][ba].bits); + /* scale factor bits required for subband */ + sel_bits = 2; + sc_bits = 6 * sfsPerScfsi[scfsi[ch][sb]]; + if (nch == 2 && sb >= jsbound) { + /* each new js sb has L+R scfsis */ + sel_bits += 2; + sc_bits += 6 * sfsPerScfsi[scfsi[1 - ch][sb]]; + } + req_bits += smp_bits + sel_bits + sc_bits; + } + } + return req_bits; +} + +/************************************************************************ +* +* main_bit_allocation (Layer II) +* +* PURPOSE:For joint stereo mode, determines which of the 4 joint +* stereo modes is needed. Then calls *_a_bit_allocation(), which +* allocates bits for each of the subbands until there are no more bits +* left, or the MNR is at the noise/no_noise threshold. +* +* SEMANTICS: +* +* For joint stereo mode, joint stereo is changed to stereo if +* there are enough bits to encode stereo at or better than the +* no-noise threshold (NOISY_MIN_MNR). Otherwise, the system +* iteratively allocates less bits by using joint stereo until one +* of the following occurs: +* - there are no more noisy subbands (MNR >= NOISY_MIN_MNR) +* - mode_ext has been reduced to 0, which means that all but the +* lowest 4 subbands have been converted from stereo to joint +* stereo, and no more subbands may be converted +* +* This function calls *_bits_for_nonoise() and *_a_bit_allocation(). +* +************************************************************************/ +void main_bit_allocation (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options * glopts) +{ + int noisy_sbs; + int mode, mode_ext, lay; + int rq_db; /* av_db = *adb; Not Used MFC Nov 99 */ + + /* these are the tables which specify the limits within which the VBR can vary + You can't vary outside these ranges, otherwise a new alloc table would have to + be loaded in the middle of encoding. This VBR hack is dodgy - the standard + says that LayerII decoders don't have to support a variable bitrate, but Layer3 + decoders must do so. Hence, it is unlikely that a compliant layer2 decoder would be + written to dynmically change allocation tables. *BUT* a layer3 encoder might handle it + by default meaning we could switch tables mid-encode and enjoy a wider range of bitrates + for the VBR encoding. + None of this needs to be done for LSF, since there is only *one* possible alloc table in LSF + MFC Feb 2003 */ + int vbrlimits[2][3][2] = { + /* MONO */ + { /* 44 */ {6, 10}, + /* 48 */ {3, 10}, + /* 32 */ {6, 10}}, + /* STEREO */ + { /* 44 */ {10, 14}, + /* 48 */ {7, 14}, + /* 32 */ {10, 14}} + }; + + static int init = 0; + static int lower = 10, upper = 10; + static int bitrateindextobits[15] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int guessindex = 0; + + if (init == 0) { + int nch = 1; + int sfreq; + frame_header *header = frame->header; + init++; + if (header->version == 0) { + /* LSF: so can use any bitrate index from 1->15 */ + lower = 1; + upper = 14; + } else { + if (frame->actual_mode == MPG_MD_MONO) + nch = 0; + sfreq = header->sampling_frequency; + lower = vbrlimits[nch][sfreq][0]; + upper = vbrlimits[nch][sfreq][1]; + } + if (glopts->verbosity > 2) + fprintf (stdout, "VBR bitrate index limits [%i -> %i]\n", lower, upper); + + { + /* set up a conversion table for bitrateindex->bits for this version/sampl freq + This will be used to find the best bitrate to cope with the number of bits that + are needed (as determined by VBR_bits_for_nonoise) */ + int brindex; + frame_header *header = frame->header; + for (brindex = lower; brindex <= upper; brindex++) { + bitrateindextobits[brindex] = + (int) (1152.0 / s_freq[header->version][header->sampling_frequency]) * + ((double) bitrate[header->version][brindex]); + } + } + + } + + if ((mode = frame->actual_mode) == MPG_MD_JOINT_STEREO) { + frame->header->mode = MPG_MD_STEREO; + frame->header->mode_ext = 0; + frame->jsbound = frame->sblimit; + if ((rq_db = bits_for_nonoise (perm_smr, scfsi, frame)) > *adb) { + frame->header->mode = MPG_MD_JOINT_STEREO; + mode_ext = 4; /* 3 is least severe reduction */ + lay = frame->header->lay; + do { + --mode_ext; + frame->jsbound = js_bound (mode_ext); + rq_db = bits_for_nonoise (perm_smr, scfsi, frame); + } + while ((rq_db > *adb) && (mode_ext > 0)); + frame->header->mode_ext = mode_ext; + } /* well we either eliminated noisy sbs or mode_ext == 0 */ + } + + /* decide on which bit allocation method to use */ + if (glopts->vbr == FALSE) { + /* Just do the old bit allocation method */ + noisy_sbs = a_bit_allocation (perm_smr, scfsi, bit_alloc, adb, frame); + } else { + /* do the VBR bit allocation method */ + frame->header->bitrate_index = lower; + *adb = available_bits (frame->header, glopts); + { + int brindex; + int found = FALSE; + + /* Work out how many bits are needed for there to be no noise (ie all MNR > 0.0 + VBRLEVEL) */ + int req = + VBR_bits_for_nonoise (perm_smr, scfsi, frame, glopts->vbrlevel); + + /* Look up this value in the bitrateindextobits table to find what bitrate we should use for + this frame */ + for (brindex = lower; brindex <= upper; brindex++) { + if (bitrateindextobits[brindex] > req) { + /* this method always *overestimates* the bits that are needed + i.e. it will usually guess right but + when it's wrong it'll guess a higher bitrate than actually required. + e.g. on "messages from earth" track 6, the guess was + wrong on 75/36341 frames. each time it guessed higher. + MFC Feb 2003 */ + guessindex = brindex; + found = TRUE; + break; + } + } + /* Just for sanity */ + if (found == FALSE) + guessindex = upper; + } + + frame->header->bitrate_index = guessindex; + *adb = available_bits (frame->header, glopts); + + /* update the statistics */ + vbrstats[frame->header->bitrate_index]++; + + if (glopts->verbosity > 2) { + /* print out the VBR stats every 1000th frame */ + static int count = 0; + int i; + if ((count++ % 1000) == 0) { + for (i = 1; i < 15; i++) + fprintf (stdout, "%4i ", vbrstats[i]); + fprintf (stdout, "\n"); + } + + /* Print out *every* frames bitrateindex, bits required, and bits available at this bitrate */ + if (glopts->verbosity > 5) + fprintf (stdout, + "> bitrate index %2i has %i bits available to encode the %i bits\n", + frame->header->bitrate_index, *adb, + VBR_bits_for_nonoise (perm_smr, scfsi, frame, + glopts->vbrlevel)); + + } + + noisy_sbs = + VBR_bit_allocation (perm_smr, scfsi, bit_alloc, adb, frame, glopts); + } +} + +void VBR_maxmnr (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch, options * glopts) +{ + int i, k; + double small; + + small = 999999.0; + *min_sb = -1; + *min_ch = -1; + for (k = 0; k < nch; ++k) + for (i = 0; i < sblimit; i++) + if (used[k][i] != 2 && small > mnr[k][i]) { + small = mnr[k][i]; + *min_sb = i; + *min_ch = k; + } +} +/******************** +MFC Feb 2003 +VBR_bit_allocation is different to the normal a_bit_allocation in that +it is known beforehand that there are definitely enough bits to do what we +have to - i.e. a bitrate was specificially chosen in main_bit_allocation so +that we have enough bits to encode what we have to. +This function should take that into account and just greedily assign +the bits, rather than fussing over the minimum MNR subband - we know +each subband gets its required bits, why quibble? +This function doesn't chew much CPU, so I haven't made any attempt +to do this yet. +*********************/ +int +VBR_bit_allocation (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options * glopts) +{ + int i, min_ch, min_sb, oth_ch, k, increment, scale, seli, ba; + int bspl, bscf, bsel, ad, bbal = 0; + double mnr[2][SBLIMIT]; + char used[2][SBLIMIT]; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + static char init = 0; + static int banc = 32, berr = 0; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + if (!init) { + init = 1; + if (frame->header->error_protection) + berr = 16; /* added 92-08-11 shn */ + } + + for (i = 0; i < jsbound; ++i) + bbal += nch * (*alloc)[i][0].bits; + for (i = jsbound; i < sblimit; ++i) + bbal += (*alloc)[i][0].bits; + *adb -= bbal + berr + banc; + ad = *adb; + + for (i = 0; i < sblimit; i++) + for (k = 0; k < nch; k++) { + mnr[k][i] = snr[0] - perm_smr[k][i]; + bit_alloc[k][i] = 0; + used[k][i] = 0; + } + bspl = bscf = bsel = 0; + + do { + /* locate the subband with minimum SMR */ + VBR_maxmnr (mnr, used, sblimit, nch, &min_sb, &min_ch, glopts); + + if (min_sb > -1) { /* there was something to find */ + /* find increase in bit allocation in subband [min] */ + increment = + SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb] + 1].group * + (*alloc)[min_sb][bit_alloc[min_ch][min_sb] + 1].bits); + if (used[min_ch][min_sb]) + increment -= + SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb]].group * + (*alloc)[min_sb][bit_alloc[min_ch][min_sb]].bits); + + /* scale factor bits required for subband [min] */ + oth_ch = 1 - min_ch; /* above js bound, need both chans */ + if (used[min_ch][min_sb]) + scale = seli = 0; + else { /* this channel had no bits or scfs before */ + seli = 2; + scale = 6 * sfsPerScfsi[scfsi[min_ch][min_sb]]; + if (nch == 2 && min_sb >= jsbound) { + /* each new js sb has L+R scfsis */ + seli += 2; + scale += 6 * sfsPerScfsi[scfsi[oth_ch][min_sb]]; + } + } + + /* check to see enough bits were available for */ + /* increasing resolution in the minimum band */ + if (ad >= bspl + bscf + bsel + seli + scale + increment) { + ba = ++bit_alloc[min_ch][min_sb]; /* next up alloc */ + bspl += increment; /* bits for subband sample */ + bscf += scale; /* bits for scale factor */ + bsel += seli; /* bits for scfsi code */ + used[min_ch][min_sb] = 1; /* subband has bits */ + mnr[min_ch][min_sb] = + -perm_smr[min_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant + 1]; + /* Check if subband has been fully allocated max bits */ + if (ba >= (1 << (*alloc)[min_sb][0].bits) - 1) + used[min_ch][min_sb] = 2; /* don't let this sb get any more bits */ + } else + used[min_ch][min_sb] = 2; /* can't increase this alloc */ + + if (min_sb >= jsbound && nch == 2) { + /* above jsbound, alloc applies L+R */ + ba = bit_alloc[oth_ch][min_sb] = bit_alloc[min_ch][min_sb]; + used[oth_ch][min_sb] = used[min_ch][min_sb]; + mnr[oth_ch][min_sb] = + -perm_smr[oth_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant + 1]; + } + + } + } + while (min_sb > -1); /* until could find no channel */ + + /* Calculate the number of bits left */ + ad -= bspl + bscf + bsel; + *adb = ad; + for (k = 0; k < nch; k++) + for (i = sblimit; i < SBLIMIT; i++) + bit_alloc[k][i] = 0; + + return 0; +} + +/************************************************************************ +* +* a_bit_allocation (Layer II) +* +* PURPOSE:Adds bits to the subbands with the lowest mask-to-noise +* ratios, until the maximum number of bits for the subband has +* been allocated. +* +* SEMANTICS: +* 1. Find the subband and channel with the smallest MNR (#min_sb#, +* and #min_ch#) +* 2. Calculate the increase in bits needed if we increase the bit +* allocation to the next higher level +* 3. If there are enough bits available for increasing the resolution +* in #min_sb#, #min_ch#, and the subband has not yet reached its +* maximum allocation, update the bit allocation, MNR, and bits + available accordingly +* 4. Repeat until there are no more bits left, or no more available +* subbands. (A subband is still available until the maximum +* number of bits for the subband has been allocated, or there +* aren't enough bits to go to the next higher resolution in the + subband.) +* +************************************************************************/ + +void maxmnr (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch) +{ + int i, k; + double small; + + small = 999999.0; + *min_sb = -1; + *min_ch = -1; + for (k = 0; k < nch; ++k) + for (i = 0; i < sblimit; i++) + if (used[k][i] != 2 && small > mnr[k][i]) { + small = mnr[k][i]; + *min_sb = i; + *min_ch = k; + } +} + +int a_bit_allocation (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame) +{ + int i, min_ch, min_sb, oth_ch, k, increment, scale, seli, ba; + int bspl, bscf, bsel, ad, bbal = 0; + double mnr[2][SBLIMIT]; + char used[2][SBLIMIT]; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + static char init = 0; + static int banc = 32, berr = 0; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + +#define CHECKITERx +#ifdef CHECKITER + int count=0; +#endif + + if (!init) { + init = 1; + if (frame->header->error_protection) + berr = 16; /* added 92-08-11 shn */ + } + + for (i = 0; i < jsbound; ++i) + bbal += nch * (*alloc)[i][0].bits; + for (i = jsbound; i < sblimit; ++i) + bbal += (*alloc)[i][0].bits; + *adb -= bbal + berr + banc; + ad = *adb; + + for (i = 0; i < sblimit; i++) + for (k = 0; k < nch; k++) { + mnr[k][i] = snr[0] - perm_smr[k][i]; + bit_alloc[k][i] = 0; + used[k][i] = 0; + } + bspl = bscf = bsel = 0; + + do { +#ifdef CHECKITER + count++; +#endif + /* locate the subband with minimum SMR */ + maxmnr (mnr, used, sblimit, nch, &min_sb, &min_ch); + + if (min_sb > -1) { /* there was something to find */ + /* find increase in bit allocation in subband [min] */ + increment = + SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb] + 1].group * + (*alloc)[min_sb][bit_alloc[min_ch][min_sb] + 1].bits); + if (used[min_ch][min_sb]) + increment -= + SCALE_BLOCK * ((*alloc)[min_sb][bit_alloc[min_ch][min_sb]].group * + (*alloc)[min_sb][bit_alloc[min_ch][min_sb]].bits); + + /* scale factor bits required for subband [min] */ + oth_ch = 1 - min_ch; /* above js bound, need both chans */ + if (used[min_ch][min_sb]) + scale = seli = 0; + else { /* this channel had no bits or scfs before */ + seli = 2; + scale = 6 * sfsPerScfsi[scfsi[min_ch][min_sb]]; + if (nch == 2 && min_sb >= jsbound) { + /* each new js sb has L+R scfsis */ + seli += 2; + scale += 6 * sfsPerScfsi[scfsi[oth_ch][min_sb]]; + } + } + + /* check to see enough bits were available for */ + /* increasing resolution in the minimum band */ + if (ad >= bspl + bscf + bsel + seli + scale + increment) { + ba = ++bit_alloc[min_ch][min_sb]; /* next up alloc */ + bspl += increment; /* bits for subband sample */ + bscf += scale; /* bits for scale factor */ + bsel += seli; /* bits for scfsi code */ + used[min_ch][min_sb] = 1; /* subband has bits */ + mnr[min_ch][min_sb] = + -perm_smr[min_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant + 1]; + /* Check if subband has been fully allocated max bits */ + if (ba >= (1 << (*alloc)[min_sb][0].bits) - 1) + used[min_ch][min_sb] = 2; /* don't let this sb get any more bits */ + } else + used[min_ch][min_sb] = 2; /* can't increase this alloc */ + + if (min_sb >= jsbound && nch == 2) { + /* above jsbound, alloc applies L+R */ + ba = bit_alloc[oth_ch][min_sb] = bit_alloc[min_ch][min_sb]; + used[oth_ch][min_sb] = used[min_ch][min_sb]; + mnr[oth_ch][min_sb] = + -perm_smr[oth_ch][min_sb] + snr[(*alloc)[min_sb][ba].quant + 1]; + } + + } + } + while (min_sb > -1); /* until could find no channel */ + + /* Calculate the number of bits left */ + ad -= bspl + bscf + bsel; + *adb = ad; + for (k = 0; k < nch; k++) + for (i = sblimit; i < SBLIMIT; i++) + bit_alloc[k][i] = 0; + +#ifdef USELESSCODE + /* this function is declared to return an INT, which is meant to be a count + of the subbands which are still noisy. But, the return value is ignored, + so why bother? Is the count of noisy_sbs useful as any sort of + quality measure? Leave this in, until I'm sure that noisy_sbs couldn't + be used for something + MFC Feb 2003 */ + + noisy_sbs = 0; /* calc worst noise in case */ + for (k = 0; k < nch; ++k) { + for (i = 0; i < sblimit; i++) { + if (mnr[k][i] < NOISY_MIN_MNR) + ++noisy_sbs; /* noise is not masked */ + } + } + return noisy_sbs; +#endif +#ifdef CHECKITER + fprintf(stdout,"a bit alloc %i\n", count); +#endif + return 0; +} + +/************************************************************************ +* +* subband_quantization (Layer II) +* +* PURPOSE:Quantizes subband samples to appropriate number of bits +* +* SEMANTICS: Subband samples are divided by their scalefactors, which + makes the quantization more efficient. The scaled samples are +* quantized by the function a*x+b, where a and b are functions of +* the number of quantization levels. The result is then truncated +* to the appropriate number of bits and the MSB is inverted. +* +* Note that for fractional 2's complement, inverting the MSB for a + negative number x is equivalent to adding 1 to it. +* +************************************************************************/ +#define PDS3 +#ifdef PDS3 +static double a[17] = { + 0.750000000, 0.625000000, 0.875000000, 0.562500000, 0.937500000, + 0.968750000, 0.984375000, 0.992187500, 0.996093750, 0.998046875, + 0.999023438, 0.999511719, 0.999755859, 0.999877930, 0.999938965, + 0.999969482, 0.999984741 +}; + +static double b[17] = { + -0.250000000, -0.375000000, -0.125000000, -0.437500000, -0.062500000, + -0.031250000, -0.015625000, -0.007812500, -0.003906250, -0.001953125, + -0.000976563, -0.000488281, -0.000244141, -0.000122070, -0.000061035, + -0.000030518, -0.000015259 +}; + +static unsigned int pds_quant_bits[17] = { + /* for a number of quantization steps; */ + /* 3, 5, 7, 9, 15, + 31, 63, 127, 255, 511, + 1023, 2047, 4095, 8191, 16383, + 32767, 65535 + */ + /* below we need : */ + 2, 4, 4, 8, 8, + 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, + 16384, 32768 +}; +/* to retain succesfull quant */ +/* This is only a quick and dirty tric to speed up ISO code */ +/* In below quant routine : also rewrote loops to decrement */ +/* Added/changed by Patrick De Smet, Nov. 1999 */ + +/* PDS TODO: maybe it is faster not to store pds_quant_bits */ +/* but rather store (char) n, and use (1L shift left n) ; */ +/* is a shift faster than loading unsigned int from array ? */ + +void +subband_quantization (unsigned int scalar[2][3][SBLIMIT], + double sb_samples[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int j_scale[3][SBLIMIT], + double j_samps[3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + frame_info * frame) +{ + int i, j, k, s, qnt, sig; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + double d; + al_table *alloc = frame->alloc; + + for (s = 3; s--;) + for (j = SCALE_BLOCK; j--;) + for (i = sblimit; i--;) + for (k = ((i < jsbound) ? nch : 1); k--;) + if (bit_alloc[k][i]) { + /* scale and quantize FLOATing point sample */ + if (nch == 2 && i >= jsbound) /* use j-stereo samples */ + d = j_samps[s][j][i] / multiple[j_scale[s][i]]; + else + d = sb_samples[k][s][j][i] / multiple[scalar[k][s][i]]; + if (fabs(d) > 1.0) + fprintf (stderr, "Not scaled properly %d %d %d %d\n", k, s, j, + i); + qnt = (*alloc)[i][bit_alloc[k][i]].quant; + d = d * a[qnt] + b[qnt]; + /* extract MSB N-1 bits from the FLOATing point sample */ + if (d >= 0) + sig = 1; + else { + sig = 0; + d += 1.0; + } + sbband[k][s][j][i] = + (unsigned int) (d * (double) (pds_quant_bits[qnt])); + /* tag the inverted sign bit to sbband at position N */ + /* The bit inversion is a must for grouping with 3,5,9 steps + so it is done for all subbands */ + if (sig) + sbband[k][s][j][i] |= (pds_quant_bits[qnt]); + } + for (s = 3; s--;) + for (j = sblimit; j < SBLIMIT; j++) + for (i = SCALE_BLOCK; i--;) + for (k = nch; k--;) + sbband[k][s][i][j] = 0; +} +#else + +static double a[17] = { + 0.750000000, 0.625000000, 0.875000000, 0.562500000, 0.937500000, + 0.968750000, 0.984375000, 0.992187500, 0.996093750, 0.998046875, + 0.999023438, 0.999511719, 0.999755859, 0.999877930, 0.999938965, + 0.999969482, 0.999984741 +}; + +static double b[17] = { + -0.250000000, -0.375000000, -0.125000000, -0.437500000, -0.062500000, + -0.031250000, -0.015625000, -0.007812500, -0.003906250, -0.001953125, + -0.000976563, -0.000488281, -0.000244141, -0.000122070, -0.000061035, + -0.000030518, -0.000015259 +}; + +void +subband_quantization (unsigned int scalar[2][3][SBLIMIT], + double sb_samples[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int j_scale[3][SBLIMIT], + double j_samps[3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + frame_info * frame) +{ + int i, j, k, s, n, qnt, sig; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + unsigned int stps; + double d; + al_table *alloc = frame->alloc; + + for (s = 0; s < 3; s++) + for (j = 0; j < SCALE_BLOCK; j++) + for (i = 0; i < sblimit; i++) + for (k = 0; k < ((i < jsbound) ? nch : 1); k++) + if (bit_alloc[k][i]) { + /* scale and quantize FLOATing point sample */ + if (nch == 2 && i >= jsbound) /* use j-stereo samples */ + d = j_samps[s][j][i] / multiple[j_scale[s][i]]; + else + d = sb_samples[k][s][j][i] / multiple[scalar[k][s][i]]; + if (mod (d) > 1.0) + fprintf (stderr, "Not scaled properly %d %d %d %d\n", k, s, j, + i); + qnt = (*alloc)[i][bit_alloc[k][i]].quant; + d = d * a[qnt] + b[qnt]; + /* extract MSB N-1 bits from the FLOATing point sample */ + if (d >= 0) + sig = 1; + else { + sig = 0; + d += 1.0; + } + n = 0; + stps = (*alloc)[i][bit_alloc[k][i]].steps; + while ((1L << n) < stps) + n++; + n--; + sbband[k][s][j][i] = (unsigned int) (d * (double) (1L << n)); + /* tag the inverted sign bit to sbband at position N */ + /* The bit inversion is a must for grouping with 3,5,9 steps + so it is done for all subbands */ + if (sig) + sbband[k][s][j][i] |= 1 << n; + } + + for (k = 0; k < nch; k++) + for (s = 0; s < 3; s++) + for (i = 0; i < SCALE_BLOCK; i++) + for (j = sblimit; j < SBLIMIT; j++) + sbband[k][s][i][j] = 0; +} +#endif + +/************************************************************************* +* encode_bit_alloc (Layer II) +* +* PURPOSE:Writes bit allocation information onto bitstream +* +* Layer II uses 4,3,2, or 0 bits depending on the +* quantization table used. +* +************************************************************************/ + +void encode_bit_alloc (unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs) +{ + int i, k; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + + for (i = 0; i < sblimit; i++) + for (k = 0; k < ((i < jsbound) ? nch : 1); k++) + putbits (bs, bit_alloc[k][i], (*alloc)[i][0].bits); +} + +/************************************************************************ +* +* sample_encoding (Layer II) +* +* PURPOSE:Put one frame of subband samples on to the bitstream +* +* SEMANTICS: The number of bits allocated per sample is read from +* the bit allocation information #bit_alloc#. Layer 2 +* supports writing grouped samples for quantization steps +* that are not a power of 2. +* +************************************************************************/ + +void sample_encoding (unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs) +{ + unsigned int temp; + unsigned int i, j, k, s, x, y; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + al_table *alloc = frame->alloc; + + for (s = 0; s < 3; s++) + for (j = 0; j < SCALE_BLOCK; j += 3) + for (i = 0; i < sblimit; i++) + for (k = 0; k < ((i < jsbound) ? nch : 1); k++) + if (bit_alloc[k][i]) { + if ((*alloc)[i][bit_alloc[k][i]].group == 3) { + for (x = 0; x < 3; x++) + putbits (bs, sbband[k][s][j + x][i], + (*alloc)[i][bit_alloc[k][i]].bits); + } else { + y = (*alloc)[i][bit_alloc[k][i]].steps; + temp = + sbband[k][s][j][i] + sbband[k][s][j + 1][i] * y + + sbband[k][s][j + 2][i] * y * y; + putbits (bs, temp, (*alloc)[i][bit_alloc[k][i]].bits); + } + } +} + +/************************************************************************ +* +* encode_CRC +* +************************************************************************/ + +void encode_CRC (unsigned int crc, Bit_stream_struc * bs) +{ + putbits (bs, crc, 16); +} diff --git a/libtoolame-dab/encode.h b/libtoolame-dab/encode.h new file mode 100644 index 0000000..136967a --- /dev/null +++ b/libtoolame-dab/encode.h @@ -0,0 +1,47 @@ + +void create_ana_filter (double[SBLIMIT][64]); +void encode_info (frame_info *, Bit_stream_struc *); +void combine_LR (double[2][3][SCALE_BLOCK][SBLIMIT], + double[3][SCALE_BLOCK][SBLIMIT], int); +void scale_factor_calc (double[][3][SCALE_BLOCK][SBLIMIT], + unsigned int[][3][SBLIMIT], int, int); +void pick_scale (unsigned int[2][3][SBLIMIT], frame_info *, + double[2][SBLIMIT]); +void put_scale (unsigned int[2][3][SBLIMIT], frame_info *, + double[2][SBLIMIT]); +void transmission_pattern (unsigned int[2][3][SBLIMIT], + unsigned int[2][SBLIMIT], frame_info *); +void encode_scale (unsigned int[2][SBLIMIT], + unsigned int[2][SBLIMIT], + unsigned int[2][3][SBLIMIT], frame_info *, + Bit_stream_struc *); +int bits_for_nonoise (double[2][SBLIMIT], unsigned int[2][SBLIMIT], + frame_info *); +void main_bit_allocation (double[2][SBLIMIT], + unsigned int[2][SBLIMIT], + unsigned int[2][SBLIMIT], int *, + frame_info *, options *); + +int a_bit_allocation (double[2][SBLIMIT], unsigned int[2][SBLIMIT], + unsigned int[2][SBLIMIT], int *, frame_info *); +void subband_quantization (unsigned int[2][3][SBLIMIT], + double[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int[3][SBLIMIT], + double[3][SCALE_BLOCK][SBLIMIT], + unsigned int[2][SBLIMIT], + unsigned int[2][3][SCALE_BLOCK][SBLIMIT], + frame_info *); +void encode_bit_alloc (unsigned int[2][SBLIMIT], frame_info *, + Bit_stream_struc *); +void sample_encoding (unsigned int[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int[2][SBLIMIT], frame_info *, + Bit_stream_struc *); +void encode_CRC (unsigned int, Bit_stream_struc *); + +void maxmnr (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, int stereo, int *min_sb, int *min_ch); + +int VBR_bits_for_nonoise (double perm_smr[2][SBLIMIT], unsigned int scfsi[2][SBLIMIT], frame_info * frame, int vbrlevel); +void VBR_maxmnr (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, int stereo, int *min_sb, int *min_ch, options * glopts); +int VBR_bit_allocation (double perm_smr[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], unsigned int bit_alloc[2][SBLIMIT], int *adb, frame_info * frame, options * glopts); + diff --git a/libtoolame-dab/encode_new.c b/libtoolame-dab/encode_new.c new file mode 100644 index 0000000..2e797c9 --- /dev/null +++ b/libtoolame-dab/encode_new.c @@ -0,0 +1,1188 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "common.h" +#include "options.h" +#include "bitstream.h" +#include "availbits.h" +#include "encode_new.h" + +#define NUMTABLES 5 +int vbrstats_new[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* There are really only 9 distinct lines in the allocation tables + each member of this table is an index into */ +/* step_index[linenumber][index] */ +static int step_index[9][16] = { + /*0*/ {0, 1, 3, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17}, + /*1*/ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,17}, + /*2*/ {0, 1, 2, 3, 4, 5, 6,17, 0, 0, 0, 0, 0, 0, 0, 0}, + /*3*/ {0, 1, 2, 17,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /*4*/ {0, 1, 2, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16}, + /*5*/ {0, 1, 2, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0}, + /* From ISO13818 Table B.1 */ + /*6*/ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, + /*7*/ {0, 1, 2, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0}, + /*8*/ {0, 1, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static int nbal[9] = {4, 4, 3, 2, 4, 3, 4, 3, 2}; + + +/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 */ +/* The number of steps allowed */ +static int steps[18] = {0, 3, 5, 7, 9, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535}; +/* The power of 2 just under the steps value */ +static int steps2n[18]={0, 2, 4, 4, 8, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}; +/* The bits per codeword from TableB.4 */ +static int bits[18] = {0, 5, 7, 3, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; +/* Samples per codeword Table B.4 Page 53 */ +//static int group[18] = {0, 3, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static int group[18] = {0, 1, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +/* nbal */ + +/* The sblimits of the 5 allocation tables + 4 tables for MPEG-1 + 1 table for MPEG-2 LSF */ +static int table_sblimit[5] = {27, 30, 8, 12, 30}; + +/* Each table contains a list of allowable quantization steps. + There are only 9 distinct lists of steps. + This table gives the index of which of the 9 lists is being used + A "-1" entry means that it is above the sblimit for this table */ +static int line[5][SBLIMIT] = { + /*00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 */ + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,-1,-1,-1,-1,-1}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,-1,-1}, + {4, 4, 5, 5, 5, 5, 5, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + {4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + /* LSF Table */ + {6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} +}; + +/* This is ISO11172 Table B.1 */ +double scalefactor[64] = { /* Equation for nth element = 2 / (cuberoot(2) ^ n) */ + 2.00000000000000, 1.58740105196820, 1.25992104989487, + 1.00000000000000, 0.79370052598410, 0.62996052494744, 0.50000000000000, + 0.39685026299205, 0.31498026247372, 0.25000000000000, 0.19842513149602, + 0.15749013123686, 0.12500000000000, 0.09921256574801, 0.07874506561843, + 0.06250000000000, 0.04960628287401, 0.03937253280921, 0.03125000000000, + 0.02480314143700, 0.01968626640461, 0.01562500000000, 0.01240157071850, + 0.00984313320230, 0.00781250000000, 0.00620078535925, 0.00492156660115, + 0.00390625000000, 0.00310039267963, 0.00246078330058, 0.00195312500000, + 0.00155019633981, 0.00123039165029, 0.00097656250000, 0.00077509816991, + 0.00061519582514, 0.00048828125000, 0.00038754908495, 0.00030759791257, + 0.00024414062500, 0.00019377454248, 0.00015379895629, 0.00012207031250, + 0.00009688727124, 0.00007689947814, 0.00006103515625, 0.00004844363562, + 0.00003844973907, 0.00003051757813, 0.00002422181781, 0.00001922486954, + 0.00001525878906, 0.00001211090890, 0.00000961243477, 0.00000762939453, + 0.00000605545445, 0.00000480621738, 0.00000381469727, 0.00000302772723, + 0.00000240310869, 0.00000190734863, 0.00000151386361, 0.00000120155435, + 1E-20 +}; + +/* ISO11172 Table C.5 Layer II Signal to Noise Raios + MFC FIX find a reference for these in terms of bits->SNR value + Index into table is the steps index + index steps SNR + 0 0 0.00 + 1 3 7.00 + 2 5 11.00 + 3 7 16.00 + 4 9 20.84 + etc +*/ +static double SNR[18] = { 0.00, 7.00, 11.00, 16.00, 20.84, + 25.28, 31.59, 37.75, 43.84, + 49.89, 55.93, 61.96, 67.98, 74.01, + 80.03, 86.05, 92.01, 98.01 +}; + +int tablenum=0; + +int encode_init(frame_info *frame) { + int ws, bsp, br_per_ch, sfrq; + + bsp = frame->header->bitrate_index; + br_per_ch = bitrate[frame->header->version][bsp] / frame->nch; + ws = frame->header->sampling_frequency; + sfrq = s_freq[frame->header->version][ws]; + /* decision rules refer to per-channel bitrates (kbits/sec/chan) */ + if (frame->header->version == MPEG_AUDIO_ID) { /* MPEG-1 */ + if ((sfrq == 48 && br_per_ch >= 56) + || (br_per_ch >= 56 && br_per_ch <= 80)) + tablenum = 0; + else if (sfrq != 48 && br_per_ch >= 96) + tablenum = 1; + else if (sfrq != 32 && br_per_ch <= 48) + tablenum = 2; + else + tablenum = 3; + } else { /* MPEG-2 LSF */ + tablenum = 4; + } + fprintf(stdout,"encode_init: using tablenum %i with sblimit %i\n",tablenum, table_sblimit[tablenum]); + +#define DUMPTABLESx +#ifdef DUMPTABLES + { + int tablenumber,j,sblimit, sb; + fprintf(stdout,"Tables B.21,b,c,d from ISO11172 and the LSF table from ISO13818\n"); + for (tablenumber=0;tablenumber<NUMTABLES;tablenumber++) { + /* Print Table Header */ + fprintf(stdout,"Tablenum %i\n",tablenumber); + fprintf(stdout,"sb nbal "); + for (j=0;j<16;j++) + fprintf(stdout,"%6i ",j); + fprintf(stdout,"\n"); + fprintf(stdout,"-----------------------------------------------------------------------------------------------------------------------\n"); + + sblimit = table_sblimit[tablenumber]; + for (sb=0;sb<SBLIMIT;sb++) { + int thisline = line[tablenumber][sb]; + fprintf(stdout,"%2i %4i ",sb,nbal[thisline]); + if (nbal[thisline] != 0) + for (j=0; j<(1<<nbal[thisline]); j++) + fprintf(stdout,"%6i ", steps[ step_index[thisline][j] ]); + fprintf(stdout,"\n"); + } + fprintf(stdout,"\n"); + } + exit(0); + } +#endif + return (table_sblimit[tablenum]); +} + +/* + scale_factor_calc + pick_scale + if JOINTSTEREO + combine_LR + scale_factor_calc + use psy model to determine SMR + transmission pattern + main_bit_allocation + if (error protection) + calc CRC + encode_info + if (error_protection) + encode_CRC + encode_bit_alloc + encode_scale + subband_quantization + sample_encoding +*/ + + +void scalefactor_calc_new (double sb_sample[][3][SCALE_BLOCK][SBLIMIT], + unsigned int sf_index[][3][SBLIMIT], int nch, + int sblimit) +{ + /* Optimized to use binary search instead of linear scan through the + scalefactor table; guarantees to find scalefactor in only 5 + jumps/comparisons and not in {0 (lin. best) to 63 (lin. worst)}. + Scalefactors for subbands > sblimit are no longer computed. + Uses a single sblimit-loop. + Patrick De Smet Oct 1999. */ + int ch, gr; + /* Using '--' loops to avoid possible "cmp value + bne/beq" compiler */ + /* inefficiencies. Below loops should compile to "bne/beq" only code */ + for (ch = nch; ch--;) + for (gr = 3; gr--;) { + int sb; + for (sb = sblimit; sb--;) { + int j; + unsigned int l; + register double temp; + unsigned int scale_fac; + /* Determination of max. over each set of 12 subband samples: */ + /* PDS TODO: maybe this could/should ??!! be integrated into */ + /* the subband filtering routines? */ + register double cur_max = fabs (sb_sample[ch][gr][SCALE_BLOCK - 1][sb]); + for (j = SCALE_BLOCK - 1; j--;) { + if ((temp = fabs (sb_sample[ch][gr][j][sb])) > cur_max) + cur_max = temp; + } + /* PDS: binary search in the scalefactor table: */ + /* This is the real speed up: */ + for (l = 16, scale_fac = 32; l; l >>= 1) { + if (cur_max <= scalefactor[scale_fac]) + scale_fac += l; + else + scale_fac -= l; + } + if (cur_max > scalefactor[scale_fac]) + scale_fac--; + sf_index[ch][gr][sb] = scale_fac; + /* There is a direct way of working out the index, if the + maximum value is known but since + it involves a log it isn't really speedy. + Items in the scalefactor[] table are calculated by: + the n'th entry = 2 / (cuberoot(2) ^ n) + And so using a bit of maths you get: + index = (int)(log(2.0/cur_max) / LNCUBEROOTTWO); + fprintf(stdout,"cur_max %.14lf scalefactorindex %i multiple %.14lf\n",cur_max, scale_fac, scalefactor[scale_fac]); + */ + } + } +} +double mod (double a) +{ + return (a > 0) ? a : -a; +} + +/* Combine L&R channels into a mono joint stereo channel */ +void combine_LR_new (double sb_sample[2][3][SCALE_BLOCK][SBLIMIT], + double joint_sample[3][SCALE_BLOCK][SBLIMIT], int sblimit) { + int sb, sample, gr; + + for (sb = 0; sb < sblimit; ++sb) + for (sample = 0; sample < SCALE_BLOCK; ++sample) + for (gr = 0; gr < 3; ++gr) + joint_sample[gr][sample][sb] = + .5 * (sb_sample[0][gr][sample][sb] + sb_sample[1][gr][sample][sb]); +} + +/* PURPOSE:For each subband, puts the smallest scalefactor of the 3 + associated with a frame into #max_sc#. This is used + used by Psychoacoustic Model I. + Someone in dist10 source code's history, somebody wrote the following: + "(I would recommend changin max_sc to min_sc)" + + In psy model 1, the *maximum* out of the scale picked here and + the maximum SPL within each subband is selected. So I'd think that + a maximum here makes heaps of sense. + + MFC FIX: Feb 2003 - is this only needed for psy model 1? +*/ +void find_sf_max (unsigned int sf_index[2][3][SBLIMIT], frame_info * frame, + double sf_max[2][SBLIMIT]) +{ + int sb, gr, ch; + int lowest_sf_index; + int nch = frame->nch; + int sblimit = frame->sblimit; + + for (ch = 0; ch < nch; ch++) + for (sb = 0; sb < sblimit; sb++) { + for (gr = 1, lowest_sf_index = sf_index[ch][0][sb]; gr < 3; gr++) + if (lowest_sf_index > sf_index[ch][gr][sb]) + lowest_sf_index = sf_index[ch][gr][sb]; + sf_max[ch][sb] = multiple[lowest_sf_index]; + } + for (sb = sblimit; sb < SBLIMIT; sb++) + sf_max[0][sb] = sf_max[1][sb] = 1E-20; +} + +/* sf_transmission_pattern + PURPOSE:For a given subband, determines whether to send 1, 2, or + all 3 of the scalefactors, and fills in the scalefactor + select information accordingly + + This is From ISO11172 Sect C.1.5.2.5 "coding of scalefactors" + and + Table C.4 "LayerII Scalefactors Transmission Pattern" +*/ +void sf_transmission_pattern (unsigned int sf_index[2][3][SBLIMIT], + unsigned int sf_selectinfo[2][SBLIMIT], + frame_info * frame) +{ + int nch = frame->nch; + int sblimit = frame->sblimit; + int dscf[2]; + int class[2], i, j, k; + static int pattern[5][5] = { {0x123, 0x122, 0x122, 0x133, 0x123}, + {0x113, 0x111, 0x111, 0x444, 0x113}, + {0x111, 0x111, 0x111, 0x333, 0x113}, + {0x222, 0x222, 0x222, 0x333, 0x123}, + {0x123, 0x122, 0x122, 0x133, 0x123} + }; + + for (k = 0; k < nch; k++) + for (i = 0; i < sblimit; i++) { + dscf[0] = (sf_index[k][0][i] - sf_index[k][1][i]); + dscf[1] = (sf_index[k][1][i] - sf_index[k][2][i]); + for (j = 0; j < 2; j++) { + if (dscf[j] <= -3) + class[j] = 0; + else if (dscf[j] > -3 && dscf[j] < 0) + class[j] = 1; + else if (dscf[j] == 0) + class[j] = 2; + else if (dscf[j] > 0 && dscf[j] < 3) + class[j] = 3; + else + class[j] = 4; + } + switch (pattern[class[0]][class[1]]) { + case 0x123: + sf_selectinfo[k][i] = 0; + break; + case 0x122: + sf_selectinfo[k][i] = 3; + sf_index[k][2][i] = sf_index[k][1][i]; + break; + case 0x133: + sf_selectinfo[k][i] = 3; + sf_index[k][1][i] = sf_index[k][2][i]; + break; + case 0x113: + sf_selectinfo[k][i] = 1; + sf_index[k][1][i] = sf_index[k][0][i]; + break; + case 0x111: + sf_selectinfo[k][i] = 2; + sf_index[k][1][i] = sf_index[k][2][i] = sf_index[k][0][i]; + break; + case 0x222: + sf_selectinfo[k][i] = 2; + sf_index[k][0][i] = sf_index[k][2][i] = sf_index[k][1][i]; + break; + case 0x333: + sf_selectinfo[k][i] = 2; + sf_index[k][0][i] = sf_index[k][1][i] = sf_index[k][2][i]; + break; + case 0x444: + sf_selectinfo[k][i] = 2; + if (sf_index[k][0][i] > sf_index[k][2][i]) + sf_index[k][0][i] = sf_index[k][2][i]; + sf_index[k][1][i] = sf_index[k][2][i] = sf_index[k][0][i]; + } + } +} + +void write_header (frame_info * frame, Bit_stream_struc * bs) +{ + frame_header *header = frame->header; + + putbits (bs, 0xfff, 12); /* syncword 12 bits */ + put1bit (bs, header->version); /* ID 1 bit */ + putbits (bs, 4 - header->lay, 2); /* layer 2 bits */ + put1bit (bs, !header->error_protection); /* bit set => no err prot */ + putbits (bs, header->bitrate_index, 4); + putbits (bs, header->sampling_frequency, 2); + put1bit (bs, header->padding); + put1bit (bs, header->extension); /* private_bit */ + putbits (bs, header->mode, 2); + putbits (bs, header->mode_ext, 2); + put1bit (bs, header->copyright); + put1bit (bs, header->original); + putbits (bs, header->emphasis, 2); +} + +/************************************************************************* + encode_bit_alloc (Layer II) + + PURPOSE:Writes bit allocation information onto bitstream + + 4,3,2, or 0 bits depending on the quantization table used. + +************************************************************************/ +void write_bit_alloc (unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs) +{ + int sb, ch; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + + for (sb = 0; sb < sblimit; sb++) { + if (sb < jsbound) { + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ch++) + putbits (bs, bit_alloc[ch][sb], nbal[ line[tablenum][sb] ]); // (*alloc)[sb][0].bits); + } + else + putbits (bs, bit_alloc[0][sb], nbal[ line[tablenum][sb] ]); //(*alloc)[sb][0].bits); + } +} + +/************************************************************************ + write_scalefactors + + PURPOSE:The encoded scalar factor information is arranged and + queued into the output fifo to be transmitted. + + The three scale factors associated with + a given subband and channel are transmitted in accordance + with the scfsi, which is transmitted first. + +************************************************************************/ + +void write_scalefactors (unsigned int bit_alloc[2][SBLIMIT], + unsigned int sf_selectinfo[2][SBLIMIT], + unsigned int sf_index[2][3][SBLIMIT], frame_info * frame, + Bit_stream_struc * bs) +{ + int nch = frame->nch; + int sblimit = frame->sblimit; + int sb, gr, ch; + + /* Write out the scalefactor selection information */ + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < nch; ch++) + if (bit_alloc[ch][sb]) + putbits (bs, sf_selectinfo[ch][sb], 2); + + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < nch; ch++) + if (bit_alloc[ch][sb]) /* above jsbound, bit_alloc[0][i] == ba[1][i] */ + switch (sf_selectinfo[ch][sb]) { + case 0: + for (gr = 0; gr < 3; gr++) + putbits (bs, sf_index[ch][gr][sb], 6); + break; + case 1: + case 3: + putbits (bs, sf_index[ch][0][sb], 6); + putbits (bs, sf_index[ch][2][sb], 6); + break; + case 2: + putbits (bs, sf_index[ch][0][sb], 6); + } +} + + +/* ISO11172 Table C.6 Layer II quantization co-efficients */ +static double a[18] = { + 0, + 0.750000000, 0.625000000, 0.875000000, 0.562500000, 0.937500000, + 0.968750000, 0.984375000, 0.992187500, 0.996093750, 0.998046875, + 0.999023438, 0.999511719, 0.999755859, 0.999877930, 0.999938965, + 0.999969482, 0.999984741 +}; + +static double b[18] = { + 0, + -0.250000000, -0.375000000, -0.125000000, -0.437500000, -0.062500000, + -0.031250000, -0.015625000, -0.007812500, -0.003906250, -0.001953125, + -0.000976563, -0.000488281, -0.000244141, -0.000122070, -0.000061035, + -0.000030518, -0.000015259 +}; + +/************************************************************************ + subband_quantization (Layer II) + + PURPOSE:Quantizes subband samples to appropriate number of bits + + SEMANTICS: Subband samples are divided by their scalefactors, which + makes the quantization more efficient. The scaled samples are + quantized by the function a*x+b, where a and b are functions of + the number of quantization levels. The result is then truncated + to the appropriate number of bits and the MSB is inverted. + + Note that for fractional 2's complement, inverting the MSB for a + negative number x is equivalent to adding 1 to it. + +************************************************************************/ +void +subband_quantization_new (unsigned int sf_index[2][3][SBLIMIT], + double sb_samples[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int j_scale[3][SBLIMIT], + double j_samps[3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + frame_info * frame) +{ + int sb, j, ch, gr, qnt_coeff_index, sig; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + double d; + + for (gr = 0; gr < 3; gr++) + for (j = 0; j < SCALE_BLOCK; j++) + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ch++) + + if (bit_alloc[ch][sb]) { + /* scale and quantize FLOATing point sample */ + if (nch == 2 && sb >= jsbound) /* use j-stereo samples */ + d = j_samps[gr][j][sb] / scalefactor[j_scale[gr][sb]]; + else + d = sb_samples[ch][gr][j][sb] / scalefactor[sf_index[ch][gr][sb]]; + + /* Check that the wrong scale factor hasn't been chosen - + which would result in a scaled sample being > 1.0 + This error shouldn't ever happen *unless* something went wrong in + scalefactor calc + + if (mod (d) > 1.0) + fprintf (stderr, "Not scaled properly %d %d %d %d\n", ch, gr, j, + sb); + */ + + { + /* 'index' indicates which "step line" we are using */ + int index = line[tablenum][sb]; + + /* Find the "step index" within that line */ + qnt_coeff_index = step_index[index][bit_alloc[ch][sb]]; + } + d = d * a[qnt_coeff_index] + b[qnt_coeff_index]; + + /* extract MSB N-1 bits from the FLOATing point sample */ + if (d >= 0) + sig = 1; + else { + sig = 0; + d += 1.0; + } + + sbband[ch][gr][j][sb] = (unsigned int) (d * (double)steps2n[qnt_coeff_index]); + /* tag the inverted sign bit to sbband at position N */ + /* The bit inversion is a must for grouping with 3,5,9 steps + so it is done for all subbands */ + if (sig) + sbband[ch][gr][j][sb] |= steps2n[qnt_coeff_index]; + } + + /* Set everything above the sblimit to 0 */ + for (ch = 0; ch < nch; ch++) + for (gr = 0; gr < 3; gr++) + for (sb = 0; sb < SCALE_BLOCK; sb++) + for (j = sblimit; j < SBLIMIT; j++) + sbband[ch][gr][sb][j] = 0; +} + +/************************************************************************ + sample_encoding + + PURPOSE:Put one frame of subband samples on to the bitstream + + SEMANTICS: The number of bits allocated per sample is read from + the bit allocation information #bit_alloc#. Layer 2 + supports writing grouped samples for quantization steps + that are not a power of 2. + +***********************************************************************/ +void write_samples_new (unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs) +{ + unsigned int temp; + unsigned int sb, j, ch, gr, x, y; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + + for (gr = 0; gr < 3; gr++) + for (j = 0; j < SCALE_BLOCK; j += 3) + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ch++) + + if (bit_alloc[ch][sb]) { + int thisline = line[tablenum][sb]; + int thisstep_index = step_index[thisline][bit_alloc[ch][sb]]; + /* Check how many samples per codeword */ + if (group[thisstep_index] == 3) { + /* Going to send 1 sample per codeword -> 3 samples */ + for (x = 0; x < 3; x++) { + putbits (bs, sbband[ch][gr][j + x][sb], bits[thisstep_index]); + } + } else { + /* ISO11172 Sec C.1.5.2.8 + If steps=3, 5 or 9, then three consecutive samples are coded + as one codeword i.e. only one value (V) is transmitted for this + triplet. If the 3 subband samples are x,y,z then + V = (steps*steps)*z + steps*y +x + */ + y = steps[thisstep_index]; + temp = + sbband[ch][gr][j][sb] + sbband[ch][gr][j + 1][sb] * y + + sbband[ch][gr][j + 2][sb] * y * y; + putbits (bs, temp, bits[thisstep_index]); + } + } +} + + +//#include "bit_alloc_new.c" +/***************************************************************************************/ +/* Bit Allocation Routines */ + + +/************************************************************************ +* +* bits_for_nonoise (Layer II) +* +* PURPOSE:Returns the number of bits required to produce a +* mask-to-noise ratio better or equal to the noise/no_noise threshold. +* +* SEMANTICS: +* bbal = # bits needed for encoding bit allocation +* bsel = # bits needed for encoding scalefactor select information +* banc = # bits needed for ancillary data (header info included) +* +* For each subband and channel, will add bits until one of the +* following occurs: +* - Hit maximum number of bits we can allocate for that subband +* - MNR is better than or equal to the minimum masking level +* (NOISY_MIN_MNR) +* Then the bits required for scalefactors, scfsi, bit allocation, +* and the subband samples are tallied (#req_bits#) and returned. +* +* (NOISY_MIN_MNR) is the smallest MNR a subband can have before it is +* counted as 'noisy' by the logic which chooses the number of JS +* subbands. +* +* Joint stereo is supported. +* +************************************************************************/ + +int bits_for_nonoise_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], frame_info * frame, float min_mnr, + unsigned int bit_alloc[2][SBLIMIT]) +{ + int sb, ch, ba; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + int req_bits = 0, bbal = 0, berr = 0, banc = 32; + int maxAlloc, sel_bits, sc_bits, smp_bits; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + /* MFC Feb 2003 + This works out the basic number of bits just to get a valid (but empty) + frame. + This needs to be done for every frame, since a joint_stereo frame + will change the number of basic bits (depending on the sblimit in + the particular js mode that's been selected */ + + /* Make sure there's room for the error protection bits */ + if (frame->header->error_protection) + berr = 16; + else + berr = 0; + + /* Count the number of bits required to encode the quantization index for both + channels in each subband. If we're above the jsbound, then pretend we only + have one channel */ + for (sb = 0; sb < jsbound; ++sb) + bbal += nch * nbal[ line[tablenum][sb] ]; //(*alloc)[sb][0].bits; + for (sb = jsbound; sb < sblimit; ++sb) + bbal += nbal[ line[tablenum][sb] ]; //(*alloc)[sb][0].bits; + req_bits = banc + bbal + berr; + + for (sb = 0; sb < sblimit; ++sb) + for (ch = 0; ch < ((sb < jsbound) ? nch : 1); ++ch) { + int thisline = line[tablenum][sb]; + + /* How many possible steps are there to choose from ? */ + maxAlloc = (1 << nbal[ line[tablenum][sb] ]) -1; //(*alloc)[sb][0].bits) - 1; + sel_bits = sc_bits = smp_bits = 0; + /* Keep choosing the next number of steps (and hence our SNR value) + until we have the required MNR value */ + for (ba = 0; ba < maxAlloc - 1; ++ba) { + int thisstep_index = step_index[thisline][ba]; + if ((SNR[thisstep_index] - SMR[ch][sb]) >= min_mnr) + break; /* we found enough bits */ + } + if (nch == 2 && sb >= jsbound) /* check other JS channel */ + for (; ba < maxAlloc - 1; ++ba) { + int thisstep_index = step_index[thisline][ba]; + if ((SNR[thisstep_index] - SMR[1-ch][sb]) >= min_mnr) + break; + } + if (ba > 0) { + //smp_bits = SCALE_BLOCK * ((*alloc)[sb][ba].group * (*alloc)[sb][ba].bits); + int thisstep_index = step_index[thisline][ba]; + smp_bits = SCALE_BLOCK * group[thisstep_index] * bits[thisstep_index]; + /* scale factor bits required for subband */ + sel_bits = 2; + sc_bits = 6 * sfsPerScfsi[scfsi[ch][sb]]; + if (nch == 2 && sb >= jsbound) { + /* each new js sb has L+R scfsis */ + sel_bits += 2; + sc_bits += 6 * sfsPerScfsi[scfsi[1 - ch][sb]]; + } + req_bits += smp_bits + sel_bits + sc_bits; + } + bit_alloc[ch][sb] = ba; + } + return req_bits; +} + + + +/************************************************************************ +* +* main_bit_allocation (Layer II) +* +* PURPOSE:For joint stereo mode, determines which of the 4 joint +* stereo modes is needed. Then calls *_a_bit_allocation(), which +* allocates bits for each of the subbands until there are no more bits +* left, or the MNR is at the noise/no_noise threshold. +* +* SEMANTICS: +* +* For joint stereo mode, joint stereo is changed to stereo if +* there are enough bits to encode stereo at or better than the +* no-noise threshold (NOISY_MIN_MNR). Otherwise, the system +* iteratively allocates less bits by using joint stereo until one +* of the following occurs: +* - there are no more noisy subbands (MNR >= NOISY_MIN_MNR) +* - mode_ext has been reduced to 0, which means that all but the +* lowest 4 subbands have been converted from stereo to joint +* stereo, and no more subbands may be converted +* +* This function calls *_bits_for_nonoise() and *_a_bit_allocation(). +* +************************************************************************/ +void main_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options * glopts) +{ + int noisy_sbs; + int mode, mode_ext, lay; + int rq_db; /* av_db = *adb; Not Used MFC Nov 99 */ + + /* these are the tables which specify the limits within which the VBR can vary + You can't vary outside these ranges, otherwise a new alloc table would have to + be loaded in the middle of encoding. This VBR hack is dodgy - the standard + says that LayerII decoders don't have to support a variable bitrate, but Layer3 + decoders must do so. Hence, it is unlikely that a compliant layer2 decoder would be + written to dynmically change allocation tables. *BUT* a layer3 encoder might handle it + by default, meaning we could switch tables mid-encode and enjoy a wider range of bitrates + for the VBR encoding. + None of this needs to be done for LSF, since there is only *one* possible alloc table in LSF + MFC Feb 2003 */ + int vbrlimits[2][3][2] = { + /* MONO */ + { /* 44 */ {6, 10}, + /* 48 */ {3, 10}, + /* 32 */ {6, 10}}, + /* STEREO */ + { /* 44 */ {10, 14}, + /* 48 */ {7, 14}, + /* 32 */ {10, 14}} + }; + + static int init = 0; + static int lower = 10, upper = 10; + static int bitrateindextobits[15] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int guessindex = 0; + + if (init == 0) { + int nch = 2; + int sfreq; + frame_header *header = frame->header; + init++; + if (header->version == 0) { + /* LSF: so can use any bitrate index from 1->15 */ + lower = 1; + upper = 14; + } else { + if (frame->actual_mode == MPG_MD_MONO) + nch = 1; + sfreq = header->sampling_frequency; + lower = vbrlimits[nch-1][sfreq][0]; + upper = vbrlimits[nch-1][sfreq][1]; + } + if (glopts->verbosity > 2) + fprintf (stdout, "VBR bitrate index limits [%i -> %i]\n", lower, upper); + + { + /* set up a conversion table for bitrateindex->bits for this version/sampl freq + This will be used to find the best bitrate to cope with the number of bits that + are needed (as determined by VBR_bits_for_nonoise) */ + int brindex; + frame_header *header = frame->header; + for (brindex = lower; brindex <= upper; brindex++) { + bitrateindextobits[brindex] = + (int) (1152.0 / s_freq[header->version][header->sampling_frequency]) * + ((double) bitrate[header->version][brindex]); + } + } + + } + + if ((mode = frame->actual_mode) == MPG_MD_JOINT_STEREO) { + frame->header->mode = MPG_MD_STEREO; + frame->header->mode_ext = 0; + frame->jsbound = frame->sblimit; + if ((rq_db = bits_for_nonoise_new (SMR, scfsi, frame, 0, bit_alloc)) > *adb) { + frame->header->mode = MPG_MD_JOINT_STEREO; + mode_ext = 4; /* 3 is least severe reduction */ + lay = frame->header->lay; + do { + --mode_ext; + frame->jsbound = js_bound (mode_ext); + rq_db = bits_for_nonoise_new (SMR, scfsi, frame, 0, bit_alloc); + } + while ((rq_db > *adb) && (mode_ext > 0)); + frame->header->mode_ext = mode_ext; + } /* well we either eliminated noisy sbs or mode_ext == 0 */ + } + + /* decide on which bit allocation method to use */ + if (glopts->vbr == FALSE) { + /* Just do the old bit allocation method */ + noisy_sbs = a_bit_allocation_new (SMR, scfsi, bit_alloc, adb, frame); + } else { + /* do the VBR bit allocation method */ + frame->header->bitrate_index = lower; + *adb = available_bits (frame->header, glopts); + { + int brindex; + int found = FALSE; + + /* Work out how many bits are needed for there to be no noise (ie all MNR > VBRLEVEL) */ + int req = + bits_for_nonoise_new (SMR, scfsi, frame, glopts->vbrlevel, bit_alloc); + + /* Look up this value in the bitrateindextobits table to find what bitrate we should use for + this frame */ + for (brindex = lower; brindex <= upper; brindex++) { + if (bitrateindextobits[brindex] > req) { + /* this method always *overestimates* the bits that are needed + i.e. it will usually guess right but + when it's wrong it'll guess a higher bitrate than actually required. + e.g. on "messages from earth" track 6, the guess was + wrong on 75/36341 frames. each time it guessed higher. + MFC Feb 2003 */ + guessindex = brindex; + found = TRUE; + break; + } + } + /* Just for sanity */ + if (found == FALSE) + guessindex = upper; + } + + frame->header->bitrate_index = guessindex; + *adb = available_bits (frame->header, glopts); + + /* update the statistics */ + vbrstats_new[frame->header->bitrate_index]++; + + if (glopts->verbosity > 2) { + /* print out the VBR stats every 1000th frame */ + static int count = 0; + int i; + if ((count++ % 1000) == 0) { + for (i = 1; i < 15; i++) + fprintf (stdout, "%4i ", vbrstats_new[i]); + fprintf (stdout, "\n"); + } + + /* Print out *every* frames bitrateindex, bits required, and bits available at this bitrate */ + if (glopts->verbosity > 5) + fprintf (stdout, + "> bitrate index %2i has %i bits available to encode the %i bits\n", + frame->header->bitrate_index, *adb, + bits_for_nonoise_new (SMR, scfsi, frame, + glopts->vbrlevel, bit_alloc)); + + } + + noisy_sbs = + VBR_bit_allocation_new (SMR, scfsi, bit_alloc, adb, frame, glopts); + } +} + +void VBR_maxmnr_new (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch, options * glopts) +{ + int sb, ch; + double small; + + small = 999999.0; + *min_sb = -1; + *min_ch = -1; + +#define NEWBITx +#ifdef NEWBIT + /* Keep going until all subbands have reached the MNR level that we specified */ + for (ch=0;ch<nch;ch++) + for (sb=0;sb<sblimit;sb++) + if (mnr[ch][sb] < glopts->vbrlevel) { + *min_sb = sb; + *min_ch = ch; + //fprintf(stdout,"."); + //fflush(stdout); + return; + } +#endif + + /* Then start adding bits to whichever is the min MNR */ + for (ch = 0; ch < nch; ++ch) + for (sb = 0; sb < sblimit; sb++) + if (used[ch][sb] != 2 && small > mnr[ch][sb]) { + small = mnr[ch][sb]; + *min_sb = sb; + *min_ch = ch; + } + //fprintf(stdout,"Min sb: %i\n",*min_sb); +} +/******************** +MFC Feb 2003 +VBR_bit_allocation is different to the normal a_bit_allocation in that +it is known beforehand that there are definitely enough bits to do what we +have to - i.e. a bitrate was specificially chosen in main_bit_allocation so +that we have enough bits to encode what we have to. +This function should take that into account and just greedily assign +the bits, rather than fussing over the minimum MNR subband - we know +each subband gets its required bits, why quibble? +This function doesn't chew much CPU, so I haven't made any attempt +to do this yet. +*********************/ +int VBR_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options *glopts) +{ + int sb, min_ch, min_sb, oth_ch, ch, increment, scale, seli, ba; + int bspl, bscf, bsel, ad, bbal = 0; + double mnr[2][SBLIMIT]; + char used[2][SBLIMIT]; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + //al_table *alloc = frame->alloc; + static char init = 0; + static int banc = 32, berr = 0; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + int thisstep_index; + + if (!init) { + init = 1; + if (frame->header->error_protection) + berr = 16; /* added 92-08-11 shn */ + } + + /* No need to worry about jsbound here as JS is disabled for VBR mode */ + for (sb = 0; sb < sblimit; sb++) + bbal += nch * nbal[ line[tablenum][sb] ]; + *adb -= bbal + berr + banc; + ad = *adb; + + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < nch; ch++) { + mnr[ch][sb] = SNR[0] - SMR[ch][sb]; + bit_alloc[ch][sb] = 0; + used[ch][sb] = 0; + } + bspl = bscf = bsel = 0; + + do { + /* locate the subband with minimum SMR */ + VBR_maxmnr_new (mnr, used, sblimit, nch, &min_sb, &min_ch, glopts); + + if (min_sb > -1) { /* there was something to find */ + int thisline = line[tablenum][min_sb]; { + /* find increase in bit allocation in subband [min] */ + int nextstep_index = step_index[thisline][bit_alloc[min_ch][min_sb]+1]; + increment = SCALE_BLOCK * group[nextstep_index] * bits[nextstep_index]; + } + if (used[min_ch][min_sb]) { + /* If we've already increased the limit on this ch/sb, then + subtract the last thing that we added */ + thisstep_index = step_index[thisline][bit_alloc[min_ch][min_sb]]; + increment -= SCALE_BLOCK * group[thisstep_index] * bits[thisstep_index]; + } + + /* scale factor bits required for subband [min] */ + oth_ch = 1 - min_ch; /* above js bound, need both chans */ + if (used[min_ch][min_sb]) + scale = seli = 0; + else { /* this channel had no bits or scfs before */ + seli = 2; + scale = 6 * sfsPerScfsi[scfsi[min_ch][min_sb]]; + if (nch == 2 && min_sb >= jsbound) { + /* each new js sb has L+R scfsis */ + seli += 2; + scale += 6 * sfsPerScfsi[scfsi[oth_ch][min_sb]]; + } + } + + /* check to see enough bits were available for */ + /* increasing resolution in the minimum band */ + if (ad >= bspl + bscf + bsel + seli + scale + increment) { + /* Then there are enough bits to have another go at allocating */ + ba = ++bit_alloc[min_ch][min_sb]; /* next up alloc */ + bspl += increment; /* bits for subband sample */ + bscf += scale; /* bits for scale factor */ + bsel += seli; /* bits for scfsi code */ + used[min_ch][min_sb] = 1; /* subband has bits */ + thisstep_index = step_index[thisline][ba]; + mnr[min_ch][min_sb] = SNR[thisstep_index] - SMR[min_ch][min_sb]; + /* Check if this min_sb subband has been fully allocated max bits */ + if (ba >= (1 << nbal[ line[tablenum][min_sb] ]) -1 ) //(*alloc)[min_sb][0].bits) - 1) + used[min_ch][min_sb] = 2; /* don't let this sb get any more bits */ + } else + used[min_ch][min_sb] = 2; /* can't increase this alloc */ + } + } + while (min_sb > -1); /* until could find no channel */ + + /* Calculate the number of bits left */ + ad -= bspl + bscf + bsel; + *adb = ad; + for (ch = 0; ch < nch; ch++) + for (sb = sblimit; sb < SBLIMIT; sb++) + bit_alloc[ch][sb] = 0; + + return 0; +} + + + +/************************************************************************ +* +* a_bit_allocation (Layer II) +* +* PURPOSE:Adds bits to the subbands with the lowest mask-to-noise +* ratios, until the maximum number of bits for the subband has +* been allocated. +* +* SEMANTICS: +* 1. Find the subband and channel with the smallest MNR (#min_sb#, +* and #min_ch#) +* 2. Calculate the increase in bits needed if we increase the bit +* allocation to the next higher level +* 3. If there are enough bits available for increasing the resolution +* in #min_sb#, #min_ch#, and the subband has not yet reached its +* maximum allocation, update the bit allocation, MNR, and bits + available accordingly +* 4. Repeat until there are no more bits left, or no more available +* subbands. (A subband is still available until the maximum +* number of bits for the subband has been allocated, or there +* aren't enough bits to go to the next higher resolution in the + subband.) +* +************************************************************************/ + +void maxmnr_new (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch) +{ + int sb, ch; + double small; + + small = 999999.0; + *min_sb = -1; + *min_ch = -1; + for (ch = 0; ch < nch; ++ch) + for (sb = 0; sb < sblimit; sb++) + if (used[ch][sb] != 2 && small > mnr[ch][sb]) { + small = mnr[ch][sb]; + *min_sb = sb; + *min_ch = ch; + } +} +int a_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame) +{ + int sb, min_ch, min_sb, oth_ch, ch, increment, scale, seli, ba; + int bspl, bscf, bsel, ad, bbal = 0; + double mnr[2][SBLIMIT]; + char used[2][SBLIMIT]; + int nch = frame->nch; + int sblimit = frame->sblimit; + int jsbound = frame->jsbound; + //al_table *alloc = frame->alloc; + static char init = 0; + static int banc = 32, berr = 0; + static int sfsPerScfsi[] = { 3, 2, 1, 2 }; /* lookup # sfs per scfsi */ + + int thisstep_index; + + if (!init) { + init = 1; + if (frame->header->error_protection) + berr = 16; /* added 92-08-11 shn */ + } + + for (sb = 0; sb < jsbound; sb++) + bbal += nch * nbal[ line[tablenum][sb] ]; //(*alloc)[sb][0].bits; + for (sb = jsbound; sb < sblimit; sb++) + bbal += nbal[ line[tablenum][sb] ]; //(*alloc)[sb][0].bits; + *adb -= bbal + berr + banc; + ad = *adb; + + for (sb = 0; sb < sblimit; sb++) + for (ch = 0; ch < nch; ch++) { + mnr[ch][sb] = SNR[0] - SMR[ch][sb]; + bit_alloc[ch][sb] = 0; + used[ch][sb] = 0; + } + bspl = bscf = bsel = 0; + + do { + /* locate the subband with minimum SMR */ + maxmnr_new (mnr, used, sblimit, nch, &min_sb, &min_ch); + + if (min_sb > -1) { /* there was something to find */ + int thisline = line[tablenum][min_sb]; { + /* find increase in bit allocation in subband [min] */ + int nextstep_index = step_index[thisline][bit_alloc[min_ch][min_sb]+1]; + increment = SCALE_BLOCK * group[nextstep_index] * bits[nextstep_index]; + } + if (used[min_ch][min_sb]) { + /* If we've already increased the limit on this ch/sb, then + subtract the last thing that we added */ + thisstep_index = step_index[thisline][bit_alloc[min_ch][min_sb]]; + increment -= SCALE_BLOCK * group[thisstep_index] * bits[thisstep_index]; + } + + /* scale factor bits required for subband [min] */ + oth_ch = 1 - min_ch; /* above js bound, need both chans */ + if (used[min_ch][min_sb]) + scale = seli = 0; + else { /* this channel had no bits or scfs before */ + seli = 2; + scale = 6 * sfsPerScfsi[scfsi[min_ch][min_sb]]; + if (nch == 2 && min_sb >= jsbound) { + /* each new js sb has L+R scfsis */ + seli += 2; + scale += 6 * sfsPerScfsi[scfsi[oth_ch][min_sb]]; + } + } + + /* check to see enough bits were available for */ + /* increasing resolution in the minimum band */ + if (ad >= bspl + bscf + bsel + seli + scale + increment) { + /* Then there are enough bits to have another go at allocating */ + ba = ++bit_alloc[min_ch][min_sb]; /* next up alloc */ + bspl += increment; /* bits for subband sample */ + bscf += scale; /* bits for scale factor */ + bsel += seli; /* bits for scfsi code */ + used[min_ch][min_sb] = 1; /* subband has bits */ + thisstep_index = step_index[thisline][ba]; + mnr[min_ch][min_sb] = SNR[thisstep_index] - SMR[min_ch][min_sb]; + /* Check if this min_sb subband has been fully allocated max bits */ + if (ba >= (1 << nbal[ line[tablenum][min_sb] ]) -1 ) //(*alloc)[min_sb][0].bits) - 1) + used[min_ch][min_sb] = 2; /* don't let this sb get any more bits */ + } else + used[min_ch][min_sb] = 2; /* can't increase this alloc */ + + if (min_sb >= jsbound && nch == 2) { + /* above jsbound, alloc applies L+R */ + ba = bit_alloc[oth_ch][min_sb] = bit_alloc[min_ch][min_sb]; + used[oth_ch][min_sb] = used[min_ch][min_sb]; + thisstep_index = step_index[thisline][ba]; + mnr[oth_ch][min_sb] = SNR[thisstep_index] - SMR[oth_ch][min_sb]; + //mnr[oth_ch][min_sb] = SNR[(*alloc)[min_sb][ba].quant + 1] - SMR[oth_ch][min_sb]; + } + + } + } + while (min_sb > -1); /* until could find no channel */ + + /* Calculate the number of bits left */ + ad -= bspl + bscf + bsel; + *adb = ad; + for (ch = 0; ch < nch; ch++) + for (sb = sblimit; sb < SBLIMIT; sb++) + bit_alloc[ch][sb] = 0; + + return 0; +} + diff --git a/libtoolame-dab/encode_new.h b/libtoolame-dab/encode_new.h new file mode 100644 index 0000000..bcd086d --- /dev/null +++ b/libtoolame-dab/encode_new.h @@ -0,0 +1,63 @@ +int encode_init(frame_info *frame); +void scalefactor_calc_new (double sb_sample[][3][SCALE_BLOCK][SBLIMIT], + unsigned int scalar[][3][SBLIMIT], int nch, + int sblimit); + +double mod (double a); + +void combine_LR_new (double sb_sample[2][3][SCALE_BLOCK][SBLIMIT], + double joint_sample[3][SCALE_BLOCK][SBLIMIT], int sblimit); + +void find_sf_max (unsigned int sf_index[2][3][SBLIMIT], frame_info * frame, + double sf_max[2][SBLIMIT]); + +void sf_transmission_pattern (unsigned int sf_index[2][3][SBLIMIT], + unsigned int sf_selectinfo[2][SBLIMIT], + frame_info * frame); + +void write_header (frame_info * frame, Bit_stream_struc * bs); + +void write_bit_alloc (unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs); + +void write_scalefactors (unsigned int bit_alloc[2][SBLIMIT], + unsigned int sf_selectinfo[2][SBLIMIT], + unsigned int scalar[2][3][SBLIMIT], frame_info * frame, + Bit_stream_struc * bs); + +void subband_quantization_new (unsigned int sf_index[2][3][SBLIMIT], + double sb_samples[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int j_scale[3][SBLIMIT], + double j_samps[3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + frame_info * frame); + +void write_samples_new (unsigned int sbband[2][3][SCALE_BLOCK][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], + frame_info * frame, Bit_stream_struc * bs); + +/******************************************************* + Bit Allocation Stuff +******************************************************/ + +int bits_for_nonoise_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], frame_info * frame, float min_mnr, + unsigned int bit_alloc[2][SBLIMIT]); +void main_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options * glopts); +void VBR_maxmnr_new (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch, options * glopts); +int +VBR_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame, options * glopts); +void maxmnr_new (double mnr[2][SBLIMIT], char used[2][SBLIMIT], int sblimit, + int nch, int *min_sb, int *min_ch); +int a_bit_allocation_new (double SMR[2][SBLIMIT], + unsigned int scfsi[2][SBLIMIT], + unsigned int bit_alloc[2][SBLIMIT], int *adb, + frame_info * frame); diff --git a/libtoolame-dab/encoder.h b/libtoolame-dab/encoder.h new file mode 100644 index 0000000..507c0e8 --- /dev/null +++ b/libtoolame-dab/encoder.h @@ -0,0 +1,92 @@ +#ifndef ENCODER_DOT_H +#define ENCODER_DOT_H +#include "options.h" + +/* General Definitions */ + +/* Default Input Arguments (for command line control) */ + +#define DFLT_LAY 2 /* default encoding layer is II */ +#define DFLT_MOD 'j' /* default mode is joint stereo */ +#define DFLT_PSY 1 /* default psych model is 1 */ +#define DFLT_SFQ 48.0 /* default input sampling rate is 48 kHz because DAB */ +#define DFLT_EMP 'n' /* default de-emphasis is none */ +#define DFLT_EXT ".mp2" /* default output file extension */ +#define DFLT_BRI 10 /* default bitrate_index = 10 (192kbps) */ + +#define FILETYPE_ENCODE 'TEXT' +#define CREATOR_ENCODE 'MpgD' + +/* This is the smallest MNR a subband can have before it is counted + as 'noisy' by the logic which chooses the number of JS subbands */ + +#define NOISY_MIN_MNR 0.0 + +/* Psychacoustic Model 1 Definitions */ + +#define CB_FRACTION 0.33 +#define MAX_SNR 1000 +#define NOISE 10 +#define TONE 20 +#define DBMIN -200.0 +#define LAST -1 +#define STOP -100 +#define POWERNORM 90.3090 /* = 20 * log10(32768) to normalize */ +/* max output power to 96 dB per spec */ + +/* Psychoacoustic Model 2 Definitions */ + +#define LOGBLKSIZE 10 +#define BLKSIZE 1024 +#define HBLKSIZE 513 +#define CBANDS 64 +#define LXMIN 32.0 + +/*********************************************************************** +* +* Encoder Type Definitions +* +***********************************************************************/ + +/* Psychoacoustic Model 1 Type Definitions */ + +typedef int IFFT2[FFT_SIZE / 2]; +typedef int IFFT[FFT_SIZE]; +typedef double D9[9]; +typedef double D10[10]; +typedef double D640[640]; +typedef double D1408[1408]; +typedef double DFFT2[FFT_SIZE / 2]; +typedef double DFFT[FFT_SIZE]; +typedef double DSBL[SBLIMIT]; +typedef double D2SBL[2][SBLIMIT]; + +typedef struct +{ + int line; + double bark, hear, x; +} +g_thres, *g_ptr; + +typedef struct +{ + double x; + int type, next, map; +} +mask, *mask_ptr; + +/* Psychoacoustic Model 2 Type Definitions */ + +typedef int ICB[CBANDS]; +typedef int IHBLK[HBLKSIZE]; +typedef FLOAT F32[32]; +typedef FLOAT F2_32[2][32]; +typedef FLOAT FCB[CBANDS]; +typedef FLOAT FCBCB[CBANDS][CBANDS]; +typedef FLOAT FBLK[BLKSIZE]; +typedef FLOAT FHBLK[HBLKSIZE]; +typedef FLOAT F2HBLK[2][HBLKSIZE]; +typedef FLOAT F22HBLK[2][2][HBLKSIZE]; +typedef double DCB[CBANDS]; + +#endif diff --git a/libtoolame-dab/enwindow.h b/libtoolame-dab/enwindow.h new file mode 100644 index 0000000..4119242 --- /dev/null +++ b/libtoolame-dab/enwindow.h @@ -0,0 +1,130 @@ +double enwindow[512] = { 0.000000000, + -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000477, + -0.000000477, -0.000000954, -0.000000954, + -0.000000954, -0.000000954, -0.000001431, -0.000001431, -0.000001907, + -0.000001907, -0.000002384, -0.000002384, + -0.000002861, -0.000003338, -0.000003338, -0.000003815, -0.000004292, + -0.000004768, -0.000005245, -0.000006199, + -0.000006676, -0.000007629, -0.000008106, -0.000009060, -0.000010014, + -0.000011444, -0.000012398, -0.000013828, + -0.000014782, -0.000016689, -0.000018120, -0.000019550, -0.000021458, + -0.000023365, -0.000025272, -0.000027657, + -0.000030041, -0.000032425, -0.000034809, -0.000037670, -0.000040531, + -0.000043392, -0.000046253, -0.000049591, + -0.000052929, -0.000055790, -0.000059605, -0.000062943, -0.000066280, + -0.000070095, -0.000073433, -0.000076771, + -0.000080585, -0.000083923, -0.000087261, -0.000090599, -0.000093460, + -0.000096321, -0.000099182, 0.000101566, + 0.000103951, 0.000105858, 0.000107288, 0.000108242, 0.000108719, + 0.000108719, 0.000108242, 0.000106812, + 0.000105381, 0.000102520, 0.000099182, 0.000095367, 0.000090122, + 0.000084400, 0.000077724, 0.000069618, + 0.000060558, 0.000050545, 0.000039577, 0.000027180, 0.000013828, + -0.000000954, -0.000017166, -0.000034332, + -0.000052929, -0.000072956, -0.000093937, -0.000116348, -0.000140190, + -0.000165462, -0.000191212, -0.000218868, + -0.000247478, -0.000277042, -0.000307560, -0.000339031, -0.000371456, + -0.000404358, -0.000438213, -0.000472546, + -0.000507355, -0.000542164, -0.000576973, -0.000611782, -0.000646591, + -0.000680923, -0.000714302, -0.000747204, + -0.000779152, -0.000809669, -0.000838757, -0.000866413, -0.000891685, + -0.000915051, -0.000935555, -0.000954151, + -0.000968933, -0.000980854, -0.000989437, -0.000994205, -0.000995159, + -0.000991821, -0.000983715, 0.000971317, + 0.000953674, 0.000930786, 0.000902653, 0.000868797, 0.000829220, + 0.000783920, 0.000731945, 0.000674248, + 0.000610352, 0.000539303, 0.000462532, 0.000378609, 0.000288486, + 0.000191689, 0.000088215, -0.000021458, + -0.000137329, -0.000259876, -0.000388145, -0.000522137, -0.000661850, + -0.000806808, -0.000956535, -0.001111031, + -0.001269817, -0.001432419, -0.001597881, -0.001766682, -0.001937389, + -0.002110004, -0.002283096, -0.002457142, + -0.002630711, -0.002803326, -0.002974033, -0.003141880, -0.003306866, + -0.003467083, -0.003622532, -0.003771782, + -0.003914356, -0.004048824, -0.004174709, -0.004290581, -0.004395962, + -0.004489899, -0.004570484, -0.004638195, + -0.004691124, -0.004728317, -0.004748821, -0.004752159, -0.004737377, + -0.004703045, -0.004649162, -0.004573822, + -0.004477024, -0.004357815, -0.004215240, -0.004049301, -0.003858566, + -0.003643036, -0.003401756, 0.003134727, + 0.002841473, 0.002521515, 0.002174854, 0.001800537, 0.001399517, + 0.000971317, 0.000515938, 0.000033379, + -0.000475883, -0.001011848, -0.001573563, -0.002161503, -0.002774239, + -0.003411293, -0.004072189, -0.004756451, + -0.005462170, -0.006189346, -0.006937027, -0.007703304, -0.008487225, + -0.009287834, -0.010103703, -0.010933399, + -0.011775017, -0.012627602, -0.013489246, -0.014358521, -0.015233517, + -0.016112804, -0.016994476, -0.017876148, + -0.018756866, -0.019634247, -0.020506859, -0.021372318, -0.022228718, + -0.023074150, -0.023907185, -0.024725437, + -0.025527000, -0.026310921, -0.027073860, -0.027815342, -0.028532982, + -0.029224873, -0.029890060, -0.030526638, + -0.031132698, -0.031706810, -0.032248020, -0.032754898, -0.033225536, + -0.033659935, -0.034055710, -0.034412861, + -0.034730434, -0.035007000, -0.035242081, -0.035435200, -0.035586357, + -0.035694122, -0.035758972, 0.035780907, + 0.035758972, 0.035694122, 0.035586357, 0.035435200, 0.035242081, + 0.035007000, 0.034730434, 0.034412861, + 0.034055710, 0.033659935, 0.033225536, 0.032754898, 0.032248020, + 0.031706810, 0.031132698, 0.030526638, + 0.029890060, 0.029224873, 0.028532982, 0.027815342, 0.027073860, + 0.026310921, 0.025527000, 0.024725437, + 0.023907185, 0.023074150, 0.022228718, 0.021372318, 0.020506859, + 0.019634247, 0.018756866, 0.017876148, + 0.016994476, 0.016112804, 0.015233517, 0.014358521, 0.013489246, + 0.012627602, 0.011775017, 0.010933399, + 0.010103703, 0.009287834, 0.008487225, 0.007703304, 0.006937027, + 0.006189346, 0.005462170, 0.004756451, + 0.004072189, 0.003411293, 0.002774239, 0.002161503, 0.001573563, + 0.001011848, 0.000475883, -0.000033379, + -0.000515938, -0.000971317, -0.001399517, -0.001800537, -0.002174854, + -0.002521515, -0.002841473, 0.003134727, + 0.003401756, 0.003643036, 0.003858566, 0.004049301, 0.004215240, + 0.004357815, 0.004477024, 0.004573822, + 0.004649162, 0.004703045, 0.004737377, 0.004752159, 0.004748821, + 0.004728317, 0.004691124, 0.004638195, + 0.004570484, 0.004489899, 0.004395962, 0.004290581, 0.004174709, + 0.004048824, 0.003914356, 0.003771782, + 0.003622532, 0.003467083, 0.003306866, 0.003141880, 0.002974033, + 0.002803326, 0.002630711, 0.002457142, + 0.002283096, 0.002110004, 0.001937389, 0.001766682, 0.001597881, + 0.001432419, 0.001269817, 0.001111031, + 0.000956535, 0.000806808, 0.000661850, 0.000522137, 0.000388145, + 0.000259876, 0.000137329, 0.000021458, + -0.000088215, -0.000191689, -0.000288486, -0.000378609, -0.000462532, + -0.000539303, -0.000610352, -0.000674248, + -0.000731945, -0.000783920, -0.000829220, -0.000868797, -0.000902653, + -0.000930786, -0.000953674, 0.000971317, + 0.000983715, 0.000991821, 0.000995159, 0.000994205, 0.000989437, + 0.000980854, 0.000968933, 0.000954151, + 0.000935555, 0.000915051, 0.000891685, 0.000866413, 0.000838757, + 0.000809669, 0.000779152, 0.000747204, + 0.000714302, 0.000680923, 0.000646591, 0.000611782, 0.000576973, + 0.000542164, 0.000507355, 0.000472546, + 0.000438213, 0.000404358, 0.000371456, 0.000339031, 0.000307560, + 0.000277042, 0.000247478, 0.000218868, + 0.000191212, 0.000165462, 0.000140190, 0.000116348, 0.000093937, + 0.000072956, 0.000052929, 0.000034332, + 0.000017166, 0.000000954, -0.000013828, -0.000027180, -0.000039577, + -0.000050545, -0.000060558, -0.000069618, + -0.000077724, -0.000084400, -0.000090122, -0.000095367, -0.000099182, + -0.000102520, -0.000105381, -0.000106812, + -0.000108242, -0.000108719, -0.000108719, -0.000108242, -0.000107288, + -0.000105858, -0.000103951, 0.000101566, + 0.000099182, 0.000096321, 0.000093460, 0.000090599, 0.000087261, + 0.000083923, 0.000080585, 0.000076771, + 0.000073433, 0.000070095, 0.000066280, 0.000062943, 0.000059605, + 0.000055790, 0.000052929, 0.000049591, + 0.000046253, 0.000043392, 0.000040531, 0.000037670, 0.000034809, + 0.000032425, 0.000030041, 0.000027657, + 0.000025272, 0.000023365, 0.000021458, 0.000019550, 0.000018120, + 0.000016689, 0.000014782, 0.000013828, + 0.000012398, 0.000011444, 0.000010014, 0.000009060, 0.000008106, + 0.000007629, 0.000006676, 0.000006199, + 0.000005245, 0.000004768, 0.000004292, 0.000003815, 0.000003338, + 0.000003338, 0.000002861, 0.000002384, + 0.000002384, 0.000001907, 0.000001907, 0.000001431, 0.000001431, + 0.000000954, 0.000000954, 0.000000954, + 0.000000954, 0.000000477, 0.000000477, 0.000000477, 0.000000477, + 0.000000477, 0.000000477 +}; diff --git a/libtoolame-dab/fft.c b/libtoolame-dab/fft.c new file mode 100644 index 0000000..985bdd4 --- /dev/null +++ b/libtoolame-dab/fft.c @@ -0,0 +1,1296 @@ +/* +** FFT and FHT routines +** Copyright 1988, 1993; Ron Mayer +** +** fht(fz,n); +** Does a hartley transform of "n" points in the array "fz". +** +** NOTE: This routine uses at least 2 patented algorithms, and may be +** under the restrictions of a bunch of different organizations. +** Although I wrote it completely myself; it is kind of a derivative +** of a routine I once authored and released under the GPL, so it +** may fall under the free software foundation's restrictions; +** it was worked on as a Stanford Univ project, so they claim +** some rights to it; it was further optimized at work here, so +** I think this company claims parts of it. The patents are +** held by R. Bracewell (the FHT algorithm) and O. Buneman (the +** trig generator), both at Stanford Univ. +** If it were up to me, I'd say go do whatever you want with it; +** but it would be polite to give credit to the following people +** if you use this anywhere: +** Euler - probable inventor of the fourier transform. +** Gauss - probable inventor of the FFT. +** Hartley - probable inventor of the hartley transform. +** Buneman - for a really cool trig generator +** Mayer(me) - for authoring this particular version and +** including all the optimizations in one package. +** Thanks, +** Ron Mayer; mayer@acuson.com +** +*/ +#include <stdio.h> +#include <math.h> +#include "common.h" +#include "fft.h" +#define SQRT2 1.4142135623730951454746218587388284504414 + + +static FLOAT costab[20] = { + .00000000000000000000000000000000000000000000000000, + .70710678118654752440084436210484903928483593768847, + .92387953251128675612818318939678828682241662586364, + .98078528040323044912618223613423903697393373089333, + .99518472667219688624483695310947992157547486872985, + .99879545620517239271477160475910069444320361470461, + .99969881869620422011576564966617219685006108125772, + .99992470183914454092164649119638322435060646880221, + .99998117528260114265699043772856771617391725094433, + .99999529380957617151158012570011989955298763362218, + .99999882345170190992902571017152601904826792288976, + .99999970586288221916022821773876567711626389934930, + .99999992646571785114473148070738785694820115568892, + .99999998161642929380834691540290971450507605124278, + .99999999540410731289097193313960614895889430318945, + .99999999885102682756267330779455410840053741619428 +}; +static FLOAT sintab[20] = { + 1.0000000000000000000000000000000000000000000000000, + .70710678118654752440084436210484903928483593768846, + .38268343236508977172845998403039886676134456248561, + .19509032201612826784828486847702224092769161775195, + .09801714032956060199419556388864184586113667316749, + .04906767432741801425495497694268265831474536302574, + .02454122852291228803173452945928292506546611923944, + .01227153828571992607940826195100321214037231959176, + .00613588464915447535964023459037258091705788631738, + .00306795676296597627014536549091984251894461021344, + .00153398018628476561230369715026407907995486457522, + .00076699031874270452693856835794857664314091945205, + .00038349518757139558907246168118138126339502603495, + .00019174759731070330743990956198900093346887403385, + .00009587379909597734587051721097647635118706561284, + .00004793689960306688454900399049465887274686668768 +}; + +/* This is a simplified version for n an even power of 2 */ +/* MFC: In the case of LayerII encoding, n==1024 always. */ + +static void fht (FLOAT * fz) +{ + int i, k, k1, k2, k3, k4, kx; + FLOAT *fi, *fn, *gi; + FLOAT t_c, t_s; + + FLOAT a; + static const struct { + unsigned short k1, k2; + } k1k2tab[8 * 62] = { + { + 0x020, 0x010} + , { + 0x040, 0x008} + , { + 0x050, 0x028} + , { + 0x060, 0x018} + , { + 0x068, 0x058} + , { + 0x070, 0x038} + , { + 0x080, 0x004} + , { + 0x088, 0x044} + , { + 0x090, 0x024} + , { + 0x098, 0x064} + , { + 0x0a0, 0x014} + , { + 0x0a4, 0x094} + , { + 0x0a8, 0x054} + , { + 0x0b0, 0x034} + , { + 0x0b8, 0x074} + , { + 0x0c0, 0x00c} + , { + 0x0c4, 0x08c} + , { + 0x0c8, 0x04c} + , { + 0x0d0, 0x02c} + , { + 0x0d4, 0x0ac} + , { + 0x0d8, 0x06c} + , { + 0x0e0, 0x01c} + , { + 0x0e4, 0x09c} + , { + 0x0e8, 0x05c} + , { + 0x0ec, 0x0dc} + , { + 0x0f0, 0x03c} + , { + 0x0f4, 0x0bc} + , { + 0x0f8, 0x07c} + , { + 0x100, 0x002} + , { + 0x104, 0x082} + , { + 0x108, 0x042} + , { + 0x10c, 0x0c2} + , { + 0x110, 0x022} + , { + 0x114, 0x0a2} + , { + 0x118, 0x062} + , { + 0x11c, 0x0e2} + , { + 0x120, 0x012} + , { + 0x122, 0x112} + , { + 0x124, 0x092} + , { + 0x128, 0x052} + , { + 0x12c, 0x0d2} + , { + 0x130, 0x032} + , { + 0x134, 0x0b2} + , { + 0x138, 0x072} + , { + 0x13c, 0x0f2} + , { + 0x140, 0x00a} + , { + 0x142, 0x10a} + , { + 0x144, 0x08a} + , { + 0x148, 0x04a} + , { + 0x14c, 0x0ca} + , { + 0x150, 0x02a} + , { + 0x152, 0x12a} + , { + 0x154, 0x0aa} + , { + 0x158, 0x06a} + , { + 0x15c, 0x0ea} + , { + 0x160, 0x01a} + , { + 0x162, 0x11a} + , { + 0x164, 0x09a} + , { + 0x168, 0x05a} + , { + 0x16a, 0x15a} + , { + 0x16c, 0x0da} + , { + 0x170, 0x03a} + , { + 0x172, 0x13a} + , { + 0x174, 0x0ba} + , { + 0x178, 0x07a} + , { + 0x17c, 0x0fa} + , { + 0x180, 0x006} + , { + 0x182, 0x106} + , { + 0x184, 0x086} + , { + 0x188, 0x046} + , { + 0x18a, 0x146} + , { + 0x18c, 0x0c6} + , { + 0x190, 0x026} + , { + 0x192, 0x126} + , { + 0x194, 0x0a6} + , { + 0x198, 0x066} + , { + 0x19a, 0x166} + , { + 0x19c, 0x0e6} + , { + 0x1a0, 0x016} + , { + 0x1a2, 0x116} + , { + 0x1a4, 0x096} + , { + 0x1a6, 0x196} + , { + 0x1a8, 0x056} + , { + 0x1aa, 0x156} + , { + 0x1ac, 0x0d6} + , { + 0x1b0, 0x036} + , { + 0x1b2, 0x136} + , { + 0x1b4, 0x0b6} + , { + 0x1b8, 0x076} + , { + 0x1ba, 0x176} + , { + 0x1bc, 0x0f6} + , { + 0x1c0, 0x00e} + , { + 0x1c2, 0x10e} + , { + 0x1c4, 0x08e} + , { + 0x1c6, 0x18e} + , { + 0x1c8, 0x04e} + , { + 0x1ca, 0x14e} + , { + 0x1cc, 0x0ce} + , { + 0x1d0, 0x02e} + , { + 0x1d2, 0x12e} + , { + 0x1d4, 0x0ae} + , { + 0x1d6, 0x1ae} + , { + 0x1d8, 0x06e} + , { + 0x1da, 0x16e} + , { + 0x1dc, 0x0ee} + , { + 0x1e0, 0x01e} + , { + 0x1e2, 0x11e} + , { + 0x1e4, 0x09e} + , { + 0x1e6, 0x19e} + , { + 0x1e8, 0x05e} + , { + 0x1ea, 0x15e} + , { + 0x1ec, 0x0de} + , { + 0x1ee, 0x1de} + , { + 0x1f0, 0x03e} + , { + 0x1f2, 0x13e} + , { + 0x1f4, 0x0be} + , { + 0x1f6, 0x1be} + , { + 0x1f8, 0x07e} + , { + 0x1fa, 0x17e} + , { + 0x1fc, 0x0fe} + , { + 0x200, 0x001} + , { + 0x202, 0x101} + , { + 0x204, 0x081} + , { + 0x206, 0x181} + , { + 0x208, 0x041} + , { + 0x20a, 0x141} + , { + 0x20c, 0x0c1} + , { + 0x20e, 0x1c1} + , { + 0x210, 0x021} + , { + 0x212, 0x121} + , { + 0x214, 0x0a1} + , { + 0x216, 0x1a1} + , { + 0x218, 0x061} + , { + 0x21a, 0x161} + , { + 0x21c, 0x0e1} + , { + 0x21e, 0x1e1} + , { + 0x220, 0x011} + , { + 0x221, 0x211} + , { + 0x222, 0x111} + , { + 0x224, 0x091} + , { + 0x226, 0x191} + , { + 0x228, 0x051} + , { + 0x22a, 0x151} + , { + 0x22c, 0x0d1} + , { + 0x22e, 0x1d1} + , { + 0x230, 0x031} + , { + 0x232, 0x131} + , { + 0x234, 0x0b1} + , { + 0x236, 0x1b1} + , { + 0x238, 0x071} + , { + 0x23a, 0x171} + , { + 0x23c, 0x0f1} + , { + 0x23e, 0x1f1} + , { + 0x240, 0x009} + , { + 0x241, 0x209} + , { + 0x242, 0x109} + , { + 0x244, 0x089} + , { + 0x246, 0x189} + , { + 0x248, 0x049} + , { + 0x24a, 0x149} + , { + 0x24c, 0x0c9} + , { + 0x24e, 0x1c9} + , { + 0x250, 0x029} + , { + 0x251, 0x229} + , { + 0x252, 0x129} + , { + 0x254, 0x0a9} + , { + 0x256, 0x1a9} + , { + 0x258, 0x069} + , { + 0x25a, 0x169} + , { + 0x25c, 0x0e9} + , { + 0x25e, 0x1e9} + , { + 0x260, 0x019} + , { + 0x261, 0x219} + , { + 0x262, 0x119} + , { + 0x264, 0x099} + , { + 0x266, 0x199} + , { + 0x268, 0x059} + , { + 0x269, 0x259} + , { + 0x26a, 0x159} + , { + 0x26c, 0x0d9} + , { + 0x26e, 0x1d9} + , { + 0x270, 0x039} + , { + 0x271, 0x239} + , { + 0x272, 0x139} + , { + 0x274, 0x0b9} + , { + 0x276, 0x1b9} + , { + 0x278, 0x079} + , { + 0x27a, 0x179} + , { + 0x27c, 0x0f9} + , { + 0x27e, 0x1f9} + , { + 0x280, 0x005} + , { + 0x281, 0x205} + , { + 0x282, 0x105} + , { + 0x284, 0x085} + , { + 0x286, 0x185} + , { + 0x288, 0x045} + , { + 0x289, 0x245} + , { + 0x28a, 0x145} + , { + 0x28c, 0x0c5} + , { + 0x28e, 0x1c5} + , { + 0x290, 0x025} + , { + 0x291, 0x225} + , { + 0x292, 0x125} + , { + 0x294, 0x0a5} + , { + 0x296, 0x1a5} + , { + 0x298, 0x065} + , { + 0x299, 0x265} + , { + 0x29a, 0x165} + , { + 0x29c, 0x0e5} + , { + 0x29e, 0x1e5} + , { + 0x2a0, 0x015} + , { + 0x2a1, 0x215} + , { + 0x2a2, 0x115} + , { + 0x2a4, 0x095} + , { + 0x2a5, 0x295} + , { + 0x2a6, 0x195} + , { + 0x2a8, 0x055} + , { + 0x2a9, 0x255} + , { + 0x2aa, 0x155} + , { + 0x2ac, 0x0d5} + , { + 0x2ae, 0x1d5} + , { + 0x2b0, 0x035} + , { + 0x2b1, 0x235} + , { + 0x2b2, 0x135} + , { + 0x2b4, 0x0b5} + , { + 0x2b6, 0x1b5} + , { + 0x2b8, 0x075} + , { + 0x2b9, 0x275} + , { + 0x2ba, 0x175} + , { + 0x2bc, 0x0f5} + , { + 0x2be, 0x1f5} + , { + 0x2c0, 0x00d} + , { + 0x2c1, 0x20d} + , { + 0x2c2, 0x10d} + , { + 0x2c4, 0x08d} + , { + 0x2c5, 0x28d} + , { + 0x2c6, 0x18d} + , { + 0x2c8, 0x04d} + , { + 0x2c9, 0x24d} + , { + 0x2ca, 0x14d} + , { + 0x2cc, 0x0cd} + , { + 0x2ce, 0x1cd} + , { + 0x2d0, 0x02d} + , { + 0x2d1, 0x22d} + , { + 0x2d2, 0x12d} + , { + 0x2d4, 0x0ad} + , { + 0x2d5, 0x2ad} + , { + 0x2d6, 0x1ad} + , { + 0x2d8, 0x06d} + , { + 0x2d9, 0x26d} + , { + 0x2da, 0x16d} + , { + 0x2dc, 0x0ed} + , { + 0x2de, 0x1ed} + , { + 0x2e0, 0x01d} + , { + 0x2e1, 0x21d} + , { + 0x2e2, 0x11d} + , { + 0x2e4, 0x09d} + , { + 0x2e5, 0x29d} + , { + 0x2e6, 0x19d} + , { + 0x2e8, 0x05d} + , { + 0x2e9, 0x25d} + , { + 0x2ea, 0x15d} + , { + 0x2ec, 0x0dd} + , { + 0x2ed, 0x2dd} + , { + 0x2ee, 0x1dd} + , { + 0x2f0, 0x03d} + , { + 0x2f1, 0x23d} + , { + 0x2f2, 0x13d} + , { + 0x2f4, 0x0bd} + , { + 0x2f5, 0x2bd} + , { + 0x2f6, 0x1bd} + , { + 0x2f8, 0x07d} + , { + 0x2f9, 0x27d} + , { + 0x2fa, 0x17d} + , { + 0x2fc, 0x0fd} + , { + 0x2fe, 0x1fd} + , { + 0x300, 0x003} + , { + 0x301, 0x203} + , { + 0x302, 0x103} + , { + 0x304, 0x083} + , { + 0x305, 0x283} + , { + 0x306, 0x183} + , { + 0x308, 0x043} + , { + 0x309, 0x243} + , { + 0x30a, 0x143} + , { + 0x30c, 0x0c3} + , { + 0x30d, 0x2c3} + , { + 0x30e, 0x1c3} + , { + 0x310, 0x023} + , { + 0x311, 0x223} + , { + 0x312, 0x123} + , { + 0x314, 0x0a3} + , { + 0x315, 0x2a3} + , { + 0x316, 0x1a3} + , { + 0x318, 0x063} + , { + 0x319, 0x263} + , { + 0x31a, 0x163} + , { + 0x31c, 0x0e3} + , { + 0x31d, 0x2e3} + , { + 0x31e, 0x1e3} + , { + 0x320, 0x013} + , { + 0x321, 0x213} + , { + 0x322, 0x113} + , { + 0x323, 0x313} + , { + 0x324, 0x093} + , { + 0x325, 0x293} + , { + 0x326, 0x193} + , { + 0x328, 0x053} + , { + 0x329, 0x253} + , { + 0x32a, 0x153} + , { + 0x32c, 0x0d3} + , { + 0x32d, 0x2d3} + , { + 0x32e, 0x1d3} + , { + 0x330, 0x033} + , { + 0x331, 0x233} + , { + 0x332, 0x133} + , { + 0x334, 0x0b3} + , { + 0x335, 0x2b3} + , { + 0x336, 0x1b3} + , { + 0x338, 0x073} + , { + 0x339, 0x273} + , { + 0x33a, 0x173} + , { + 0x33c, 0x0f3} + , { + 0x33d, 0x2f3} + , { + 0x33e, 0x1f3} + , { + 0x340, 0x00b} + , { + 0x341, 0x20b} + , { + 0x342, 0x10b} + , { + 0x343, 0x30b} + , { + 0x344, 0x08b} + , { + 0x345, 0x28b} + , { + 0x346, 0x18b} + , { + 0x348, 0x04b} + , { + 0x349, 0x24b} + , { + 0x34a, 0x14b} + , { + 0x34c, 0x0cb} + , { + 0x34d, 0x2cb} + , { + 0x34e, 0x1cb} + , { + 0x350, 0x02b} + , { + 0x351, 0x22b} + , { + 0x352, 0x12b} + , { + 0x353, 0x32b} + , { + 0x354, 0x0ab} + , { + 0x355, 0x2ab} + , { + 0x356, 0x1ab} + , { + 0x358, 0x06b} + , { + 0x359, 0x26b} + , { + 0x35a, 0x16b} + , { + 0x35c, 0x0eb} + , { + 0x35d, 0x2eb} + , { + 0x35e, 0x1eb} + , { + 0x360, 0x01b} + , { + 0x361, 0x21b} + , { + 0x362, 0x11b} + , { + 0x363, 0x31b} + , { + 0x364, 0x09b} + , { + 0x365, 0x29b} + , { + 0x366, 0x19b} + , { + 0x368, 0x05b} + , { + 0x369, 0x25b} + , { + 0x36a, 0x15b} + , { + 0x36b, 0x35b} + , { + 0x36c, 0x0db} + , { + 0x36d, 0x2db} + , { + 0x36e, 0x1db} + , { + 0x370, 0x03b} + , { + 0x371, 0x23b} + , { + 0x372, 0x13b} + , { + 0x373, 0x33b} + , { + 0x374, 0x0bb} + , { + 0x375, 0x2bb} + , { + 0x376, 0x1bb} + , { + 0x378, 0x07b} + , { + 0x379, 0x27b} + , { + 0x37a, 0x17b} + , { + 0x37c, 0x0fb} + , { + 0x37d, 0x2fb} + , { + 0x37e, 0x1fb} + , { + 0x380, 0x007} + , { + 0x381, 0x207} + , { + 0x382, 0x107} + , { + 0x383, 0x307} + , { + 0x384, 0x087} + , { + 0x385, 0x287} + , { + 0x386, 0x187} + , { + 0x388, 0x047} + , { + 0x389, 0x247} + , { + 0x38a, 0x147} + , { + 0x38b, 0x347} + , { + 0x38c, 0x0c7} + , { + 0x38d, 0x2c7} + , { + 0x38e, 0x1c7} + , { + 0x390, 0x027} + , { + 0x391, 0x227} + , { + 0x392, 0x127} + , { + 0x393, 0x327} + , { + 0x394, 0x0a7} + , { + 0x395, 0x2a7} + , { + 0x396, 0x1a7} + , { + 0x398, 0x067} + , { + 0x399, 0x267} + , { + 0x39a, 0x167} + , { + 0x39b, 0x367} + , { + 0x39c, 0x0e7} + , { + 0x39d, 0x2e7} + , { + 0x39e, 0x1e7} + , { + 0x3a0, 0x017} + , { + 0x3a1, 0x217} + , { + 0x3a2, 0x117} + , { + 0x3a3, 0x317} + , { + 0x3a4, 0x097} + , { + 0x3a5, 0x297} + , { + 0x3a6, 0x197} + , { + 0x3a7, 0x397} + , { + 0x3a8, 0x057} + , { + 0x3a9, 0x257} + , { + 0x3aa, 0x157} + , { + 0x3ab, 0x357} + , { + 0x3ac, 0x0d7} + , { + 0x3ad, 0x2d7} + , { + 0x3ae, 0x1d7} + , { + 0x3b0, 0x037} + , { + 0x3b1, 0x237} + , { + 0x3b2, 0x137} + , { + 0x3b3, 0x337} + , { + 0x3b4, 0x0b7} + , { + 0x3b5, 0x2b7} + , { + 0x3b6, 0x1b7} + , { + 0x3b8, 0x077} + , { + 0x3b9, 0x277} + , { + 0x3ba, 0x177} + , { + 0x3bb, 0x377} + , { + 0x3bc, 0x0f7} + , { + 0x3bd, 0x2f7} + , { + 0x3be, 0x1f7} + , { + 0x3c0, 0x00f} + , { + 0x3c1, 0x20f} + , { + 0x3c2, 0x10f} + , { + 0x3c3, 0x30f} + , { + 0x3c4, 0x08f} + , { + 0x3c5, 0x28f} + , { + 0x3c6, 0x18f} + , { + 0x3c7, 0x38f} + , { + 0x3c8, 0x04f} + , { + 0x3c9, 0x24f} + , { + 0x3ca, 0x14f} + , { + 0x3cb, 0x34f} + , { + 0x3cc, 0x0cf} + , { + 0x3cd, 0x2cf} + , { + 0x3ce, 0x1cf} + , { + 0x3d0, 0x02f} + , { + 0x3d1, 0x22f} + , { + 0x3d2, 0x12f} + , { + 0x3d3, 0x32f} + , { + 0x3d4, 0x0af} + , { + 0x3d5, 0x2af} + , { + 0x3d6, 0x1af} + , { + 0x3d7, 0x3af} + , { + 0x3d8, 0x06f} + , { + 0x3d9, 0x26f} + , { + 0x3da, 0x16f} + , { + 0x3db, 0x36f} + , { + 0x3dc, 0x0ef} + , { + 0x3dd, 0x2ef} + , { + 0x3de, 0x1ef} + , { + 0x3e0, 0x01f} + , { + 0x3e1, 0x21f} + , { + 0x3e2, 0x11f} + , { + 0x3e3, 0x31f} + , { + 0x3e4, 0x09f} + , { + 0x3e5, 0x29f} + , { + 0x3e6, 0x19f} + , { + 0x3e7, 0x39f} + , { + 0x3e8, 0x05f} + , { + 0x3e9, 0x25f} + , { + 0x3ea, 0x15f} + , { + 0x3eb, 0x35f} + , { + 0x3ec, 0x0df} + , { + 0x3ed, 0x2df} + , { + 0x3ee, 0x1df} + , { + 0x3ef, 0x3df} + , { + 0x3f0, 0x03f} + , { + 0x3f1, 0x23f} + , { + 0x3f2, 0x13f} + , { + 0x3f3, 0x33f} + , { + 0x3f4, 0x0bf} + , { + 0x3f5, 0x2bf} + , { + 0x3f6, 0x1bf} + , { + 0x3f7, 0x3bf} + , { + 0x3f8, 0x07f} + , { + 0x3f9, 0x27f} + , { + 0x3fa, 0x17f} + , { + 0x3fb, 0x37f} + , { + 0x3fc, 0x0ff} + , { + 0x3fd, 0x2ff} + , { + 0x3fe, 0x1ff} + }; + { + int i; + for (i = 0; i < sizeof k1k2tab / sizeof k1k2tab[0]; ++i) { + k1 = k1k2tab[i].k1; + k2 = k1k2tab[i].k2; + a = fz[k1]; + fz[k1] = fz[k2]; + fz[k2] = a; + } + } + + for (fi = fz, fn = fz + 1024; fi < fn; fi += 4) { + FLOAT f0, f1, f2, f3; + f1 = fi[0] - fi[1]; + f0 = fi[0] + fi[1]; + f3 = fi[2] - fi[3]; + f2 = fi[2] + fi[3]; + fi[2] = (f0 - f2); + fi[0] = (f0 + f2); + fi[3] = (f1 - f3); + fi[1] = (f1 + f3); + } + + k = 0; + do { + FLOAT s1, c1; + k += 2; + k1 = 1 << k; + k2 = k1 << 1; + k4 = k2 << 1; + k3 = k2 + k1; + kx = k1 >> 1; + fi = fz; + gi = fi + kx; + fn = fz + 1024; + do { + FLOAT g0, f0, f1, g1, f2, g2, f3, g3; + f1 = fi[0] - fi[k1]; + f0 = fi[0] + fi[k1]; + f3 = fi[k2] - fi[k3]; + f2 = fi[k2] + fi[k3]; + fi[k2] = f0 - f2; + fi[0] = f0 + f2; + fi[k3] = f1 - f3; + fi[k1] = f1 + f3; + g1 = gi[0] - gi[k1]; + g0 = gi[0] + gi[k1]; + g3 = SQRT2 * gi[k3]; + g2 = SQRT2 * gi[k2]; + gi[k2] = g0 - g2; + gi[0] = g0 + g2; + gi[k3] = g1 - g3; + gi[k1] = g1 + g3; + gi += k4; + fi += k4; + } + while (fi < fn); + t_c = costab[k]; + t_s = sintab[k]; + c1 = 1; + s1 = 0; + for (i = 1; i < kx; i++) { + FLOAT c2, s2; + FLOAT t = c1; + c1 = t * t_c - s1 * t_s; + s1 = t * t_s + s1 * t_c; + c2 = c1 * c1 - s1 * s1; + s2 = 2 * (c1 * s1); + fn = fz + 1024; + fi = fz + i; + gi = fz + k1 - i; + do { + FLOAT a, b, g0, f0, f1, g1, f2, g2, f3, g3; + b = s2 * fi[k1] - c2 * gi[k1]; + a = c2 * fi[k1] + s2 * gi[k1]; + f1 = fi[0] - a; + f0 = fi[0] + a; + g1 = gi[0] - b; + g0 = gi[0] + b; + b = s2 * fi[k3] - c2 * gi[k3]; + a = c2 * fi[k3] + s2 * gi[k3]; + f3 = fi[k2] - a; + f2 = fi[k2] + a; + g3 = gi[k2] - b; + g2 = gi[k2] + b; + b = s1 * f2 - c1 * g3; + a = c1 * f2 + s1 * g3; + fi[k2] = f0 - a; + fi[0] = f0 + a; + gi[k3] = g1 - b; + gi[k1] = g1 + b; + b = c1 * g2 - s1 * f3; + a = s1 * g2 + c1 * f3; + gi[k2] = g0 - a; + gi[0] = g0 + a; + fi[k3] = f1 - b; + fi[k1] = f1 + b; + gi += k4; + fi += k4; + } + while (fi < fn); + } + } + while (k4 < 1024); +} + +#ifdef NEWATAN +#define ATANSIZE 2000 +#define ATANSCALE 50.0 + static FLOAT atan_t[ATANSIZE]; + +FLOAT atan_table(FLOAT y, FLOAT x) { + int index; + double index_d = ATANSCALE * fabs(y/x); + + // Don't cast an infinite to an int, that's undefined behaviour + if (isfinite(index_d)) { + index = (int)(ATANSCALE * fabs(y/x)); + } + else { + index = ATANSIZE-1; + } + + if (index>=ATANSIZE) + index = ATANSIZE-1; + + if (y>0 && x<0) + return( PI - atan_t[index] ); + + if (y<0 && x>0) + return( -atan_t[index] ); + + if (y<0 && x<0) + return( atan_t[index] - PI ); + + return(atan_t[index]); +} + +void atan_table_init(void) { + int i; + for (i=0;i<ATANSIZE;i++) + atan_t[i] = atan((double)i/ATANSCALE); +} + +#endif //NEWATAN + +/* For variations on psycho model 2: + N always equals 1024 + BUT in the returned values, no energy/phi is used at or above an index of 513 */ +void psycho_2_fft (FLOAT * x_real, FLOAT * energy, FLOAT * phi) + /* got rid of size "N" argument as it is always 1024 for layerII */ +{ + FLOAT a, b; + int i, j; +#ifdef NEWATAN + static int init=0; + + if (!init) { + atan_table_init(); + init++; + } +#endif + + + fht (x_real); + + + energy[0] = x_real[0] * x_real[0]; + + for (i = 1, j = 1023; i < 512; i++, j--) { + a = x_real[i]; + b = x_real[j]; + /* MFC FIXME Mar03 Why is this divided by 2.0? + if a and b are the real and imaginary components then + r = sqrt(a^2 + b^2), + but, back in the psycho2 model, they calculate r=sqrt(energy), + which, if you look at the original equation below is different */ + energy[i] = (a * a + b * b) / 2.0; + if (energy[i] < 0.0005) { + energy[i] = 0.0005; + phi[i] = 0; + } else +#ifdef NEWATAN + { + phi[i] = atan_table(-a, b) + PI/4; + } +#else + { + phi[i] = atan2(-(double)a, (double)b) + PI/4; + } +#endif + } + energy[512] = x_real[512] * x_real[512]; + phi[512] = atan2 (0.0, (double) x_real[512]); +} + + +void psycho_1_fft (FLOAT * x_real, FLOAT * energy, int N) +{ + FLOAT a, b; + int i, j; + + fht (x_real); + + energy[0] = x_real[0] * x_real[0]; + + for (i = 1, j = N - 1; i < N / 2; i++, j--) { + a = x_real[i]; + b = x_real[j]; + energy[i] = (a * a + b * b) / 2.0; + } + energy[N / 2] = x_real[N / 2] * x_real[N / 2]; +} + + + diff --git a/libtoolame-dab/fft.h b/libtoolame-dab/fft.h new file mode 100644 index 0000000..726bd3fb --- /dev/null +++ b/libtoolame-dab/fft.h @@ -0,0 +1,9 @@ + +//void fft (FLOAT[BLKSIZE], FLOAT[BLKSIZE], FLOAT[BLKSIZE], FLOAT[BLKSIZE], int); + +void psycho_2_fft (FLOAT * x_real, FLOAT * energy, FLOAT * phi); +void psycho_1_fft (FLOAT * x_real, FLOAT * energy, int N); + + +void atan_table_init(void); +FLOAT atan_table(FLOAT y, FLOAT x); diff --git a/libtoolame-dab/freqtable.h b/libtoolame-dab/freqtable.h new file mode 100644 index 0000000..d3f422b --- /dev/null +++ b/libtoolame-dab/freqtable.h @@ -0,0 +1 @@ +
typedef struct
{
int line;
double bark;
double hear;
}
MaskingThreshold;
static const int SecondFreqEntries[7] =
{ 130, 126, 132, 0, 132, 132, 132 };
static const MaskingThreshold SecondFreqSubband[7][132] = {
/* 2th0, 130 entries */
{{1, 0.425, 45.05},
{2, 0.850, 25.87},
{3, 1.273, 18.70},
{4, 1.694, 14.85},
{5, 2.112, 12.41},
{6, 2.525, 10.72},
{7, 2.934, 9.47},
{8, 3.337, 8.50},
{9, 3.733, 7.73},
{10, 4.124, 7.10},
{11, 4.507, 6.56},
{12, 4.882, 6.11},
{13, 5.249, 5.72},
{14, 5.608, 5.37},
{15, 5.959, 5.07},
{16, 6.301, 4.79},
{17, 6.634, 4.55},
{18, 6.959, 4.32},
{19, 7.274, 4.11},
{20, 7.581, 3.92},
{21, 7.879, 3.74},
{22, 8.169, 3.57},
{23, 8.450, 3.40},
{24, 8.723, 3.25},
{25, 8.987, 3.10},
{26, 9.244, 2.95},
{27, 9.493, 2.81},
{28, 9.734, 2.67},
{29, 9.968, 2.53},
{30, 10.195, 2.39},
{31, 10.416, 2.25},
{32, 10.629, 2.11},
{33, 10.836, 1.97},
{34, 11.037, 1.83},
{35, 11.232, 1.68},
{36, 11.421, 1.53},
{37, 11.605, 1.38},
{38, 11.783, 1.23},
{39, 11.957, 1.07},
{40, 12.125, 0.90},
{41, 12.289, 0.74},
{42, 12.448, 0.56},
{43, 12.603, 0.39},
{44, 12.753, 0.21},
{45, 12.900, 0.02},
{46, 13.042, -0.17},
{47, 13.181, -0.36},
{48, 13.317, -0.56},
{50, 13.577, -0.96},
{52, 13.826, -1.38},
{54, 14.062, -1.79},
{56, 14.288, -2.21},
{58, 14.504, -2.63},
{60, 14.711, -3.03},
{62, 14.909, -3.41},
{64, 15.100, -3.77},
{66, 15.284, -4.09},
{68, 15.460, -4.37},
{70, 15.631, -4.60},
{72, 15.796, -4.78},
{74, 15.955, -4.91},
{76, 16.110, -4.97},
{78, 16.260, -4.98},
{80, 16.406, -4.92},
{82, 16.547, -4.81},
{84, 16.685, -4.65},
{86, 16.820, -4.43},
{88, 16.951, -4.17},
{90, 17.079, -3.87},
{92, 17.205, -3.54},
{94, 17.327, -3.19},
{96, 17.447, -2.82},
{100, 17.680, -2.06},
{104, 17.905, -1.32},
{108, 18.121, -0.64},
{112, 18.331, -0.04},
{116, 18.534, 0.47},
{120, 18.731, 0.89},
{124, 18.922, 1.23},
{128, 19.108, 1.51},
{132, 19.289, 1.74},
{136, 19.464, 1.93},
{140, 19.635, 2.11},
{144, 19.801, 2.28},
{148, 19.963, 2.46},
{152, 20.120, 2.63},
{156, 20.273, 2.82},
{160, 20.421, 3.03},
{164, 20.565, 3.25},
{168, 20.705, 3.49},
{172, 20.840, 3.74},
{176, 20.972, 4.02},
{180, 21.099, 4.32},
{184, 21.222, 4.64},
{188, 21.342, 4.98},
{192, 21.457, 5.35},
{200, 21.677, 6.15},
{208, 21.882, 7.07},
{216, 22.074, 8.10},
{224, 22.253, 9.25},
{232, 22.420, 10.54},
{240, 22.576, 11.97},
{248, 22.721, 13.56},
{256, 22.857, 15.31},
{264, 22.984, 17.23},
{272, 23.102, 19.34},
{280, 23.213, 21.64},
{288, 23.317, 24.15},
{296, 23.415, 26.88},
{304, 23.506, 29.84},
{312, 23.592, 33.05},
{320, 23.673, 36.52},
{328, 23.749, 40.25},
{336, 23.821, 44.27},
{344, 23.888, 48.59},
{352, 23.952, 53.22},
{360, 24.013, 58.18},
{368, 24.070, 63.49},
{376, 24.125, 68.00},
{384, 24.176, 68.00},
{392, 24.225, 68.00},
{400, 24.271, 68.00},
{408, 24.316, 68.00},
{416, 24.358, 68.00},
{424, 24.398, 68.00},
{432, 24.436, 68.00},
{440, 24.473, 68.00},
{448, 24.508, 68.00},
{456, 24.542, 68.00},
{464, 24.574, 68.00},
{0, 0.0, 0.0},
{0, 0.0, 0.0}},
/* 2th1, 126 entries */
{{1, 0.463, 42.10},
{2, 0.925, 24.17},
{3, 1.385, 17.47},
{4, 1.842, 13.87},
{5, 2.295, 11.60},
{6, 2.742, 10.01},
{7, 3.184, 8.84},
{8, 3.618, 7.94},
{9, 4.045, 7.22},
{10, 4.463, 6.62},
{11, 4.872, 6.12},
{12, 5.272, 5.70},
{13, 5.661, 5.33},
{14, 6.041, 5.00},
{15, 6.411, 4.71},
{16, 6.770, 4.45},
{17, 7.119, 4.21},
{18, 7.457, 4.00},
{19, 7.785, 3.79},
{20, 8.103, 3.61},
{21, 8.410, 3.43},
{22, 8.708, 3.26},
{23, 8.996, 3.09},
{24, 9.275, 2.93},
{25, 9.544, 2.78},
{26, 9.805, 2.63},
{27, 10.057, 2.47},
{28, 10.301, 2.32},
{29, 10.537, 2.17},
{30, 10.765, 2.02},
{31, 10.986, 1.86},
{32, 11.199, 1.71},
{33, 11.406, 1.55},
{34, 11.606, 1.38},
{35, 11.800, 1.21},
{36, 11.988, 1.04},
{37, 12.170, 0.86},
{38, 12.347, 0.67},
{39, 12.518, 0.49},
{40, 12.684, 0.29},
{41, 12.845, 0.09},
{42, 13.002, -0.11},
{43, 13.154, -0.32},
{44, 13.302, -0.54},
{45, 13.446, -0.75},
{46, 13.586, -0.97},
{47, 13.723, -1.20},
{48, 13.855, -1.43},
{50, 14.111, -1.88},
{52, 14.354, -2.34},
{54, 14.585, -2.79},
{56, 14.807, -3.22},
{58, 15.018, -3.62},
{60, 15.221, -3.98},
{62, 15.415, -4.30},
{64, 15.602, -4.57},
{66, 15.783, -4.77},
{68, 15.956, -4.91},
{70, 16.124, -4.98},
{72, 16.287, -4.97},
{74, 16.445, -4.90},
{76, 16.598, -4.76},
{78, 16.746, -4.55},
{80, 16.891, -4.29},
{82, 17.032, -3.99},
{84, 17.169, -3.64},
{86, 17.303, -3.26},
{88, 17.434, -2.86},
{90, 17.563, -2.45},
{92, 17.688, -2.04},
{94, 17.811, -1.63},
{96, 17.932, -1.24},
{100, 18.166, -0.51},
{104, 18.392, 0.12},
{108, 18.611, 0.64},
{112, 18.823, 1.06},
{116, 19.028, 1.39},
{120, 19.226, 1.66},
{124, 19.419, 1.88},
{128, 19.606, 2.08},
{132, 19.788, 2.27},
{136, 19.964, 2.46},
{140, 20.135, 2.65},
{144, 20.300, 2.86},
{148, 20.461, 3.09},
{152, 20.616, 3.33},
{156, 20.766, 3.60},
{160, 20.912, 3.89},
{164, 21.052, 4.20},
{168, 21.188, 4.54},
{172, 21.318, 4.91},
{176, 21.445, 5.31},
{180, 21.567, 5.73},
{184, 21.684, 6.18},
{188, 21.797, 6.67},
{192, 21.906, 7.19},
{200, 22.113, 8.33},
{208, 22.304, 9.63},
{216, 22.482, 11.08},
{224, 22.646, 12.71},
{232, 22.799, 14.53},
{240, 22.941, 16.54},
{248, 23.072, 18.77},
{256, 23.195, 21.23},
{264, 23.309, 23.94},
{272, 23.415, 26.90},
{280, 23.515, 30.14},
{288, 23.607, 33.67},
{296, 23.694, 37.51},
{304, 23.775, 41.67},
{312, 23.852, 46.17},
{320, 23.923, 51.04},
{328, 23.991, 56.29},
{336, 24.054, 61.94},
{344, 24.114, 68.00},
{352, 24.171, 68.00},
{360, 24.224, 68.00},
{368, 24.275, 68.00},
{376, 24.322, 68.00},
{384, 24.368, 68.00},
{392, 24.411, 68.00},
{400, 24.452, 68.00},
{408, 24.491, 68.00},
{416, 24.528, 68.00},
{424, 24.564, 68.00},
{432, 24.597, 68.00},
{0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0}},
/* 2th2, 132 entries */
{{1, 0.309, 58.23},
{2, 0.617, 33.44},
{3, 0.925, 24.17},
{4, 1.232, 19.20},
{5, 1.538, 16.05},
{6, 1.842, 13.87},
{7, 2.145, 12.26},
{8, 2.445, 11.01},
{9, 2.742, 10.01},
{10, 3.037, 9.20},
{11, 3.329, 8.52},
{12, 3.618, 7.94},
{13, 3.903, 7.44},
{14, 4.185, 7.00},
{15, 4.463, 6.62},
{16, 4.736, 6.28},
{17, 5.006, 5.97},
{18, 5.272, 5.70},
{19, 5.533, 5.44},
{20, 5.789, 5.21},
{21, 6.041, 5.00},
{22, 6.289, 4.80},
{23, 6.532, 4.62},
{24, 6.770, 4.45},
{25, 7.004, 4.29},
{26, 7.233, 4.14},
{27, 7.457, 4.00},
{28, 7.677, 3.86},
{29, 7.892, 3.73},
{30, 8.103, 3.61},
{31, 8.309, 3.49},
{32, 8.511, 3.37},
{33, 8.708, 3.26},
{34, 8.901, 3.15},
{35, 9.090, 3.04},
{36, 9.275, 2.93},
{37, 9.456, 2.83},
{38, 9.632, 2.73},
{39, 9.805, 2.63},
{40, 9.974, 2.53},
{41, 10.139, 2.42},
{42, 10.301, 2.32},
{43, 10.459, 2.22},
{44, 10.614, 2.12},
{45, 10.765, 2.02},
{46, 10.913, 1.92},
{47, 11.058, 1.81},
{48, 11.199, 1.71},
{50, 11.474, 1.49},
{52, 11.736, 1.27},
{54, 11.988, 1.04},
{56, 12.230, 0.80},
{58, 12.461, 0.55},
{60, 12.684, 0.29},
{62, 12.898, 0.02},
{64, 13.104, -0.25},
{66, 13.302, -0.54},
{68, 13.493, -0.83},
{70, 13.678, -1.12},
{72, 13.855, -1.43},
{74, 14.027, -1.73},
{76, 14.193, -2.04},
{78, 14.354, -2.34},
{80, 14.509, -2.64},
{82, 14.660, -2.93},
{84, 14.807, -3.22},
{86, 14.949, -3.49},
{88, 15.087, -3.74},
{90, 15.221, -3.98},
{92, 15.351, -4.20},
{94, 15.478, -4.40},
{96, 15.602, -4.57},
{100, 15.841, -4.82},
{104, 16.069, -4.96},
{108, 16.287, -4.97},
{112, 16.496, -4.86},
{116, 16.697, -4.63},
{120, 16.891, -4.29},
{124, 17.078, -3.87},
{128, 17.259, -3.39},
{132, 17.434, -2.86},
{136, 17.605, -2.31},
{140, 17.770, -1.77},
{144, 17.932, -1.24},
{148, 18.089, -0.74},
{152, 18.242, -0.29},
{156, 18.392, 0.12},
{160, 18.539, 0.48},
{164, 18.682, 0.79},
{168, 18.823, 1.06},
{172, 18.960, 1.29},
{176, 19.095, 1.49},
{180, 19.226, 1.66},
{184, 19.356, 1.81},
{188, 19.482, 1.95},
{192, 19.606, 2.08},
{200, 19.847, 2.33},
{208, 20.079, 2.59},
{216, 20.300, 2.86},
{224, 20.513, 3.17},
{232, 20.717, 3.51},
{240, 20.912, 3.89},
{248, 21.098, 4.31},
{256, 21.275, 4.79},
{264, 21.445, 5.31},
{272, 21.606, 5.88},
{280, 21.760, 6.50},
{288, 21.906, 7.19},
{296, 22.046, 7.93},
{304, 22.178, 8.75},
{312, 22.304, 9.63},
{320, 22.424, 10.58},
{328, 22.538, 11.60},
{336, 22.646, 12.71},
{344, 22.749, 13.90},
{352, 22.847, 15.18},
{352, 22.941, 16.54},
{368, 23.030, 18.01},
{376, 23.114, 19.57},
{384, 23.195, 21.23},
{382, 23.272, 23.01},
{400, 23.345, 24.90},
{408, 23.415, 26.90},
{416, 23.482, 29.03},
{424, 23.546, 31.28},
{432, 23.607, 33.67},
{440, 23.666, 36.19},
{448, 23.722, 38.86},
{456, 23.775, 41.67},
{464, 23.827, 44.63},
{472, 23.876, 47.76},
{480, 23.923, 51.04}},
/* 2th3, 0 entries (all dummies) */
{{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0},
{0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0},
{0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0,
0.0},
{0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0,
0.0}, {0,
0.0,
0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0, 0.0}, {0, 0.0, 0.0},
{0, 0.0, 0.0}, {0, 0.0,
0.0}},
/* 2th4, 132 entries */
{{1, 0.213, 68.00},
{2, 0.425, 45.05},
{3, 0.638, 32.57},
{4, 0.850, 25.87},
{5, 1.062, 21.63},
{6, 1.273, 18.70},
{7, 1.484, 16.52},
{8, 1.694, 14.85},
{9, 1.903, 13.51},
{10, 2.112, 12.41},
{11, 2.319, 11.50},
{12, 2.525, 10.72},
{13, 2.730, 10.05},
{14, 2.934, 9.47},
{15, 3.136, 8.96},
{16, 3.337, 8.50},
{17, 3.536, 8.10},
{18, 3.733, 7.73},
{19, 3.929, 7.40},
{20, 4.124, 7.10},
{21, 4.316, 6.82},
{22, 4.507, 6.56},
{23, 4.695, 6.33},
{24, 4.882, 6.11},
{25, 5.067, 5.91},
{26, 5.249, 5.72},
{27, 5.430, 5.54},
{28, 5.608, 5.37},
{29, 5.785, 5.22},
{30, 5.959, 5.07},
{31, 6.131, 4.93},
{32, 6.301, 4.79},
{33, 6.469, 4.67},
{34, 6.634, 4.55},
{35, 6.798, 4.43},
{36, 6.959, 4.32},
{37, 7.118, 4.21},
{38, 7.274, 4.11},
{39, 7.429, 4.01},
{40, 7.581, 3.92},
{41, 7.731, 3.83},
{42, 7.879, 3.74},
{43, 8.025, 3.65},
{44, 8.169, 3.57},
{45, 8.310, 3.48},
{46, 8.450, 3.40},
{47, 8.587, 3.33},
{48, 8.723, 3.25},
{50, 8.987, 3.10},
{52, 9.244, 2.95},
{54, 9.493, 2.81},
{56, 9.734, 2.67},
{58, 9.968, 2.53},
{60, 10.195, 2.39},
{62, 10.416, 2.25},
{64, 10.629, 2.11},
{66, 10.836, 1.97},
{68, 11.037, 1.83},
{70, 11.232, 1.68},
{72, 11.421, 1.53},
{74, 11.605, 1.38},
{76, 11.783, 1.23},
{78, 11.957, 1.07},
{80, 12.125, 0.90},
{82, 12.289, 0.74},
{84, 12.448, 0.56},
{86, 12.603, 0.39},
{88, 12.753, 0.21},
{90, 12.900, 0.02},
{92, 13.042, -0.17},
{94, 13.181, -0.36},
{96, 13.317, -0.56},
{100, 13.578, -0.96},
{104, 13.826, -1.38},
{108, 14.062, -1.79},
{112, 14.288, -2.21},
{116, 14.504, -2.63},
{120, 14.711, -3.03},
{124, 14.909, -3.41},
{128, 15.100, -3.77},
{132, 15.284, -4.09},
{136, 15.460, -4.37},
{140, 15.631, -4.60},
{144, 15.796, -4.78},
{148, 15.955, -4.91},
{152, 16.110, -4.97},
{156, 16.260, -4.98},
{160, 16.406, -4.92},
{164, 16.547, -4.81},
{168, 16.685, -4.65},
{172, 16.820, -4.43},
{176, 16.951, -4.17},
{180, 17.079, -3.87},
{184, 17.205, -3.54},
{188, 17.327, -3.19},
{192, 17.447, -2.82},
{200, 17.680, -2.06},
{208, 17.905, -1.32},
{216, 18.121, -0.64},
{224, 18.331, -0.04},
{232, 18.534, 0.47},
{240, 18.731, 0.89},
{248, 18.922, 1.23},
{256, 19.108, 1.51},
{264, 19.289, 1.74},
{272, 19.464, 1.93},
{280, 19.635, 2.11},
{288, 19.801, 2.28},
{296, 19.963, 2.46},
{304, 20.120, 2.63},
{312, 20.273, 2.82},
{320, 20.421, 3.03},
{328, 20.565, 3.25},
{336, 20.705, 3.49},
{344, 20.840, 3.74},
{352, 20.972, 4.02},
{360, 21.099, 4.32},
{368, 21.222, 4.64},
{376, 21.342, 4.98},
{384, 21.457, 5.35},
{392, 21.569, 5.74},
{400, 21.677, 6.15},
{408, 21.781, 6.60},
{416, 21.882, 7.07},
{424, 21.980, 7.57},
{432, 22.074, 8.10},
{440, 22.165, 8.66},
{448, 22.253, 9.25},
{456, 22.338, 9.88},
{464, 22.420, 10.54},
{472, 22.499, 11.24},
{480, 22.576, 11.97}},
/* 2th5, 132 entries */
{{1, 0.232, 68.00},
{2, 0.463, 42.10},
{3, 0.694, 30.43},
{4, 0.925, 24.17},
{5, 1.156, 20.22},
{6, 1.385, 17.47},
{7, 1.614, 15.44},
{8, 1.842, 13.87},
{9, 2.069, 12.62},
{10, 2.295, 11.60},
{11, 2.519, 10.74},
{12, 2.742, 10.01},
{13, 2.964, 9.39},
{14, 3.184, 8.84},
{15, 3.402, 8.37},
{16, 3.618, 7.94},
{17, 3.832, 7.56},
{18, 4.045, 7.22},
{19, 4.255, 6.90},
{20, 4.463, 6.62},
{21, 4.668, 6.36},
{22, 4.872, 6.12},
{23, 5.073, 5.90},
{24, 5.272, 5.70},
{25, 5.468, 5.50},
{26, 5.661, 5.33},
{27, 5.853, 5.16},
{28, 6.041, 5.00},
{29, 6.227, 4.85},
{30, 6.411, 4.71},
{31, 6.592, 4.58},
{32, 6.770, 4.45},
{33, 6.946, 4.33},
{34, 7.119, 4.21},
{35, 7.289, 4.10},
{36, 7.457, 4.00},
{37, 7.622, 3.89},
{38, 7.785, 3.79},
{39, 7.945, 3.70},
{40, 8.103, 3.61},
{41, 8.258, 3.51},
{42, 8.410, 3.43},
{43, 8.560, 3.34},
{44, 8.708, 3.26},
{45, 8.853, 3.17},
{46, 8.996, 3.09},
{47, 9.137, 3.01},
{48, 9.275, 2.93},
{50, 9.544, 2.78},
{52, 9.805, 2.63},
{54, 10.057, 2.47},
{56, 10.301, 2.32},
{58, 10.537, 2.17},
{60, 10.765, 2.02},
{62, 10.986, 1.86},
{64, 11.199, 1.71},
{66, 11.406, 1.55},
{68, 11.606, 1.38},
{70, 11.800, 1.21},
{72, 11.988, 1.04},
{74, 12.170, 0.86},
{76, 12.347, 0.67},
{78, 12.518, 0.49},
{80, 12.684, 0.29},
{82, 12.845, 0.09},
{84, 13.002, -0.11},
{86, 13.154, -0.32},
{88, 13.302, -0.54},
{90, 13.446, -0.75},
{92, 13.586, -0.97},
{94, 13.723, -1.20},
{96, 13.855, -1.43},
{100, 14.111, -1.88},
{104, 14.354, -2.34},
{108, 14.585, -2.79},
{112, 14.807, -3.22},
{116, 15.018, -3.62},
{120, 15.221, -3.98},
{124, 15.415, -4.30},
{128, 15.602, -4.57},
{132, 15.783, -4.77},
{136, 15.956, -4.91},
{140, 16.124, -4.98},
{144, 16.287, -4.97},
{148, 16.445, -4.90},
{152, 16.598, -4.76},
{156, 16.746, -4.55},
{160, 16.891, -4.29},
{164, 17.032, -3.99},
{168, 17.169, -3.64},
{172, 17.303, -3.26},
{176, 17.434, -2.86},
{180, 17.563, -2.45},
{184, 17.688, -2.04},
{188, 17.811, -1.63},
{192, 17.932, -1.24},
{200, 18.166, -0.51},
{208, 18.392, 0.12},
{216, 18.611, 0.64},
{224, 18.823, 1.06},
{232, 19.028, 1.39},
{240, 19.226, 1.66},
{248, 19.419, 1.88},
{256, 19.606, 2.08},
{264, 19.788, 2.27},
{272, 19.964, 2.46},
{280, 20.135, 2.65},
{288, 20.300, 2.86},
{296, 20.461, 3.09},
{304, 20.616, 3.33},
{312, 20.766, 3.60},
{320, 20.912, 3.89},
{328, 21.052, 4.20},
{336, 21.188, 4.54},
{344, 21.318, 4.91},
{352, 21.445, 5.31},
{360, 21.567, 5.73},
{368, 21.684, 6.18},
{376, 21.797, 6.67},
{384, 21.906, 7.19},
{392, 22.012, 7.74},
{400, 22.113, 8.33},
{408, 22.210, 8.96},
{416, 22.304, 9.63},
{424, 22.395, 10.33},
{432, 22.482, 11.08},
{440, 22.566, 11.87},
{448, 22.646, 12.71},
{456, 22.724, 13.59},
{464, 22.799, 14.53},
{472, 22.871, 15.51},
{480, 22.941, 16.54}},
/* 2th6, 132 entries */
{{1, 0.154, 68.00},
{2, 0.309, 58.23},
{3, 0.463, 42.10},
{4, 0.617, 33.44},
{5, 0.771, 27.97},
{6, 0.925, 24.17},
{7, 1.079, 21.36},
{8, 1.232, 19.20},
{9, 1.385, 17.47},
{10, 1.538, 16.05},
{11, 1.690, 14.87},
{12, 1.842, 13.87},
{13, 1.994, 13.01},
{14, 2.145, 12.26},
{15, 2.295, 11.60},
{16, 2.445, 11.01},
{17, 2.594, 10.49},
{18, 2.742, 10.01},
{19, 2.890, 9.59},
{20, 3.037, 9.20},
{21, 3.184, 8.84},
{22, 3.329, 8.52},
{23, 3.474, 8.22},
{24, 3.618, 7.94},
{25, 3.761, 7.68},
{26, 3.903, 7.44},
{27, 4.045, 7.22},
{28, 4.185, 7.00},
{29, 4.324, 6.81},
{30, 4.463, 6.62},
{31, 4.600, 6.44},
{32, 4.736, 6.28},
{33, 4.872, 6.12},
{34, 5.006, 5.97},
{35, 5.139, 5.83},
{36, 5.272, 5.70},
{37, 5.403, 5.57},
{38, 5.533, 5.44},
{39, 5.661, 5.33},
{40, 5.789, 5.21},
{41, 5.916, 5.10},
{42, 6.041, 5.00},
{43, 6.166, 4.90},
{44, 6.289, 4.80},
{45, 6.411, 4.71},
{46, 6.532, 4.62},
{47, 6.651, 4.53},
{48, 6.770, 4.45},
{50, 7.004, 4.29},
{52, 7.233, 4.14},
{54, 7.457, 4.00},
{56, 7.677, 3.86},
{58, 7.892, 3.73},
{60, 8.103, 3.61},
{62, 8.309, 3.49},
{64, 8.511, 3.37},
{66, 8.708, 3.26},
{68, 8.901, 3.15},
{70, 9.090, 3.04},
{72, 9.275, 2.93},
{74, 9.456, 2.83},
{76, 9.632, 2.73},
{78, 9.805, 2.63},
{80, 9.974, 2.53},
{82, 10.139, 2.42},
{84, 10.301, 2.32},
{86, 10.459, 2.22},
{88, 10.614, 2.12},
{90, 10.765, 2.02},
{92, 10.913, 1.92},
{94, 11.058, 1.81},
{96, 11.199, 1.71},
{100, 11.474, 1.49},
{104, 11.736, 1.27},
{108, 11.988, 1.04},
{112, 12.230, 0.80},
{116, 12.461, 0.55},
{120, 12.684, 0.29},
{124, 12.898, 0.02},
{128, 13.104, -0.25},
{132, 13.302, -0.54},
{136, 13.493, -0.83},
{140, 13.678, -1.12},
{144, 13.855, -1.43},
{148, 14.027, -1.73},
{152, 14.193, -2.04},
{156, 14.354, -2.34},
{160, 14.509, -2.64},
{164, 14.660, -2.93},
{168, 14.807, -3.22},
{172, 14.949, -3.49},
{176, 15.087, -3.74},
{180, 15.221, -3.98},
{184, 15.351, -4.20},
{188, 15.478, -4.40},
{192, 15.602, -4.57},
{200, 15.841, -4.82},
{208, 16.069, -4.96},
{216, 16.287, -4.97},
{224, 16.496, -4.86},
{232, 16.697, -4.63},
{240, 16.891, -4.29},
{248, 17.078, -3.87},
{256, 17.259, -3.39},
{264, 17.434, -2.86},
{272, 17.605, -2.31},
{280, 17.770, -1.77},
{288, 17.932, -1.24},
{296, 18.089, -0.74},
{304, 18.242, -0.29},
{312, 18.392, 0.12},
{320, 18.539, 0.48},
{328, 18.682, 0.79},
{336, 18.823, 1.06},
{344, 18.960, 1.29},
{352, 19.095, 1.49},
{360, 19.226, 1.66},
{368, 19.356, 1.81},
{376, 19.482, 1.95},
{384, 19.606, 2.08},
{392, 19.728, 2.21},
{400, 19.847, 2.33},
{408, 19.964, 2.46},
{416, 20.079, 2.59},
{424, 20.191, 2.72},
{432, 20.300, 2.86},
{440, 20.408, 3.01},
{448, 20.513, 3.17},
{456, 20.616, 3.33},
{464, 20.717, 3.51},
{472, 20.815, 3.69},
{480, 20.912, 3.89}}
};
\ No newline at end of file diff --git a/libtoolame-dab/html/changes.html b/libtoolame-dab/html/changes.html new file mode 100644 index 0000000..544ad7b --- /dev/null +++ b/libtoolame-dab/html/changes.html @@ -0,0 +1,107 @@ +<html> +<head> +<title>tooLAME changes</title> +<style> +<!-- BODY { BACKGROUND: #FFFFFF; COLOR: #000000; FONT-SIZE: 10pt; FONT-FAMILY: verdana, sans-serif } + A { COLOR: #111177; TEXT-DECORATION: none } + TD { font-size: medium; font-weight:normal } +--!> +</STYLE> +</head> +<body> +<table border = 0 width="75%" align="center"><tr><td> +<h1>TooLAME 02l - 2 March 2003</h1> +<UL> +<LI> <b>Major psychoacoustic model overhauls</b> +<UL> + <LI> For more detail, see <a href="psycho.html">psycho models</a> + <LI> <b>Psychoacoustic Model 3</b> + <UL> + <LI> Psycho3 is a reimplementation of the psychoacoustic model 1 from the + ISO standard. Pretty much totally rewritten from the ground up, following the nomenclature of the ISO standard. + <LI> Uses arrays for keeping tone/noise labels rather than the really + hard to grok pointer-stuff from the dist10 code. + <LI> Uses Painter + Spanias' Formula for the ATH rather than the tables from the standard. + <LI> Uses LAME's freq-to-bark conversion to construct the critical bands. + <LI> Future: Needs a proper geometric mean for weighting the noise. Needs one more function added to the decimation routines which would eliminate maskers within 0.5 dB of each other. + <LI> Eliminated all the ISO/dist10 tables. Everything is from equations or built from scratch. + </ul> + <LI> <b>Psychoacoustic Model 4</b> + <UL> + <LI> A reimplementation of psychoacoustic model 2. + <LI> Eliminated all the ISO/dist10 tables. Everything (ath, bark, critical bands) is from equations or built from scratch + <LI> FUTURE: For psycho model 2 and 4 there's some really bad "warbling" and "Davros" type noise. Depending on the loudness of your sound sample, this can get really annoying. I don't know where it's coming from. + </ul> + <LI> <b>Psychoacoustic Model 0</b> + <UL> + <LI> This model uses the ATH and the scalefactors for each subband to build an approximate SMR for each subband at nearly zero cost. + <LI> Based upon an idea mentioned in "Low power mpeg/audio encoders using simplified psychoacoustic model and fast bit allocation" by Hyen-O Oh et al. + <LI> For the amount of effort that this psycho model puts in, the results are pretty good. + <LI> Future: Add some parameters to the equation to allow it to be tweaked on the fly. + </UL> + <LI> <b>Psychoacoustic Model -1</b> + <UL> + <LI> This is the old "fast" psychoacoustic model ("-f"). + <LI> All it does is copy over a static set of pre-calculated SMR values + <LI> Sounds OK for most stuff. + </UL> +</UL> +<LI> <b>New bitstream encoding routines (encode_new.c)</b> +<UL> + <LI> All the old tables.c/alloc_table stuff is now superfluous. + <LI> All tables are now at the top of encode_new.c + <LI> The tables have quite a bit of indirection to get to the value that you need (but really not any more indirection than the old alloc_table stuff). Probably need to add some more docs to say what's going on. + <LI> These new routines are the default, but you can remove the "NEWENCODE" definition and use the old ones (just in case). + <LI> The new routines will become the default in the next release. +</UL> +<LI> <b>More speed</b> +<UL> +<LI> All the trig stuff for psychomodel 4 is now done with tables instead of calculating exact values. +<LI> The <i>exact</i> trig values aren't really used directly in the encoder. They're sort of averaged over a couple of iterations and used as a predictor of uncertainty. So being off a few thousandths won't really affect anything. +</UL> +</UL> +<HL> +<h1>TooLAME 02k - 16 February 2003</h1> +<UL> +<LI> Some great speedups with a combined filtersubband and windowsubband (Ricardo Schelp ricardoschelp at arnet.com.ar) +<LI> Cleaned up the psycho model calling (should be easier to add your own psycho +model if you felt like having a hack) +<LI> DAB Extensions are now of variable length controlled by an argument to the -D switch + (Nicolas Croiset - ncroiset at vdl.fr) +<LI> Fixed raw PCM reading to no longer miss the first 40 bytes. (MFC) +<LI> No longer a 4GB limit when reading from stdin (or if your filesys supports) (Nicolas) +<LI> Tweaks to the end of the bitstream to allow concatentation of mp2 files (Nicolas) +<LI> Finally (?) fixed the segfaults using psy model 1 (Nicolas et al) +</ul> +<HL> +<h1>TooLAME 02j - 12 Feb 2003</h1> +<UL> +<LI>Definitely LGPL now. + +<LI>encode.c - VBR mode has been stabilised to work correctly for all sampling frequencies (<a href="vbr.html">README.VBR</a> has more details) + +<LI>get_audio.c has become audio_read.c - cleaned up that really dodgy wave header parsing. +(thanks to Philippe Jouguet - philippe.jouguet at vdl.fr and Henrik Herranen - leopold at vlsi.fi) + +<LI>spelling fix for 'extension' - Philippe again + +<LI>psycho_I.c - Speedup for "% 1408" calcs "-DSAMI_P1" sami.sallinen at g-cluster.com + (about 4% overall speedup for me) + +<LI>subband.c - Pointer arithmetic for filter subband "-DSAMI_SB" (sami again) + (doesn't give any advantage over gcc3.2 on my system) + +<LI>psycho_II.c +<UL> + <LI> enabled the use of gcc's _sincos(). "-DSINCOS -D_GNU_SOURCE" + about a 5% overall speed-up in encoding (Philippe again) + <LI> added the LSF frequencies so that you can use psy model 2 with LSF (good old Philippe) +</UL> +<LI>verbosity - added a '-t' flag to set the 'talkativity' level needed for transcode plugin (Andreas neukoetter - anti at webhome.de) + +<LI>toolame.c - LSF files should now select a valid default bitrate by default. (96kbps) + +</li> +</tr></td> +</body> +</html> diff --git a/libtoolame-dab/html/default.html b/libtoolame-dab/html/default.html new file mode 100644 index 0000000..b5a7b94 --- /dev/null +++ b/libtoolame-dab/html/default.html @@ -0,0 +1,16 @@ +<html> +<head> +<title>Stuff and Thing</title> +<style> +<!-- BODY { BACKGROUND: #FFFFFF; COLOR: #000000; FONT-SIZE: 10pt; FONT-FAMILY: verdana, sans-serif } + A { COLOR: #111177; TEXT-DECORATION: none } + TD { font-size: medium; font-weight:normal } +--!> +</STYLE> +</head> +<body> +<table border = 0 width="75%" align="center"><tr><td> +Text goes here +</tr></td> +</body> +</html> diff --git a/libtoolame-dab/html/psycho.html b/libtoolame-dab/html/psycho.html new file mode 100644 index 0000000..c02ad53 --- /dev/null +++ b/libtoolame-dab/html/psycho.html @@ -0,0 +1,58 @@ +<html> +<head> +<title>tooLAME Psychoacoustic Models</title> +<style> +<!-- BODY { BACKGROUND: #FFFFFF; COLOR: #000000; FONT-SIZE: 10pt; FONT-FAMILY: verdana, sans-serif } + A { COLOR: #111177; TEXT-DECORATION: none } + TD { font-size: medium; font-weight:normal } +--!> +</STYLE> +</head> +<body> +<table border = 0 width="75%" align="center"><tr><td> +<h1>Psychoacoustic Models in tooLAME</h1> +<h3> Introduction </h3> +In MPEG audio encoding, a psychoacoustic model (PAM) is used to determine which are the sonically important parts of the waveform that is being encoded. The PAM looks for loud sounds which may mask soft sounds, noise which may affect the level of sounds nearby, sounds which are too soft for us to hear and should be ignored and so on. The information from the PAM is used to determine which parts of the spectrum should get more bits and thus be encoded at greater quality - and which parts are inaudible/unimportant and should thus get fewer bits.<p> +In MPEG Audio LayerII encoding, 1152 sound samples are read in - this constitutes a <i>frame</i>. For each frame the PAM outputs just <b>32</b> values (The values are the Signal to Masking Ratio [SMR] in that subband). This is important! There are only 32 values to determine how to alloctate bits for 1152 samples - this is a pretty coarse technique.<p> +The different PAMs listed below use different techniques to decide on these 32 values. Some models are better than others - meaning that the 32 values chosen are pretty good at spreading the bits where they should go. Even with a really bad PAM (e.g. Model -1) you can still get satisfactory results a lot of the time. <P> +All of these models have strengths and weaknesses. The model <i>you</i> end up using will be the one that produces the best sound for your ears, for your audio. <p> + +<h3> Psychoacoustic Model -1 </h3> +This PAM doesn't actually look at the samples being encoded to decide upon the output values. There is simply a set of 32 default values which are used, regardless of input.<p> +<b>Pros</b>: Faaaast. Low complexity.<br> +<b>Cons</b>: Absolutely no attempt to consider any of the masking effects that would help the audio sound better<br> + +<h3> Psychoacoustic Model 0 </h3> +This PAM looks at the sizes of the <i>scalefactors</i> for the audio and combines it with the Absolute Threshold of Hearing (ATH) to make the 32 SMR values.<p> +<b>Pros</b>: Faaast. Low complexity. Sounds better than PAM-1<br> +<b>Cons</b>: This model has absolutely no mathematical basis and does not use any perceptual model of hearing. It simply juggles some of the numbers of the input sound to determine the values.<br> + +<h3> Psychoacoustic Model 1 and 2</h3> +These PAMs are from the ISO standard. Just because they are the standard, doesn't mean that they are any good. Look at <a href="http://lame.sourceforge.net">LAME</a> which basically threw out the MP3 standard psycho models and made their own (GPSYCHO).<p> +<b>Pros</b>: A reference for future PAMs<br> +<b>Cons</b>: Terrible ISO code, buggy tables, poor documentation.<br> + +<h3> Psychoacoustic Model 3</h3> +A re-implementation of psychoacoustic model 1. ISO11172 was used as the guide for re-writing this PAM from the ground up.<p> +<b>Pros</b>: No more obscure tables of values from the ISO code. Hopefully a good base to work upon for tweaking PAMs<br> +<b>Cons</b>: At the moment, doesn't really sound any better than PAM1<br> + +<h3>Psychoacoustic Model 4</h3> +A cleaned up version of PAM2.<p> +<b>Pros</b>: Faster than PAM2. No more obscure tables of values from the ISO standard. Hopefully a good base to work from for improving the PAMs<br> +<b>Cons</b>: Still has the same "warbling"/"Davros" problems as PAM2.<br> + +<h3> Future psychoacoustic models </h3> +There's a heap that could be done. Unfortunately, I've got a set of tin ears, crappy speakers and a noisy computer room. If you've got the capability to do proper PAM testing then please feel free to do so. Otherwise, I'll just keep plodding along with new ideas as they arise, such as: +<UL> +<LI> Temporal masking (there's no pre-echo or anything in tooLAME) +<LI> Left Right Masking +<LI> A PAM that's fully tuneable from the command line? +<LI> Graphical output of SMR values etc. Would allow better debugging of PAMs +<LI> Re-sampling routines +<LI> Low/High pass filtering +</UL> + +</tr></td> +</body> +</html> diff --git a/libtoolame-dab/html/readme.html b/libtoolame-dab/html/readme.html new file mode 100644 index 0000000..c62394a --- /dev/null +++ b/libtoolame-dab/html/readme.html @@ -0,0 +1,236 @@ +<html> +<head> +<title>TooLAME: MPEG 1/2 Layer II Audio Encoder</title> +<style> +<!-- BODY { BACKGROUND: #FFFFFF; COLOR: #000000; FONT-SIZE: 10pt; FONT-FAMILY: verdana, sans-serif } + A { COLOR: #111177; TEXT-DECORATION: none } + TD { font-size: medium; font-weight:normal } +--!> +</STYLE> +</head> +<body> +<table border = 0 width="75%" align="center"><tr><td> + +<h2>tooLAME - an optimized mpeg 1/2 layer 2 audio encoder</h2> +Copyright (C) 2002, 2003 Michael Cheng [mikecheng at NOT planckenergy com] remove the NOT +http://www.planckenergy.com/</p> + +<h2>Contents</h2> +<UL> +<LI> LGPL +<LI> Introduction +<LI> Usage +<LI> Examples +<LI> Contributors +<LI> References +</UL> + +<h2>LGPL</h2> +<pre> +All changes to the ISO source are licensed under the LGPL +(see LGPL.txt for details) + +tooLAME is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +tooLAME is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with tooLAME; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +</pre> + +<h2>Introduction</h2> + +tooLAME is an optimized Mpeg Audio 1/2 Layer 2 encoder. It is based heavily on +<UL> + <LI>the ISO dist10 code + <LI>improvement to algorithms as part of the LAME project (www.sulaco.org/mp3) + <LI>work by myself and other contributors (see CONTRIBUTORS) +</ul> +<h2>Installation</h2> +<OL> +<LI> edit Makefile (at least change the architecture type [ARCH] to suit your machine) +<LI> 'make' +</ol> + +<h2>Usage</h2> + +<pre> + ./toolame [options] [input file] [output file] + +Input File + tooLAME parses AIFF and WAV files for file info + raw PCM is assumed if no header is found + for stdin use a - + +Output File + file is automatically renamed from *.* to *.mp2 + for stdout use a - + +Input Options + -s [int] + if inputting raw PCM sound, you must specify the sample rate + default sample rate is 44.1khz. + + -a + downmix from stereo to mono + if the incoming file is stereo, combine the audio into + a single channel + + -x + force byte-swapping of the input. (current endian detection is dodgy, + so if toolame produces only noise, use -x ) + + -g + swap the LR channels of a stereo file + +Output Options + -m [char] + the encoding mode (default 'j') + 's' stereo + 'd' dual channel + 'j' joint stereo + 'm' mono + + -p [int] + which psy model to use (default '1') + Different models for the psychoacoustics + Models: -1 to 4 + + -b [int] + the total bitrate + For 48/44.1/32kHz default = 192 + For 24/22.05/16kHz default = 96 + + -v [int] + Switch on VBR mode. + The higher the number the better the quality. + Useful range -10 to 10. + See README.VBR for details. + + +Operation + -f + fast mode turns off calculation of the psychoacoustic model. + Instead a set of default values are assumed + + -q [int] + quick mode calculates the psy model every 'num' frames. + +Misc + -d emp + de-emphasis (default 'n') + -c + mark as copyright + -o + mark as original + -e + add error protection + -r + force padding bits off + -D + add DAB extensions + -t [int] + 'talkativity' setting. 0 = no message. 3 = too much information + (-t 20 will probably flood you off your terminal) +</pre> + +<h2>Examples</h2> + +<pre> + toolame sound.wav +</pre> + This will encode sound.wav to sound.mp2 using the default bitrate of 192 kbps + and using the default psychoacoustic model (model 1)</p> + +<pre> + toolame -p 2 -v 5 sound.wav newfile.mp2 +</pre> + Encode sound.wav to newfile.mp2 using psychoacoustic model 2 and encoding + with variable bitrate. The high value of the "-v" argument means that + the encoding will tend to favour higher bitrates.</p> + +<pre> + toolame -p 2 -v -5 sound.wav newfile.mp2 +</pre> + Same as example above, except that the negative value of the "-v" argument + means that the lower bitrates will be favoured over the higher ones.</p> + +<pre> + cat sound.raw | toolame -s 22050 -f -b 96 - newfile.mp2 +</pre> + Toolame is encoding from stdin at a bitrate of 96kbps and is using the + 'fast' mode which means that no psychoacoustic modelling is done. The + input file is raw pcm so the sample rate needs to be specified (22050Hz)</p> + +<h2>Contributors</h2> + +<UL> +<LI>Dist10 code writers +<LI>LAME specific contributions +<UL> + <LI>fht routines from Ron Mayer mayer at acuson.com + <LI>fht tweaking by Mathew Hendry math at vissci.com + <LI>window_subband & filter_subband from LAME circa v3.30 + (multiple LAME authors) + (before Takehiro's window/filter/mdct combination) +</UL> +<LI> Oliver Lietz - lietz at nanocosmos.de - Tables included in the exe + +<LI> Patrick de Smet - pds at telin.rug.ac.be - scale_factor calc speedup. subband_quantization speedup + +<LI> Federico Grau - grauf at rfa.org - and Bill Eldridge - bill at hk.rfa.org - option for "no padding" + +<LI> Nick Burch - gagravarr at SoftHome.net - WAV file reading, os/2 Makefile mods. + +<LI> Phillipe Jouguet - philippe.jouguet at vdldiffusion.com - DAB extensions. spelling, LSF using psyII, WAVE reading [02j] + +<LI> Henrik Herranen - leopold at vlsi.fi - fixed WAVE reading [02j] + +<LI> Andreas Neukoetter - anti at webhome.de - verbosity patch '-t' switch for transcode plugin [02j] + +<LI> Sami Sallinen - sami.sallinen at g-cluster.com - filter_subband loop unroll, psycho_i fix for "% 1408" calcs [02j] + +<LI> Ricardo Schelp - ricardoschelp at arnet.com.ar - merged window/filter subband for a nice speedup [02k] + +<LI> Nicolas Croiset - ncroiset at vdl.fr - DAB length control, ignore 4GB limit when reading from stdin, fixed bitstream ending to allow concatenation of mp2 files, fixes for psycho1 model [02k] + +<LI> Mike Cheng mikecheng at NOT planckenergy.com - Most of the rest + +</UL> + +<h2>References</h2> + +Kumar, M & Zubair, M., A high performance software implementation of mpeg audio +encoder, 1996, ICASSP Conf Proceedings (I think)</p> + +Fischer, K.A., Calculation of the psychoacoustic simultaneous masked threshold +based on MPEG/Audio Encoder Model One, ICSI Technical Report, 1997 +ftp://ftp.icsi.berkeley.edu/pub/real/kyrill/PsychoMpegOne.tar.Z </p> + +Hyen-O et al, New Implementation techniques of a real-time mpeg-2 audio encoding +system. p2287, ICASSP 99.</p> + +Imai, T., et al, MPEG-1 Audio real-time encoding system, IEEE Trans on Consumer +Electronics, v44, n3 1998. p888</p> + +Teh, D., et al, Efficient bit allocation algorithm for ISO/MPEG audio encoder, +Electronics Letters, v34, n8, p721</p> + +Murphy, C & Anandakumar, K, Real-time MPEG-1 audio coding and decoding on a DSP +Chip, IEEE Trans on Consumer Electronics, v43, n1, 1997 p40</p> + +Hans, M & Bhaskaran, V., A compliant MPEG-1 layer II audio decoder with 16-B +arithmetic operations, IEEE Signal Proc Letters v4 n5 1997 p121</p> + +[mikecheng at NOT planckenergy com] remove the NOT</p> + +</tr></td> +</body> +</html> diff --git a/libtoolame-dab/html/vbr.html b/libtoolame-dab/html/vbr.html new file mode 100644 index 0000000..5f7ae38 --- /dev/null +++ b/libtoolame-dab/html/vbr.html @@ -0,0 +1,239 @@ +<html> +<head> +<title>tooLAME: MPEG Audio Layer II VBR</title> +<style> +<!-- BODY { BACKGROUND: #FFFFFF; COLOR: #000000; FONT-SIZE: 10pt; FONT-FAMILY: verdana, sans-serif } + A { COLOR: #111177; TEXT-DECORATION: none } + TD { font-size: medium; font-weight:normal } +--!> +</STYLE> +</head> +<body> + +<table border = 0 width="75%" align="center"><tr><td> +<h1> tooLAME: MPEG Audio Layer II VBR </h1> + +<h2>Contents</h2> +<Ul> +<LI>Introduction +<LI>Usage +<LI>Bitrate Ranges for various Sampling frequencies +<LI>Why can't the bitrate vary from 32kbps to 384kbps for every file? +<UL> + <LI>Short Answer + <LI>Long Answer +</UL> +<LI> Tech Stuff +</UL> + +<h2>Introduction</h2> +VBR mode works by selecting a different bitrate for each frame. Frames +which are harder to encode will be allocated more bits i.e. a higher bitrate.</p> + +LayerII VBR is a complete hack - the ISO standard actually says that decoders are not +required to support it. As a hack, its implementation is a pain to try and understand. +If you're mega-keen to get full range VBR working, either (a) send me money (b) grab the +ISO standard and a C compiler and email me.</p> + +<h2>Usage</h2> +<pre> + toolame -v [level] inputfile outputfile. +</pre> +A level of 5 works very well for me.</p> + +The level value can is a measurement of quality - the higher +the level the higher the average bitrate of the resultant file. +[See TECH STUFF for a better explanation of what the value does]</p> + +The confusing part of my implementation of LayerII VBR is that it's different from MP3 VBR. +<UL> +<LI>The range of bitrates used is controlled by the input sampling frequency. (See below "Bitrate ranges") +<LI>The tendency to use higher bitrates is governed by the <level>. +</ul> + +E.g. Say you have a 44.1kHz Stereo file. In VBR mode, the bitrate can range from 192 to 384 kbps. +Using "-v -5" will force the encoder to favour the lower bitrate. +Using "-v 5" will force the encoder to favour the upper bitrate. +The value can actually be *any* int. -27, 233, 47. The larger the number, the greater +the bitrate bias.</p> + +<h2>Bitrate Ranges</h2> + +When making a VBR stream, the bitrate is only allowed to vary within +set limits</p> + +<pre> +48kHz +Stereo: 112-384kbps Mono: 56-192kbps + +44.1kHz & 32kHz +Stereo: 192-384kbps Mono: 96-192kbps + +24kHz, 22.05kHz & 16kHz +Stereo/Mono: 8-160kbps +</pre> + +<h2>Why doesn't the VBR mode work the same as MP3VBR? The Short Answer</h2> +<b>Why can't the bitrate vary from 32kbps to 384kbps for every file?</b></p> +According to the standard (ISO/IEC 11172-3:1993) Section 2.4.2.3 +<pre> + "In order to provide the smallest possible delay and complexity, the + decoder is not required to support a continuously variable bitrate when + in layer I or II. Layer III supports variable bitrate by switching the + bitrate index." + + and + + "For Layer II, not all combinations of total bitrate and mode are allowed." +</pre> + +Hence, most LayerII coders would not have been written with VBR in mind, and +LayerII VBR is a hack. It works for limited cases. Getting it to work to +the same extent as MP3-style VBR will be a major hack.</p> + +(If you *really* want better bitrate ranges, read "The Long Answer" and submit your mega-patch.)</p> + +<h2>Why doesn't the VBR mode work the same as MP3VBR? The Long Answer</h2> +<b>Why can't the bitrate vary from 32kbps to 384kbps for every file?</b> + +<h3>Reason 1: The standard limits the range</h3> + +As quoted above from the standard for 48/44.1/32kHz: +<pre> + "For Layer II, not all combinations of total bitrate and mode are allowed. See + the following table." + +Bitrate Allowed Modes +(kbps) +32 mono only +48 mono only +56 mono only +64 all modes +80 mono only +96 all modes +112 all modes +128 all modes +160 all modes +192 all modes +224 stereo only +256 stereo only +320 stereo only +384 stereo only +</pre> + +So based upon this table alone, you *could* have VBR stereo encoding which varies +smoothly from 96 to 384kbps. Or you could have have VBR mono encoding which varies from +32 to 192kbps. But since the top and bottom bitrates don't apply to all modes, it would +be impossible to have a stereo file encoded from 32 to 384 kbps.</p> + +But this isn't what is really limiting the allowable bitrate range - the bit allocation +tables are the major hurdle.</p> + +<h3>Reason 2: The bit allocation tables don't allow it</h3> + +From the standard, Section 2.4.3.3.1 "Bit allocation decoding"</p> +<pre> + "For different combinations of bitrate and sampling frequency, different bit + allocation tables exist. +</pre> +These bit allocation tables are pre-determined tables (in Annex B of the standard) which +indicate +<UL> + <LI>how many bits to read for the initial data (2,3 or 4) + <LI>these bits are then used as an index back into the table to + find the number of quantize levels for the samples in this subband +</ul> +But the table used (and hence the number of bits and the calculated index) are different +for different combinations of bitrate and sampling frequency.</p> + +I will use TableB.2a as an example.</p> + +Table B.2a Applies for the following combinations. +<pre> +Sampling Freq Bitrates in (kbps/channel) [emphasis: this is a PER CHANNEL bitrate] +48 56, 64, 80, 96, 112, 128, 160, 192 +44.1 56, 64, 80 +32 56, 64, 80 +</pre> +If we have a STEREO 48kHz input file, and we use this table, then the bitrates +we could calculate from this would be 112, 128, 160, 192, 224, 256, 320 and 384 kbps.</p> + +This table contains no information on how to encode stuff at bitrates less than 112kbps +(for a stereo file). You would have to load allocation table B.2c to encode stereo at +64kbps and 128kbps.</p> + +Since it would be a MAJOR piece of hacking to get the different tables shifted in and out +during the encoding process, once an allocation table is loaded *IT IS NOT CHANGED*.</p> + +Hence, the best table is picked at the start of the encoding process, and the encoder +is stuck with it for the rest of the encode. </p> + +For toolame-02j, I have picked the table it loads for different +sampling frequencies in order to optimize the range of bitrates possible. +<pre> +48 kHz - Table B.2a + Stereo Bitrate Range: 112 - 384 + Mono Bitrate Range : 56 - 192 + +44.1/32 kHz - Table B.2b + Stereo Bitrate Range: 192 - 384 + Mono Bitrate Range: 96 - 192 + +24/22.05/16 kHz - LSF Table (Standard ISO/IEC 13818.3:1995 Annex B, Table B.1) + There is only 1 table for the Lower Sampling Frequencies + All modes (mono and stereo) are allowable at all bitrates + So at the Lower Sampling Frequencies you *can* have a completely variable + bitrate over the entire range. +</pre> +<h2>Tech Stuff</h2> + +The VBR mode is mainly centered around the main_bit_allocation() and +a_bit_allocation() routines in encode.c.</p> + +The limited range of VBR is due to my particular implementation which restricts +ranges to within one alloc table (see tables B.2a, B.2b, B.2c and B.2d in ISO 11172). +The VBR range for 32/44.1khz lies within B.2b, and the 48khz VBR lies within table B.2a.</p> + +I'm not sure whether it is worth extending these ranges down to lower bitrates. +The work required to switch alloc tables *during* the encoding is major.</p> + +In the case of silence, it might be worth doing a quick check for very low signals +and writing a pre-calculated *blank* 32kpbs frame. [probably also a lot of work].</p> + +<h3>How CBR works</h3> +<UL> +<LI> Use the psycho model to determine the MNRs for each subband + [MNR = the ratio of "masking" to "noise"] + (From an encoding perspective, a bigger MNR in a subband means that + it sounds better since the noise is more masked)) +<LI> calculate the available data bits (adb) for this bitrate. +<LI> Based upon the MNR (Masking:Noise Ratio) values, allocate bits to each + subband +<LI> Keep increasing the bits to whichever subband currently has the min MNR + value until we have no bits left. +<LI> This mode does not guarentee that all the subbands are without noise + ie there may still be subbands with MNR less than 0.0 (noisy!) +</ul> + +<h3>How VBR works</h3> +<UL> +<LI> pretend we have lots of bits to spare, and work out the bits which would + raise the MNR in each subband to the level given by the argument on the + command line "-v [int]" +<LI> Pick the bitrate which has more bits than the required_bits we just calculated +<LI> calculate a_bit_allocation() +<LI> VBR "guarantees" that all subbands have MNR > VBRLEVEL or that we have + reached the maximum bitrate. +</ul> + +<h2>FUTURE</h2> +<UL> +<LI> with this VBR mode, we know the bits aren't going to run out, so we can + just assign them "greedily". +<LI> VBR_a_bit_allocation() is yet to be written :) +</ul> + + +</tr></td> +</body> +</html> diff --git a/libtoolame-dab/ieeefloat.c b/libtoolame-dab/ieeefloat.c new file mode 100644 index 0000000..296d805 --- /dev/null +++ b/libtoolame-dab/ieeefloat.c @@ -0,0 +1,93 @@ +/* Copyright (C) 1988-1991 Apple Computer, Inc. + * All Rights Reserved. + * + * Warranty Information + * Even though Apple has reviewed this software, Apple makes no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the warranty information. + * + * Machine-independent I/O routines for IEEE FLOATing-point numbers. + * + * NaN's and infinities are converted to HUGE_VAL or HUGE, which + * happens to be infinity on IEEE machines. Unfortunately, it is + * impossible to preserve NaN's in a machine-independent way. + * Infinities are, however, preserved on IEEE machines. + * + * These routines have been tested on the following machines: + * Apple Macintosh, MPW 3.1 C compiler + * Apple Macintosh, THINK C compiler + * Silicon Graphics IRIS, MIPS compiler + * Cray X/MP and Y/MP + * Digital Equipment VAX + * Sequent Balance (Multiprocesor 386) + * NeXT + * + * + * Implemented by Malcolm Slaney and Ken Turkowski. + * + * Malcolm Slaney contributions during 1988-1990 include big- and little- + * endian file I/O, conversion to and from Motorola's extended 80-bit + * FLOATing-point format, and conversions to and from IEEE single- + * precision FLOATing-point format. + * + * In 1991, Ken Turkowski implemented the conversions to and from + * IEEE double-precision format, added more precision to the extended + * conversions, and accommodated conversions involving +/- infinity, + * NaN's, and denormalized numbers. + * + * $Id: ieeeFLOAT.c,v 1.1 1993/06/11 17:45:46 malcolm Exp $ + * + * $Log: ieeeFLOAT.c,v $ + * Revision 1.1 1993/06/11 17:45:46 malcolm + * Initial revision + * + */ + +#include <stdio.h> +#include <math.h> +#include "ieeefloat.h" +#include "common.h" + +# define FloatToUnsigned(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1)) +# define UnsignedToFloat(u) (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0) + +double ConvertFromIeeeExtended (bytes) + char *bytes; +{ + double f; + long expon; + unsigned long hiMant, loMant; + + expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); + hiMant = ((unsigned long) (bytes[2] & 0xFF) << 24) + | ((unsigned long) (bytes[3] & 0xFF) << 16) | + ((unsigned long) (bytes[4] & 0xFF) << 8) | + ((unsigned long) (bytes[5] & 0xFF)); + loMant = ((unsigned long) (bytes[6] & 0xFF) << 24) + | ((unsigned long) (bytes[7] & 0xFF) << 16) | + ((unsigned long) (bytes[8] & 0xFF) << 8) | + ((unsigned long) (bytes[9] & 0xFF)); + + if (expon == 0 && hiMant == 0 && loMant == 0) { + f = 0; + } else { + if (expon == 0x7FFF) { /* Infinity or NaN */ + f = HUGE_VAL; + } else { + expon -= 16383; + f = ldexp (UnsignedToFloat (hiMant), expon -= 31); + f += ldexp (UnsignedToFloat (loMant), expon -= 32); + } + } + + if (bytes[0] & 0x80) + return -f; + else + return f; +} diff --git a/libtoolame-dab/ieeefloat.h b/libtoolame-dab/ieeefloat.h new file mode 100644 index 0000000..01b1cdd --- /dev/null +++ b/libtoolame-dab/ieeefloat.h @@ -0,0 +1,63 @@ +#ifndef IEEE_FLOAT_H__ +#define IEEE_FLOAT_H__ +/* Copyright (C) 1988-1991 Apple Computer, Inc. + * All Rights Reserved. + * + * Warranty Information + * Even though Apple has reviewed this software, Apple makes no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the warranty information. + * + * Machine-independent I/O routines for IEEE FLOATing-point numbers. + * + * NaN's and infinities are converted to HUGE_VAL or HUGE, which + * happens to be infinity on IEEE machines. Unfortunately, it is + * impossible to preserve NaN's in a machine-independent way. + * Infinities are, however, preserved on IEEE machines. + * + * These routines have been tested on the following machines: + * Apple Macintosh, MPW 3.1 C compiler + * Apple Macintosh, THINK C compiler + * Silicon Graphics IRIS, MIPS compiler + * Cray X/MP and Y/MP + * Digital Equipment VAX + * Sequent Balance (Multiprocesor 386) + * NeXT + * + * + * Implemented by Malcolm Slaney and Ken Turkowski. + * + * Malcolm Slaney contributions during 1988-1990 include big- and little- + * endian file I/O, conversion to and from Motorola's extended 80-bit + * FLOATing-point format, and conversions to and from IEEE single- + * precision FLOATing-point format. + * + * In 1991, Ken Turkowski implemented the conversions to and from + * IEEE double-precision format, added more precision to the extended + * conversions, and accommodated conversions involving +/- infinity, + * NaN's, and denormalized numbers. + * + * $Id: ieeeFLOAT.h,v 1.1 1993/06/11 17:45:46 malcolm Exp $ + * + * $Log: ieeeFLOAT.h,v $ + * Revision 1.1 1993/06/11 17:45:46 malcolm + * Initial revision + * + */ + +#include <math.h> + +typedef float Single; + +#define kFloatLength 4 +#define kDoubleLength 8 +#define kExtendedLength 10 + +double ConvertFromIeeeExtended (char *bytes); +#endif diff --git a/libtoolame-dab/mem.c b/libtoolame-dab/mem.c new file mode 100644 index 0000000..216ec2b --- /dev/null +++ b/libtoolame-dab/mem.c @@ -0,0 +1,44 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "common.h" +#include "mem.h" + +/******************************************************************************* +* +* Allocate number of bytes of memory equal to "block". +* +*******************************************************************************/ + +void *mem_alloc (unsigned long block, char *item) +{ + + void *ptr; + + ptr = (void *) malloc (block); + + if (ptr != NULL) { + memset (ptr, 0, block); + } else { + fprintf (stderr, "Unable to allocate %s\n", item); + exit (0); + } + return (ptr); +} + + +/**************************************************************************** +* +* Free memory pointed to by "*ptr_addr". +* +*****************************************************************************/ + +void mem_free (void **ptr_addr) +{ + + if (*ptr_addr != NULL) { + free (*ptr_addr); + *ptr_addr = NULL; + } + +} diff --git a/libtoolame-dab/mem.h b/libtoolame-dab/mem.h new file mode 100644 index 0000000..dc3fb9c --- /dev/null +++ b/libtoolame-dab/mem.h @@ -0,0 +1,2 @@ +void *mem_alloc (unsigned long, char *); +void mem_free (void **); diff --git a/libtoolame-dab/musicin.h b/libtoolame-dab/musicin.h new file mode 100644 index 0000000..f89f1f8 --- /dev/null +++ b/libtoolame-dab/musicin.h @@ -0,0 +1,55 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: loop.h,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: loop.h,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +#ifndef LOOP_DOT_H +#define LOOP_DOT_H +#include "common.h" + +/********************************************************************** + * date programmers comment * + * 25. 6.92 Toshiyuki Ishino Ver 1.0 * + * 29.10.92 Masahiro Iwadare Ver 2.0 * + * 17. 4.93 Masahiro Iwadare Updated for IS Modification * + * * + *********************************************************************/ + +extern int cont_flag; + +#define e 2.71828182845 + +#define CBLIMIT 21 + +#define SFB_LMAX 22 +#define SFB_SMAX 13 + +extern int pretab[]; + +struct scalefac_struct +{ + int l[23]; + int s[14]; +}; + +extern struct scalefac_struct sfBandIndex[]; /* Table B.8 -- in loop.c */ + +int nint (double in); + +#define maximum(A,B) ( (A) > (B) ? (A) : (B) ) +#define minimum(A,B) ( (A) < (B) ? (A) : (B) ) +#define signum( A ) ( (A) > 0 ? 1 : -1 ) + +/* GLOBALE VARIABLE */ + +extern int bit_buffer[50000]; + +#endif diff --git a/libtoolame-dab/options.h b/libtoolame-dab/options.h new file mode 100644 index 0000000..899a6f1 --- /dev/null +++ b/libtoolame-dab/options.h @@ -0,0 +1,30 @@ +#ifndef OPTIONS_H +#define OPTIONS_H + +#define INPUT_SELECT_JACK 1 +#define INPUT_SELECT_WAV 2 +#define INPUT_SELECT_VLC 3 + +typedef struct +{ + int usepsy; /* TRUE by default, use the psy model */ + int usepadbit; /* TRUE by default, use a padding bit */ + int quickmode; /* FALSE calculate psy model for every frame */ + int quickcount; /* 10 when quickmode = TRUE, calculate psymodel every 10th frame */ + int downmix; /* FALSE downmix from stereo to mono */ + int byteswap; /* FALSE swap the bytes */ + int channelswap; /* FALSE swap the channels */ + int dab; /* FALSE DAB extensions */ + int vbr; /* FALSE switch for VBR mode */ + float vbrlevel; /* 0 level of VBR . higher is better */ + float athlevel; /* 0 extra argument to the ATH equation - + used for VBR in LAME */ + int verbosity; /* 2 by default. 0 is no output at all */ + int input_select; /* 1=use JACK input, 2=use wav input, 3=use VLC input */ + int show_level; /* 1=show the sox-like audio level measurement */ +} +options; + +options glopts; +#endif + diff --git a/libtoolame-dab/pds_subband.c b/libtoolame-dab/pds_subband.c new file mode 100644 index 0000000..04938c4 --- /dev/null +++ b/libtoolame-dab/pds_subband.c @@ -0,0 +1,361 @@ +#include "common.h" +#include "encoder.h" + +void IDCT32 (double *, double *, int); + +/*********************************************************************** + An implementation of a modified window subband as seen in Kumar & Zubair's +"A high performance software implentation of mpeg audio encoder" +I think from IEEE ASCAP 1996 proceedings + +input: shift in 32*12 (384) new samples into a 864 point buffer. +ch - which channel we're looking at. + +This routine basically does 12 calls to window subband all in one go. +Not yet called in code. here for testing only. +************************************************************************/ +#define NEWWS +void window_subband12 (short **buffer, int ch) +{ + static double x[2][864]; /* 2 channels, 864 buffer for each */ + double *xk; + double t[12]; /* a temp buffer for summing values */ + double y[12][64]; /* 12 output arrays of 64 values */ + int i, j, k, m; + static double c[512]; /* enwindow array */ + static int init = 0; + double c0; + + if (!init) { + read_ana_window (c); + printf ("done init\n"); + init++; + } + + xk = x[ch]; /* an easier way of referencing the array */ + + /* shift 384 new samples into the buffer */ + for (i = 863; i >= 384; i--) + xk[i] = xk[i - 384]; + for (i = 383; i >= 0; i--) + xk[i] = (double) *(*buffer)++ / SCALE; + + for (j = 0; j < 64; j++) { + for (k = 0; k < 12; k++) + t[k] = 0; + for (i = 0; i < 8; i++) { + m = i * 64 + j; + c0 = c[m]; + t[0] += c0 * xk[m + 352]; + t[1] += c0 * xk[m + 320]; + t[2] += c0 * xk[m + 288]; + t[3] += c0 * xk[m + 256]; + t[4] += c0 * xk[m + 224]; + t[5] += c0 * xk[m + 192]; + t[6] += c0 * xk[m + 160]; + t[7] += c0 * xk[m + 128]; + t[8] += c0 * xk[m + 96]; + t[9] += c0 * xk[m + 64]; + t[10] += c0 * xk[m + 32]; + t[11] += c0 * xk[m]; + } + for (i = 0; i < 12; i++) { + y[i][j] = t[i]; + } + } +#define DB1x +#ifdef DB1 + for (i = 0; i < 12; i++) { + printf ("--%i--\n", i); + for (j = 0; j < 64; j++) { + printf ("%f\t", y[i][j]); + if ((j + 1) % 4 == 0) + printf ("\n"); + } + } + exit (0); +#endif +} + + +/************************************************************************/ +/* +/* read_ana_window() +/* +/* PURPOSE: Reads encoder window file "enwindow" into array #ana_win# +/* +/************************************************************************/ + +void read_ana_window (ana_win) + double ana_win[HAN_SIZE]; +{ + int i, j[4]; + FILE *fp; + double f[4]; + char t[150]; + + if (!(fp = OpenTableFile ("enwindow"))) { + printf ("Please check analysis window table 'enwindow'\n"); + exit (1); + } + for (i = 0; i < 512; i += 4) { + fgets (t, 150, fp); + sscanf (t, "C[%d] = %lf C[%d] = %lf C[%d] = %lf C[%d] = %lf\n", j, f, + j + 1, f + 1, j + 2, f + 2, j + 3, f + 3); + if (i == j[0]) { + ana_win[i] = f[0]; + ana_win[i + 1] = f[1]; + ana_win[i + 2] = f[2]; + ana_win[i + 3] = f[3]; + } else { + printf ("Check index in analysis window table\n"); + exit (1); + } + fgets (t, 150, fp); + } + fclose (fp); +} + +/************************************************************************/ +/* +/* window_subband() +/* +/* PURPOSE: Overlapping window on PCM samples +/* +/* SEMANTICS: +/* 32 16-bit pcm samples are scaled to fractional 2's complement and +/* concatenated to the end of the window buffer #x#. The updated window +/* buffer #x# is then windowed by the analysis window #c# to produce the +/* windowed sample #z# +/* +/************************************************************************/ +#ifdef COMBWS +void window_subband (short **buffer, double s[SBLIMIT], int k, int sblimit) +{ + typedef double XX[2][HAN_SIZE]; + static XX *x; + double *xk; + int i; + static int off[2] = { 0, 0 }; + static char init = 0; + double t; + static double enwindow[512]; + double *ep0, *ep1, *ep2, *ep3, *ep4, *ep5, *ep6, *ep7; + double z[64]; + double yprime[32]; + if (!init) { + read_ana_window (enwindow); + x = (XX *) mem_alloc (sizeof (XX), "x"); + memset (x, 0, 2 * HAN_SIZE * sizeof (double)); + init = 1; + } + xk = (*x)[k]; + + /* replace 32 oldest samples with 32 new samples */ + for (i = 0; i < 32; i++) + xk[31 - i + off[k]] = (double) *(*buffer)++ / SCALE; + + ep0 = &enwindow[0]; + ep1 = &enwindow[64]; + ep2 = &enwindow[128]; + ep3 = &enwindow[192]; + ep4 = &enwindow[256]; + ep5 = &enwindow[320]; + ep6 = &enwindow[384]; + ep7 = &enwindow[448]; + + /* shift samples into proper window positions */ + for (i = 0; i < 64; i++) { + t = xk[(i + off[k]) & (512 - 1)] * *ep0++; + t += xk[(i + 64 + off[k]) & (512 - 1)] * *ep1++; + t += xk[(i + 128 + off[k]) & (512 - 1)] * *ep2++; + t += xk[(i + 192 + off[k]) & (512 - 1)] * *ep3++; + t += xk[(i + 256 + off[k]) & (512 - 1)] * *ep4++; + t += xk[(i + 320 + off[k]) & (512 - 1)] * *ep5++; + t += xk[(i + 384 + off[k]) & (512 - 1)] * *ep6++; + t += xk[(i + 448 + off[k]) & (512 - 1)] * *ep7++; + z[i] = t; + } + + off[k] += 480; /*offset is modulo (HAN_SIZE-1) */ + off[k] &= HAN_SIZE - 1; + + yprime[0] = z[16]; + for (i = 1; i <= 16; i++) + yprime[i] = z[i + 16] + z[16 - i]; + for (i = 17; i <= 31; i++) + yprime[i] = z[i + 16] - z[80 - i]; + IDCT32 (yprime, s, sblimit); + /* filter_subband (z,s); */ +} +#else +void window_subband (short **buffer, double z[64], int k) +{ + typedef double XX[2][HAN_SIZE]; + static XX *x; + double *xk; + int i; + static int off[2] = { 0, 0 }; + static char init = 0; + double t; + static double enwindow[512]; + double *ep0, *ep1, *ep2, *ep3, *ep4, *ep5, *ep6, *ep7; + if (!init) { + read_ana_window (enwindow); + x = (XX *) mem_alloc (sizeof (XX), "x"); + memset (x, 0, 2 * HAN_SIZE * sizeof (double)); + init = 1; + } + xk = (*x)[k]; + + /* replace 32 oldest samples with 32 new samples */ + /* PDS old code: */ + /* for (i=0;i<32;i++) + xk[31-i+off[k]] = (double) *(*buffer)++/SCALE; + */ + { + register double *xk_t = xk + off[k]; + for (i = 32; i--;) + xk_t[i] = (double) *(*buffer)++; + } + + ep0 = &enwindow[0]; + ep1 = &enwindow[64]; + ep2 = &enwindow[128]; + ep3 = &enwindow[192]; + ep4 = &enwindow[256]; + ep5 = &enwindow[320]; + ep6 = &enwindow[384]; + ep7 = &enwindow[448]; + + /* shift samples into proper window positions */ + for (i = 0; i < 64; i++) { + t = xk[(i + off[k]) & (512 - 1)] * *ep0++; + t += xk[(i + 64 + off[k]) & (512 - 1)] * *ep1++; + t += xk[(i + 128 + off[k]) & (512 - 1)] * *ep2++; + t += xk[(i + 192 + off[k]) & (512 - 1)] * *ep3++; + t += xk[(i + 256 + off[k]) & (512 - 1)] * *ep4++; + t += xk[(i + 320 + off[k]) & (512 - 1)] * *ep5++; + t += xk[(i + 384 + off[k]) & (512 - 1)] * *ep6++; + t += xk[(i + 448 + off[k]) & (512 - 1)] * *ep7++; + z[i] = t; + } + + off[k] += 480; /*offset is modulo (HAN_SIZE-1) */ + off[k] &= HAN_SIZE - 1; + +} +#endif +/************************************************************************/ +/* +/* create_ana_filter() +/* +/* PURPOSE: Calculates the analysis filter bank coefficients +/* +/* SEMANTICS: +/* Calculates the analysis filterbank coefficients and rounds to the +/* 9th decimal place accuracy of the filterbank tables in the ISO +/* document. The coefficients are stored in #filter# +/* +/************************************************************************/ + +void create_ana_filter (filter) + double filter[SBLIMIT][64]; +{ + register int i, k; + + for (i = 0; i < 32; i++) + for (k = 0; k < 64; k++) { + if ((filter[i][k] = + 1e9 * cos ((double) ((2 * i + 1) * (16 - k) * PI64))) >= 0) + modf (filter[i][k] + 0.5, &filter[i][k]); + else + modf (filter[i][k] - 0.5, &filter[i][k]); + filter[i][k] *= 1e-9; + } +} + +/************************************************************************ +* +* filter_subband() +* +* PURPOSE: Calculates the analysis filter bank coefficients +* +* SEMANTICS: +* The windowed samples #z# is filtered by the digital filter matrix #m# +* to produce the subband samples #s#. This done by first selectively +* picking out values from the windowed samples, and then multiplying +* them by the filter matrix, producing 32 subband samples. +* +************************************************************************/ +void create_dct_matrix (filter) + double filter[16][32]; +{ + register int i, k; + + for (i = 0; i < 16; i++) + for (k = 0; k < 32; k++) { + if ((filter[i][k] = 1e9 * cos ((double) ((2 * i + 1) * k * PI64))) >= 0) + modf (filter[i][k] + 0.5, &filter[i][k]); + else + modf (filter[i][k] - 0.5, &filter[i][k]); + filter[i][k] *= 1e-9; + filter[i][k] /= (double) SCALE; /* PDS */ + } + /* PDS this code could/should be replaced; use simple cos */ + /* and don't do additional rounding ??? See LAME(e.g.3.34) */ +} + +void IDCT32 (xin, xout, sblimit) + double *xin, *xout; + int sblimit; +{ + int i, j; + double s0, s1; + typedef double MM[16][32]; + static MM *m = 0; + if (m == 0) { + m = (MM *) mem_alloc (sizeof (MM), "filter"); + create_dct_matrix (*m); + } + /* Only compute subband filter info for frequency ranges which */ + /* will be really needed/encoded later. Code is "general", but */ + /* only produces speed up in low qual/bps coding situations. */ + /* Added/adapted by PDS Oct 1999. */ + for (i = ((sblimit > 16) ? SBLIMIT - sblimit : sblimit); i--;) { + s0 = 0.0; + for (j = 0; j < 32; j++) { + s0 += (*m)[i][j] * xin[j + 0]; + } + xout[i] = s0; + } + for (i = SBLIMIT - sblimit; i < 16; i++) { + s0 = s1 = 0.0; + for (j = 0; j < 32; j += 2) { + s0 += (*m)[i][j] * xin[j]; + s1 += (*m)[i][j + 1] * xin[j + 1]; + } + xout[i] = s0 + s1; + xout[31 - i] = s0 - s1; + } + /* PDS TODO: use pointers instead of arrays ??? */ + /* PDS TODO: is '--' j loop faster then original */ + /* code: ' for( j=0; j<32; j+=2 ) { ... } ' ? */ +} + +void filter_subband (z, s, sblimit) + double z[HAN_SIZE], s[SBLIMIT]; + int sblimit; +{ + double yprime[32]; + int i, j; + + { + yprime[0] = z[16]; + for (i = 1; i <= 16; i++) + yprime[i] = z[i + 16] + z[16 - i]; + for (i = 17; i <= 31; i++) + yprime[i] = z[i + 16] - z[80 - i]; + IDCT32 (yprime, s, sblimit); + } +} diff --git a/libtoolame-dab/portableio.c b/libtoolame-dab/portableio.c new file mode 100644 index 0000000..ed4c067 --- /dev/null +++ b/libtoolame-dab/portableio.c @@ -0,0 +1,110 @@ +/* Copyright (C) 1988-1991 Apple Computer, Inc. + * All Rights Reserved. + * + * Warranty Information + * Even though Apple has reviewed this software, Apple makes no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the warranty information. + * + * + * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc) + * pack bytes from high to low (they are big-endian). + * Use the HighLow routines to match the native format + * of these machines. + * + * Intel-like machines (PCs, Sequent) + * pack bytes from low to high (the are little-endian). + * Use the LowHigh routines to match the native format + * of these machines. + * + * These routines have been tested on the following machines: + * Apple Macintosh, MPW 3.1 C compiler + * Apple Macintosh, THINK C compiler + * Silicon Graphics IRIS, MIPS compiler + * Cray X/MP and Y/MP + * Digital Equipment VAX + * + * + * Implemented by Malcolm Slaney and Ken Turkowski. + * + * Malcolm Slaney contributions during 1988-1990 include big- and little- + * endian file I/O, conversion to and from Motorola's extended 80-bit + * FLOATing-point format, and conversions to and from IEEE single- + * precision FLOATing-point format. + * + * In 1991, Ken Turkowski implemented the conversions to and from + * IEEE double-precision format, added more precision to the extended + * conversions, and accommodated conversions involving +/- infinity, + * NaN's, and denormalized numbers. + * + * $Id: portableio.c,v 2.6 1991/04/30 17:06:02 malcolm Exp $ + * + * $Log: portableio.c,v $ + * Revision 2.6 91/04/30 17:06:02 malcolm + * Apr 2000 + * MFC - hacked out everything we don't need for layer II + */ + +#include <stdio.h> +#include <math.h> +#include "portableio.h" +#include "common.h" + +/**************************************************************** + * Big/little-endian independent I/O routines. + ****************************************************************/ +int Read16BitsHighLow (fp) + FILE *fp; +{ + int first, second, result; + + first = 0xff & getc (fp); + second = 0xff & getc (fp); + + result = (first << 8) + second; +#ifndef THINK_C42 + if (result & 0x8000) + result = result - 0x10000; +#endif /* THINK_C */ + return (result); +} + +double ReadIeeeExtendedHighLow (fp) + FILE *fp; +{ + char bits[kExtendedLength]; + + ReadBytes (fp, bits, kExtendedLength); + return ConvertFromIeeeExtended (bits); +} + +int Read32BitsHighLow (fp) + FILE *fp; +{ + int first, second, result; + + first = 0xffff & Read16BitsHighLow (fp); + second = 0xffff & Read16BitsHighLow (fp); + + result = (first << 16) + second; +#ifdef CRAY + if (result & 0x80000000) + result = result - 0x100000000; +#endif + return (result); +} + +void ReadBytes (fp, p, n) + FILE *fp; + char *p; + int n; +{ + while (!feof (fp) & (n-- > 0)) + *p++ = getc (fp); +} diff --git a/libtoolame-dab/portableio.h b/libtoolame-dab/portableio.h new file mode 100644 index 0000000..70b7d23 --- /dev/null +++ b/libtoolame-dab/portableio.h @@ -0,0 +1,89 @@ +#ifndef PORTABLEIO_H__ +#define PORTABLEIO_H__ +/* Copyright (C) 1988-1991 Apple Computer, Inc. + * All Rights Reserved. + * + * Warranty Information + * Even though Apple has reviewed this software, Apple makes no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the warranty information. + * + * Machine-independent I/O routines for 8-, 16-, 24-, and 32-bit integers. + * + * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc) + * pack bytes from high to low (they are big-endian). + * Use the HighLow routines to match the native format + * of these machines. + * + * Intel-like machines (PCs, Sequent) + * pack bytes from low to high (the are little-endian). + * Use the LowHigh routines to match the native format + * of these machines. + * + * These routines have been tested on the following machines: + * Apple Macintosh, MPW 3.1 C compiler + * Apple Macintosh, THINK C compiler + * Silicon Graphics IRIS, MIPS compiler + * Cray X/MP and Y/MP + * Digital Equipment VAX + * + * + * Implemented by Malcolm Slaney and Ken Turkowski. + * + * Malcolm Slaney contributions during 1988-1990 include big- and little- + * endian file I/O, conversion to and from Motorola's extended 80-bit + * FLOATing-point format, and conversions to and from IEEE single- + * precision FLOATing-point format. + * + * In 1991, Ken Turkowski implemented the conversions to and from + * IEEE double-precision format, added more precision to the extended + * conversions, and accommodated conversions involving +/- infinity, + * NaN's, and denormalized numbers. + * + * $Id: portableio.h,v 2.6 1991/04/30 17:06:02 malcolm Exp $ + * + * $Log: portableio.h,v $ + * Revision 2.6 91/04/30 17:06:02 malcolm + */ + +#include <stdio.h> +#include "ieeefloat.h" + +int ReadByte (FILE * fp); +int Read16BitsLowHigh (FILE * fp); +int Read16BitsHighLow (FILE * fp); +void Write8Bits (FILE * fp, int i); +void Write16BitsLowHigh (FILE * fp, int i); +void Write16BitsHighLow (FILE * fp, int i); +int Read24BitsHighLow (FILE * fp); +int Read32Bits (FILE * fp); +int Read32BitsHighLow (FILE * fp); +void Write32Bits (FILE * fp, int i); +void Write32BitsLowHigh (FILE * fp, int i); +void Write32BitsHighLow (FILE * fp, int i); +void ReadBytes (FILE * fp, char *p, int n); +void ReadBytesSwapped (FILE * fp, char *p, int n); +void WriteBytes (FILE * fp, char *p, int n); +void WriteBytesSwapped (FILE * fp, char *p, int n); +double ReadIeeeFloatHighLow (FILE * fp); +double ReadIeeeFloatLowHigh (FILE * fp); +double ReadIeeeDoubleHighLow (FILE * fp); +double ReadIeeeDoubleLowHigh (FILE * fp); +double ReadIeeeExtendedHighLow (FILE * fp); +double ReadIeeeExtendedLowHigh (FILE * fp); +void WriteIeeeFloatLowHigh (FILE * fp, double num); +void WriteIeeeFloatHighLow (FILE * fp, double num); +void WriteIeeeDoubleLowHigh (FILE * fp, double num); +void WriteIeeeDoubleHighLow (FILE * fp, double num); +void WriteIeeeExtendedLowHigh (FILE * fp, double num); +void WriteIeeeExtendedHighLow (FILE * fp, double num); + +#define Read32BitsLowHigh(f) Read32Bits(f) +#define WriteString(f,s) fwrite(s,strlen(s),sizeof(char),f) +#endif diff --git a/libtoolame-dab/psycho_0.c b/libtoolame-dab/psycho_0.c new file mode 100644 index 0000000..f3c41f1 --- /dev/null +++ b/libtoolame-dab/psycho_0.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <math.h> +#include "common.h" +#include "ath.h" +#include "encoder.h" +#include "psycho_0.h" + +/* MFC Mar 03 + It's almost obscene how well this psycho model works for the amount of + computational effort that's put in. + + I got the idea from: + Hyen-O Oh et al "Low power mpeg audio encoders using simplified psychoacoustic model + and fast bit allocation" + IEEE Trans on Consumer Electronics v47 n3 August 2001. p613 + + All this model does is look at the lowest ATH value within the subband, and then looks + at the scalefactors. It combines the two in a real dodgy way to get the SMRs. + + Although the output values aren't really close to any of the other psycho models, + the spread of values and the relative sizes of the values for the different subbands + is about right + + Feel free to make any sort of generic change you want. Add or subtract numbers, take + logs, whatever. Fiddle with the numbers until we get a good SMR output */ + +void psycho_0(double SMR[2][SBLIMIT], int nch, unsigned int scalar[2][3][SBLIMIT], FLOAT sfreq) { + int ch, sb, gr; + int minscaleindex[2][SBLIMIT]; /* Smaller scale indexes mean bigger scalefactors */ + static FLOAT ath_min[SBLIMIT]; + int i; + static int init=0; + + if (!init) { + FLOAT freqperline = sfreq/1024.0; + for (sb=0;sb<SBLIMIT;sb++) { + ath_min[sb] = 1000; /* set it huge */ + } + + /* Find the minimum ATH in each subband */ + for (i=0;i<512;i++) { + FLOAT thisfreq = i * freqperline; + FLOAT ath_val = ATH_dB(thisfreq, 0); + if (ath_val < ath_min[i>>4]) + ath_min[i>>4] = ath_val; + } + init++; + } + + /* Find the minimum scalefactor index for each ch/sb */ + for (ch=0;ch<nch;ch++) + for (sb=0;sb<SBLIMIT;sb++) + minscaleindex[ch][sb] = scalar[ch][0][sb]; + + for (ch=0;ch<nch;ch++) + for (gr=1;gr<3;gr++) + for (sb=0;sb<SBLIMIT;sb++) + if (minscaleindex[ch][sb] > scalar[ch][gr][sb]) + minscaleindex[ch][sb] = scalar[ch][gr][sb]; + + /* Oh yeah. Fudge the hell out of the SMR calculations + by combining the scalefactor table index and the min ATH in that subband + There are probably more elegant/correct ways of combining these values, + but who cares? It works pretty well + MFC Mar 03 */ + for (ch=0;ch<nch;ch++) + for (sb=0;sb<SBLIMIT;sb++) + SMR[ch][sb] = 2.0 * (30.0 - minscaleindex[ch][sb]) - ath_min[sb]; +} diff --git a/libtoolame-dab/psycho_0.h b/libtoolame-dab/psycho_0.h new file mode 100644 index 0000000..02bc46d --- /dev/null +++ b/libtoolame-dab/psycho_0.h @@ -0,0 +1 @@ +void psycho_0(double SMR[2][SBLIMIT], int nch, unsigned int scalar[2][3][SBLIMIT], FLOAT sfreq); diff --git a/libtoolame-dab/psycho_1.c b/libtoolame-dab/psycho_1.c new file mode 100644 index 0000000..004813c --- /dev/null +++ b/libtoolame-dab/psycho_1.c @@ -0,0 +1,601 @@ +#include <stdio.h> +#include <math.h> +#include "common.h" +#include "encoder.h" +#include "mem.h" +#include "fft.h" +#include "psycho_1.h" +#include "psycho_1_priv.h" + +#define DBTAB 1000 +double dbtable[DBTAB]; + +/********************************************************************** + + This module implements the psychoacoustic model I for the + MPEG encoder layer II. It uses simplified tonal and noise masking + threshold analysis to generate SMR for the encoder bit allocation + routine. + +**********************************************************************/ + +void psycho_1 (short buffer[2][1152], double scale[2][SBLIMIT], + double ltmin[2][SBLIMIT], frame_info * frame) +{ + frame_header *header = frame->header; + int nch = frame->nch; + int sblimit = frame->sblimit; + int k, i, tone = 0, noise = 0; + static char init = 0; + static int off[2] = { 256, 256 }; + double sample[FFT_SIZE]; + double spike[2][SBLIMIT]; + static D1408 *fft_buf; + static mask_ptr power; + static g_ptr ltg; + FLOAT energy[FFT_SIZE]; + + /* call functions for critical boundaries, freq. */ + if (!init) { /* bands, bark values, and mapping */ + fft_buf = (D1408 *) mem_alloc ((long) sizeof (D1408) * 2, "fft_buf"); + power = (mask_ptr) mem_alloc (sizeof (mask) * HAN_SIZE, "power"); + if (header->version == MPEG_AUDIO_ID) { + psycho_1_read_cbound (header->lay, header->sampling_frequency); + psycho_1_read_freq_band (<g, header->lay, header->sampling_frequency); + } else { + psycho_1_read_cbound (header->lay, header->sampling_frequency + 4); + psycho_1_read_freq_band (<g, header->lay, header->sampling_frequency + 4); + } + psycho_1_make_map (power, ltg); + for (i = 0; i < 1408; i++) + fft_buf[0][i] = fft_buf[1][i] = 0; + + psycho_1_init_add_db (); /* create the add_db table */ + + init = 1; + } + for (k = 0; k < nch; k++) { + /* check pcm input for 3 blocks of 384 samples */ + /* sami's speedup, added in 02j + saves about 4% overall during an encode */ + int ok = off[k] % 1408; + for (i = 0; i < 1152; i++) { + fft_buf[k][ok++] = (double) buffer[k][i] / SCALE; + if (ok >= 1408) + ok = 0; + } + ok = (off[k] + 1216) % 1408; + for (i = 0; i < FFT_SIZE; i++) { + sample[i] = fft_buf[k][ok++]; + if (ok >= 1408) + ok = 0; + } + off[k] += 1152; + off[k] %= 1408; + + psycho_1_hann_fft_pickmax (sample, power, &spike[k][0], energy); + psycho_1_tonal_label (power, &tone); + psycho_1_noise_label (power, &noise, ltg, energy); + //psycho_1_dump(power, &tone, &noise) ; + psycho_1_subsampling (power, ltg, &tone, &noise); + psycho_1_threshold (power, ltg, &tone, &noise, + bitrate[header->version][header->bitrate_index] / nch); + psycho_1_minimum_mask (ltg, <min[k][0], sblimit); + psycho_1_smr (<min[k][0], &spike[k][0], &scale[k][0], sblimit); + } + +} + + +int crit_band; +int *cbound; +int sub_size; + +void psycho_1_read_cbound (int lay, int freq) +/* this function reads in critical band boundaries */ +{ + +#include "critband.h" + //static const int FirstCriticalBand[7][27] = {... + + int i, k; + + if ((lay < 1) || (lay > 2)) { + printf ("Internal error (read_cbound())\n"); + return; + } + if ((freq < 0) || (freq > 6) || (freq == 3)) { + printf ("Internal error (read_cbound())\n"); + return; + } + + crit_band = SecondCriticalBand[freq][0]; + cbound = (int *) mem_alloc (sizeof (int) * crit_band, "cbound"); + for (i = 0; i < crit_band; i++) { + k = SecondCriticalBand[freq][i + 1]; + if (k != 0) { + cbound[i] = k; + } else { + printf ("Internal error (read_cbound())\n"); + return; + } + } +} + +void psycho_1_read_freq_band (ltg, lay, freq) /* this function reads in */ + int lay, freq; /* frequency bands and bark */ + g_ptr *ltg; /* values */ +{ + +#include "freqtable.h" + + int i, k; + + if ((freq < 0) || (freq > 6) || (freq == 3)) { + printf ("Internal error (read_freq_band())\n"); + return; + } + + /* read input for freq. subbands */ + + sub_size = SecondFreqEntries[freq] + 1; + *ltg = (g_ptr) mem_alloc (sizeof (g_thres) * sub_size, "ltg"); + (*ltg)[0].line = 0; /* initialize global masking threshold */ + (*ltg)[0].bark = 0.0; + (*ltg)[0].hear = 0.0; + for (i = 1; i < sub_size; i++) { + k = SecondFreqSubband[freq][i - 1].line; + if (k != 0) { + (*ltg)[i].line = k; + (*ltg)[i].bark = SecondFreqSubband[freq][i - 1].bark; + (*ltg)[i].hear = SecondFreqSubband[freq][i - 1].hear; + } else { + printf ("Internal error (read_freq_band())\n"); + return; + } + } +} + + +void psycho_1_make_map (mask power[HAN_SIZE], g_thres * ltg) +/* this function calculates the global masking threshold */ +{ + int i, j; + + for (i = 1; i < sub_size; i++) + for (j = ltg[i - 1].line; j <= ltg[i].line; j++) + power[j].map = i; +} + +void psycho_1_init_add_db (void) +{ + int i; + double x; + for (i = 0; i < DBTAB; i++) { + x = (double) i / 10.0; + dbtable[i] = 10 * log10 (1 + pow (10.0, x / 10.0)) - x; + } +} + +double add_db (double a, double b) +{ + /* MFC - if the difference between a and b is large (>99), then just return the + largest one. (about 10% of the time) + - For differences between 0 and 99, return the largest value, but add + in a pre-calculated difference value. + - the value 99 was chosen arbitarily. + - maximum (a-b) i've seen is 572 */ + FLOAT fdiff; + int idiff; + fdiff = (10.0 * (a - b)); + + if (fdiff > 990.0) { + return a; + } + if (fdiff < -990.0) { + return (b); + } + + idiff = (int) fdiff; + if (idiff >= 0) { + return (a + dbtable[idiff]); + } + + return (b + dbtable[-idiff]); +} + +/**************************************************************** +* Window the samples then, +* Fast Fourier transform of the input samples. +* +* ( call the FHT-based fft() in fft.c ) +* +* +****************************************************************/ +void psycho_1_hann_fft_pickmax (double sample[FFT_SIZE], mask power[HAN_SIZE], + double spike[SBLIMIT], FLOAT energy[FFT_SIZE]) +{ + FLOAT x_real[FFT_SIZE]; + register int i, j; + register double sqrt_8_over_3; + static int init = 0; + static double *window; + double sum; + + if (!init) { /* calculate window function for the Fourier transform */ + window = (double *) mem_alloc (sizeof (DFFT), "window"); + sqrt_8_over_3 = pow (8.0 / 3.0, 0.5); + for (i = 0; i < FFT_SIZE; i++) { + /* Hann window formula */ + window[i] = + sqrt_8_over_3 * 0.5 * (1 - + cos (2.0 * PI * i / (FFT_SIZE))) / FFT_SIZE; + } + init = 1; + } + for (i = 0; i < FFT_SIZE; i++) + x_real[i] = (FLOAT) (sample[i] * window[i]); + + psycho_1_fft (x_real, energy, FFT_SIZE); + + for (i = 0; i < HAN_SIZE; i++) { /* calculate power density spectrum */ + if (energy[i] < 1E-20) + power[i].x = -200.0 + POWERNORM; + else + power[i].x = 10 * log10 (energy[i]) + POWERNORM; + power[i].next = STOP; + power[i].type = FALSE; + } + + /* Calculate the sum of spectral component in each subband from bound 4-16 */ + +#define CF 1073741824 /* pow(10, 0.1*POWERNORM) */ +#define DBM 1E-20 /* pow(10.0, 0.1*DBMIN */ + for (i = 0; i < HAN_SIZE; spike[i >> 4] = 10.0 * log10 (sum), i += 16) { + for (j = 0, sum = DBM; j < 16; j++) + sum += CF * energy[i + j]; + } +} + +/**************************************************************** +* +* This function labels the tonal component in the power +* spectrum. +* +****************************************************************/ + +void psycho_1_tonal_label (mask power[HAN_SIZE], int *tone) +/* this function extracts (tonal) sinusoidals from the spectrum */ +{ + int i, j, last = LAST, first, run, last_but_one = LAST; /* dpwe */ + double max; + + *tone = LAST; + for (i = 2; i < HAN_SIZE - 12; i++) { + if (power[i].x > power[i - 1].x && power[i].x >= power[i + 1].x) { + power[i].type = TONE; + power[i].next = LAST; + if (last != LAST) + power[last].next = i; + else + first = *tone = i; + last = i; + } + } + last = LAST; + first = *tone; + *tone = LAST; + while ((first != LAST) && (first != STOP)) { /* the conditions for the tonal */ + if (first < 3 || first > 500) + run = 0; /* otherwise k+/-j will be out of bounds */ + else if (first < 63) + run = 2; /* components in layer II, which */ + else if (first < 127) + run = 3; /* are the boundaries for calc. */ + else if (first < 255) + run = 6; /* the tonal components */ + else + run = 12; + max = power[first].x - 7; /* after calculation of tonal */ + for (j = 2; j <= run; j++) /* components, set to local max */ + if (max < power[first - j].x || max < power[first + j].x) { + power[first].type = FALSE; + break; + } + if (power[first].type == TONE) { /* extract tonal components */ + int help = first; + if (*tone == LAST) + *tone = first; + while ((power[help].next != LAST) && (power[help].next - first) <= run) + help = power[help].next; + help = power[help].next; + power[first].next = help; + if ((first - last) <= run) { + if (last_but_one != LAST) + power[last_but_one].next = first; + } + if (first > 1 && first < 500) { /* calculate the sum of the */ + double tmp; /* powers of the components */ + tmp = add_db (power[first - 1].x, power[first + 1].x); + power[first].x = add_db (power[first].x, tmp); + } + for (j = 1; j <= run; j++) { + power[first - j].x = power[first + j].x = DBMIN; + power[first - j].next = power[first + j].next = STOP; + power[first - j].type = power[first + j].type = FALSE; + } + last_but_one = last; + last = first; + first = power[first].next; + } else { + int ll; + if (last == LAST); /* *tone = power[first].next; dpwe */ + else + power[last].next = power[first].next; + ll = first; + first = power[first].next; + power[ll].next = STOP; + } + } +} + +/**************************************************************** +* +* This function groups all the remaining non-tonal +* spectral lines into critical band where they are replaced by +* one single line. +* +****************************************************************/ + +void psycho_1_noise_label (mask * power, int *noise, g_thres * ltg, + FLOAT energy[FFT_SIZE]) +{ + int i, j, centre, last = LAST; + double index, weight, sum; + /* calculate the remaining spectral */ + for (i = 0; i < crit_band - 1; i++) { /* lines for non-tonal components */ + for (j = cbound[i], weight = 0.0, sum = DBMIN; j < cbound[i + 1]; j++) { + if (power[j].type != TONE) { + if (power[j].x != DBMIN) { + sum = add_db (power[j].x, sum); + /* Weight is used in finding the geometric mean of the noise energy within a subband */ + weight += CF * energy[j] * (double) (j - cbound[i]) / (double) (cbound[i + 1] - cbound[i]); /* correction */ + power[j].x = DBMIN; + } + } /* check to see if the spectral line is low dB, and if */ + } /* so replace the center of the critical band, which is */ + /* the center freq. of the noise component */ + + if (sum <= DBMIN) + centre = (cbound[i + 1] + cbound[i]) / 2; + else { + /* fprintf(stderr, "%i [%f %f] -", count++,weight/pow(10.0,0.1*sum), weight*pow(10.0,-0.1*sum)); */ + index = weight * pow (10.0, -0.1 * sum); + centre = + cbound[i] + (int) (index * (double) (cbound[i + 1] - cbound[i])); + } + + + /* locate next non-tonal component until finished; */ + /* add to list of non-tonal components */ + + /* Masahiro Iwadare's fix for infinite looping problem? */ + if (power[centre].type == TONE) { + if (power[centre + 1].type == TONE) { + centre++; + } else + centre--; + } + + if (last == LAST) + *noise = centre; + else { + power[centre].next = LAST; + power[last].next = centre; + } + power[centre].x = sum; + power[centre].type = NOISE; + last = centre; + } +} + +/**************************************************************** +* +* This function reduces the number of noise and tonal +* component for further threshold analysis. +* +****************************************************************/ + +void psycho_1_subsampling (mask power[HAN_SIZE], g_thres * ltg, int *tone, int *noise) +{ + int i, old; + + i = *tone; + old = STOP; /* calculate tonal components for */ + + while ((i != LAST) && (i != STOP)) + { /* reduction of spectral lines */ + if (power[i].x < ltg[power[i].map].hear) { + power[i].type = FALSE; + power[i].x = DBMIN; + if (old == STOP) + *tone = power[i].next; + else + power[old].next = power[i].next; + } else + old = i; + i = power[i].next; + } + i = *noise; + old = STOP; /* calculate non-tonal components for */ + while ((i != LAST) && (i != STOP)) { /* reduction of spectral lines */ + if (power[i].x < ltg[power[i].map].hear) { + power[i].type = FALSE; + power[i].x = DBMIN; + if (old == STOP) + *noise = power[i].next; + else + power[old].next = power[i].next; + } else + old = i; + i = power[i].next; + } + i = *tone; + old = STOP; + while ((i != LAST) && (i != STOP)) + { /* if more than one */ + if (power[i].next == LAST) + break; /* tonal component */ + if (ltg[power[power[i].next].map].bark - /* is less than .5 */ + ltg[power[i].map].bark < 0.5) { /* bark, take the */ + if (power[power[i].next].x > power[i].x) { /* maximum */ + if (old == STOP) + *tone = power[i].next; + else + power[old].next = power[i].next; + power[i].type = FALSE; + power[i].x = DBMIN; + i = power[i].next; + } else { + power[power[i].next].type = FALSE; + power[power[i].next].x = DBMIN; + power[i].next = power[power[i].next].next; + old = i; + } + } else { + old = i; + i = power[i].next; + } + } +} + +/**************************************************************** +* +* This function calculates the individual threshold and +* sum with the quiet threshold to find the global threshold. +* +****************************************************************/ + +/* mainly just changed the way range checking was done MFC Nov 1999 */ +void psycho_1_threshold (mask power[HAN_SIZE], g_thres * ltg, int *tone, int *noise, + int bit_rate) +{ + int k, t; + double dz, tmps, vf; + + for (k = 1; k < sub_size; k++) { + ltg[k].x = DBMIN; + t = *tone; /* calculate individual masking threshold for */ + while ((t != LAST) && (t != STOP)) + { /* components in order to find the global */ + dz = ltg[k].bark - ltg[power[t].map].bark; /* distance of bark value */ + if (dz >= -3.0 && dz < 8.0) { + tmps = -1.525 - 0.275 * ltg[power[t].map].bark - 4.5 + power[t].x; + /* masking function for lower & upper slopes */ + if (dz < -1) + vf = 17 * (dz + 1) - (0.4 * power[t].x + 6); + else if (dz < 0) + vf = (0.4 * power[t].x + 6) * dz; + else if (dz < 1) + vf = (-17 * dz); + else + vf = -(dz - 1) * (17 - 0.15 * power[t].x) - 17; + ltg[k].x = add_db (ltg[k].x, tmps + vf); + } + t = power[t].next; + } + + t = *noise; /* calculate individual masking threshold */ + while ((t != LAST) && (t != STOP)) { /* for non-tonal components to find LTG */ + dz = ltg[k].bark - ltg[power[t].map].bark; /* distance of bark value */ + if (dz >= -3.0 && dz < 8.0) { + tmps = -1.525 - 0.175 * ltg[power[t].map].bark - 0.5 + power[t].x; + /* masking function for lower & upper slopes */ + if (dz < -1) + vf = 17 * (dz + 1) - (0.4 * power[t].x + 6); + else if (dz < 0) + vf = (0.4 * power[t].x + 6) * dz; + else if (dz < 1) + vf = (-17 * dz); + else + vf = -(dz - 1) * (17 - 0.15 * power[t].x) - 17; + ltg[k].x = add_db (ltg[k].x, tmps + vf); + } + t = power[t].next; + } + if (bit_rate < 96) + ltg[k].x = add_db (ltg[k].hear, ltg[k].x); + else + ltg[k].x = add_db (ltg[k].hear - 12.0, ltg[k].x); + } + +} + +/**************************************************************** +* +* This function finds the minimum masking threshold and +* return the value to the encoder. +* +****************************************************************/ + +void psycho_1_minimum_mask (g_thres * ltg, double ltmin[SBLIMIT], int sblimit) +{ + double min; + int i, j; + + j = 1; + for (i = 0; i < sblimit; i++) + if (j >= sub_size - 1) /* check subband limit, and */ + ltmin[i] = ltg[sub_size - 1].hear; /* calculate the minimum masking */ + else { /* level of LTMIN for each subband */ + min = ltg[j].x; + while (ltg[j].line >> 4 == i && j < sub_size) { + if (min > ltg[j].x) + min = ltg[j].x; + j++; + } + ltmin[i] = min; + } +} + +/***************************************************************** +* +* This procedure is called in musicin to pick out the +* smaller of the scalefactor or threshold. +* +*****************************************************************/ + +void psycho_1_smr (double ltmin[SBLIMIT], double spike[SBLIMIT], double scale[SBLIMIT], + int sblimit) +{ + int i; + double max; + + for (i = 0; i < sblimit; i++) { /* determine the signal */ + max = 20 * log10 (scale[i] * 32768) - 10; /* level for each subband */ + if (spike[i] > max) + max = spike[i]; /* for the maximum scale */ + max -= ltmin[i]; /* factors */ + ltmin[i] = max; + } +} + +void psycho_1_dump(mask power[HAN_SIZE], int *tone, int *noise) { + int t; + + fprintf(stdout,"1 Ton: "); + t=*tone; + while (t!=LAST && t!=STOP) { + fprintf(stdout,"[%i] %3.0f ",t, power[t].x); + t = power[t].next; + } + fprintf(stdout,"\n"); + + fprintf(stdout,"1 Nos: "); + t=*noise; + while (t!=LAST && t!=STOP) { + fprintf(stdout,"[%i] %3.0f ",t, power[t].x); + t = power[t].next; + } + fprintf(stdout,"\n"); +} diff --git a/libtoolame-dab/psycho_1.h b/libtoolame-dab/psycho_1.h new file mode 100644 index 0000000..c678716 --- /dev/null +++ b/libtoolame-dab/psycho_1.h @@ -0,0 +1,2 @@ + +void psycho_1 (short[2][1152], double[2][SBLIMIT], double[2][SBLIMIT], frame_info *); diff --git a/libtoolame-dab/psycho_1_priv.h b/libtoolame-dab/psycho_1_priv.h new file mode 100644 index 0000000..58b2aa8 --- /dev/null +++ b/libtoolame-dab/psycho_1_priv.h @@ -0,0 +1,22 @@ + + + + + +void psycho_1_read_cbound (int lay, int freq); +void psycho_1_read_freq_band (g_ptr *, int, int); +void psycho_1_init_add_db (void); +double add_db (double a, double b); +void psycho_1_make_map (mask[HAN_SIZE], g_thres *); + +void psycho_1_hann_fft_pickmax (double sample[FFT_SIZE], mask power[HAN_SIZE], double spike[SBLIMIT], FLOAT energy[FFT_SIZE]); +void psycho_1_tonal_label (mask power[HAN_SIZE], int *tone); +void psycho_1_noise_label (mask *power, int *noise, g_thres *, FLOAT[FFT_SIZE]); +void psycho_1_subsampling (mask[HAN_SIZE], g_thres *, int *, int *); +void psycho_1_threshold (mask power[HAN_SIZE], g_thres *, int *, int *, int); +void psycho_1_minimum_mask (g_thres *, double[SBLIMIT], int); +void psycho_1_smr (double[SBLIMIT], double[SBLIMIT], double[SBLIMIT], int); + + + +void psycho_1_dump(mask power[HAN_SIZE], int *tone, int *noise); diff --git a/libtoolame-dab/psycho_2.c b/libtoolame-dab/psycho_2.c new file mode 100644 index 0000000..4d80575 --- /dev/null +++ b/libtoolame-dab/psycho_2.c @@ -0,0 +1,438 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "common.h" +#include "encoder.h" +#include "mem.h" +#include "fft.h" +#include "psycho_2.h" + +/* The static variables "r", "phi_sav", "new", "old" and "oldest" have */ +/* to be remembered for the unpredictability measure. For "r" and */ +/* "phi_sav", the first index from the left is the channel select and */ +/* the second index is the "age" of the data. */ + +static int new = 0, old = 1, oldest = 0; +static int init = 0, flush, sync_flush, syncsize, sfreq_idx; + +/* The following static variables are constants. */ + +static double nmt = 5.5; + +static FLOAT crit_band[27] = { 0, 100, 200, 300, 400, 510, 630, 770, + 920, 1080, 1270, 1480, 1720, 2000, 2320, 2700, + 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, + 15500, 25000, 30000 +}; + +static FLOAT bmax[27] = { 20.0, 20.0, 20.0, 20.0, 20.0, 17.0, 15.0, + 10.0, 7.0, 4.4, 4.5, 4.5, 4.5, 4.5, + 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, + 4.5, 4.5, 4.5, 3.5, 3.5, 3.5 +}; + +static FLOAT *grouped_c, *grouped_e, *nb, *cb, *ecb, *bc; +static FLOAT *wsamp_r, *phi, *energy; +static FLOAT *c, *fthr; +static F32 *snrtmp; + +static int *numlines; +static int *partition; +static FLOAT *cbval, *rnorm; +static FLOAT *window; +static FLOAT *absthr; +static double *tmn; +static FCB *s; +static FHBLK *lthr; +static F2HBLK *r, *phi_sav; + +void psycho_2_init (double sfreq); + +void psycho_2 (short int *buffer, short int savebuf[1056], int chn, + double *smr, double sfreq, options *glopts) +/* to match prototype : FLOAT args are always double */ +{ + unsigned int i, j, k; + FLOAT r_prime, phi_prime; + FLOAT minthres, sum_energy; + double tb, temp1, temp2, temp3; + + if (init == 0) { + psycho_2_init (sfreq); + init++; + } + + for (i = 0; i < 2; i++) { + /***************************************************************************** + * Net offset is 480 samples (1056-576) for layer 2; this is because one must* + * stagger input data by 256 samples to synchronize psychoacoustic model with* + * filter bank outputs, then stagger so that center of 1024 FFT window lines * + * up with center of 576 "new" audio samples. * + + flush = 384*3.0/2.0; = 576 + syncsize = 1056; + sync_flush = syncsize - flush; 480 + BLKSIZE = 1024 + *****************************************************************************/ + + for (j = 0; j < 480; j++) { + savebuf[j] = savebuf[j + flush]; + wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]); + } + for (; j < 1024; j++) { + savebuf[j] = *buffer++; + wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]); + } + for (; j < 1056; j++) + savebuf[j] = *buffer++; + + /**Compute FFT****************************************************************/ + psycho_2_fft (wsamp_r, energy, phi); + /***************************************************************************** + * calculate the unpredictability measure, given energy[f] and phi[f] * + *****************************************************************************/ + /*only update data "age" pointers after you are done with both channels */ + /*for layer 1 computations, for the layer 2 double computations, the pointers */ + /*are reset automatically on the second pass */ + { + if (new == 0) { + new = 1; + oldest = 1; + } else { + new = 0; + oldest = 0; + } + if (old == 0) + old = 1; + else + old = 0; + } + for (j = 0; j < HBLKSIZE; j++) { + r_prime = 2.0 * r[chn][old][j] - r[chn][oldest][j]; + phi_prime = 2.0 * phi_sav[chn][old][j] - phi_sav[chn][oldest][j]; + r[chn][new][j] = sqrt ((double) energy[j]); + phi_sav[chn][new][j] = phi[j]; +#ifdef SINCOS + { + // 12% faster + //#warning "Use __sincos" + double sphi, cphi, sprime, cprime; + __sincos ((double) phi[j], &sphi, &cphi); + __sincos ((double) phi_prime, &sprime, &cprime); + temp1 = r[chn][new][j] * cphi - r_prime * cprime; + temp2 = r[chn][new][j] * sphi - r_prime * sprime; + } +#else + temp1 = + r[chn][new][j] * cos ((double) phi[j]) - + r_prime * cos ((double) phi_prime); + temp2 = + r[chn][new][j] * sin ((double) phi[j]) - + r_prime * sin ((double) phi_prime); +#endif + + temp3 = r[chn][new][j] + fabs ((double) r_prime); + if (temp3 != 0) + c[j] = sqrt (temp1 * temp1 + temp2 * temp2) / temp3; + else + c[j] = 0; + } + /***************************************************************************** + * Calculate the grouped, energy-weighted, unpredictability measure, * + * grouped_c[], and the grouped energy. grouped_e[] * + *****************************************************************************/ + + for (j = 1; j < CBANDS; j++) { + grouped_e[j] = 0; + grouped_c[j] = 0; + } + grouped_e[0] = energy[0]; + grouped_c[0] = energy[0] * c[0]; + for (j = 1; j < HBLKSIZE; j++) { + grouped_e[partition[j]] += energy[j]; + grouped_c[partition[j]] += energy[j] * c[j]; + } + + /***************************************************************************** + * convolve the grouped energy-weighted unpredictability measure * + * and the grouped energy with the spreading function, s[j][k] * + *****************************************************************************/ + for (j = 0; j < CBANDS; j++) { + ecb[j] = 0; + cb[j] = 0; + for (k = 0; k < CBANDS; k++) { + if (s[j][k] != 0.0) { + ecb[j] += s[j][k] * grouped_e[k]; + cb[j] += s[j][k] * grouped_c[k]; + } + } + if (ecb[j] != 0) + cb[j] = cb[j] / ecb[j]; + else + cb[j] = 0; + } + + /***************************************************************************** + * Calculate the required SNR for each of the frequency partitions * + * this whole section can be accomplished by a table lookup * + *****************************************************************************/ + for (j = 0; j < CBANDS; j++) { + if (cb[j] < .05) + cb[j] = 0.05; + else if (cb[j] > .5) + cb[j] = 0.5; + tb = -0.434294482 * log ((double) cb[j]) - 0.301029996; + cb[j] = tb; + bc[j] = tmn[j] * tb + nmt * (1.0 - tb); + k = cbval[j] + 0.5; + bc[j] = (bc[j] > bmax[k]) ? bc[j] : bmax[k]; + bc[j] = exp ((double) -bc[j] * LN_TO_LOG10); + } + + /***************************************************************************** + * Calculate the permissible noise energy level in each of the frequency * + * partitions. Include absolute threshold and pre-echo controls * + * this whole section can be accomplished by a table lookup * + *****************************************************************************/ + for (j = 0; j < CBANDS; j++) + if (rnorm[j] && numlines[j]) + nb[j] = ecb[j] * bc[j] / (rnorm[j] * numlines[j]); + else + nb[j] = 0; + for (j = 0; j < HBLKSIZE; j++) { + /*temp1 is the preliminary threshold */ + temp1 = nb[partition[j]]; + temp1 = (temp1 > absthr[j]) ? temp1 : absthr[j]; +#ifdef LAYERI + /*do not use pre-echo control for layer 2 because it may do bad things to the */ + /* MUSICAM bit allocation algorithm */ + if (lay == 1) { + fthr[j] = (temp1 < lthr[chn][j]) ? temp1 : lthr[chn][j]; + temp2 = temp1 * 0.00316; + fthr[j] = (temp2 > fthr[j]) ? temp2 : fthr[j]; + } else + fthr[j] = temp1; + lthr[chn][j] = LXMIN * temp1; +#else + fthr[j] = temp1; + lthr[chn][j] = LXMIN * temp1; +#endif + } + + /***************************************************************************** + * Translate the 512 threshold values to the 32 filter bands of the coder * + *****************************************************************************/ + for (j = 0; j < 193; j += 16) { + minthres = 60802371420160.0; + sum_energy = 0.0; + for (k = 0; k < 17; k++) { + if (minthres > fthr[j + k]) + minthres = fthr[j + k]; + sum_energy += energy[j + k]; + } + snrtmp[i][j / 16] = sum_energy / (minthres * 17.0); + snrtmp[i][j / 16] = 4.342944819 * log ((double) snrtmp[i][j / 16]); + } + for (j = 208; j < (HBLKSIZE - 1); j += 16) { + minthres = 0.0; + sum_energy = 0.0; + for (k = 0; k < 17; k++) { + minthres += fthr[j + k]; + sum_energy += energy[j + k]; + } + snrtmp[i][j / 16] = sum_energy / minthres; + snrtmp[i][j / 16] = 4.342944819 * log ((double) snrtmp[i][j / 16]); + } + /***************************************************************************** + * End of Psychoacuostic calculation loop * + *****************************************************************************/ + } + for (i = 0; i < 32; i++) { + smr[i] = (snrtmp[0][i] > snrtmp[1][i]) ? snrtmp[0][i] : snrtmp[1][i]; + } +} + +/******************************** + * init psycho model 2 + ********************************/ +void psycho_2_init (double sfreq) +{ + int i, j; + FLOAT freq_mult; + double temp1, temp2, temp3; + FLOAT bval_lo; + + grouped_c = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_c"); + grouped_e = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_e"); + nb = (FLOAT *) mem_alloc (sizeof (FCB), "nb"); + cb = (FLOAT *) mem_alloc (sizeof (FCB), "cb"); + ecb = (FLOAT *) mem_alloc (sizeof (FCB), "ecb"); + bc = (FLOAT *) mem_alloc (sizeof (FCB), "bc"); + wsamp_r = (FLOAT *) mem_alloc (sizeof (FBLK), "wsamp_r"); + phi = (FLOAT *) mem_alloc (sizeof (FBLK), "phi"); + energy = (FLOAT *) mem_alloc (sizeof (FBLK), "energy"); + c = (FLOAT *) mem_alloc (sizeof (FHBLK), "c"); + fthr = (FLOAT *) mem_alloc (sizeof (FHBLK), "fthr"); + snrtmp = (F32 *) mem_alloc (sizeof (F2_32), "snrtmp"); + + numlines = (int *) mem_alloc (sizeof (ICB), "numlines"); + partition = (int *) mem_alloc (sizeof (IHBLK), "partition"); + cbval = (FLOAT *) mem_alloc (sizeof (FCB), "cbval"); + rnorm = (FLOAT *) mem_alloc (sizeof (FCB), "rnorm"); + window = (FLOAT *) mem_alloc (sizeof (FBLK), "window"); + absthr = (FLOAT *) mem_alloc (sizeof (FHBLK), "absthr"); + tmn = (double *) mem_alloc (sizeof (DCB), "tmn"); + s = (FCB *) mem_alloc (sizeof (FCBCB), "s"); + lthr = (FHBLK *) mem_alloc (sizeof (F2HBLK), "lthr"); + r = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "r"); + phi_sav = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "phi_sav"); + + i = sfreq + 0.5; + switch (i) { + case 32000: + case 16000: + sfreq_idx = 0; + break; + case 44100: + case 22050: + sfreq_idx = 1; + break; + case 48000: + case 24000: + sfreq_idx = 2; + break; + default: + fprintf (stderr, "error, invalid sampling frequency: %d Hz\n", i); + exit (-1); + } + fprintf (stderr, "absthr[][] sampling frequency index: %d\n", sfreq_idx); + psycho_2_read_absthr (absthr, sfreq_idx); + + flush = 384 * 3.0 / 2.0; + syncsize = 1056; + sync_flush = syncsize - flush; + + /* calculate HANN window coefficients */ + /* for(i=0;i<BLKSIZE;i++)window[i]=0.5*(1-cos(2.0*PI*i/(BLKSIZE-1.0))); */ + for (i = 0; i < BLKSIZE; i++) + window[i] = 0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE)); + /* reset states used in unpredictability measure */ + for (i = 0; i < HBLKSIZE; i++) { + r[0][0][i] = r[1][0][i] = r[0][1][i] = r[1][1][i] = 0; + phi_sav[0][0][i] = phi_sav[1][0][i] = 0; + phi_sav[0][1][i] = phi_sav[1][1][i] = 0; + lthr[0][i] = 60802371420160.0; + lthr[1][i] = 60802371420160.0; + } + /***************************************************************************** + * Initialization: Compute the following constants for use later * + * partition[HBLKSIZE] = the partition number associated with each * + * frequency line * + * cbval[CBANDS] = the center (average) bark value of each * + * partition * + * numlines[CBANDS] = the number of frequency lines in each partition * + * tmn[CBANDS] = tone masking noise * + *****************************************************************************/ + /* compute fft frequency multiplicand */ + freq_mult = sfreq / BLKSIZE; + + /* calculate fft frequency, then bval of each line (use fthr[] as tmp storage) */ + for (i = 0; i < HBLKSIZE; i++) { + temp1 = i * freq_mult; + j = 1; + while (temp1 > crit_band[j]) + j++; + fthr[i] = + j - 1 + (temp1 - crit_band[j - 1]) / (crit_band[j] - crit_band[j - 1]); + } + partition[0] = 0; + /* temp2 is the counter of the number of frequency lines in each partition */ + temp2 = 1; + cbval[0] = fthr[0]; + bval_lo = fthr[0]; + for (i = 1; i < HBLKSIZE; i++) { + if ((fthr[i] - bval_lo) > 0.33) { + partition[i] = partition[i - 1] + 1; + cbval[partition[i - 1]] = cbval[partition[i - 1]] / temp2; + cbval[partition[i]] = fthr[i]; + bval_lo = fthr[i]; + numlines[partition[i - 1]] = temp2; + temp2 = 1; + } else { + partition[i] = partition[i - 1]; + cbval[partition[i]] += fthr[i]; + temp2++; + } + } + numlines[partition[i - 1]] = temp2; + cbval[partition[i - 1]] = cbval[partition[i - 1]] / temp2; + + /************************************************************************ + * Now compute the spreading function, s[j][i], the value of the spread-* + * ing function, centered at band j, for band i, store for later use * + ************************************************************************/ + for (j = 0; j < CBANDS; j++) { + for (i = 0; i < CBANDS; i++) { + temp1 = (cbval[i] - cbval[j]) * 1.05; + if (temp1 >= 0.5 && temp1 <= 2.5) { + temp2 = temp1 - 0.5; + temp2 = 8.0 * (temp2 * temp2 - 2.0 * temp2); + } else + temp2 = 0; + temp1 += 0.474; + temp3 = + 15.811389 + 7.5 * temp1 - + 17.5 * sqrt ((double) (1.0 + temp1 * temp1)); + if (temp3 <= -100) + s[i][j] = 0; + else { + temp3 = (temp2 + temp3) * LN_TO_LOG10; + s[i][j] = exp (temp3); + } + } + } + + /* Calculate Tone Masking Noise values */ + for (j = 0; j < CBANDS; j++) { + temp1 = 15.5 + cbval[j]; + tmn[j] = (temp1 > 24.5) ? temp1 : 24.5; + /* Calculate normalization factors for the net spreading functions */ + rnorm[j] = 0; + for (i = 0; i < CBANDS; i++) { + rnorm[j] += s[j][i]; + } + } + + if (glopts.verbosity > 10){ + /* Dump All the Values to STDOUT and exit */ + int wlow, whigh=0; + fprintf(stdout,"psy model 2 init\n"); + fprintf(stdout,"index \tnlines \twlow \twhigh \tbval \tminval \ttmn\n"); + for (i=0;i<CBANDS;i++) { + wlow = whigh+1; + whigh = wlow + numlines[i] - 1; + fprintf(stdout,"%i \t%i \t%i \t%i \t%5.2f \t%4.2f \t%4.2f\n",i+1, numlines[i],wlow, whigh, cbval[i],bmax[(int)(cbval[i]+0.5)],tmn[i]); + } + exit(0); + } + +} + +void psycho_2_read_absthr (absthr, table) + FLOAT *absthr; + int table; +{ + int j; +#include "absthr.h" + + if ((table < 0) || (table > 3)) { + printf ("internal error: wrong table number"); + return; + } + + for (j = 0; j < HBLKSIZE; j++) { + absthr[j] = absthr_table[table][j]; + } + return; +} diff --git a/libtoolame-dab/psycho_2.h b/libtoolame-dab/psycho_2.h new file mode 100644 index 0000000..6ee0a48 --- /dev/null +++ b/libtoolame-dab/psycho_2.h @@ -0,0 +1,2 @@ +void psycho_2_read_absthr (FLOAT *, int); +void psycho_2 (short int *, short int[1056], int, double *snr32, double sfreq, options *glopts); diff --git a/libtoolame-dab/psycho_3.c b/libtoolame-dab/psycho_3.c new file mode 100644 index 0000000..3dbd462 --- /dev/null +++ b/libtoolame-dab/psycho_3.c @@ -0,0 +1,539 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "common.h" +#include "options.h" +#include "encoder.h" +#include "mem.h" +#include "fft.h" +#include "ath.h" +#define OLDTHRESHx +#include "psycho_3.h" +#include "psycho_3priv.h" + +/* This is a reimplementation of psy model 1 using the ISO11172 standard. + I found the original dist10 code (which is full of pointers) to be + a horrible thing to try and understand and debug. + This implementation is not built for speed, but is rather meant to + clearly outline the steps specified by the standard (still, it's only + a tiny fraction slower than the dist10 code, and nothing has been optimized) + MFC Feb 2003 */ + +/* Keep a table to fudge the adding of dB */ +#define DBTAB 1000 +static double dbtable[DBTAB]; + +#define CRITBANDMAX 32 /* this is much higher than it needs to be. really only about 24 */ +int cbands=0; /* How many critical bands there really are */ +int cbandindex[CRITBANDMAX]; /* The spectral line index of the start of + each critical band */ + +#define SUBSIZE 136 +int freq_subset[SUBSIZE]; +FLOAT bark[HBLKSIZE], ath[HBLKSIZE]; + +int *numlines; +FLOAT *cbval; +int partition[HBLKSIZE]; +static D1408 *fft_buf; + +frame_header *header; + + +double psycho_3_add_db (double a, double b) +{ + /* MFC - if the difference between a and b is large (>99), then just return the + largest one. (about 10% of the time) + - For differences between 0 and 99, return the largest value, but add + in a pre-calculated difference value. + - the value 99 was chosen arbitarily. + - maximum (a-b) i've seen is 572 */ + FLOAT fdiff; + int idiff; + fdiff = (10.0 * (a - b)); + + if (fdiff > 990.0) { + return a; + } + if (fdiff < -990.0) { + return (b); + } + + idiff = (int) fdiff; + if (idiff >= 0) { + return (a + dbtable[idiff]); + } + + return (b + dbtable[-idiff]); +} + +void psycho_3 (short buffer[2][1152], double scale[2][SBLIMIT], + double ltmin[2][SBLIMIT], frame_info * frame, options *glopts) +{ + int nch = frame->nch; + int sblimit = frame->sblimit; + int k, i; + static char init = 0; + static int off[2] = { 256, 256 }; + FLOAT sample[BLKSIZE]; + + FLOAT energy[BLKSIZE]; + FLOAT power[HBLKSIZE]; + FLOAT Xtm[HBLKSIZE], Xnm[HBLKSIZE]; + int tonelabel[HBLKSIZE], noiselabel[HBLKSIZE]; + FLOAT LTg[HBLKSIZE]; + double Lsb[SBLIMIT]; + + header = frame->header; + + if (init==0) { + psycho_3_init(glopts); + init++; + } + + + for (k = 0; k < nch; k++) { + int ok = off[k] % 1408; + for (i = 0; i < 1152; i++) { + fft_buf[k][ok++] = (FLOAT) buffer[k][i] / SCALE; + if (ok >= 1408) + ok = 0; + } + ok = (off[k] + 1216) % 1408; + for (i = 0; i < BLKSIZE; i++) { + sample[i] = fft_buf[k][ok++]; + if (ok >= 1408) + ok = 0; + } + + off[k] += 1152; + off[k] %= 1408; + + psycho_3_fft(sample, energy); + psycho_3_powerdensityspectrum(energy, power); + psycho_3_spl(Lsb, power, &scale[k][0]); + psycho_3_tonal_label (power, tonelabel, Xtm); + psycho_3_noise_label (power, energy, tonelabel, noiselabel, Xnm); + if (glopts->verbosity > 20) + psycho_3_dump(tonelabel, Xtm, noiselabel, Xnm); + psycho_3_decimation(ath, tonelabel, Xtm, noiselabel, Xnm, bark); + psycho_3_threshold(LTg, tonelabel, Xtm, noiselabel, Xnm, bark, ath, bitrate[header->version][header->bitrate_index] / nch, freq_subset); + psycho_3_minimummasking(LTg, <min[k][0], freq_subset); + psycho_3_smr(<min[k][0], Lsb); + } +} + +/* ISO11172 Sec D.1 Step 1 - Window with HANN and then perform the FFT */ +void psycho_3_fft(FLOAT sample[BLKSIZE], FLOAT energy[BLKSIZE]) +{ + FLOAT x_real[BLKSIZE]; + int i; + static int init = 0; + static FLOAT *window; + + if (!init) { /* calculate window function for the Fourier transform */ + window = (FLOAT *) mem_alloc (sizeof (DFFT), "window"); + register FLOAT sqrt_8_over_3 = pow (8.0 / 3.0, 0.5); + for (i = 0; i < BLKSIZE; i++) { + window[i] = sqrt_8_over_3 * 0.5 * (1 - cos (2.0 * PI * i / (BLKSIZE))) / BLKSIZE; + } + init++; + } + + /* convolve the samples with the hann window */ + for (i = 0; i < BLKSIZE; i++) + x_real[i] = (FLOAT) (sample[i] * window[i]); + /* do the FFT */ + psycho_1_fft (x_real, energy, BLKSIZE); +} + +/* Sect D.1 Step 1 - convert the energies into dB */ +void psycho_3_powerdensityspectrum(FLOAT energy[BLKSIZE], FLOAT power[HBLKSIZE]) { + int i; + for (i=1;i<HBLKSIZE;i++) { + if (energy[i] < 1E-20) + power[i] = -200.0 + POWERNORM; + else + power[i] = 10 * log10 (energy[i]) + POWERNORM; + } +} + +/* Sect D.1 Step 2 - Determine the sound pressure level in each subband */ +void psycho_3_spl(double *Lsb, FLOAT *power, double *scale) { + int i; + FLOAT Xmax[SBLIMIT]; + + for (i=0;i<SBLIMIT;i++) { + Xmax[i] = DBMIN; + } + /* Find the maximum SPL in the power spectrum */ + for (i=1;i<HBLKSIZE;i++) { + int index = i>>4; + if (Xmax[index] < power[i]) + Xmax[index] = power[i]; + } + + /* Compare it to the sound pressure based upon the scale for this subband + and pick the maximum one */ + for (i=0;i<SBLIMIT;i++) { + double val = 20 * log10 (scale[i] * 32768) - 10; + Lsb[i] = MAX(Xmax[i], val); + } +} + +/* Sect D.1 Step 4 Label the Tonal Components */ +void psycho_3_tonal_label (FLOAT power[HBLKSIZE], int *tonelabel, FLOAT Xtm[HBLKSIZE]) +{ + int i; + int maxima[HBLKSIZE]; + + /* Find the maxima as per ISO11172 D.1.4.a */ + maxima[0]=maxima[HBLKSIZE-1]=0; + tonelabel[0]=tonelabel[HBLKSIZE-1]=0; + Xtm[0] = Xtm[HBLKSIZE-1] = DBMIN; + for (i=1;i<HBLKSIZE-1;i++) { + tonelabel[i] = 0; + Xtm[i] = DBMIN; + if (power[i]>power[i-1] && power[i]>power[i+1]) /* The first criteria for a maximum */ + maxima[i]=1; + else + maxima[i]=0; + } + + { + /* Now find the tones as per ISO11172 D.1 Step4.b */ + /* The standard is a bit vague (surprise surprise). + So I'm going to assume that + - a tone must be 7dB greater than *all* the relevant neighbours + - once a tone is found, the neighbours are immediately set to -inf dB + */ + + psycho_3_tonal_label_range(power, tonelabel, maxima, Xtm, 2, 63, 2); + psycho_3_tonal_label_range(power, tonelabel, maxima, Xtm, 63,127,3); + psycho_3_tonal_label_range(power, tonelabel, maxima, Xtm, 127,255,6); + psycho_3_tonal_label_range(power, tonelabel, maxima, Xtm, 255,500,12); + + } +} + +/* Sect D.1 Step4b + A tone within the range (start -> end), must be 7.0 dB greater than + all it's neighbours within +/- srange. Don't count its immediate neighbours. */ +void psycho_3_tonal_label_range(FLOAT *power, int *tonelabel, int *maxima, FLOAT *Xtm, int start, int end, int srange) { + int j,k; + + for (k=start;k<end;k++) /* Search for all the maxima in this range */ + if (maxima[k] == 1) { + tonelabel[k] = TONE; /* assume it's a TONE and then prove otherwise */ + for (j=-srange;j<=+srange;j++) /* Check the neighbours within +/- srange */ + if (abs(j) > 1) /* Don't count the immediate neighbours, or itself */ + if ((power[k] - power[k+j]) < 7.0) + tonelabel[k] = 0; /* Not greater by 7dB, therefore not a tone */ + if (tonelabel[k] == TONE) { + /* Calculate the sound pressure level for this tone by summing + the adjacent spectral lines + Xtm[k] = 10 * log10( pow(10.0, 0.1*power[k-1]) + pow(10.0, 0.1*power[k]) + + pow(10.0, 0.1*power[k+1]) ); */ + double temp = psycho_3_add_db(power[k-1], power[k]); + Xtm[k] = psycho_3_add_db(temp, power[k+1]); + + /* *ALL* spectral lines within +/- srange are set to -inf dB + So that when we do the noise calculate, they are not counted */ + for (j=-srange;j<=+srange;j++) + power[k+j] = DBMIN; + } + } +} + +void psycho_3_init_add_db (void) +{ + int i; + double x; + for (i = 0; i < DBTAB; i++) { + x = (double) i / 10.0; + dbtable[i] = 10 * log10 (1 + pow (10.0, x / 10.0)) - x; + } +} + +/* D.1 Step 4.c Labelling non-tonal (noise) components + Sum the energies in each critical band (the tone energies have been removed + during the tone labelling). + Find the "geometric mean" of these energies - i.e. find the best spot to put the + sum of energies within this critical band. */ +void psycho_3_noise_label (FLOAT power[HBLKSIZE], FLOAT energy[BLKSIZE], int *tonelabel, int *noiselabel, FLOAT Xnm[HBLKSIZE]) { + int i,j; + + Xnm[0] = DBMIN; + for (i=0;i<cbands;i++) { + /* for each critical band */ + double sum = DBMIN; + double esum=0; + double centreweight = 0; + int centre; + for (j=cbandindex[i]; j<cbandindex[i+1]; j++) { + Xnm[j] = DBMIN; + /* go through all the spectral lines within the critical band, + adding the energies. The tone energies have already been removed */ + if (power[j] != DBMIN) { + /* Found a noise energy, add it to the sum */ + sum = psycho_3_add_db(power[j], sum); + + /* calculations for the geometric mean + FIXME MFC Feb 2003: Would it just be easier to + do the *whole* of psycho_1 in the energy domain rather than + in the dB domain? + FIXME: This is just a lazy arsed arithmetic mean. Don't know + if it's really going to make that much difference */ + esum += energy[j]; /* Calculate the sum of energies */ + centreweight += (j - cbandindex[i]) * energy[j]; /* And the energy moment */ + } + } + + if (sum<=DBMIN) + /* If the energy sum is really small, just pretend the noise occurs + in the centre frequency line */ + centre = (cbandindex[i] + cbandindex[i+1])/2; + else + /* Otherwise, work out the mean position of the noise, and put it there. */ + centre = cbandindex[i] + (int)(centreweight/esum); + + Xnm[centre] = sum; + noiselabel[centre] = NOISE; + } +} + +/* ISO11172 D.1 Step 5 + Get rid of noise/tones that aren't greater than the ATH + If two tones are within 0.5bark, then delete the tone with the lower energy */ +void psycho_3_decimation(FLOAT *ath, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark) { + int i; + + /* Delete components which aren't above the ATH */ + for (i=1;i<HBLKSIZE;i++) { + if (noiselabel[i]==NOISE) { + if (Xnm[i] < ath[i]) { + /* this masker isn't above the ATH : delete it */ + Xnm[i] = DBMIN; + noiselabel[i]=0; + } + } + if (tonelabel[i] == TONE) { + if (Xtm[i] < ath[i]) { + Xtm[i] = DBMIN; + tonelabel[i]=0; + } + } + } + /* Search for tones that are within 0.5 bark */ + /* MFC FIXME Feb 2003: haven't done this yet */ + +} + +/* ISO11172 Sect D.1 Step 6 + Calculation of individual masking thresholds + Work out how each of the tones&noises maskes other frequencies + NOTE: Only a subset of other frequencies is checked. According to the + standard different subbands are subsampled to different amounts. + See psycho_3_init and freq_subset */ +void psycho_3_threshold(FLOAT *LTg, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark, FLOAT *ath, int bit_rate, int *freq_subset) { + int i,j,k; + FLOAT LTtm[SUBSIZE]; + FLOAT LTnm[SUBSIZE]; + + for (i=0;i<SUBSIZE;i++) { + LTtm[i] = DBMIN; + LTnm[i] = DBMIN; + } + /* Loop over the entire spectrum and find every noise and tone + And then with each noise/tone work out how it masks + the spectral lines around it */ + for (k=1;k<HBLKSIZE;k++) { + /* Find every tone */ + if (tonelabel[k]==TONE) { + for (j=0;j<SUBSIZE;j++) { + /* figure out how it masks the levels around it */ + FLOAT dz = bark[freq_subset[j]] - bark[k]; + if (dz >= -3.0 && dz < 8.0) { + FLOAT vf; + FLOAT av = -1.525 - 0.275 * bark[k] - 4.5 + Xtm[k]; + /* masking function for lower & upper slopes */ + if (dz < -1) + vf = 17 * (dz + 1) - (0.4 * Xtm[k] + 6); + else if (dz < 0) + vf = (0.4 * Xtm[k] + 6) * dz; + else if (dz < 1) + vf = (-17 * dz); + else + vf = -(dz - 1) * (17 - 0.15 * Xtm[k]) - 17; + LTtm[j] = psycho_3_add_db (LTtm[j], av + vf); + } + } + } + + /* find every noise label */ + if (noiselabel[k]==NOISE) { + for (j=0;j<SUBSIZE;j++) { + /* figure out how it masks the levels around it */ + FLOAT dz = bark[freq_subset[j]] - bark[k]; + if (dz >= -3.0 && dz < 8.0) { + FLOAT vf; + FLOAT av = -1.525 - 0.175 * bark[k] - 0.5 + Xnm[k]; + /* masking function for lower & upper slopes */ + if (dz < -1) + vf = 17 * (dz + 1) - (0.4 * Xnm[k] + 6); + else if (dz < 0) + vf = (0.4 * Xnm[k] + 6) * dz; + else if (dz < 1) + vf = (-17 * dz); + else + vf = -(dz - 1) * (17 - 0.15 * Xnm[k]) - 17; + LTnm[j] = psycho_3_add_db (LTnm[j], av + vf); + } + } + } + } + + /* ISO11172 D.1 Step 7 + Calculate the global masking threhold */ + for (i=0;i<SUBSIZE;i++) { + LTg[i] = psycho_3_add_db(LTnm[i], LTtm[i]); + if (bit_rate < 96) + LTg[i] = psycho_3_add_db(ath[freq_subset[i]], LTg[i]); + else + LTg[i] = psycho_3_add_db(ath[freq_subset[i]]-12.0, LTg[i]); + } +} + + /* Find the minimum LTg for each subband. ISO11172 Sec D.1 Step 8 */ +void psycho_3_minimummasking(FLOAT *LTg, double *LTmin, int *freq_subset) { + int i; + + for (i=0;i<SBLIMIT;i++) + LTmin[i] = 999999.9; + + for (i=0;i<SUBSIZE;i++) { + int index = freq_subset[i]>>4; + if (LTmin[index] > LTg[i]) { + LTmin[index] = LTg[i]; + } + } +} + +/* ISO11172 Sect D.1 Step 9 + Calculate the signal-to-mask ratio + MFC FIXME Feb 2003 for better calling from + toolame, add a "float SMR[]" array and return it */ +void psycho_3_smr(double *LTmin, double *Lsb) { + int i; + for (i=0;i<SBLIMIT;i++) { + LTmin[i] = Lsb[i] - LTmin[i]; + } +} + +void psycho_3_init(options *glopts) { + int i; + int cbase = 0; /* current base index for the bark range calculation */ + + fft_buf = (D1408 *) mem_alloc ((long) sizeof (D1408) * 2, "fft_buf"); + + /* Initialise the tables for the adding dB */ + psycho_3_init_add_db(); + + /* For each spectral line calculate the bark and the ATH (in dB) */ + FLOAT sfreq = (FLOAT) s_freq[header->version][header->sampling_frequency] * 1000; + for (i=1;i<HBLKSIZE; i++) { + FLOAT freq = i * sfreq/BLKSIZE; + bark[i] = freq2bark(freq); + ath[i] = ATH_dB(freq,glopts->athlevel); + } + + { /* Work out the critical bands + Starting from line 0, all lines within 1 bark of the starting + bark are added to the same critical band. When a line is greater + by 1.0 of a bark, start a new critical band. */ + + numlines = (int *)calloc(HBLKSIZE, sizeof(int)); + cbval = (float *)calloc(HBLKSIZE, sizeof(float)); + cbandindex[0] = 1; + for (i=1;i<HBLKSIZE;i++) { + if ((bark[i] - bark[cbase]) > 1.0) { /* 1 critical band? 1 bark? */ + /* this frequency line is too different from the starting line, + (in terms of the bark distance) + so make this spectral line the first member of the next critical band */ + cbase = i; /* Start the new critical band from this frequency line */ + cbands++; + cbandindex[cbands] = cbase; + } + /* partition[i] tells us which critical band the i'th frequency line is in */ + partition[i] = cbands; + /* keep a count of how many frequency lines are in each partition */ + numlines[cbands]++; + } + + cbands++; + cbandindex[cbands] = 513; /* Set the top of the last critical band */ + + /* For each crtical band calculate the average bark value + cbval [central bark value] */ + for (i=1;i<HBLKSIZE;i++) + cbval[partition[i]] += bark[i]; /* sum up all the bark values */ + for (i=1;i<CBANDS;i++) { + if (numlines[i] != 0) + cbval[i] /= numlines[i]; /* divide by the number of values */ + else { + cbval[i]=0; /* this isn't a partition */ + } + } + } + + { + /* For Step6 - For the calculation of individual masking thresholds + the spectral lines are subsampled + i.e. no need to work out the masking for every single spectral line. + Depending upon which subband the calculation is for, you + can skip a number of lines + There are 16 lines per subband -> 32 * 16 = 512 + Subband 0-2 : Every line (3 * 16 = 48 lines) + Subband 3-5 : Every Second line (3 * 16/2 = 24 lines) + Subband 6-11 : Every 4th line (6 * 16/4 = 24 lines) + Subband 12-31 : Every 12th line (20 * 16/8 = 40 lines) + + create this subset of frequencies (freq_subset) */ + int freq_index=0; + for (i=1;i<(3*16)+1;i++) + freq_subset[freq_index++] = i; + for (;i<(6*16)+1;i+=2) + freq_subset[freq_index++] = i; + for (;i<(12*16)+1;i+=4) + freq_subset[freq_index++] = i; + for (;i<(32*16)+1;i+=8) + freq_subset[freq_index++] = i; + } + + if (glopts->verbosity > 4) { + fprintf(stdout,"%i critical bands\n",cbands); + for (i=0;i<cbands;i++) + fprintf(stdout,"cband %i spectral line index %i\n",i,cbandindex[i]); + fprintf(stdout,"%i Subsampled spectral lines\n",SUBSIZE); + for (i=0;i<SUBSIZE;i++) + fprintf(stdout,"%i Spectral line %i Bark %.2f\n",i,freq_subset[i], bark[freq_subset[i]]); + } +} + +void psycho_3_dump(int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm) { + int i; + fprintf(stdout,"3 Ton:"); + for (i=1;i<HAN_SIZE;i++) { + if (tonelabel[i] == TONE) + fprintf(stdout,"[%i] %3.0f ",i,Xtm[i]); + } + fprintf(stdout,"\n"); + + fprintf(stdout,"3 Nos:"); + for (i=1;i<HAN_SIZE;i++) { + if (noiselabel[i] == NOISE) + fprintf(stdout,"[%i] %3.0f ",i,Xnm[i]); + } + fprintf(stdout,"\n"); +} diff --git a/libtoolame-dab/psycho_3.h b/libtoolame-dab/psycho_3.h new file mode 100644 index 0000000..8953c08 --- /dev/null +++ b/libtoolame-dab/psycho_3.h @@ -0,0 +1,4 @@ +void psycho_3 (short[2][1152], double[2][SBLIMIT], + double[2][SBLIMIT], frame_info *, options *glopts); + +void psycho_3_init(options *glopts); diff --git a/libtoolame-dab/psycho_3priv.h b/libtoolame-dab/psycho_3priv.h new file mode 100644 index 0000000..d4fc01c --- /dev/null +++ b/libtoolame-dab/psycho_3priv.h @@ -0,0 +1,28 @@ +void psycho_3_fft(FLOAT *sample, FLOAT *energy); +void psycho_3_powerdensityspectrum(FLOAT *energy, FLOAT *power); + +void psycho_3_tonal_label (FLOAT *power, int *tonelabel, FLOAT *Xtm); +void psycho_3_tonal_label_range(FLOAT *power, int *type, int *maxima, FLOAT *Xtm, int start, int end, int srange) ; + + +void psycho_3_init_add_db (void); +double psycho_3_add_db (double a, double b); + +void psycho_3_noise_label (FLOAT *power, FLOAT *energy, int *tonelabel, int *noiselabel, FLOAT *Xnm); +void psycho_3_decimation(FLOAT *ath, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark); + +void psycho_3_threshold(FLOAT *LTg, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark, FLOAT *ath, int bit_rate, int *freq_subset); + +void psycho_3_minimummasking(FLOAT *LTg, double *LTmin, int *freq_subset); + +void psycho_3_spl(double *Lsb, FLOAT *power, double *scale); + +void psycho_3_smr(double *LTmin, double *Lsb); + +#ifdef OLDTHRESH +void psycho_3_threshold_old(FLOAT *LTg, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark, FLOAT *ath, int bit_rate); +void psycho_3_minimummasking_old(FLOAT *LTg, double *LTmin); +#endif + +void psycho_3_dump(int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm); +void psycho_3_threshold_new(FLOAT *LTg, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark, FLOAT *ath, int bit_rate, int *freq_subset); diff --git a/libtoolame-dab/psycho_4.c b/libtoolame-dab/psycho_4.c new file mode 100644 index 0000000..b2abc76 --- /dev/null +++ b/libtoolame-dab/psycho_4.c @@ -0,0 +1,507 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "common.h" +#include "options.h" +#include "encoder.h" +#include "mem.h" +#include "fft.h" +#include "ath.h" +#include "psycho_4.h" + +/**************************************************************** +PSYCHO_4 by MFC Feb 2003 + +This is a cleaned up implementation of psy model 2. +This is basically because I was sick of the inconsistencies between +the notation in the ISO docs and in the sourcecode. + +I've nicked a bunch of stuff from LAME to make this a bit easier to grok +- ATH values (this also overcomes the lack of mpeg-2 tables + which meant that LSF never had proper values) +- freq2bark() to convert frequencies directly to bark values. +- spreading_function() isolated the calculation of the spreading function. + Basically the same code as before, just isolated in its own function. + LAME seem to does some extra tweaks to the ISO1117s model. + Not really sure if they help or hinder, so I've commented them out (#ifdef LAME) + +NB: Because of some of the tweaks to bark value calculation etc, it is now possible +to have 64 CBANDS. There's no real limit on the actual number of paritions. +I wonder if it's worth experimenting with really higher numbers? Probably won't make +that much difference to the final SNR values, but it's something worth trying + Maybe CBANDS should be a dynamic value, calculated by the psycho_init function + CBANDS definition has been changed in encoder.h from 63 to 64 + +****************************************************************/ + + +/* The static variables "r", "phi_sav", "new", "old" and "oldest" have + to be remembered for the unpredictability measure. For "r" and + "phi_sav", the first index from the left is the channel select and + the second index is the "age" of the data. */ + +static int new = 0, old = 1, oldest = 0; +static int init = 0; + +/* NMT is a constant 5.5dB. ISO11172 Sec D.2.4.h */ +static double NMT = 5.5; + +/* The index into this array is a bark value + This array gives the 'minval' values from ISO11172 Tables D.3.x */ +static FLOAT minval[27] = { + 0.0, /* bark = 0 */ + 20.0, /* 1 */ + 20.0, /* 2 */ + 20.0, /* 3 */ + 20.0, /* 4 */ + 20.0, /* 5 */ + 17.0, /* 6 */ + 15.0, /* 7 */ + 10.0, /* 8 */ + 7.0, /* 9 */ + 4.4, /* 10 */ + 4.5, 4.5, 4.5,4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, /* 11 - 25 */ + 3.5 /* 26 */ +}; + + +static FLOAT *grouped_c, *grouped_e, *nb, *cb, *tb, *ecb, *bc; +static FLOAT *wsamp_r, *phi, *energy; +static FLOAT *c, *bark, *thr; +static F32 *snrtmp; + +static int *numlines; +static int *partition; +static FLOAT *cbval, *rnorm; +static FLOAT *window; +static FLOAT *ath; +static double *tmn; +static FCB *s; +static FHBLK *lthr; +static F2HBLK *r, *phi_sav; + +#define TRIGTABLESIZE 3142 +#define TRIGTABLESCALE 1000.0 +static FLOAT cos_table[TRIGTABLESIZE]; +static FLOAT sin_table[TRIGTABLESIZE]; +void psycho_4_trigtable_init(void) { + + int i; + for (i=0;i<TRIGTABLESIZE;i++) { + cos_table[i] = cos((double)i/TRIGTABLESCALE); + sin_table[i] = sin((double)i/TRIGTABLESCALE); + } +} + +FLOAT psycho_4_cos(FLOAT phi) { + int index; + int sign=1; + + index = (int)(fabs(phi) * TRIGTABLESCALE); + while (index>=TRIGTABLESIZE) { + index -= TRIGTABLESIZE; + sign*=-1; + } + return(sign * cos_table[index]); +} + +FLOAT psycho_4_sin(FLOAT phi) { + int index; + int sign=1; + + index = (int)(fabs(phi) * TRIGTABLESCALE); + while (index>=TRIGTABLESIZE) { + index -= TRIGTABLESIZE; + sign*=-1; + } + if (phi<0) + return(-1 * sign * sin_table[index]); + return(sign * sin_table[index]); +} + + +void psycho_4 (short int *buffer, short int savebuf[1056], int chn, + double *smr, double sfreq, options *glopts) +/* to match prototype : FLOAT args are always double */ +{ + unsigned int run, i, j, k; + FLOAT r_prime, phi_prime; + FLOAT npart, epart; + + if (init == 0) { + psycho_4_init (sfreq, glopts); + init++; + } + + for (run = 0; run < 2; run++) { + /* Net offset is 480 samples (1056-576) for layer 2; this is because one must + stagger input data by 256 samples to synchronize psychoacoustic model with + filter bank outputs, then stagger so that center of 1024 FFT window lines + up with center of 576 "new" audio samples. + + flush = 384*3.0/2.0; = 576 + syncsize = 1056; + sync_flush = syncsize - flush; 480 + BLKSIZE = 1024 */ + for (j = 0; j < 480; j++) { + savebuf[j] = savebuf[j + 576]; + wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]); + } + for (; j < 1024; j++) { + savebuf[j] = *buffer++; + wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]); + } + for (; j < 1056; j++) + savebuf[j] = *buffer++; + + + /* Compute FFT */ + psycho_2_fft (wsamp_r, energy, phi); + + /* calculate the unpredictability measure, given energy[f] and phi[f] + (the age pointers [new/old/oldest] are reset automatically on the second pass */ + { + if (new == 0) { + new = 1; + oldest = 1; + } else { + new = 0; + oldest = 0; + } + if (old == 0) + old = 1; + else + old = 0; + } + + for (j = 0; j < HBLKSIZE; j++) { +#ifdef NEWATAN + double temp1, temp2, temp3; + r_prime = 2.0 * r[chn][old][j] - r[chn][oldest][j]; + phi_prime = 2.0 * phi_sav[chn][old][j] - phi_sav[chn][oldest][j]; + + r[chn][new][j] = sqrt ((double) energy[j]); + phi_sav[chn][new][j] = phi[j]; + + { + temp1 = + r[chn][new][j] * psycho_4_cos(phi[j]) - + r_prime * psycho_4_cos(phi_prime); + temp2 = + r[chn][new][j] * psycho_4_sin(phi[j]) - + r_prime * psycho_4_sin(phi_prime); + //fprintf(stdout,"[%5.2f %5.2f] [%5.2f %5.2f]\n",temp1, mytemp1, temp2, mytemp2); + + } + + + temp3 = r[chn][new][j] + fabs ((double) r_prime); + if (temp3 != 0) + c[j] = sqrt (temp1 * temp1 + temp2 * temp2) / temp3; + else + c[j] = 0; +#else + double temp1, temp2, temp3; + r_prime = 2.0 * r[chn][old][j] - r[chn][oldest][j]; + phi_prime = 2.0 * phi_sav[chn][old][j] - phi_sav[chn][oldest][j]; + + r[chn][new][j] = sqrt ((double) energy[j]); + phi_sav[chn][new][j] = phi[j]; + + + temp1 = + r[chn][new][j] * cos ((double) phi[j]) - + r_prime * cos ((double) phi_prime); + temp2 = + r[chn][new][j] * sin ((double) phi[j]) - + r_prime * sin ((double) phi_prime); + + temp3 = r[chn][new][j] + fabs ((double) r_prime); + if (temp3 != 0) + c[j] = sqrt (temp1 * temp1 + temp2 * temp2) / temp3; + else + c[j] = 0; +#endif + } + + /* For each partition, sum all the energy in that partition - grouped_e + and calculated the energy-weighted unpredictability measure - grouped_c + ISO 11172 Section D.2.4.e */ + for (j = 1; j < CBANDS; j++) { + grouped_e[j] = 0; + grouped_c[j] = 0; + } + grouped_e[0] = energy[0]; + grouped_c[0] = energy[0] * c[0]; + for (j = 1; j < HBLKSIZE; j++) { + grouped_e[partition[j]] += energy[j]; + grouped_c[partition[j]] += energy[j] * c[j]; + } + + /* convolve the grouped energy-weighted unpredictability measure + and the grouped energy with the spreading function + ISO 11172 D.2.4.f */ + for (j = 0; j < CBANDS; j++) { + ecb[j] = 0; + cb[j] = 0; + for (k = 0; k < CBANDS; k++) { + if (s[j][k] != 0.0) { + ecb[j] += s[j][k] * grouped_e[k]; + cb[j] += s[j][k] * grouped_c[k]; + } + } + if (ecb[j] != 0) + cb[j] = cb[j] / ecb[j]; + else + cb[j] = 0; + } + + /* Convert cb to tb (the tonality index) + ISO11172 SecD.2.4.g */ + for (i=0;i<CBANDS;i++) { + if (cb[i] < 0.05) + cb[i] = 0.05; + else if (cb[i] > 0.5) + cb[i] = 0.5; + tb[i] = -0.301029996 - 0.434294482 * log((double) cb[i]); + } + + + /* Calculate the required SNR for each of the frequency partitions + ISO 11172 Sect D.2.4.h */ + for (j = 0; j < CBANDS; j++) { + FLOAT SNR, SNRtemp; + SNRtemp = tmn[j] * tb[j] + NMT * (1.0 - tb[j]); + SNR = MAX(SNRtemp, minval[(int)cbval[j]]); + bc[j] = exp ((double) -SNR * LN_TO_LOG10); + } + + /* Calculate the permissible noise energy level in each of the frequency + partitions. + This section used to have pre-echo control but only for LayerI + ISO 11172 Sec D.2.4.k - Spread the threshold energy over FFT lines */ + for (j = 0; j < CBANDS; j++) { + if (rnorm[j] && numlines[j]) + nb[j] = ecb[j] * bc[j] / (rnorm[j] * numlines[j]); + else + nb[j] = 0; + } + + /* ISO11172 Sec D.2.4.l - thr[] the final energy threshold of audibility */ + for (j = 0; j < HBLKSIZE; j++) + thr[j] = MAX(nb[partition[j]], ath[j]); + + /* Translate the 512 threshold values to the 32 filter bands of the coder + Using ISO 11172 Table D.5 and Section D.2.4.n */ + for (j = 0; j < 193; j += 16) { + /* WIDTH = 0 */ + npart = 60802371420160.0; + epart = 0.0; + for (k = 0; k < 17; k++) { + if (thr[j + k] < npart) + npart = thr[j + k]; /* For WIDTH==0, find the minimum noise, and + later multiply by the number of indexes i.e. 17 */ + epart += energy[j + k]; + } + snrtmp[run][j / 16] = 4.342944819 * log((double)(epart/(npart*17.0))); + } + for (j = 208; j < (HBLKSIZE - 1); j += 16) { + /* WIDTH = 1 */ + npart = 0.0; + epart = 0.0; + for (k = 0; k < 17; k++) { + npart += thr[j + k]; /* For WIDTH==1, sum the noise */ + epart += energy[j + k]; + } + snrtmp[run][j / 16] = 4.342944819 * log ((double) (epart/npart)); + } + } + + /* Pick the maximum value of the two runs ISO 11172 Sect D.2.1 */ + for (i = 0; i < 32; i++) + smr[i] = MAX(snrtmp[0][i], snrtmp[1][i]); + +} + +/******************************** + * init psycho model 2 + ********************************/ +void psycho_4_init (double sfreq, options *glopts) +{ + int i, j; + + /* Allocate memory for all the static variables */ + psycho_4_allocmem(); + + /* Set up the SIN/COS tables */ + psycho_4_trigtable_init(); + + /* calculate HANN window coefficients */ + for (i = 0; i < BLKSIZE; i++) + window[i] = 0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE)); + + /* For each FFT line from 0(DC) to 512(Nyquist) calculate + - bark : the bark value of this fft line + - ath : the absolute threshold of hearing for this line [ATH] + + Since it is a 1024 point FFT, each line in the fft corresponds + to 1/1024 of the total frequency. + Line 0 should correspond to DC - which doesn't really have a ATH afaik + Line 1 should be 1/1024th of the Sampling Freq + Line 512 should be the nyquist freq */ + for (i=0; i<HBLKSIZE; i++) { + FLOAT freq = i * sfreq/BLKSIZE; + bark[i] = freq2bark(freq); + /* The ath tables in the dist10 code seem to be a little out of kilter. + they seem to start with index 0 corresponding to (sampling freq)/1024. + When in doubt, i'm going to assume that the dist10 code is wrong. MFC Feb2003 */ + ath[i] = ATH_energy(freq,glopts->athlevel); + //fprintf(stdout,"%.2f ",ath[i]); + } + + + /* Work out the partitions + Starting from line 0, all lines within 0.33 of the starting + bark are added to the same partition. When a line is greater + by 0.33 of a bark, start a new partition. */ + int partition_count = 0; /* keep a count of the partitions */ + int cbase = 0; /* current base index for the bark range calculation */ + for (i=0;i<HBLKSIZE;i++) { + if ((bark[i] - bark[cbase]) > 0.33) { /* 1/3 critical band? */ + /* this frequency line is too different from the starting line, + (in terms of the bark distance) + so close that previous partition, and make this line the first + member of the next partition */ + cbase = i; /* Start the new partition from this frequency */ + partition_count++; + } + /* partition[i] tells us which partition the i'th frequency line is in */ + partition[i] = partition_count; + /* keep a count of how many frequency lines are in each partition */ + numlines[partition_count]++; + } + + /* For each partition within the frequency space, + calculate the average bark value - cbval [central bark value] */ + for (i=0;i<HBLKSIZE;i++) + cbval[partition[i]] += bark[i]; /* sum up all the bark values */ + for (i=0;i<CBANDS;i++) { + if (numlines[i] != 0) + cbval[i] /= numlines[i]; /* divide by the number of values */ + else { + cbval[i]=0; /* this isn't a partition */ + } + } + + + /* Calculate the spreading function. ISO 11172 Section D.2.3 */ + for (i=0;i<CBANDS;i++) { + for (j=0;j<CBANDS;j++) { + s[i][j] = psycho_4_spreading_function( 1.05 * (cbval[i] - cbval[j]) ); + rnorm[i] += s[i][j]; /* sum the spreading function values for each partition so that + they can be normalised later on */ + } + } + + /* Calculate Tone Masking Noise values. ISO 11172 Tables D.3.x */ + for (j = 0; j < CBANDS; j++) + tmn[j] = MAX(15.5+cbval[j], 24.5); + + + if (glopts->verbosity > 10) { + /* Dump All the Values to STDOUT */ + int wlow, whigh=0; + int ntot=0; + fprintf(stdout,"psy model 4 init\n"); + fprintf(stdout,"index \tnlines \twlow \twhigh \tbval \tminval \ttmn\n"); + for (i=0;i<CBANDS;i++) + if (numlines[i] != 0) { + wlow = whigh+1; + whigh = wlow + numlines[i] - 1; + fprintf(stdout,"%i \t%i \t%i \t%i \t%5.2f \t%4.2f \t%4.2f\n",i+1, numlines[i],wlow, whigh, cbval[i],minval[(int)cbval[i]],tmn[i]); + ntot += numlines[i]; + } + fprintf(stdout,"total lines %i\n",ntot); + exit(0); + } +} + +/* The spreading function. Values returned in units of energy + Argument 'bark' is the difference in bark values between the + centre of two partitions. + This has been taken from LAME. MFC Feb 2003 */ +FLOAT8 psycho_4_spreading_function(FLOAT8 bark) { + + FLOAT8 tempx,x,tempy,temp; + tempx = bark; +#ifdef LAME + /* MP3 standard actually spreads these values a little more */ + if (tempx>=0) tempx *= 3; + else tempx *=1.5; +#endif + + if(tempx>=0.5 && tempx<=2.5) + { + temp = tempx - 0.5; + x = 8.0 * (temp*temp - 2.0 * temp); + } + else x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); + + if (tempy <= -60.0) return 0.0; + + tempx = exp( (x + tempy)*LN_TO_LOG10 ); + +#ifdef LAME + /* I'm not sure where the magic value of 0.6609193 comes from. + toolame will just keep using the rnorm to normalise the spreading function + MFC Feb 2003 */ + /* Normalization. The spreading function should be normalized so that: + +inf + / + | s3 [ bark ] d(bark) = 1 + / + -inf + */ + tempx /= .6609193; +#endif + return tempx; + +} + +void psycho_4_allocmem() { + grouped_c = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_c"); + grouped_e = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_e"); + nb = (FLOAT *) mem_alloc (sizeof (FCB), "nb"); + cb = (FLOAT *) mem_alloc (sizeof (FCB), "cb"); + tb = (FLOAT *) mem_alloc (sizeof (FCB), "tb"); + ecb = (FLOAT *) mem_alloc (sizeof (FCB), "ecb"); + bc = (FLOAT *) mem_alloc (sizeof (FCB), "bc"); + wsamp_r = (FLOAT *) mem_alloc (sizeof (FBLK), "wsamp_r"); + phi = (FLOAT *) mem_alloc (sizeof (FBLK), "phi"); + energy = (FLOAT *) mem_alloc (sizeof (FBLK), "energy"); + c = (FLOAT *) mem_alloc (sizeof (FHBLK), "c"); + bark = (FLOAT *) mem_alloc (sizeof (FHBLK), "bark"); + thr = (FLOAT *) mem_alloc (sizeof (FHBLK), "thr"); + snrtmp = (F32 *) mem_alloc (sizeof (F2_32), "snrtmp"); + + numlines = (int *) mem_alloc (sizeof (ICB), "numlines"); + partition = (int *) mem_alloc (sizeof (IHBLK), "partition"); + cbval = (FLOAT *) mem_alloc (sizeof (FCB), "cbval"); + rnorm = (FLOAT *) mem_alloc (sizeof (FCB), "rnorm"); + window = (FLOAT *) mem_alloc (sizeof (FBLK), "window"); + ath = (FLOAT *) mem_alloc (sizeof (FHBLK), "ath"); + tmn = (double *) mem_alloc (sizeof (DCB), "tmn"); + s = (FCB *) mem_alloc (sizeof (FCBCB), "s"); + lthr = (FHBLK *) mem_alloc (sizeof (F2HBLK), "lthr"); + r = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "r"); + phi_sav = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "phi_sav"); + +} + + + + + diff --git a/libtoolame-dab/psycho_4.h b/libtoolame-dab/psycho_4.h new file mode 100644 index 0000000..e065956 --- /dev/null +++ b/libtoolame-dab/psycho_4.h @@ -0,0 +1,8 @@ +void psycho_4 (short int *, short int[1056], int, double *smr, double sfeq, options *glopts); +void psycho_4_init (double sfreq, options *glopts); +FLOAT8 psycho_4_spreading_function(FLOAT8 bark); +void psycho_4_allocmem(void); + +void psycho_4_trigtable_init(void); +FLOAT psycho_4_cos(FLOAT phi); +FLOAT psycho_4_sin(FLOAT phi); diff --git a/libtoolame-dab/psycho_n1.c b/libtoolame-dab/psycho_n1.c new file mode 100644 index 0000000..9134023 --- /dev/null +++ b/libtoolame-dab/psycho_n1.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include "common.h" +#include "psycho_n1.h" + +/* this is the null psychoacoustic model + All it does it copy some predefined values. + No actual modelling takes place */ + +/* a bunch of SNR values I sort of made up MFC 1 oct 99 + Found by averaging the SNR values over a sound file + FIXME: Do a more rigourous investigation MFC Feb 2003 */ + +// From Castanets.wav +static FLOAT snrdef[32] = { + 30, 17, 16, 10, 3, 12, 8, 2.5, 5, 5, 6, 6, 5, 6, 10, 6, -4, + -10, -21, -30, -42, -55, -68, -75, -75, -75, -75, -75, -91, -107, -110, -108 +}; + +#ifdef TESTSNR +// Using TMBG song "I am not your broom" about 1min. Psy Model 2 +static FLOAT snrdefa[32] = { + 31, 17, 11, 9, 9, 7, 5, 3, 3, 3, 3, 3, 3, 1, -0, -2, + -5, -9,-15,-22,-32,-42,-54,-62,-63,-64,-66,-67,-83,-96,-98,-102 +}; + +// Using Babylon5 "messages from earth: track 6" 15mins. Psy Model 2. +static FLOAT snrdefb[32] = { + 30, 17, 11, 9, 8, 9, 6, 5, 5, 4, 4, 3, 2, -0, -2, -5, + -8,-13,-19,-27,-35,-46,-55,-64,-65,-66,-68,-69,-84,-97,-99,-104 +}; + +// Using Babylon5 "messages from earth: track 6" 15mins. Psy Model 1 +static FLOAT snrdefc[32] = { + 32, 26, 22, 18, 16, 14, 12, 11, 10, 9, 9, 8, 6, 6, 4, 2, + 0, -2, -7,-12,-18,-27,-35,-47,-53,-54,-56,-57,-57,-70, 0, 0 +}; +#endif + +void psycho_n1(double ltmin[2][SBLIMIT], int stereo) +{ + int i, k; + + for (k = 0; k < stereo; k++) + for (i = 0; i < SBLIMIT; i++) + ltmin[k][i] = snrdef[i]; +} diff --git a/libtoolame-dab/psycho_n1.h b/libtoolame-dab/psycho_n1.h new file mode 100644 index 0000000..249697d --- /dev/null +++ b/libtoolame-dab/psycho_n1.h @@ -0,0 +1,2 @@ + +void psycho_n1(double ltmin[2][SBLIMIT], int stereo); diff --git a/libtoolame-dab/subband.c b/libtoolame-dab/subband.c new file mode 100644 index 0000000..8544b60 --- /dev/null +++ b/libtoolame-dab/subband.c @@ -0,0 +1,310 @@ +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "common.h" +#include "encoder.h" +#include "mem.h" +#include "bitstream.h" +#include "encode.h" +#include "enwindow.h" +#include "subband.h" + + +#ifdef REFERENCECODE +/************************************************************************ +* +* window_subband() +* +* PURPOSE: Overlapping window on PCM samples +* +* SEMANTICS: +* 32 16-bit pcm samples are scaled to fractional 2's complement and +* concatenated to the end of the window buffer #x#. The updated window +* buffer #x# is then windowed by the analysis window #c# to produce the +* windowed sample #z# +* +************************************************************************/ + +void window_subband (short **buffer, double z[64], int k) +{ + typedef double XX[2][HAN_SIZE]; + static XX *x; + double *xk; + int i; + static int off[2] = { 0, 0 }; + static char init = 0; + double t; + double *ep0, *ep1, *ep2, *ep3, *ep4, *ep5, *ep6, *ep7; + if (!init) { + x = (XX *) mem_alloc (sizeof (XX), "x"); + memset (x, 0, 2 * HAN_SIZE * sizeof (double)); + init = 1; + } + xk = (*x)[k]; + + /* replace 32 oldest samples with 32 new samples */ + for (i = 0; i < 32; i++) + xk[31 - i + off[k]] = (double) *(*buffer)++ / SCALE; + + ep0 = &enwindow[0]; + ep1 = &enwindow[64]; + ep2 = &enwindow[128]; + ep3 = &enwindow[192]; + ep4 = &enwindow[256]; + ep5 = &enwindow[320]; + ep6 = &enwindow[384]; + ep7 = &enwindow[448]; + + /* shift samples into proper window positions */ + for (i = 0; i < 64; i++) { + t = xk[(i + off[k]) & (512 - 1)] * *ep0++; + t += xk[(i + 64 + off[k]) & (512 - 1)] * *ep1++; + t += xk[(i + 128 + off[k]) & (512 - 1)] * *ep2++; + t += xk[(i + 192 + off[k]) & (512 - 1)] * *ep3++; + t += xk[(i + 256 + off[k]) & (512 - 1)] * *ep4++; + t += xk[(i + 320 + off[k]) & (512 - 1)] * *ep5++; + t += xk[(i + 384 + off[k]) & (512 - 1)] * *ep6++; + t += xk[(i + 448 + off[k]) & (512 - 1)] * *ep7++; + z[i] = t; + } + + off[k] += 480; /*offset is modulo (HAN_SIZE-1) */ + off[k] &= HAN_SIZE - 1; + +} + + +/************************************************************************ +* +* filter_subband() +* +* PURPOSE: Calculates the analysis filter bank coefficients +* +* SEMANTICS: +* The windowed samples #z# is filtered by the digital filter matrix #m# +* to produce the subband samples #s#. This done by first selectively +* picking out values from the windowed samples, and then multiplying +* them by the filter matrix, producing 32 subband samples. +* +************************************************************************/ +void filter_subband (double z[HAN_SIZE], double s[SBLIMIT]) +{ + double yprime[32]; + register int i, j; + + static double m[16][32]; + static int init = 0; + + if (init == 0) { + init++; + create_dct_matrix (m); + } + + yprime[0] = z[16]; + for (i = 1; i <= 16; i++) + yprime[i] = z[i + 16] + z[16 - i]; + for (i = 17; i <= 31; i++) + yprime[i] = z[i + 16] - z[80 - i]; + + for (i = 15; i >= 0; i--) { + register double s0 = 0.0, s1 = 0.0; + register double *mp = m[i]; + register double *xinp = yprime; + for (j = 0; j < 8; j++) { + s0 += *mp++ * *xinp++; + s1 += *mp++ * *xinp++; + s0 += *mp++ * *xinp++; + s1 += *mp++ * *xinp++; + } + s[i] = s0 + s1; + s[31 - i] = s0 - s1; + } +} +#endif //REFERENCECODE + +void create_dct_matrix (double filter[16][32]) +{ + register int i, k; + + for (i = 0; i < 16; i++) + for (k = 0; k < 32; k++) { + if ((filter[i][k] = 1e9 * cos ((double) ((2 * i + 1) * k * PI64))) >= 0) + modf (filter[i][k] + 0.5, &filter[i][k]); + else + modf (filter[i][k] - 0.5, &filter[i][k]); + filter[i][k] *= 1e-9; + } +} + + +#ifdef NEWWS +/*********************************************************************** + An implementation of a modified window subband as seen in Kumar & Zubair's +"A high performance software implentation of mpeg audio encoder" +I think from IEEE ASCAP 1996 proceedings + +input: shift in 32*12 (384) new samples into a 864 point buffer. +ch - which channel we're looking at. + +This routine basically does 12 calls to window subband all in one go. +Not yet called in code. here for testing only. +************************************************************************/ +void window_subband12 (short **buffer, int ch) +{ + static double x[2][864]; /* 2 channels, 864 buffer for each */ + double *xk; + double t[12]; /* a temp buffer for summing values */ + double y[12][64]; /* 12 output arrays of 64 values */ + int i, j, k, m; + static double c[512]; /* enwindow array */ + static int init = 0; + double c0; + + xk = x[ch]; /* an easier way of referencing the array */ + + /* shift 384 new samples into the buffer */ + for (i = 863; i >= 384; i--) + xk[i] = xk[i - 384]; + for (i = 383; i >= 0; i--) + xk[i] = (double) *(*buffer)++ / SCALE; + + for (j = 0; j < 64; j++) { + for (k = 0; k < 12; k++) + t[k] = 0; + for (i = 0; i < 8; i++) { + m = i * 64 + j; + c0 = c[m]; + t[0] += c0 * xk[m + 352]; + t[1] += c0 * xk[m + 320]; + t[2] += c0 * xk[m + 288]; + t[3] += c0 * xk[m + 256]; + t[4] += c0 * xk[m + 224]; + t[5] += c0 * xk[m + 192]; + t[6] += c0 * xk[m + 160]; + t[7] += c0 * xk[m + 128]; + t[8] += c0 * xk[m + 96]; + t[9] += c0 * xk[m + 64]; + t[10] += c0 * xk[m + 32]; + t[11] += c0 * xk[m]; + } + for (i = 0; i < 12; i++) { + y[i][j] = t[i]; + } + } +} +#endif /* NEWWS */ + + +//____________________________________________________________________________ +//____ WindowFilterSubband() _________________________________________ +//____ RS&A - Feb 2003 _______________________________________________________ +void WindowFilterSubband (short *pBuffer, int ch, double s[SBLIMIT]) +{ + register int i, j; + int pa, pb, pc, pd, pe, pf, pg, ph; + double t; + double *dp, *dp2; + double *pEnw; + double y[64]; + double yprime[32]; + + static double x[2][512]; + static double m[16][32]; + static int init = 0; + static int off[2]; + static int half[2]; + + if (init == 0) { + init++; + off[0] = 0; + off[1] = 0; + half[0] = 0; + half[1] = 0; + for (i = 0; i < 2; i++) + for (j = 0; j < 512; j++) + x[i][j] = 0; + create_dct_matrix (m); + } + + dp = x[ch] + off[ch] + half[ch] * 256; + + /* replace 32 oldest samples with 32 new samples */ + for (i = 0; i < 32; i++) + dp[(31 - i) * 8] = (double) pBuffer[i] / SCALE; + + // looks like "school example" but does faster ... + dp = (x[ch] + half[ch] * 256); + pa = off[ch]; + pb = (pa + 1) % 8; + pc = (pa + 2) % 8; + pd = (pa + 3) % 8; + pe = (pa + 4) % 8; + pf = (pa + 5) % 8; + pg = (pa + 6) % 8; + ph = (pa + 7) % 8; + + for (i = 0; i < 32; i++) { + dp2 = dp + i * 8; + pEnw = enwindow + i; + t = dp2[pa] * pEnw[0]; + t += dp2[pb] * pEnw[64]; + t += dp2[pc] * pEnw[128]; + t += dp2[pd] * pEnw[192]; + t += dp2[pe] * pEnw[256]; + t += dp2[pf] * pEnw[320]; + t += dp2[pg] * pEnw[384]; + t += dp2[ph] * pEnw[448]; + y[i] = t; + } + + yprime[0] = y[16]; // Michael Chen´s dct filter + + dp = half[ch] ? x[ch] : (x[ch] + 256); + pa = half[ch] ? (off[ch] + 1) & 7 : off[ch]; + pb = (pa + 1) % 8; + pc = (pa + 2) % 8; + pd = (pa + 3) % 8; + pe = (pa + 4) % 8; + pf = (pa + 5) % 8; + pg = (pa + 6) % 8; + ph = (pa + 7) % 8; + + for (i = 0; i < 32; i++) { + dp2 = dp + i * 8; + pEnw = enwindow + i + 32; + t = dp2[pa] * pEnw[0]; + t += dp2[pb] * pEnw[64]; + t += dp2[pc] * pEnw[128]; + t += dp2[pd] * pEnw[192]; + t += dp2[pe] * pEnw[256]; + t += dp2[pf] * pEnw[320]; + t += dp2[pg] * pEnw[384]; + t += dp2[ph] * pEnw[448]; + y[i + 32] = t; + // 1st pass on Michael Chen´s dct filter + if (i > 0 && i < 17) + yprime[i] = y[i + 16] + y[16 - i]; + } + + // 2nd pass on Michael Chen´s dct filter + for (i = 17; i < 32; i++) + yprime[i] = y[i + 16] - y[80 - i]; + + for (i = 15; i >= 0; i--) { + register double s0 = 0.0, s1 = 0.0; + register double *mp = m[i]; + register double *xinp = yprime; + for (j = 0; j < 8; j++) { + s0 += *mp++ * *xinp++; + s1 += *mp++ * *xinp++; + s0 += *mp++ * *xinp++; + s1 += *mp++ * *xinp++; + } + s[i] = s0 + s1; + s[31 - i] = s0 - s1; + } + + half[ch] = (half[ch] + 1) & 1; + if (half[ch] == 1) + off[ch] = (off[ch] + 7) & 7; +} diff --git a/libtoolame-dab/subband.h b/libtoolame-dab/subband.h new file mode 100644 index 0000000..2480019 --- /dev/null +++ b/libtoolame-dab/subband.h @@ -0,0 +1,9 @@ + + +void WindowFilterSubband( short *pBuffer, int ch, double s[SBLIMIT] ); +void create_dct_matrix (double filter[16][32]); + +#ifdef REFERENCECODE +void window_subband (short **buffer, double z[64], int k); +void filter_subband (double z[HAN_SIZE], double s[SBLIMIT]); +#endif diff --git a/libtoolame-dab/tables.c b/libtoolame-dab/tables.c new file mode 100644 index 0000000..2ed35b4 --- /dev/null +++ b/libtoolame-dab/tables.c @@ -0,0 +1,1086 @@ +/********************************************************************** + * MPEG/Audio Tables I/O routines + **********************************************************************/ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include "common.h" +#include "mem.h" +#include "tables.h" + +#define NUMTABLES 38 +char table_names[NUMTABLES][9]; +long table_offsets[NUMTABLES]; +int numtables = 0; +char table_filename[250]; + +int pick_table (frame_info * frame) +/* choose table, load if necess, return # sb's */ +{ + int table, lay, ws, bsp, br_per_ch, sfrq; + int sblim = frame->sblimit; /* return current value if no load */ + + lay = frame->header->lay - 1; + bsp = frame->header->bitrate_index; + br_per_ch = bitrate[frame->header->version][bsp] / frame->nch; + ws = frame->header->sampling_frequency; + sfrq = s_freq[frame->header->version][ws]; + /* decision rules refer to per-channel bitrates (kbits/sec/chan) */ + if (frame->header->version == MPEG_AUDIO_ID) { /* MPEG-1 */ + if ((sfrq == 48 && br_per_ch >= 56) + || (br_per_ch >= 56 && br_per_ch <= 80)) + table = 0; + else if (sfrq != 48 && br_per_ch >= 96) + table = 1; + else if (sfrq != 32 && br_per_ch <= 48) + table = 2; + else + table = 3; + } else { /* MPEG-2 LSF */ + table = 4; + } + if (frame->tab_num != table) { + if (frame->tab_num >= 0) + mem_free ((void **) &(frame->alloc)); + frame->alloc = (al_table *) mem_alloc (sizeof (al_table), "alloc"); + sblim = read_bit_alloc (frame->tab_num = table, frame->alloc); + } + return sblim; +} + + +/*********************************************************************** + * + * Read one of the data files ("alloc_*") specifying the bit allocation + * quatization parameters for each subband in layer II encoding + * + **********************************************************************/ + +int read_bit_alloc (table, alloc) /* read in table, return # subbands */ + int table; + al_table *alloc; +{ + + static const int startindex_subband[5] = { 0, 290, 592, 674, 788 }; + + static const char alloc_subbands[][20] = { + "<alloc_0>", + "27", + "0 0 0 4 0 0", + "0 1 3 5 1 0", + "0 2 7 3 3 2", + "0 3 15 4 3 4", + "0 4 31 5 3 5", + "0 5 63 6 3 6", + "0 6 127 7 3 7", + "0 7 255 8 3 8", + "0 8 511 9 3 9", + "0 9 1023 10 3 10", + "0 10 2047 11 3 11", + "0 11 4095 12 3 12", + "0 12 8191 13 3 13", + "0 13 16383 14 3 14", + "0 14 32767 15 3 15", + "0 15 65535 16 3 16", + "1 0 0 4 0 0", + "1 1 3 5 1 0", + "1 2 7 3 3 2", + "1 3 15 4 3 4", + "1 4 31 5 3 5", + "1 5 63 6 3 6", + "1 6 127 7 3 7", + "1 7 255 8 3 8", + "1 8 511 9 3 9", + "1 9 1023 10 3 10", + "1 10 2047 11 3 11", + "1 11 4095 12 3 12", + "1 12 8191 13 3 13", + "1 13 16383 14 3 14", + "1 14 32767 15 3 15", + "1 15 65535 16 3 16", + "2 0 0 4 0 0", + "2 1 3 5 1 0", + "2 2 7 3 3 2", + "2 3 15 4 3 4", + "2 4 31 5 3 5", + "2 5 63 6 3 6", + "2 6 127 7 3 7", + "2 7 255 8 3 8", + "2 8 511 9 3 9", + "2 9 1023 10 3 10", + "2 10 2047 11 3 11", + "2 11 4095 12 3 12", + "2 12 8191 13 3 13", + "2 13 16383 14 3 14", + "2 14 32767 15 3 15", + "2 15 65535 16 3 16", + "3 0 0 4 0 0", + "3 1 3 5 1 0", + "3 2 5 7 1 1", + "3 3 7 3 3 2", + "3 4 9 10 1 3", + "3 5 15 4 3 4", + "3 6 31 5 3 5", + "3 7 63 6 3 6", + "3 8 127 7 3 7 ", + "3 9 255 8 3 8", + "3 10 511 9 3 9", + "3 11 1023 10 3 10", + "3 12 2047 11 3 11", + "3 13 4095 12 3 12", + "3 14 8191 13 3 13", + "3 15 65535 16 3 16", + "4 0 0 4 0 0", + "4 1 3 5 1 0", + "4 2 5 7 1 1", + "4 3 7 3 3 2", + "4 4 9 10 1 3", + "4 5 15 4 3 4", + "4 6 31 5 3 5", + "4 7 63 6 3 6", + "4 8 127 7 3 7 ", + "4 9 255 8 3 8", + "4 10 511 9 3 9", + "4 11 1023 10 3 10", + "4 12 2047 11 3 11", + "4 13 4095 12 3 12", + "4 14 8191 13 3 13", + "4 15 65535 16 3 16", + "5 0 0 4 0 0", + "5 1 3 5 1 0", + "5 2 5 7 1 1", + "5 3 7 3 3 2", + "5 4 9 10 1 3", + "5 5 15 4 3 4", + "5 6 31 5 3 5", + "5 7 63 6 3 6", + "5 8 127 7 3 7 ", + "5 9 255 8 3 8", + "5 10 511 9 3 9", + "5 11 1023 10 3 10", + "5 12 2047 11 3 11", + "5 13 4095 12 3 12", + "5 14 8191 13 3 13", + "5 15 65535 16 3 16", + "6 0 0 4 0 0", + "6 1 3 5 1 0", + "6 2 5 7 1 1", + "6 3 7 3 3 2", + "6 4 9 10 1 3", + "6 5 15 4 3 4", + "6 6 31 5 3 5", + "6 7 63 6 3 6", + "6 8 127 7 3 7 ", + "6 9 255 8 3 8", + "6 10 511 9 3 9", + "6 11 1023 10 3 10", + "6 12 2047 11 3 11", + "6 13 4095 12 3 12", + "6 14 8191 13 3 13", + "6 15 65535 16 3 16", + "7 0 0 4 0 0", + "7 1 3 5 1 0", + "7 2 5 7 1 1", + "7 3 7 3 3 2", + "7 4 9 10 1 3", + "7 5 15 4 3 4", + "7 6 31 5 3 5", + "7 7 63 6 3 6", + "7 8 127 7 3 7 ", + "7 9 255 8 3 8", + "7 10 511 9 3 9", + "7 11 1023 10 3 10", + "7 12 2047 11 3 11", + "7 13 4095 12 3 12", + "7 14 8191 13 3 13", + "7 15 65535 16 3 16", + "8 0 0 4 0 0", + "8 1 3 5 1 0", + "8 2 5 7 1 1", + "8 3 7 3 3 2", + "8 4 9 10 1 3", + "8 5 15 4 3 4", + "8 6 31 5 3 5", + "8 7 63 6 3 6", + "8 8 127 7 3 7 ", + "8 9 255 8 3 8", + "8 10 511 9 3 9", + "8 11 1023 10 3 10", + "8 12 2047 11 3 11", + "8 13 4095 12 3 12", + "8 14 8191 13 3 13", + "8 15 65535 16 3 16", + "9 0 0 4 0 0", + "9 1 3 5 1 0", + "9 2 5 7 1 1", + "9 3 7 3 3 2", + "9 4 9 10 1 3", + "9 5 15 4 3 4", + "9 6 31 5 3 5", + "9 7 63 6 3 6", + "9 8 127 7 3 7 ", + "9 9 255 8 3 8", + "9 10 511 9 3 9", + "9 11 1023 10 3 10", + "9 12 2047 11 3 11", + "9 13 4095 12 3 12", + "9 14 8191 13 3 13", + "9 15 65535 16 3 16", + "10 0 0 4 0 0", + "10 1 3 5 1 0", + "10 2 5 7 1 1", + "10 3 7 3 3 2", + "10 4 9 10 1 3", + "10 5 15 4 3 4", + "10 6 31 5 3 5", + "10 7 63 6 3 6", + "10 8 127 7 3 7 ", + "10 9 255 8 3 8", + "10 10 511 9 3 9", + "10 11 1023 10 3 10", + "10 12 2047 11 3 11", + "10 13 4095 12 3 12", + "10 14 8191 13 3 13", + "10 15 65535 16 3 16", + "11 0 0 3 0 0", + "11 1 3 5 1 0", + "11 2 5 7 1 1", + "11 3 7 3 3 2", + "11 4 9 10 1 3", + "11 5 15 4 3 4", + "11 6 31 5 3 5", + "11 7 65535 16 3 16 ", + "12 0 0 3 0 0", + "12 1 3 5 1 0", + "12 2 5 7 1 1", + "12 3 7 3 3 2", + "12 4 9 10 1 3", + "12 5 15 4 3 4", + "12 6 31 5 3 5", + "12 7 65535 16 3 16 ", + "13 0 0 3 0 0", + "13 1 3 5 1 0", + "13 2 5 7 1 1", + "13 3 7 3 3 2", + "13 4 9 10 1 3", + "13 5 15 4 3 4", + "13 6 31 5 3 5", + "13 7 65535 16 3 16 ", + "14 0 0 3 0 0", + "14 1 3 5 1 0", + "14 2 5 7 1 1", + "14 3 7 3 3 2", + "14 4 9 10 1 3", + "14 5 15 4 3 4", + "14 6 31 5 3 5", + "14 7 65535 16 3 16 ", + "15 0 0 3 0 0", + "15 1 3 5 1 0", + "15 2 5 7 1 1", + "15 3 7 3 3 2", + "15 4 9 10 1 3", + "15 5 15 4 3 4", + "15 6 31 5 3 5", + "15 7 65535 16 3 16 ", + "16 0 0 3 0 0", + "16 1 3 5 1 0", + "16 2 5 7 1 1", + "16 3 7 3 3 2", + "16 4 9 10 1 3", + "16 5 15 4 3 4", + "16 6 31 5 3 5", + "16 7 65535 16 3 16 ", + "17 0 0 3 0 0", + "17 1 3 5 1 0", + "17 2 5 7 1 1", + "17 3 7 3 3 2", + "17 4 9 10 1 3", + "17 5 15 4 3 4", + "17 6 31 5 3 5", + "17 7 65535 16 3 16 ", + "18 0 0 3 0 0", + "18 1 3 5 1 0", + "18 2 5 7 1 1", + "18 3 7 3 3 2", + "18 4 9 10 1 3", + "18 5 15 4 3 4", + "18 6 31 5 3 5", + "18 7 65535 16 3 16 ", + "19 0 0 3 0 0", + "19 1 3 5 1 0", + "19 2 5 7 1 1", + "19 3 7 3 3 2", + "19 4 9 10 1 3", + "19 5 15 4 3 4", + "19 6 31 5 3 5", + "19 7 65535 16 3 16 ", + "20 0 0 3 0 0", + "20 1 3 5 1 0", + "20 2 5 7 1 1", + "20 3 7 3 3 2", + "20 4 9 10 1 3", + "20 5 15 4 3 4", + "20 6 31 5 3 5", + "20 7 65535 16 3 16 ", + "21 0 0 3 0 0", + "21 1 3 5 1 0", + "21 2 5 7 1 1", + "21 3 7 3 3 2", + "21 4 9 10 1 3", + "21 5 15 4 3 4", + "21 6 31 5 3 5", + "21 7 65535 16 3 16 ", + "22 0 0 3 0 0", + "22 1 3 5 1 0", + "22 2 5 7 1 1", + "22 3 7 3 3 2", + "22 4 9 10 1 3", + "22 5 15 4 3 4", + "22 6 31 5 3 5", + "22 7 65535 16 3 16 ", + "23 0 0 2 0 0", + "23 1 3 5 1 0", + "23 2 5 7 1 1", + "23 3 65535 16 3 16", + "24 0 0 2 0 0", + "24 1 3 5 1 0", + "24 2 5 7 1 1", + "24 3 65535 16 3 16", + "25 0 0 2 0 0", + "25 1 3 5 1 0", + "25 2 5 7 1 1", + "25 3 65535 16 3 16", + "26 0 0 2 0 0", + "26 1 3 5 1 0", + "26 2 5 7 1 1", + "26 3 65535 16 3 16", + "<alloc_1>", + "30", + "0 0 0 4 0 0", + "0 1 3 5 1 0", + "0 2 7 3 3 2", + "0 3 15 4 3 4", + "0 4 31 5 3 5", + "0 5 63 6 3 6", + "0 6 127 7 3 7", + "0 7 255 8 3 8", + "0 8 511 9 3 9", + "0 9 1023 10 3 10", + "0 10 2047 11 3 11", + "0 11 4095 12 3 12", + "0 12 8191 13 3 13", + "0 13 16383 14 3 14", + "0 14 32767 15 3 15", + "0 15 65535 16 3 16", + "1 0 0 4 0 0", + "1 1 3 5 1 0", + "1 2 7 3 3 2", + "1 3 15 4 3 4", + "1 4 31 5 3 5", + "1 5 63 6 3 6", + "1 6 127 7 3 7", + "1 7 255 8 3 8", + "1 8 511 9 3 9", + "1 9 1023 10 3 10", + "1 10 2047 11 3 11", + "1 11 4095 12 3 12", + "1 12 8191 13 3 13", + "1 13 16383 14 3 14", + "1 14 32767 15 3 15", + "1 15 65535 16 3 16", + "2 0 0 4 0 0", + "2 1 3 5 1 0", + "2 2 7 3 3 2", + "2 3 15 4 3 4", + "2 4 31 5 3 5", + "2 5 63 6 3 6", + "2 6 127 7 3 7", + "2 7 255 8 3 8", + "2 8 511 9 3 9", + "2 9 1023 10 3 10", + "2 10 2047 11 3 11", + "2 11 4095 12 3 12", + "2 12 8191 13 3 13", + "2 13 16383 14 3 14", + "2 14 32767 15 3 15", + "2 15 65535 16 3 16", + "3 0 0 4 0 0", + "3 1 3 5 1 0", + "3 2 5 7 1 1", + "3 3 7 3 3 2", + "3 4 9 10 1 3", + "3 5 15 4 3 4", + "3 6 31 5 3 5", + "3 7 63 6 3 6", + "3 8 127 7 3 7 ", + "3 9 255 8 3 8", + "3 10 511 9 3 9", + "3 11 1023 10 3 10", + "3 12 2047 11 3 11", + "3 13 4095 12 3 12", + "3 14 8191 13 3 13", + "3 15 65535 16 3 16", + "4 0 0 4 0 0", + "4 1 3 5 1 0", + "4 2 5 7 1 1", + "4 3 7 3 3 2", + "4 4 9 10 1 3", + "4 5 15 4 3 4", + "4 6 31 5 3 5", + "4 7 63 6 3 6", + "4 8 127 7 3 7 ", + "4 9 255 8 3 8", + "4 10 511 9 3 9", + "4 11 1023 10 3 10", + "4 12 2047 11 3 11", + "4 13 4095 12 3 12", + "4 14 8191 13 3 13", + "4 15 65535 16 3 16", + "5 0 0 4 0 0", + "5 1 3 5 1 0", + "5 2 5 7 1 1", + "5 3 7 3 3 2", + "5 4 9 10 1 3", + "5 5 15 4 3 4", + "5 6 31 5 3 5", + "5 7 63 6 3 6", + "5 8 127 7 3 7 ", + "5 9 255 8 3 8", + "5 10 511 9 3 9", + "5 11 1023 10 3 10", + "5 12 2047 11 3 11", + "5 13 4095 12 3 12", + "5 14 8191 13 3 13", + "5 15 65535 16 3 16", + "6 0 0 4 0 0", + "6 1 3 5 1 0", + "6 2 5 7 1 1", + "6 3 7 3 3 2", + "6 4 9 10 1 3", + "6 5 15 4 3 4", + "6 6 31 5 3 5", + "6 7 63 6 3 6", + "6 8 127 7 3 7 ", + "6 9 255 8 3 8", + "6 10 511 9 3 9", + "6 11 1023 10 3 10", + "6 12 2047 11 3 11", + "6 13 4095 12 3 12", + "6 14 8191 13 3 13", + "6 15 65535 16 3 16", + "7 0 0 4 0 0", + "7 1 3 5 1 0", + "7 2 5 7 1 1", + "7 3 7 3 3 2", + "7 4 9 10 1 3", + "7 5 15 4 3 4", + "7 6 31 5 3 5", + "7 7 63 6 3 6", + "7 8 127 7 3 7 ", + "7 9 255 8 3 8", + "7 10 511 9 3 9", + "7 11 1023 10 3 10", + "7 12 2047 11 3 11", + "7 13 4095 12 3 12", + "7 14 8191 13 3 13", + "7 15 65535 16 3 16", + "8 0 0 4 0 0", + "8 1 3 5 1 0", + "8 2 5 7 1 1", + "8 3 7 3 3 2", + "8 4 9 10 1 3", + "8 5 15 4 3 4", + "8 6 31 5 3 5", + "8 7 63 6 3 6", + "8 8 127 7 3 7 ", + "8 9 255 8 3 8", + "8 10 511 9 3 9", + "8 11 1023 10 3 10", + "8 12 2047 11 3 11", + "8 13 4095 12 3 12", + "8 14 8191 13 3 13", + "8 15 65535 16 3 16", + "9 0 0 4 0 0", + "9 1 3 5 1 0", + "9 2 5 7 1 1", + "9 3 7 3 3 2", + "9 4 9 10 1 3", + "9 5 15 4 3 4", + "9 6 31 5 3 5", + "9 7 63 6 3 6", + "9 8 127 7 3 7 ", + "9 9 255 8 3 8", + "9 10 511 9 3 9", + "9 11 1023 10 3 10", + "9 12 2047 11 3 11", + "9 13 4095 12 3 12", + "9 14 8191 13 3 13", + "9 15 65535 16 3 16", + "10 0 0 4 0 0", + "10 1 3 5 1 0", + "10 2 5 7 1 1", + "10 3 7 3 3 2", + "10 4 9 10 1 3", + "10 5 15 4 3 4", + "10 6 31 5 3 5", + "10 7 63 6 3 6", + "10 8 127 7 3 7 ", + "10 9 255 8 3 8", + "10 10 511 9 3 9", + "10 11 1023 10 3 10", + "10 12 2047 11 3 11", + "10 13 4095 12 3 12", + "10 14 8191 13 3 13", + "10 15 65535 16 3 16", + "11 0 0 3 0 0", + "11 1 3 5 1 0", + "11 2 5 7 1 1", + "11 3 7 3 3 2", + "11 4 9 10 1 3", + "11 5 15 4 3 4", + "11 6 31 5 3 5", + "11 7 65535 16 3 16 ", + "12 0 0 3 0 0", + "12 1 3 5 1 0", + "12 2 5 7 1 1", + "12 3 7 3 3 2", + "12 4 9 10 1 3", + "12 5 15 4 3 4", + "12 6 31 5 3 5", + "12 7 65535 16 3 16 ", + "13 0 0 3 0 0", + "13 1 3 5 1 0", + "13 2 5 7 1 1", + "13 3 7 3 3 2", + "13 4 9 10 1 3", + "13 5 15 4 3 4", + "13 6 31 5 3 5", + "13 7 65535 16 3 16 ", + "14 0 0 3 0 0", + "14 1 3 5 1 0", + "14 2 5 7 1 1", + "14 3 7 3 3 2", + "14 4 9 10 1 3", + "14 5 15 4 3 4", + "14 6 31 5 3 5", + "14 7 65535 16 3 16 ", + "15 0 0 3 0 0", + "15 1 3 5 1 0", + "15 2 5 7 1 1", + "15 3 7 3 3 2", + "15 4 9 10 1 3", + "15 5 15 4 3 4", + "15 6 31 5 3 5", + "15 7 65535 16 3 16 ", + "16 0 0 3 0 0", + "16 1 3 5 1 0", + "16 2 5 7 1 1", + "16 3 7 3 3 2", + "16 4 9 10 1 3", + "16 5 15 4 3 4", + "16 6 31 5 3 5", + "16 7 65535 16 3 16 ", + "17 0 0 3 0 0", + "17 1 3 5 1 0", + "17 2 5 7 1 1", + "17 3 7 3 3 2", + "17 4 9 10 1 3", + "17 5 15 4 3 4", + "17 6 31 5 3 5", + "17 7 65535 16 3 16 ", + "18 0 0 3 0 0", + "18 1 3 5 1 0", + "18 2 5 7 1 1", + "18 3 7 3 3 2", + "18 4 9 10 1 3", + "18 5 15 4 3 4", + "18 6 31 5 3 5", + "18 7 65535 16 3 16 ", + "19 0 0 3 0 0", + "19 1 3 5 1 0", + "19 2 5 7 1 1", + "19 3 7 3 3 2", + "19 4 9 10 1 3", + "19 5 15 4 3 4", + "19 6 31 5 3 5", + "19 7 65535 16 3 16 ", + "20 0 0 3 0 0", + "20 1 3 5 1 0", + "20 2 5 7 1 1", + "20 3 7 3 3 2", + "20 4 9 10 1 3", + "20 5 15 4 3 4", + "20 6 31 5 3 5", + "20 7 65535 16 3 16 ", + "21 0 0 3 0 0", + "21 1 3 5 1 0", + "21 2 5 7 1 1", + "21 3 7 3 3 2", + "21 4 9 10 1 3", + "21 5 15 4 3 4", + "21 6 31 5 3 5", + "21 7 65535 16 3 16 ", + "22 0 0 3 0 0", + "22 1 3 5 1 0", + "22 2 5 7 1 1", + "22 3 7 3 3 2", + "22 4 9 10 1 3", + "22 5 15 4 3 4", + "22 6 31 5 3 5", + "22 7 65535 16 3 16 ", + "23 0 0 2 0 0", + "23 1 3 5 1 0", + "23 2 5 7 1 1", + "23 3 65535 16 3 16", + "24 0 0 2 0 0", + "24 1 3 5 1 0", + "24 2 5 7 1 1", + "24 3 65535 16 3 16", + "25 0 0 2 0 0", + "25 1 3 5 1 0", + "25 2 5 7 1 1", + "25 3 65535 16 3 16", + "26 0 0 2 0 0", + "26 1 3 5 1 0", + "26 2 5 7 1 1", + "26 3 65535 16 3 16", + "27 0 0 2 0 0", + "27 1 3 5 1 0", + "27 2 5 7 1 1", + "27 3 65535 16 3 16", + "28 0 0 2 0 0", + "28 1 3 5 1 0", + "28 2 5 7 1 1", + "28 3 65535 16 3 16", + "29 0 0 2 0 0", + "29 1 3 5 1 0", + "29 2 5 7 1 1", + "29 3 65535 16 3 16", + "<alloc_2>", + "8", + "0 0 0 4 0 0", + "0 1 3 5 1 0", + "0 2 5 7 1 1", + "0 3 9 10 1 3", + "0 4 15 4 3 4", + "0 5 31 5 3 5", + "0 6 63 6 3 6", + "0 7 127 7 3 7", + "0 8 255 8 3 8", + "0 9 511 9 3 9", + "0 10 1023 10 3 10", + "0 11 2047 11 3 11", + "0 12 4095 12 3 12", + "0 13 8191 13 3 13", + "0 14 16383 14 3 14", + "0 15 32767 15 3 15", + "1 0 0 4 0 0", + "1 1 3 5 1 0", + "1 2 5 7 1 1", + "1 3 9 10 1 3", + "1 4 15 4 3 4", + "1 5 31 5 3 5", + "1 6 63 6 3 6", + "1 7 127 7 3 7", + "1 8 255 8 3 8", + "1 9 511 9 3 9", + "1 10 1023 10 3 10", + "1 11 2047 11 3 11", + "1 12 4095 12 3 12", + "1 13 8191 13 3 13", + "1 14 16383 14 3 14", + "1 15 32767 15 3 15", + "2 0 0 3 0 0", + "2 1 3 5 1 0", + "2 2 5 7 1 1", + "2 3 9 10 1 3", + "2 4 15 4 3 4", + "2 5 31 5 3 5", + "2 6 63 6 3 6", + "2 7 127 7 3 7", + "3 0 0 3 0 0", + "3 1 3 5 1 0", + "3 2 5 7 1 1", + "3 3 9 10 1 3", + "3 4 15 4 3 4", + "3 5 31 5 3 5", + "3 6 63 6 3 6", + "3 7 127 7 3 7", + "4 0 0 3 0 0", + "4 1 3 5 1 0", + "4 2 5 7 1 1", + "4 3 9 10 1 3", + "4 4 15 4 3 4", + "4 5 31 5 3 5", + "4 6 63 6 3 6", + "4 7 127 7 3 7", + "5 0 0 3 0 0", + "5 1 3 5 1 0", + "5 2 5 7 1 1", + "5 3 9 10 1 3", + "5 4 15 4 3 4", + "5 5 31 5 3 5", + "5 6 63 6 3 6", + "5 7 127 7 3 7", + "6 0 0 3 0 0", + "6 1 3 5 1 0", + "6 2 5 7 1 1", + "6 3 9 10 1 3", + "6 4 15 4 3 4", + "6 5 31 5 3 5", + "6 6 63 6 3 6", + "6 7 127 7 3 7", + "7 0 0 3 0 0", + "7 1 3 5 1 0", + "7 2 5 7 1 1", + "7 3 9 10 1 3", + "7 4 15 4 3 4", + "7 5 31 5 3 5", + "7 6 63 6 3 6", + "7 7 127 7 3 7", + "<alloc_3>", + "12", + "0 0 0 4 0 0", + "0 1 3 5 1 0", + "0 2 5 7 1 1", + "0 3 9 10 1 3", + "0 4 15 4 3 4", + "0 5 31 5 3 5", + "0 6 63 6 3 6", + "0 7 127 7 3 7", + "0 8 255 8 3 8", + "0 9 511 9 3 9", + "0 10 1023 10 3 10", + "0 11 2047 11 3 11", + "0 12 4095 12 3 12", + "0 13 8191 13 3 13", + "0 14 16383 14 3 14", + "0 15 32767 15 3 15", + "1 0 0 4 0 0", + "1 1 3 5 1 0", + "1 2 5 7 1 1", + "1 3 9 10 1 3", + "1 4 15 4 3 4", + "1 5 31 5 3 5", + "1 6 63 6 3 6", + "1 7 127 7 3 7", + "1 8 255 8 3 8", + "1 9 511 9 3 9", + "1 10 1023 10 3 10", + "1 11 2047 11 3 11", + "1 12 4095 12 3 12", + "1 13 8191 13 3 13", + "1 14 16383 14 3 14", + "1 15 32767 15 3 15", + "2 0 0 3 0 0", + "2 1 3 5 1 0", + "2 2 5 7 1 1", + "2 3 9 10 1 3", + "2 4 15 4 3 4", + "2 5 31 5 3 5", + "2 6 63 6 3 6", + "2 7 127 7 3 7", + "3 0 0 3 0 0", + "3 1 3 5 1 0", + "3 2 5 7 1 1", + "3 3 9 10 1 3", + "3 4 15 4 3 4", + "3 5 31 5 3 5", + "3 6 63 6 3 6", + "3 7 127 7 3 7", + "4 0 0 3 0 0", + "4 1 3 5 1 0", + "4 2 5 7 1 1", + "4 3 9 10 1 3", + "4 4 15 4 3 4", + "4 5 31 5 3 5", + "4 6 63 6 3 6", + "4 7 127 7 3 7", + "5 0 0 3 0 0", + "5 1 3 5 1 0", + "5 2 5 7 1 1", + "5 3 9 10 1 3", + "5 4 15 4 3 4", + "5 5 31 5 3 5", + "5 6 63 6 3 6", + "5 7 127 7 3 7", + "6 0 0 3 0 0", + "6 1 3 5 1 0", + "6 2 5 7 1 1", + "6 3 9 10 1 3", + "6 4 15 4 3 4", + "6 5 31 5 3 5", + "6 6 63 6 3 6", + "6 7 127 7 3 7", + "7 0 0 3 0 0", + "7 1 3 5 1 0", + "7 2 5 7 1 1", + "7 3 9 10 1 3", + "7 4 15 4 3 4", + "7 5 31 5 3 5", + "7 6 63 6 3 6", + "7 7 127 7 3 7", + "8 0 0 3 0 0", + "8 1 3 5 1 0", + "8 2 5 7 1 1", + "8 3 9 10 1 3", + "8 4 15 4 3 4", + "8 5 31 5 3 5", + "8 6 63 6 3 6", + "8 7 127 7 3 7", + "9 0 0 3 0 0", + "9 1 3 5 1 0", + "9 2 5 7 1 1", + "9 3 9 10 1 3", + "9 4 15 4 3 4", + "9 5 31 5 3 5", + "9 6 63 6 3 6", + "9 7 127 7 3 7", + "10 0 0 3 0 0", + "10 1 3 5 1 0", + "10 2 5 7 1 1", + "10 3 9 10 1 3", + "10 4 15 4 3 4", + "10 5 31 5 3 5", + "10 6 63 6 3 6", + "10 7 127 7 3 7", + "11 0 0 3 0 0", + "11 1 3 5 1 0", + "11 2 5 7 1 1", + "11 3 9 10 1 3", + "11 4 15 4 3 4", + "11 5 31 5 3 5", + "11 6 63 6 3 6", + "11 7 127 7 3 7", + "<alloc_4>", + "30", + "0 0 0 4 0 0", + "0 1 3 5 1 0", + "0 2 5 7 1 1", + "0 3 7 3 3 2", + "0 4 9 10 1 3", + "0 5 15 4 3 4", + "0 6 31 5 3 5", + "0 7 63 6 3 6", + "0 8 127 7 3 7", + "0 9 255 8 3 8", + "0 10 511 9 3 9", + "0 11 1023 10 3 10", + "0 12 2047 11 3 11", + "0 13 4095 12 3 12", + "0 14 8191 13 3 13", + "0 15 16383 14 3 14", + "1 0 0 4 0 0", + "1 1 3 5 1 0", + "1 2 5 7 1 1", + "1 3 7 3 3 2", + "1 4 9 10 1 3", + "1 5 15 4 3 4", + "1 6 31 5 3 5", + "1 7 63 6 3 6", + "1 8 127 7 3 7", + "1 9 255 8 3 8", + "1 10 511 9 3 9", + "1 11 1023 10 3 10", + "1 12 2047 11 3 11", + "1 13 4095 12 3 12", + "1 14 8191 13 3 13", + "1 15 16383 14 3 14", + "2 0 0 4 0 0", + "2 1 3 5 1 0", + "2 2 5 7 1 1", + "2 3 7 3 3 2", + "2 4 9 10 1 3", + "2 5 15 4 3 4", + "2 6 31 5 3 5", + "2 7 63 6 3 6", + "2 8 127 7 3 7", + "2 9 255 8 3 8", + "2 10 511 9 3 9", + "2 11 1023 10 3 10", + "2 12 2047 11 3 11", + "2 13 4095 12 3 12", + "2 14 8191 13 3 13", + "2 15 16383 14 3 14", + "3 0 0 4 0 0", + "3 1 3 5 1 0", + "3 2 5 7 1 1", + "3 3 7 3 3 2", + "3 4 9 10 1 3", + "3 5 15 4 3 4", + "3 6 31 5 3 5", + "3 7 63 6 3 6", + "3 8 127 7 3 7", + "3 9 255 8 3 8", + "3 10 511 9 3 9", + "3 11 1023 10 3 10", + "3 12 2047 11 3 11", + "3 13 4095 12 3 12", + "3 14 8191 13 3 13", + "3 15 16383 14 3 14", + "4 0 0 3 0 0", + "4 1 3 5 1 0", + "4 2 5 7 1 1", + "4 3 9 10 1 3", + "4 4 15 4 3 4", + "4 5 31 5 3 5", + "4 6 63 6 3 6", + "4 7 127 7 3 7 ", + "5 0 0 3 0 0", + "5 1 3 5 1 0", + "5 2 5 7 1 1", + "5 3 9 10 1 3", + "5 4 15 4 3 4", + "5 5 31 5 3 5", + "5 6 63 6 3 6", + "5 7 127 7 3 7 ", + "6 0 0 3 0 0", + "6 1 3 5 1 0", + "6 2 5 7 1 1", + "6 3 9 10 1 3", + "6 4 15 4 3 4", + "6 5 31 5 3 5", + "6 6 63 6 3 6", + "6 7 127 7 3 7 ", + "7 0 0 3 0 0", + "7 1 3 5 1 0", + "7 2 5 7 1 1", + "7 3 9 10 1 3", + "7 4 15 4 3 4", + "7 5 31 5 3 5", + "7 6 63 6 3 6", + "7 7 127 7 3 7 ", + "8 0 0 3 0 0", + "8 1 3 5 1 0", + "8 2 5 7 1 1", + "8 3 9 10 1 3", + "8 4 15 4 3 4", + "8 5 31 5 3 5", + "8 6 63 6 3 6", + "8 7 127 7 3 7 ", + "9 0 0 3 0 0", + "9 1 3 5 1 0", + "9 2 5 7 1 1", + "9 3 9 10 1 3", + "9 4 15 4 3 4", + "9 5 31 5 3 5", + "9 6 63 6 3 6", + "9 7 127 7 3 7 ", + "10 0 0 3 0 0", + "10 1 3 5 1 0", + "10 2 5 7 1 1", + "10 3 9 10 1 3", + "10 4 15 4 3 4", + "10 5 31 5 3 5", + "10 6 63 6 3 6", + "10 7 127 7 3 7 ", + "11 0 0 2 0 0", + "11 1 3 5 1 0", + "11 2 5 7 1 1", + "11 3 9 10 1 3", + "12 0 0 2 0 0", + "12 1 3 5 1 0", + "12 2 5 7 1 1", + "12 3 9 10 1 3", + "13 0 0 2 0 0", + "13 1 3 5 1 0", + "13 2 5 7 1 1", + "13 3 9 10 1 3", + "14 0 0 2 0 0", + "14 1 3 5 1 0", + "14 2 5 7 1 1", + "14 3 9 10 1 3", + "15 0 0 2 0 0", + "15 1 3 5 1 0", + "15 2 5 7 1 1", + "15 3 9 10 1 3", + "16 0 0 2 0 0", + "16 1 3 5 1 0", + "16 2 5 7 1 1", + "16 3 9 10 1 3", + "17 0 0 2 0 0", + "17 1 3 5 1 0", + "17 2 5 7 1 1", + "17 3 9 10 1 3", + "18 0 0 2 0 0", + "18 1 3 5 1 0", + "18 2 5 7 1 1", + "18 3 9 10 1 3", + "19 0 0 2 0 0", + "19 1 3 5 1 0", + "19 2 5 7 1 1", + "19 3 9 10 1 3", + "20 0 0 2 0 0", + "20 1 3 5 1 0", + "20 2 5 7 1 1", + "20 3 9 10 1 3", + "21 0 0 2 0 0", + "21 1 3 5 1 0", + "21 2 5 7 1 1", + "21 3 9 10 1 3", + "22 0 0 2 0 0", + "22 1 3 5 1 0", + "22 2 5 7 1 1", + "22 3 9 10 1 3", + "23 0 0 2 0 0", + "23 1 3 5 1 0", + "23 2 5 7 1 1", + "23 3 9 10 1 3", + "24 0 0 2 0 0", + "24 1 3 5 1 0", + "24 2 5 7 1 1", + "24 3 9 10 1 3", + "25 0 0 2 0 0", + "25 1 3 5 1 0", + "25 2 5 7 1 1", + "25 3 9 10 1 3", + "26 0 0 2 0 0", + "26 1 3 5 1 0", + "26 2 5 7 1 1", + "26 3 9 10 1 3", + "27 0 0 2 0 0", + "27 1 3 5 1 0", + "27 2 5 7 1 1", + "27 3 9 10 1 3", + "28 0 0 2 0 0", + "28 1 3 5 1 0", + "28 2 5 7 1 1", + "28 3 9 10 1 3", + "29 0 0 2 0 0", + "29 1 3 5 1 0", + "29 2 5 7 1 1", + "29 3 9 10 1 3", + "<next>" + }; + + unsigned int a, b, c, d, i, j; + char t[80]; + int sblim; + int startindex; + + if ((table < 0) || (table > 4)) + table = 0; + + startindex = startindex_subband[table] + 1; + +// if (g_verbose) printf("using bit allocation table %d\n", table); + + sprintf (t, "%s", alloc_subbands[startindex]); + startindex++; + sscanf (t, "%d\n", &sblim); + + while (t[0] != '<') { + sprintf (t, "%s", alloc_subbands[startindex]); + startindex++; + if (t[0] == '<') + break; + + sscanf (t, "%d %d %d %d %d %d\n", &i, &j, &a, &b, &c, &d); + (*alloc)[i][j].steps = a; + (*alloc)[i][j].bits = b; + (*alloc)[i][j].group = c; + (*alloc)[i][j].quant = d; + } + return sblim; +} diff --git a/libtoolame-dab/tables.h b/libtoolame-dab/tables.h new file mode 100644 index 0000000..e89cbbd --- /dev/null +++ b/libtoolame-dab/tables.h @@ -0,0 +1,3 @@ +FILE *OpenTableFile (char *); +int read_bit_alloc (int, al_table *); +int pick_table (frame_info *); diff --git a/libtoolame-dab/text/common.text b/libtoolame-dab/text/common.text new file mode 100644 index 0000000..fdd6c6a --- /dev/null +++ b/libtoolame-dab/text/common.text @@ -0,0 +1,91 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: common.c,v 1.2 1997/01/19 22:28:29 rowlands Exp $ + * + * $Log: common.c,v $ + * Revision 1.2 1997/01/19 22:28:29 rowlands + * Layer 3 bug fixes from Seymour Shlien + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 2/25/91 Doulas Wong, start of version 1.0 records * + * Davis Pan * + * 5/10/91 W. Joseph Carter Created this file for all common * + * functions and global variables. * + * Ported to Macintosh and Unix. * + * Added Jean-Georges Fritsch's * + * "bitstream.c" package. * + * Added routines to handle AIFF PCM * + * sound files. * + * Added "mem_alloc()" and "mem_free()" * + * routines for memory allocation * + * portability. * + * Added routines to convert between * + * Apple SANE extended floating point * + * format and IEEE double precision * + * floating point format. For AIFF. * + * 02jul91 dpwe (Aware Inc) Moved allocation table input here; * + * Tables read from subdir TABLES_PATH. * + * Added some debug printout fns (Write*)* + * 7/10/91 Earle Jennings replacement of the one float by FLOAT * + * port to MsDos from MacIntosh version * + * 8/ 5/91 Jean-Georges Fritsch fixed bug in open_bit_stream_r() * + *10/ 1/91 S.I. Sudharsanan, Ported to IBM AIX platform. * + * Don H. Lee, * + * Peter W. Farrett * + *10/3/91 Don H. Lee implemented CRC-16 error protection * + * newly introduced functions are * + * I_CRC_calc, II_CRC_calc and * + * update_CRC. Additions and revisions * + * are marked with dhl for clarity * + *10/18/91 Jean-Georges Fritsch fixed bug in update_CRC(), * + * II_CRC_calc() and I_CRC_calc() * + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * 3/20/92 Jean-Georges Fritsch fixed bug in start-of-frame search * + * 6/15/92 Juan Pineda added refill_buffer(bs) "n" * + * initialization * + * 7/08/92 Susanne Ritscher MS-DOS, MSC6.0 port fixes * + * 7/27/92 Mike Li (re-)Port to MS-DOS * + * 8/19/92 Soren H. Nielsen Fixed bug in I_CRC_calc and in * + * II_CRC_calc. Added function: new_ext * + * for better MS-DOS compatability * + * 3/10/93 Kevin Peterson changed aiff_read_headers to handle * + * chunks in any order. now returns * + * position of sound data in file. * + * 3/31/93 Jens Spille changed IFF_* string compares to use * + * strcmp() * + * 5/30/93 Masahiro Iwadare removed the previous modification * + * for UNIX. * + * 8/27/93 Seymour Shlien, Fixes in Unix and MSDOS ports, * + * Daniel Lauzon, and * + * Bill Truerniet * + *--------------------------------------------------------------------* + * 8/24/93 Masahiro Iwadare Included IS modification in Layer III.* + * Changed for 1 pass decoding. * + * 9/07/93 Toshiyuki Ishino Integrated Layer III with Ver 3.9. * + *--------------------------------------------------------------------* + * 11/20/93 Masahiro Iwadare Integrated Layer III with Ver 4.0. * + *--------------------------------------------------------------------* + * 7/14/94 Juergen Koller rewind of bitbuffer added * + * 6/12/95 Soeren H. Nielsen Bug fix in new_ext(). * + * 7/11/95 Soeren H. Nielsen Changes for MPEG-2 LSF Layer I and II * + *--------------------------------------------------------------------* + * 8/02/95 mc@fivebats.com Added code to determine byte-order, * + * fixes to AIFF routines. Modified Mac * + * code to work with new Apple headers * + **********************************************************************/ diff --git a/libtoolame-dab/text/commonh.text b/libtoolame-dab/text/commonh.text new file mode 100644 index 0000000..b2c04eb --- /dev/null +++ b/libtoolame-dab/text/commonh.text @@ -0,0 +1,68 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: common.h,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: common.h,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 2/25/91 Doulas Wong, start of version 1.0 records * + * Davis Pan * + * 5/10/91 W. Joseph Carter Reorganized & renamed all ".h" files * + * into "common.h" and "encoder.h". * + * Ported to Macintosh and Unix. * + * Added additional type definitions for * + * AIFF, double/SANE and "bitstream.c". * + * Added function prototypes for more * + * rigorous type checking. * + * 27jun91 dpwe (Aware) Added "alloc_*" defs & prototypes * + * Defined new struct 'frame_params'. * + * Changed info.stereo to info.mode_ext * + * #define constants for mode types * + * Prototype arguments if PROTO_ARGS * + * 5/28/91 Earle Jennings added MS_DOS definition * + * MsDos function prototype declarations * + * 7/10/91 Earle Jennings added FLOAT definition as double * + *10/ 3/91 Don H. Lee implemented CRC-16 error protection * + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * Modified some function prototypes. * + * Changed BUFFER_SIZE back to 4096. * + * 7/27/92 Michael Li (re-)Ported to MS-DOS * + * 7/27/92 Masahiro Iwadare Ported to Convex * + * 8/07/92 mc@tv.tek.com * + * 8/10/92 Amit Gulati Ported to the AIX Platform (RS6000) * + * AIFF string constants redefined * + * 8/27/93 Seymour Shlien, Fixes in Unix and MSDOS ports, * + * Daniel Lauzon, and * + * Bill Truerniet * + *--------------------------------------------------------------------* + * 4/23/92 J. Pineda Added code for Layer III. * + * 11/9/92 Amit Gulati Added defines for layerIII stereo * + * modes. * + * 8/24/93 Masahiro Iwadare Included IS modification in Layer III.* + * Changed for 1 pass decoding. * + * 9/07/93 Toshiyuki Ishino Integrated Layer III with Ver 3.9. * + *--------------------------------------------------------------------* + * 11/20/93 Masahiro Iwadare Integrated Layer III with Ver 4.0. * + *--------------------------------------------------------------------* + * 7/14/94 Juergen Koller Fix for HPUX an IRIX in AIFF-Strings * + * 6/12/95 Soeren H. Nielsen Bug fix in new_ext(). * + * 7/11/95 Soeren H. Nielsen Added defs. for MPEG-2 LSF * + *--------------------------------------------------------------------* + * 8/02/95 mc@fivebats.com Changes to AIFF stuff for portability * + * to little-endian machines * + **********************************************************************/
\ No newline at end of file diff --git a/libtoolame-dab/text/encode.text b/libtoolame-dab/text/encode.text new file mode 100644 index 0000000..08a118e --- /dev/null +++ b/libtoolame-dab/text/encode.text @@ -0,0 +1,84 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: encode.c,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: encode.c,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 3/01/91 Douglas Wong, start of version 1.1 records * + * Davis Pan * + * 3/06/91 Douglas Wong rename: setup.h to endef.h * + * efilter to enfilter * + * ewindow to enwindow * + * integrated "quantizer", "scalefactor",* + * and "transmission" files * + * update routine "window_subband" * + * 3/31/91 Bill Aspromonte replaced read_filter by * + * create_an_filter * + * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * + * Incorporated Jean-Georges Fritsch's * + * "bitstream.c" package. * + * Incorporated Bill Aspromonte's * + * filterbank coefficient matrix * + * calculation routines and added * + * roundoff to coincide with specs. * + * Modified to strictly adhere to * + * encoded bitstream specs, including * + * "Berlin changes". * + * Modified PCM sound file handling to * + * process all incoming samples and fill * + * out last encoded frame with zeros * + * (silence) if needed. * + * Located and fixed numerous software * + * bugs and table data errors. * + * 19jun91 dpwe (Aware) moved "alloc_*" reader to common.c * + * Globals sblimit, alloc replaced by new* + * struct 'frame_params' passed as arg. * + * Added JOINT STEREO coding, layers I,II* + * Affects: *_bit_allocation, * + * subband_quantization, encode_bit_alloc* + * sample_encoding * + * 6/10/91 Earle Jennings modified II_subband_quantization to * + * resolve type cast problem for MS_DOS * + * 6/11/91 Earle Jennings modified to avoid overflow on MS_DOS * + * in routine filter_subband * + * 7/10/91 Earle Jennings port to MsDos from MacIntosh version * + * 8/ 8/91 Jens Spille Change for MS-C6.00 * + *10/ 1/91 S.I. Sudharsanan, Ported to IBM AIX platform. * + * Don H. Lee, * + * Peter W. Farrett * + *10/ 3/91 Don H. Lee implemented CRC-16 error protection * + * newly introduced function encode_CRC * + *11/ 8/91 Kathy Wang Documentation of code * + * All variablenames are referred to * + * with surrounding pound (#) signs * + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * 6/16/92 Shaun Astarabadi Changed I_scale_factor_calc() and * + * II_scale_factor_calc() to use scale * + * factor 0 thru 62 only and not to * + * encode index 63 into the bit stream. * + * 7/27/92 Mike Li (re-)Port to MS-DOS * + * 9/22/92 jddevine@aware.com Fixed _scale_factor_calc() defs * + * 3/31/93 Giogio Dimino changed II_a_bit_allocation() from: * + * if( ad > ...) to if(ad >= ...) * + * 8/05/93 TEST changed I_a_bit_allocation() from: * + * if( ad > ...) to if(ad >= ...) * + * 8/02/95 mc@fivebats.com Changed audio file reading code to * + * read samples big-endian * + *10/15/95 mc@fivebats.com Modified get_audio() for layer3-LSF * + **********************************************************************/
\ No newline at end of file diff --git a/libtoolame-dab/text/encoderh.text b/libtoolame-dab/text/encoderh.text new file mode 100644 index 0000000..fc79701 --- /dev/null +++ b/libtoolame-dab/text/encoderh.text @@ -0,0 +1,44 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: encoder.h,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: encoder.h,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 2/25/91 Doulas Wong, start of version 1.0 records * + * Davis Pan * + * 5/10/91 W. Joseph Carter Reorganized & renamed all ".h" files * + * into "common.h" and "encoder.h". * + * Ported to Macintosh and Unix. * + * Added function prototypes for more * + * rigorous type checking. * + * 27jun91 dpwe (Aware) moved "alloc_*" types, pros to common * + * Use ifdef PROTO_ARGS for prototypes * + * prototypes reflect frame_params struct* + * 7/10/91 Earle Jennings Conversion of all floats to FLOAT * + * 10/3/91 Don H. Lee implemented CRC-16 error protection * + * Additions and revisions are marked * + * with "dhl" for clarity * + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * Modified some function prototypes. * + * 7/27/92 Masahiro Iwadare FFT modifications for Layer 3 * + * 8/3/92 Mike Li removed declaration _stklen for DOS. * + * 9/22/92 jddevine@aware.com Fix protos for _scale_factor_calc() * + * 11/04/94 Jon Rowlands Fix protos for usage() * + * 07/11/95 Soeren H. Nielsen Changed defs. and protos for LSF * + **********************************************************************/
\ No newline at end of file diff --git a/libtoolame-dab/text/musicin.text b/libtoolame-dab/text/musicin.text new file mode 100644 index 0000000..5783f71 --- /dev/null +++ b/libtoolame-dab/text/musicin.text @@ -0,0 +1,104 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: musicin.c,v 1.2 1997/01/19 22:28:29 rowlands Exp $ + * + * $Log: musicin.c,v $ + * Revision 1.2 1997/01/19 22:28:29 rowlands + * Layer 3 bug fixes from Seymour Shlien + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 3/01/91 Douglas Wong, start of version 1.1 records * + * Davis Pan * + * 3/06/91 Douglas Wong, rename: setup.h to endef.h * + * removed extraneous variables * + * 3/21/91 J.Georges Fritsch introduction of the bit-stream * + * package. This package allows you * + * to generate the bit-stream in a * + * binary or ascii format * + * 3/31/91 Bill Aspromonte replaced the read of the SB matrix * + * by an "code generated" one * + * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * + * Incorporated Jean-Georges Fritsch's * + * "bitstream.c" package. * + * Modified to strictly adhere to * + * encoded bitstream specs, including * + * "Berlin changes". * + * Modified user interface dialog & code * + * to accept any input & output * + * filenames desired. Also added * + * de-emphasis prompt and final bail-out * + * opportunity before encoding. * + * Added AIFF PCM sound file reading * + * capability. * + * Modified PCM sound file handling to * + * process all incoming samples and fill * + * out last encoded frame with zeros * + * (silence) if needed. * + * Located and fixed numerous software * + * bugs and table data errors. * + * 27jun91 dpwe (Aware Inc) Used new frame_params struct. * + * Clear all automatic arrays. * + * Changed some variable names, * + * simplified some code. * + * Track number of bits actually sent. * + * Fixed padding slot, stereo bitrate * + * Added joint-stereo : scales L+R. * + * 6/12/91 Earle Jennings added fix for MS_DOS in obtain_param * + * 6/13/91 Earle Jennings added stack length adjustment before * + * main for MS_DOS * + * 7/10/91 Earle Jennings conversion of all float to FLOAT * + * port to MsDos from MacIntosh completed* + * 8/ 8/91 Jens Spille Change for MS-C6.00 * + * 8/22/91 Jens Spille new obtain_parameters() * + *10/ 1/91 S.I. Sudharsanan, Ported to IBM AIX platform. * + * Don H. Lee, * + * Peter W. Farrett * + *10/ 3/91 Don H. Lee implemented CRC-16 error protection * + * newly introduced functions are * + * I_CRC_calc, II_CRC_calc and encode_CRC* + * Additions and revisions are marked * + * with "dhl" for clarity * + *11/11/91 Katherine Wang Documentation of code. * + * (variables in documentation are * + * surround by the # symbol, and an '*'* + * denotes layer I or II versions) * + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * 2/25/92 Masahiro Iwadare made code cleaner and more consistent * + * 8/07/92 Mike Coleman make exit() codes return error status * + * made slight changes for portability * + *19 aug 92 Soren H. Nielsen Changed MS-DOS file name extensions. * + * 8/25/92 Shaun Astarabadi Replaced rint() function with explicit* + * rounding for portability with MSDOS. * + * 9/22/92 jddevine@aware.com Fixed _scale_factor_calc() calls. * + *10/19/92 Masahiro Iwadare added info->mode and info->mode_ext * + * updates for AIFF format files * + * 3/10/93 Kevin Peterson In parse_args, only set non default * + * bit rate if specified in arg list. * + * Use return value from aiff_read_hdrs * + * to fseek to start of sound data * + * 7/26/93 Davis Pan fixed bug in printing info->mode_ext * + * value for joint stereo condition * + * 8/27/93 Seymour Shlien, Fixes in Unix and MSDOS ports, * + * Daniel Lauzon, and * + * Bill Truerniet * + * 11/7/95 Soeren H. Nielsen LSF added. Bug fix in MSDOS ext. * + * 8/02/95 mc@fivebats.com Changed default bitrate selection so * + * it works with the new LSF stuff * + *10/01/95 mc@fivebats.com Added layer3 * + **********************************************************************/
\ No newline at end of file diff --git a/libtoolame-dab/text/psy.text b/libtoolame-dab/text/psy.text new file mode 100644 index 0000000..1e3c102 --- /dev/null +++ b/libtoolame-dab/text/psy.text @@ -0,0 +1,26 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: psy.c,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: psy.c,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 2/25/91 Davis Pan start of version 1.0 records * + * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * + * 7/10/91 Earle Jennings Ported to MsDos. * + * replace of floats with FLOAT * + * 2/11/92 W. Joseph Carter Fixed mem_alloc() arg for "absthr". * + * 7/24/92 M. Iwadare HANN window coefficients modified. * + * 7/27/92 Masahiro Iwadare Bug fix, FFT modification for Layer 3 * + * 7/27/92 Masahiro Iwadare Bug fix, "new", "old", and "oldest" * + * updates * + * 8/07/92 Mike Coleman Bug fix, read_absthr() * + * 95/3/21 Jon Rowlands Removed extra debug statements * + **********************************************************************/ diff --git a/libtoolame-dab/text/tonal.text b/libtoolame-dab/text/tonal.text new file mode 100644 index 0000000..f40499e --- /dev/null +++ b/libtoolame-dab/text/tonal.text @@ -0,0 +1,67 @@ +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: tonal.c,v 1.1 1996/02/14 04:04:23 rowlands Exp $ + * + * $Log: tonal.c,v $ + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 2/25/91 Douglas Wong start of version 1.1 records * + * 3/06/91 Douglas Wong rename: setup.h to endef.h * + * updated I_psycho_one and II_psycho_one* + * 3/11/91 W. J. Carter Added Douglas Wong's updates dated * + * 3/9/91 for I_Psycho_One() and for * + * II_Psycho_One(). * + * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * + * Located and fixed numerous software * + * bugs and table data errors. * + * 6/11/91 Davis Pan corrected several bugs * + * based on comments from H. Fuchs * + * 01jul91 dpwe (Aware Inc.) Made pow() args float * + * Removed logical bug in I_tonal_label: * + * Sometimes *tone returned == STOP * + * 7/10/91 Earle Jennings no change necessary in port to MsDos * + * 11sep91 dpwe@aware.com Subtracted 90.3dB from II_f_f_t peaks * + * 10/1/91 Peter W. Farrett Updated II_Psycho_One(),I_Psycho_One()* + * to include comments. * + *11/29/91 Masahiro Iwadare Bug fix regarding POWERNORM * + * fixed several other miscellaneous bugs* + * 2/11/92 W. Joseph Carter Ported new code to Macintosh. Most * + * important fixes involved changing * + * 16-bit ints to long or unsigned in * + * bit alloc routines for quant of 65535 * + * and passing proper function args. * + * Removed "Other Joint Stereo" option * + * and made bitrate be total channel * + * bitrate, irrespective of the mode. * + * Fixed many small bugs & reorganized. * + * 2/12/92 Masahiro Iwadare Fixed some potential bugs in * + * Davis Pan subsampling() * + * 2/25/92 Masahiro Iwadare Fixed some more potential bugs * + * 6/24/92 Tan Ah Peng Modified window for FFT * + * (denominator N-1 to N) * + * Updated all critical band rate & * + * absolute threshold tables and critical* + * boundaries for use with Layer I & II * + * Corrected boundary limits for tonal * + * component computation * + * Placement of non-tonal component at * + * geometric mean of critical band * + * (previous placement method commented * + * out - can be used if desired) * + * 3/01/93 Mike Li Infinite looping fix in noise_label() * + * 3/19/93 Jens Spille fixed integer overflow problem in * + * psychoacoutic model 1 * + * 3/19/93 Giorgio Dimino modifications to better account for * + * tonal and non-tonal components * + * 5/28/93 Sriram Jayasimha "London" mod. to psychoacoustic model1* + * 8/05/93 Masahiro Iwadare noise_label modification "option" * + * 1/21/94 Seymore Shlien fixed another infinite looping problem* + * 7/12/95 Soeren H. Nielsen Changes for LSF, new tables * + **********************************************************************/
\ No newline at end of file diff --git a/libtoolame-dab/toolame.c b/libtoolame-dab/toolame.c new file mode 100644 index 0000000..09eb69e --- /dev/null +++ b/libtoolame-dab/toolame.c @@ -0,0 +1,1457 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if defined(JACK_INPUT) +# include <jack/jack.h> +# include <jack/ringbuffer.h> +#endif +#include "common.h" +#include "encoder.h" +#include "musicin.h" +#include "options.h" +#include "audio_read.h" +#include "bitstream.h" +#include "mem.h" +#include "crc.h" +#include "psycho_n1.h" +#include "psycho_0.h" +#include "psycho_1.h" +#include "psycho_2.h" +#include "psycho_3.h" +#include "psycho_4.h" +#include "encode.h" +#include "availbits.h" +#include "subband.h" +#include "encode_new.h" +#include "toolame.h" +#include "xpad.h" +#include "utils.h" +#include "vlc_input.h" +#include "zmqoutput.h" + +#include <assert.h> + +music_in_t musicin; +Bit_stream_struc bs; +char *programName; +char toolameversion[] = "0.2l-ODR"; + +const int FPAD_LENGTH=2; + +void global_init (void) +{ + glopts.usepsy = TRUE; + glopts.usepadbit = TRUE; + glopts.quickmode = FALSE; + glopts.quickcount = 10; + glopts.downmix = FALSE; + glopts.byteswap = FALSE; + glopts.channelswap = FALSE; + glopts.vbr = FALSE; + glopts.vbrlevel = 0; + glopts.athlevel = 0; + glopts.verbosity = 2; + glopts.input_select = 0; +} + +/************************************************************************ + * + * main + * + * PURPOSE: MPEG II Encoder with + * psychoacoustic models 1 (MUSICAM) and 2 (AT&T) + * + * SEMANTICS: One overlapping frame of audio of up to 2 channels are + * processed at a time in the following order: + * (associated routines are in parentheses) + * + * 1. Filter sliding window of data to get 32 subband + * samples per channel. + * (window_subband,filter_subband) + * + * 2. If joint stereo mode, combine left and right channels + * for subbands above #jsbound#. + * (combine_LR) + * + * 3. Calculate scalefactors for the frame, and + * also calculate scalefactor select information. + * (*_scale_factor_calc) + * + * 4. Calculate psychoacoustic masking levels using selected + * psychoacoustic model. + * (psycho_i, psycho_ii) + * + * 5. Perform iterative bit allocation for subbands with low + * mask_to_noise ratios using masking levels from step 4. + * (*_main_bit_allocation) + * + * 6. If error protection flag is active, add redundancy for + * error protection. + * (*_CRC_calc) + * + * 7. Pack bit allocation, scalefactors, and scalefactor select + *headerrmation onto bitstream. + * (*_encode_bit_alloc,*_encode_scale,transmission_pattern) + * + * 8. Quantize subbands and pack them into bitstream + * (*_subband_quantization, *_sample_encoding) + * + ************************************************************************/ + +static frame_info frame; +static frame_header header; +static int frameNum; +static int xpad_len; +static int psycount; +static int model; +static unsigned int crc; + +typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT]; +typedef double JSBS[3][SCALE_BLOCK][SBLIMIT]; +typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT]; + +static SBS *sb_sample; +static JSBS *j_sample; +static SUB *subband; + +static unsigned int scalar[2][3][SBLIMIT]; +static unsigned int j_scale[3][SBLIMIT]; + +static double smr[2][SBLIMIT]; +static double max_sc[2][SBLIMIT]; +static short sam[2][1344]; + +/* Used to keep the SNR values for the fast/quick psy models */ +static FLOAT smrdef[2][32]; + +static unsigned int scfsi[2][SBLIMIT]; +static unsigned int bit_alloc[2][SBLIMIT]; + +static uint8_t* xpad_data; + +int toolame_init(void) +{ + frameNum = 0; + psycount = 0; + + header.extension = 0; + frame.header = &header; + frame.tab_num = -1; /* no table loaded */ + frame.alloc = NULL; + header.version = MPEG_AUDIO_ID; /* Default: MPEG-1 */ + + sb_sample = (SBS *) mem_alloc (sizeof (SBS), "sb_sample"); + j_sample = (JSBS *) mem_alloc (sizeof (JSBS), "j_sample"); + subband = (SUB *) mem_alloc (sizeof (SUB), "subband"); + memset ((char *) scalar, 0, sizeof (scalar)); + memset ((char *) j_scale, 0, sizeof (j_scale)); + memset ((char *) smr, 0, sizeof (smr)); + memset ((char *) max_sc, 0, sizeof (max_sc)); + memset ((char *) sam, 0, sizeof (sam)); + memset ((char *) scfsi, 0, sizeof (scfsi)); + memset ((char *) bit_alloc, 0, sizeof (bit_alloc)); + + xpad_data = NULL; + + return 0; +} + +int toolame_encode_frame(short buffer[2][1152]) +{ + extern int minimum; + const int nch = frame.nch; + const int error_protection = header.error_protection; + + short *win_buf[2] = {&buffer[0][0], &buffer[1][0]}; + + int adb = available_bits (&header, &glopts); + int lg_frame = adb / 8; + if (header.dab_extension) { + /* You must have one frame in memory if you are in DAB mode */ + /* in conformity of the norme ETS 300 401 http://www.etsi.org */ + /* see bitstream.c */ + if (frameNum == 1) + minimum = lg_frame + MINIMUM; + adb -= header.dab_extension * 8 + (xpad_len ? xpad_len : FPAD_LENGTH) * 8; + } + + { + int gr, bl, ch; + /* New polyphase filter + Combines windowing and filtering. Ricardo Feb'03 */ + for( gr = 0; gr < 3; gr++ ) + for ( bl = 0; bl < 12; bl++ ) + for ( ch = 0; ch < nch; ch++ ) + WindowFilterSubband( &buffer[ch][gr * 12 * 32 + 32 * bl], ch, + &(*sb_sample)[ch][gr][bl][0] ); + } + +#ifdef REFERENCECODE + { + /* Old code. left here for reference */ + int gr, bl, ch; + for (gr = 0; gr < 3; gr++) + for (bl = 0; bl < SCALE_BLOCK; bl++) + for (ch = 0; ch < nch; ch++) { + window_subband (&win_buf[ch], &(*win_que)[ch][0], ch); + filter_subband (&(*win_que)[ch][0], &(*sb_sample)[ch][gr][bl][0]); + } + } +#endif + + +#ifdef NEWENCODE + scalefactor_calc_new(*sb_sample, scalar, nch, frame.sblimit); + find_sf_max (scalar, &frame, max_sc); + if (frame.actual_mode == MPG_MD_JOINT_STEREO) { + /* this way we calculate more mono than we need */ + /* but it is cheap */ + combine_LR_new (*sb_sample, *j_sample, frame.sblimit); + scalefactor_calc_new (j_sample, &j_scale, 1, frame.sblimit); + } +#else + scale_factor_calc (*sb_sample, scalar, nch, frame.sblimit); + pick_scale (scalar, &frame, max_sc); + if (frame.actual_mode == MPG_MD_JOINT_STEREO) { + /* this way we calculate more mono than we need */ + /* but it is cheap */ + combine_LR (*sb_sample, *j_sample, frame.sblimit); + scale_factor_calc (j_sample, &j_scale, 1, frame.sblimit); + } +#endif + + + + if ((glopts.quickmode == TRUE) && (++psycount % glopts.quickcount != 0)) { + /* We're using quick mode, so we're only calculating the model every + 'quickcount' frames. Otherwise, just copy the old ones across */ + for (int ch = 0; ch < nch; ch++) { + for (int sb = 0; sb < SBLIMIT; sb++) + smr[ch][sb] = smrdef[ch][sb]; + } + } else { + /* calculate the psymodel */ + switch (model) { + case -1: + psycho_n1 (smr, nch); + break; + case 0: /* Psy Model A */ + psycho_0 (smr, nch, scalar, (FLOAT) s_freq[header.version][header.sampling_frequency] * 1000); + break; + case 1: + psycho_1 (buffer, max_sc, smr, &frame); + break; + case 2: + for (int ch = 0; ch < nch; ch++) { + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + } + break; + case 3: + /* Modified psy model 1 */ + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + break; + case 4: + /* Modified Psycho Model 2 */ + for (int ch = 0; ch < nch; ch++) { + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + } + break; + case 5: + /* Model 5 comparse model 1 and 3 */ + psycho_1 (buffer, max_sc, smr, &frame); + fprintf(stdout,"1 "); + smr_dump(smr,nch); + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + fprintf(stdout,"3 "); + smr_dump(smr,nch); + break; + case 6: + /* Model 6 compares model 2 and 4 */ + for (int ch = 0; ch < nch; ch++) + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"2 "); + smr_dump(smr,nch); + for (int ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4 "); + smr_dump(smr,nch); + break; + case 7: + fprintf(stdout,"Frame: %i\n",frameNum); + /* Dump the SMRs for all models */ + psycho_1 (buffer, max_sc, smr, &frame); + fprintf(stdout,"1"); + smr_dump(smr, nch); + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + fprintf(stdout,"3"); + smr_dump(smr,nch); + for (int ch = 0; ch < nch; ch++) + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"2"); + smr_dump(smr,nch); + for (int ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4"); + smr_dump(smr,nch); + break; + case 8: + /* Compare 0 and 4 */ + psycho_n1 (smr, nch); + fprintf(stdout,"0"); + smr_dump(smr,nch); + + for (int ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4"); + smr_dump(smr,nch); + break; + default: + fprintf (stderr, "Invalid psy model specification: %i\n", model); + exit (0); + } + + if (glopts.quickmode == TRUE) + /* copy the smr values and reuse them later */ + for (int ch = 0; ch < nch; ch++) { + for (int sb = 0; sb < SBLIMIT; sb++) + smrdef[ch][sb] = smr[ch][sb]; + } + + if (glopts.verbosity > 4) + smr_dump(smr, nch); + + + + + } + +#ifdef NEWENCODE + sf_transmission_pattern (scalar, scfsi, &frame); + main_bit_allocation_new (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + //main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + + if (error_protection) + CRC_calc (&frame, bit_alloc, scfsi, &crc); + + write_header (&frame, &bs); + //encode_info (&frame, &bs); + if (error_protection) + putbits (&bs, crc, 16); + write_bit_alloc (bit_alloc, &frame, &bs); + //encode_bit_alloc (bit_alloc, &frame, &bs); + write_scalefactors(bit_alloc, scfsi, scalar, &frame, &bs); + //encode_scale (bit_alloc, scfsi, scalar, &frame, &bs); + subband_quantization_new (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + *subband, &frame); + //subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + // *subband, &frame); + write_samples_new(*subband, bit_alloc, &frame, &bs); + //sample_encoding (*subband, bit_alloc, &frame, &bs); +#else + transmission_pattern (scalar, scfsi, &frame); + main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + if (error_protection) + CRC_calc (&frame, bit_alloc, scfsi, &crc); + encode_info (&frame, &bs); + if (error_protection) + encode_CRC (crc, &bs); + encode_bit_alloc (bit_alloc, &frame, &bs); + encode_scale (bit_alloc, scfsi, scalar, &frame, &bs); + subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + *subband, &frame); + sample_encoding (*subband, bit_alloc, &frame, &bs); +#endif + + + /* If not all the bits were used, write out a stack of zeros */ + for (int i = 0; i < adb; i++) { + put1bit (&bs, 0); + } + + + if (xpad_len) { + assert(xpad_len > 2); + + // insert available X-PAD + for (int i = header.dab_length - xpad_len; + i < header.dab_length - FPAD_LENGTH; + i++) { + putbits (&bs, xpad_data[i], 8); + } + } + + + for (int i = header.dab_extension - 1; i >= 0; i--) { + CRC_calcDAB (&frame, bit_alloc, scfsi, scalar, &crc, i); + /* this crc is for the previous frame in DAB mode */ + if (bs.buf_byte_idx + lg_frame < bs.buf_size) + bs.buf[bs.buf_byte_idx + lg_frame] = crc; + /* reserved 2 bytes for F-PAD in DAB mode */ + putbits (&bs, crc, 8); + } + + if (xpad_len) { + /* The F-PAD is also given us by mot-encoder */ + putbits (&bs, xpad_data[header.dab_length - 2], 8); + putbits (&bs, xpad_data[header.dab_length - 1], 8); + } + else { + putbits (&bs, 0, 16); // FPAD is all-zero + } +} + +int oldmain (int argc, char **argv) +{ + SBS *sb_sample; + JSBS *j_sample; +#ifdef REFERENCECODE + typedef double IN[2][HAN_SIZE]; + IN *win_que; +#endif + typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT]; + SUB *subband; + + frame_info frame; + frame_header header; + char original_file_name[MAX_NAME_SIZE]; + char encoded_file_name[MAX_NAME_SIZE]; + short **win_buf; + static short buffer[2][1152]; + static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT]; + static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT]; + static double smr[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT]; + // FLOAT snr32[32]; + short sam[2][1344]; /* was [1056]; */ + int model, nch, error_protection; + static unsigned int crc; + int sb, ch, adb; + unsigned long frameBits, sentBits = 0; + unsigned long num_samples; + int lg_frame; + int i; + + /* Keep track of peaks */ + int peak_left = 0; + int peak_right = 0; + + char* mot_file = NULL; + char* icy_file = NULL; + + /* Used to keep the SNR values for the fast/quick psy models */ + static FLOAT smrdef[2][32]; + + static int psycount = 0; + extern int minimum; + + sb_sample = (SBS *) mem_alloc (sizeof (SBS), "sb_sample"); + j_sample = (JSBS *) mem_alloc (sizeof (JSBS), "j_sample"); +#ifdef REFERENCECODE + win_que = (IN *) mem_alloc (sizeof (IN), "Win_que"); +#endif + subband = (SUB *) mem_alloc (sizeof (SUB), "subband"); + win_buf = (short **) mem_alloc (sizeof (short *) * 2, "win_buf"); + + /* clear buffers */ + memset ((char *) buffer, 0, sizeof (buffer)); + memset ((char *) bit_alloc, 0, sizeof (bit_alloc)); + memset ((char *) scalar, 0, sizeof (scalar)); + memset ((char *) j_scale, 0, sizeof (j_scale)); + memset ((char *) scfsi, 0, sizeof (scfsi)); + memset ((char *) smr, 0, sizeof (smr)); + memset ((char *) lgmin, 0, sizeof (lgmin)); + memset ((char *) max_sc, 0, sizeof (max_sc)); + //memset ((char *) snr32, 0, sizeof (snr32)); + memset ((char *) sam, 0, sizeof (sam)); + + global_init (); + + header.extension = 0; + frame.header = &header; + frame.tab_num = -1; /* no table loaded */ + frame.alloc = NULL; + header.version = MPEG_AUDIO_ID; /* Default: MPEG-1 */ + + programName = argv[0]; + if (argc == 1) /* no command-line args */ + short_usage (); + else + parse_args (argc, argv, &frame, &model, &num_samples, original_file_name, + encoded_file_name, &mot_file, &icy_file); + print_config (&frame, &model, original_file_name, encoded_file_name); + + uint8_t* xpad_data = NULL; + if (mot_file) { + if (header.dab_length <= 0) { + fprintf(stderr, "Invalid XPAD length specified\n"); + return 1; + } + + int err = xpad_init(mot_file, header.dab_length + 1); + if (err == -1) { + fprintf(stderr, "XPAD reader initialisation failed\n"); + return 1; + } + + xpad_data = malloc(header.dab_length + 1); + } + + /* this will load the alloc tables and do some other stuff */ + hdr_to_frps (&frame); + nch = frame.nch; + error_protection = header.error_protection; + + unsigned long samps_read; + while ((samps_read = get_audio(&musicin, buffer, num_samples, nch, &header)) > 0) { + /* Check if we have new PAD data + */ + int xpad_len = 0; + if (mot_file) { + xpad_len = xpad_read_len(xpad_data, header.dab_length + 1); + + if (xpad_len == -1) { + fprintf(stderr, "Error reading XPAD data\n"); + xpad_len = 0; + } + else if (xpad_len == 0) { + // no PAD available + } + else if (xpad_len == header.dab_length + 1) { +//#define XPAD_DEBUG +#ifdef XPAD_DEBUG + fprintf(stderr, "XPAD:"); + for (i = 0; i < xpad_len; i++) + fprintf(stderr, " %02X", xpad_data[i]); + fprintf(stderr, "\n"); +#endif + // everything OK + xpad_len = xpad_data[header.dab_length]; + assert(xpad_len > 2); + } + else { + fprintf(stderr, "xpad length=%d\n", xpad_len); + abort(); + } + } + + unsigned long j; + for (j = 0; j < 1152; j++) { + peak_left = MAX(peak_left, buffer[0][j]); + } + for (j = 0; j < 1152; j++) { + peak_right = MAX(peak_right, buffer[1][j]); + } + + // We can always set the zmq peaks, even if the output is not + // used, it just writes some variables + zmqoutput_set_peaks(peak_left, peak_right); + + if (glopts.verbosity > 1) + if (++frameNum % 10 == 0) { + + fprintf(stderr, "[%4u", frameNum); + + if (mot_file) { + fprintf(stderr, " %s", + xpad_len > 0 ? "p" : " "); + } + + if (glopts.show_level) { + fprintf(stderr, " (%6d|%-6d) ", + peak_left, peak_right); + + fprintf(stderr, "] [%6s|%-6s]\r", + level(0, &peak_left), + level(1, &peak_right) ); + } + else { + fprintf(stderr, "]\r"); + } + } + + fflush(stderr); + win_buf[0] = &buffer[0][0]; + win_buf[1] = &buffer[1][0]; + + adb = available_bits (&header, &glopts); + lg_frame = adb / 8; + if (header.dab_extension) { + /* You must have one frame in memory if you are in DAB mode */ + /* in conformity of the norme ETS 300 401 http://www.etsi.org */ + /* see bitstream.c */ + if (frameNum == 1) + minimum = lg_frame + MINIMUM; + adb -= header.dab_extension * 8 + (xpad_len ? xpad_len : FPAD_LENGTH) * 8; + } + + { + int gr, bl, ch; + /* New polyphase filter + Combines windowing and filtering. Ricardo Feb'03 */ + for( gr = 0; gr < 3; gr++ ) + for ( bl = 0; bl < 12; bl++ ) + for ( ch = 0; ch < nch; ch++ ) + WindowFilterSubband( &buffer[ch][gr * 12 * 32 + 32 * bl], ch, + &(*sb_sample)[ch][gr][bl][0] ); + } + +#ifdef REFERENCECODE + { + /* Old code. left here for reference */ + int gr, bl, ch; + for (gr = 0; gr < 3; gr++) + for (bl = 0; bl < SCALE_BLOCK; bl++) + for (ch = 0; ch < nch; ch++) { + window_subband (&win_buf[ch], &(*win_que)[ch][0], ch); + filter_subband (&(*win_que)[ch][0], &(*sb_sample)[ch][gr][bl][0]); + } + } +#endif + + +#ifdef NEWENCODE + scalefactor_calc_new(*sb_sample, scalar, nch, frame.sblimit); + find_sf_max (scalar, &frame, max_sc); + if (frame.actual_mode == MPG_MD_JOINT_STEREO) { + /* this way we calculate more mono than we need */ + /* but it is cheap */ + combine_LR_new (*sb_sample, *j_sample, frame.sblimit); + scalefactor_calc_new (j_sample, &j_scale, 1, frame.sblimit); + } +#else + scale_factor_calc (*sb_sample, scalar, nch, frame.sblimit); + pick_scale (scalar, &frame, max_sc); + if (frame.actual_mode == MPG_MD_JOINT_STEREO) { + /* this way we calculate more mono than we need */ + /* but it is cheap */ + combine_LR (*sb_sample, *j_sample, frame.sblimit); + scale_factor_calc (j_sample, &j_scale, 1, frame.sblimit); + } +#endif + + + + if ((glopts.quickmode == TRUE) && (++psycount % glopts.quickcount != 0)) { + /* We're using quick mode, so we're only calculating the model every + 'quickcount' frames. Otherwise, just copy the old ones across */ + for (ch = 0; ch < nch; ch++) { + for (sb = 0; sb < SBLIMIT; sb++) + smr[ch][sb] = smrdef[ch][sb]; + } + } else { + /* calculate the psymodel */ + switch (model) { + case -1: + psycho_n1 (smr, nch); + break; + case 0: /* Psy Model A */ + psycho_0 (smr, nch, scalar, (FLOAT) s_freq[header.version][header.sampling_frequency] * 1000); + break; + case 1: + psycho_1 (buffer, max_sc, smr, &frame); + break; + case 2: + for (ch = 0; ch < nch; ch++) { + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + } + break; + case 3: + /* Modified psy model 1 */ + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + break; + case 4: + /* Modified Psycho Model 2 */ + for (ch = 0; ch < nch; ch++) { + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + } + break; + case 5: + /* Model 5 comparse model 1 and 3 */ + psycho_1 (buffer, max_sc, smr, &frame); + fprintf(stdout,"1 "); + smr_dump(smr,nch); + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + fprintf(stdout,"3 "); + smr_dump(smr,nch); + break; + case 6: + /* Model 6 compares model 2 and 4 */ + for (ch = 0; ch < nch; ch++) + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"2 "); + smr_dump(smr,nch); + for (ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4 "); + smr_dump(smr,nch); + break; + case 7: + fprintf(stdout,"Frame: %i\n",frameNum); + /* Dump the SMRs for all models */ + psycho_1 (buffer, max_sc, smr, &frame); + fprintf(stdout,"1"); + smr_dump(smr, nch); + psycho_3 (buffer, max_sc, smr, &frame, &glopts); + fprintf(stdout,"3"); + smr_dump(smr,nch); + for (ch = 0; ch < nch; ch++) + psycho_2 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"2"); + smr_dump(smr,nch); + for (ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4"); + smr_dump(smr,nch); + break; + case 8: + /* Compare 0 and 4 */ + psycho_n1 (smr, nch); + fprintf(stdout,"0"); + smr_dump(smr,nch); + + for (ch = 0; ch < nch; ch++) + psycho_4 (&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32, + (FLOAT) s_freq[header.version][header.sampling_frequency] * + 1000, &glopts); + fprintf(stdout,"4"); + smr_dump(smr,nch); + break; + default: + fprintf (stderr, "Invalid psy model specification: %i\n", model); + exit (0); + } + + if (glopts.quickmode == TRUE) + /* copy the smr values and reuse them later */ + for (ch = 0; ch < nch; ch++) { + for (sb = 0; sb < SBLIMIT; sb++) + smrdef[ch][sb] = smr[ch][sb]; + } + + if (glopts.verbosity > 4) + smr_dump(smr, nch); + + + + + } + +#ifdef NEWENCODE + sf_transmission_pattern (scalar, scfsi, &frame); + main_bit_allocation_new (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + //main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + + if (error_protection) + CRC_calc (&frame, bit_alloc, scfsi, &crc); + + write_header (&frame, &bs); + //encode_info (&frame, &bs); + if (error_protection) + putbits (&bs, crc, 16); + write_bit_alloc (bit_alloc, &frame, &bs); + //encode_bit_alloc (bit_alloc, &frame, &bs); + write_scalefactors(bit_alloc, scfsi, scalar, &frame, &bs); + //encode_scale (bit_alloc, scfsi, scalar, &frame, &bs); + subband_quantization_new (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + *subband, &frame); + //subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + // *subband, &frame); + write_samples_new(*subband, bit_alloc, &frame, &bs); + //sample_encoding (*subband, bit_alloc, &frame, &bs); +#else + transmission_pattern (scalar, scfsi, &frame); + main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts); + if (error_protection) + CRC_calc (&frame, bit_alloc, scfsi, &crc); + encode_info (&frame, &bs); + if (error_protection) + encode_CRC (crc, &bs); + encode_bit_alloc (bit_alloc, &frame, &bs); + encode_scale (bit_alloc, scfsi, scalar, &frame, &bs); + subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc, + *subband, &frame); + sample_encoding (*subband, bit_alloc, &frame, &bs); +#endif + + + /* If not all the bits were used, write out a stack of zeros */ + for (i = 0; i < adb; i++) + put1bit (&bs, 0); + + + if (xpad_len) { + assert(xpad_len > 2); + + // insert available X-PAD + for (i = header.dab_length - xpad_len; i < header.dab_length - FPAD_LENGTH; i++) + putbits (&bs, xpad_data[i], 8); + } + + + for (i = header.dab_extension - 1; i >= 0; i--) { + CRC_calcDAB (&frame, bit_alloc, scfsi, scalar, &crc, i); + /* this crc is for the previous frame in DAB mode */ + if (bs.buf_byte_idx + lg_frame < bs.buf_size) + bs.buf[bs.buf_byte_idx + lg_frame] = crc; + /* reserved 2 bytes for F-PAD in DAB mode */ + putbits (&bs, crc, 8); + } + + if (xpad_len) { + /* The F-PAD is also given us by mot-encoder */ + putbits (&bs, xpad_data[header.dab_length - 2], 8); + putbits (&bs, xpad_data[header.dab_length - 1], 8); + } + else { + putbits (&bs, 0, 16); // FPAD is all-zero + } + +#if defined(VLC_INPUT) + if (glopts.input_select == INPUT_SELECT_VLC) { + vlc_in_write_icy(); + } +#endif + + + frameBits = sstell (&bs) - sentBits; + + if (frameBits % 8) { /* a program failure */ + fprintf (stderr, "Sent %ld bits = %ld slots plus %ld\n", frameBits, + frameBits / 8, frameBits % 8); + fprintf (stderr, "If you are reading this, the program is broken\n"); + fprintf (stderr, "Please report a bug.\n"); + exit(1); + } + + sentBits += frameBits; + + // Reset peak measurement + peak_left = 0; + peak_right = 0; + } + + fprintf(stdout, "Main loop has quit with samps_read = %zu\n", samps_read); + + close_bit_stream_w (&bs); + + if ((glopts.verbosity > 1) && (glopts.vbr == TRUE)) { + int i; +#ifdef NEWENCODE + extern int vbrstats_new[15]; +#else + extern int vbrstats[15]; +#endif + fprintf (stdout, "VBR stats:\n"); + for (i = 1; i < 15; i++) + fprintf (stdout, "%4i ", bitrate[header.version][i]); + fprintf (stdout, "\n"); + for (i = 1; i < 15; i++) +#ifdef NEWENCODE + fprintf (stdout,"%4i ",vbrstats_new[i]); +#else + fprintf (stdout, "%4i ", vbrstats[i]); +#endif + fprintf (stdout, "\n"); + } + + fprintf (stderr, + "Avg slots/frame = %.3f; b/smp = %.2f; bitrate = %.3f kbps\n", + (FLOAT) sentBits / (frameNum * 8), + (FLOAT) sentBits / (frameNum * 1152), + (FLOAT) sentBits / (frameNum * 1152) * + s_freq[header.version][header.sampling_frequency]); + + if (glopts.input_select == INPUT_SELECT_WAV) { + if ( fclose (musicin.wav_input) != 0) { + fprintf (stderr, "Could not close \"%s\".\n", original_file_name); + exit (2); + } + } + + fprintf (stderr, "\nDone\n"); + exit (0); +} + +/************************************************************************ + * + * print_config + * + * PURPOSE: Prints the encoding parameters used + * + ************************************************************************/ + +void print_config (frame_info * frame, int *psy, char *inPath, + char *outPath) +{ + frame_header *header = frame->header; + + if (glopts.verbosity == 0) + return; + + fprintf (stderr, "--------------------------------------------\n"); + if (glopts.input_select == INPUT_SELECT_JACK) { + fprintf (stderr, "Input JACK\n"); + fprintf (stderr, " name %s\n", musicin.jack_name); + } + else if (glopts.input_select == INPUT_SELECT_WAV) { + fprintf (stderr, "Input File : '%s' %.1f kHz\n", + (strcmp (inPath, "-") ? inPath : "stdin"), + s_freq[header->version][header->sampling_frequency]); + } + else if (glopts.input_select == INPUT_SELECT_VLC) { + fprintf (stderr, "Input VLC\n"); + fprintf (stderr, " URI %s\n", inPath); + } + + fprintf (stderr, "Output File: '%s'\n", + (strcmp (outPath, "-") ? outPath : "stdout")); + fprintf (stderr, "%d kbps ", bitrate[header->version][header->bitrate_index]); + fprintf (stderr, "%s ", version_names[header->version]); + if (header->mode != MPG_MD_JOINT_STEREO) + fprintf (stderr, "Layer II %s Psycho model=%d (Mode_Extension=%d)\n", + mode_names[header->mode], *psy, header->mode_ext); + else + fprintf (stderr, "Layer II %s Psy model %d \n", mode_names[header->mode], + *psy); + + fprintf (stderr, "[De-emph:%s\tCopyright:%s\tOriginal:%s\tCRC:%s]\n", + ((header->emphasis) ? "On" : "Off"), + ((header->copyright) ? "Yes" : "No"), + ((header->original) ? "Yes" : "No"), + ((header->error_protection) ? "On" : "Off")); + + fprintf (stderr, "[Padding:%s\tByte-swap:%s\tChanswap:%s\tDAB:%s]\n", + ((glopts.usepadbit) ? "Normal" : "Off"), + ((glopts.byteswap) ? "On" : "Off"), + ((glopts.channelswap) ? "On" : "Off"), + ((glopts.dab) ? "On" : "Off")); + + if (glopts.vbr == TRUE) + fprintf (stderr, "VBR Enabled. Using MNR boost of %f\n", glopts.vbrlevel); + fprintf(stderr,"ATH adjustment %f\n",glopts.athlevel); + + fprintf (stderr, "--------------------------------------------\n"); +} + + +/************************************************************************ + * + * usage + * + * PURPOSE: Writes command line syntax to the file specified by #stderr# + * + ************************************************************************/ + +void usage (void) +{ /* print syntax & exit */ + /* FIXME: maybe have an option to display better definitions of help codes, and + long equivalents of the flags */ + fprintf (stdout, "\nToolame-DAB version %s\n (http://opendigitalradio.org)\n", + toolameversion); + fprintf (stdout, "MPEG Audio Layer II encoder for DAB\n\n"); + fprintf (stdout, "usage: \n"); + fprintf (stdout, "\t%s [options] (<infile>|-j <jackname>|-V <libvlc url>) <output>\n\n", programName); + + fprintf (stdout, "Options:\n"); + fprintf (stdout, "Input\n"); + fprintf (stdout, "\t-s sfrq input smpl rate in kHz (dflt %4.1f)\n", + DFLT_SFQ); + fprintf (stdout, "\t-a downmix from stereo to mono\n"); + fprintf (stdout, "\t-x force byte-swapping of input\n"); + fprintf (stdout, "\t-g swap channels of input file\n"); + +#if defined(JACK_INPUT) + fprintf (stdout, "\t-j use jack input\n"); +#else + fprintf (stdout, "\t-j DISABLED: JACK input not compiled in\n"); +#endif + +#if defined(VLC_INPUT) + fprintf (stdout, "\t-V use libvlc input\n"); +#else + fprintf (stdout, "\t-V DISABLED: libvlc input not compiled in\n"); +#endif + + fprintf (stdout, "\t-W file when using libvlc input, write the ICY-Text to file\n"); + fprintf (stdout, "\t-L enable audio level display\n"); + fprintf (stdout, "Output\n"); + fprintf (stdout, "\t-m mode channel mode : s/d/j/m (dflt %4c)\n", + DFLT_MOD); + fprintf (stdout, "\t-y psy psychoacoustic model 0/1/2/3 (dflt %4u)\n", + DFLT_PSY); + fprintf (stdout, "\t-b br total bitrate in kbps (dflt 192)\n"); + fprintf (stdout, "\t-v lev vbr mode\n"); + fprintf (stdout, "\t-l lev ATH level (dflt 0)\n"); + fprintf (stdout, "Operation\n"); + // fprintf (stdout, "\t-f fast mode (turns off psy model)\n"); + // deprecate the -f switch. use "-y 0" instead. + fprintf (stdout, + "\t-q num quick mode. only calculate psy model every num frames\n"); + fprintf (stdout, "Misc\n"); + fprintf (stdout, "\t-d emp de-emphasis n/5/c (dflt %4c)\n", + DFLT_EMP); + fprintf (stdout, "\t-c mark as copyright\n"); + fprintf (stdout, "\t-o mark as original\n"); + fprintf (stdout, "\t-e add error protection\n"); + fprintf (stdout, "\t-r force padding bit/frame off\n"); + fprintf (stdout, "\t-p len " + "enable PAD, and read len bytes of X-PAD data per frame\n"); + fprintf (stdout, "\t-P file " + "read X-PAD data from mot-encoder from the specified file\n"); + fprintf (stdout, "\t-t talkativity 0=no messages (dflt 2)\n"); + fprintf (stdout, "Files\n"); + fprintf (stdout, + "\tinput input sound file. (WAV,AIFF,PCM or use '/dev/stdin')\n"); + fprintf (stdout, "\toutput output bit stream of encoded audio\n"); + fprintf (stdout, "\t prefix with tcp:// to use a ZMQ output\n"); + fprintf (stdout, "\t Several ZMQ destinations can be given,\n"); + fprintf (stdout, "\t separated by semicolons.\n"); + fprintf (stdout, + "\n\tAllowable bitrates for 16, 22.05 and 24kHz sample input\n"); + fprintf (stdout, + "\t8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160\n"); + fprintf (stdout, + "\n\tAllowable bitrates for 32, 44.1 and 48kHz sample input\n"); + fprintf (stdout, + "\t32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384\n"); + exit (1); +} + +/********************************************* + * void short_usage(void) + ********************************************/ +void short_usage (void) +{ + /* print a bit of info about the program */ + fprintf (stderr, "Toolame-DAB version %s\n (http://opendigitalradio.org)\n", + toolameversion); + fprintf (stderr, "MPEG Audio Layer II encoder for DAB\n\n"); +#if defined(JACK_INPUT) && defined(VLC_INPUT) + fprintf (stderr, "USAGE: %s [options] (<infile>|-j <jackname>|-V <libvlc url>) [output]\n\n", programName); +#elif defined(JACK_INPUT) + fprintf (stderr, "USAGE: %s [options] (<infile>|-j <jackname>) [output]\n\n", programName); + fprintf (stderr, "VLC input not compiled in\n"); +#elif defined(VLC_INPUT) + fprintf (stderr, "USAGE: %s [options] (<infile>|-V <libvlc url>) [output]\n\n", programName); + fprintf (stderr, "JACK input not compiled in\n"); +#else + fprintf (stderr, "USAGE: %s [options] <infile> [output]\n\n", programName); + fprintf (stderr, "Neither JACK nor libVLC input compiled in\n"); +#endif + fprintf (stderr, "Try \"%s -h\" for more information.\n", programName); + exit (0); +} + +/************************************************************************ + * + * parse_args + * + * PURPOSE: Sets encoding parameters to the specifications of the + * command line. Default settings are used for parameters + * not specified in the command line. + * + * SEMANTICS: The command line is parsed according to the following + * syntax: + * + * -j turns on JACK input + * -V turns on libVLC input + * -L turns on audio level display + * -m is followed by the mode + * -y is followed by the psychoacoustic model number + * -s is followed by the sampling rate + * -b is followed by the total bitrate, irrespective of the mode + * -d is followed by the emphasis flag + * -c is followed by the copyright/no_copyright flag + * -o is followed by the original/not_original flag + * -e is followed by the error_protection on/off flag + * -f turns off psy model (fast mode) + * -q <i> only calculate psy model every ith frame + * -a downmix from stereo to mono + * -r turn off padding bits in frames. + * -x force byte swapping of input + * -g swap the channels on an input file + * -t talkativity. how verbose should the program be. 0 = no messages. + * + * If the input file is in AIFF format, the sampling frequency is read + * from the AIFF header. + * + * The input and output filenames are read into #inpath# and #outpath#. + * + ************************************************************************/ + +void parse_args (int argc, char **argv, frame_info * frame, int *psy, + unsigned long *num_samples, char inPath[MAX_NAME_SIZE], + char outPath[MAX_NAME_SIZE], char **mot_file, char **icy_file) +{ + FLOAT srate; + int brate; + frame_header *header = frame->header; + int err = 0, i = 0; + long samplerate = 0; + + /* preset defaults */ + inPath[0] = '\0'; + outPath[0] = '\0'; + header->lay = DFLT_LAY; + switch (DFLT_MOD) { + case 's': + header->mode = MPG_MD_STEREO; + header->mode_ext = 0; + break; + case 'd': + header->mode = MPG_MD_DUAL_CHANNEL; + header->mode_ext = 0; + break; + /* in j-stereo mode, no default header->mode_ext was defined, gave error.. + now default = 2 added by MFC 14 Dec 1999. */ + case 'j': + header->mode = MPG_MD_JOINT_STEREO; + header->mode_ext = 2; + break; + case 'm': + header->mode = MPG_MD_MONO; + header->mode_ext = 0; + break; + default: + fprintf (stderr, "%s: Bad mode dflt %c\n", programName, DFLT_MOD); + abort (); + } + *psy = DFLT_PSY; + if ((header->sampling_frequency = + SmpFrqIndex ((long) (1000 * DFLT_SFQ), &header->version)) < 0) { + fprintf (stderr, "%s: bad sfrq default %.2f\n", programName, DFLT_SFQ); + abort (); + } + header->bitrate_index = 14; + brate = 0; + switch (DFLT_EMP) { + case 'n': + header->emphasis = 0; + break; + case '5': + header->emphasis = 1; + break; + case 'c': + header->emphasis = 3; + break; + default: + fprintf (stderr, "%s: Bad emph dflt %c\n", programName, DFLT_EMP); + abort (); + } + header->copyright = 0; + header->original = 0; + header->error_protection = FALSE; + header->dab_extension = 0; + + glopts.input_select = INPUT_SELECT_WAV; + + /* process args */ + while (++i < argc && err == 0) { + char c, *token, *arg, *nextArg; + int argUsed; + + token = argv[i]; + if (*token++ == '-') { + if (i + 1 < argc) + nextArg = argv[i + 1]; + else + nextArg = ""; + argUsed = 0; + if (!*token) { + /* The user wants to use stdin and/or stdout. */ + if (inPath[0] == '\0') + strncpy (inPath, argv[i], MAX_NAME_SIZE); + else if (outPath[0] == '\0') + strncpy (outPath, argv[i], MAX_NAME_SIZE); + } + while ((c = *token++)) { + if (*token /* NumericQ(token) */ ) + arg = token; + else + arg = nextArg; + switch (c) { + case 'm': + argUsed = 1; + if (*arg == 's') { + header->mode = MPG_MD_STEREO; + header->mode_ext = 0; + } else if (*arg == 'd') { + header->mode = MPG_MD_DUAL_CHANNEL; + header->mode_ext = 0; + } else if (*arg == 'j') { + header->mode = MPG_MD_JOINT_STEREO; + } else if (*arg == 'm') { + header->mode = MPG_MD_MONO; + header->mode_ext = 0; + } else { + fprintf (stderr, "%s: -m mode must be s/d/j/m not %s\n", + programName, arg); + err = 1; + } + break; + case 'y': + *psy = atoi (arg); + argUsed = 1; + break; + + case 'L': + glopts.show_level = 1; + break; + + case 's': + argUsed = 1; + srate = atof (arg); + /* samplerate = rint( 1000.0 * srate ); $A */ + samplerate = (long) ((1000.0 * srate) + 0.5); + if ((header->sampling_frequency = + SmpFrqIndex ((long) samplerate, &header->version)) < 0) + err = 1; + break; + + case 'j': + glopts.input_select = INPUT_SELECT_JACK; + break; + + case 'b': + argUsed = 1; + brate = atoi (arg); + break; + case 'd': + argUsed = 1; + if (*arg == 'n') + header->emphasis = 0; + else if (*arg == '5') + header->emphasis = 1; + else if (*arg == 'c') + header->emphasis = 3; + else { + fprintf (stderr, "%s: -d emp must be n/5/c not %s\n", programName, + arg); + err = 1; + } + break; + case 'P': + argUsed = 1; + *mot_file = arg; + break; + case 'p': + argUsed = 1; + header->dab_length = atoi(arg); + break; + case 'c': + header->copyright = 1; + break; + case 'o': + header->original = 1; + break; + case 'e': + header->error_protection = TRUE; + break; + case 'r': + glopts.usepadbit = FALSE; + header->padding = 0; + break; + case 'q': + argUsed = 1; + glopts.quickmode = TRUE; + glopts.usepsy = TRUE; + glopts.quickcount = atoi (arg); + if (glopts.quickcount == 0) { + /* just don't use psy model */ + glopts.usepsy = FALSE; + glopts.quickcount = FALSE; + } + break; + case 'a': + glopts.downmix = TRUE; + header->mode = MPG_MD_MONO; + header->mode_ext = 0; + break; + case 'x': + glopts.byteswap = TRUE; + break; + case 'v': + argUsed = 1; + glopts.vbr = TRUE; + glopts.vbrlevel = atof (arg); + glopts.usepadbit = FALSE; /* don't use padding for VBR */ + header->padding = 0; + /* MFC Feb 2003: in VBR mode, joint stereo doesn't make + any sense at the moment, as there are no noisy subbands + according to bits_for_nonoise in vbr mode */ + header->mode = MPG_MD_STEREO; /* force stereo mode */ + header->mode_ext = 0; + break; + case 'V': + glopts.input_select = INPUT_SELECT_VLC; + break; + case 'W': + argUsed = 1; + *icy_file = arg; + break; + case 'l': + argUsed = 1; + glopts.athlevel = atof(arg); + break; + case 'h': + usage (); + break; + case 'g': + glopts.channelswap = TRUE; + break; + case 't': + argUsed = 1; + glopts.verbosity = atoi (arg); + break; + default: + fprintf (stderr, "%s: unrec option %c\n", programName, c); + err = 1; + break; + } + if (argUsed) { + if (arg == token) + token = ""; /* no more from token */ + else + ++i; /* skip arg we used */ + arg = ""; + argUsed = 0; + } + } + } else { + if (inPath[0] == '\0') + strcpy (inPath, argv[i]); + else if (outPath[0] == '\0') + strcpy (outPath, argv[i]); + else { + fprintf (stderr, "%s: excess arg %s\n", programName, argv[i]); + err = 1; + } + } + } + + /* Always enable DAB mode */ + header->error_protection = TRUE; + header->dab_extension = 4; + header->padding = 0; + glopts.dab = TRUE; + + if (err) + usage (); /* If err has occured, then call usage() */ + + if (glopts.input_select != INPUT_SELECT_JACK && inPath[0] == '\0') + usage (); /* If not in jack-mode and no file specified, then call usage() */ + + if (outPath[0] == '\0') { + /* replace old extension with new one, 1992-08-19, 1995-06-12 shn */ + new_ext (inPath, DFLT_EXT, outPath); + } + + if (glopts.input_select == INPUT_SELECT_JACK) { +#if defined(JACK_INPUT) + musicin.jack_name = inPath; + *num_samples = MAX_U_32_NUM; + + setup_jack(header, musicin.jack_name); +#else + fprintf(stderr, "JACK input not compiled in\n"); + exit(1); +#endif + } + else if (glopts.input_select == INPUT_SELECT_WAV) { + if (!strcmp (inPath, "-")) { + musicin.wav_input = stdin; /* read from stdin */ + *num_samples = MAX_U_32_NUM; + } else { + if ((musicin.wav_input = fopen (inPath, "rb")) == NULL) { + fprintf (stderr, "Could not find \"%s\".\n", inPath); + exit (1); + } + parse_input_file (musicin.wav_input, inPath, header, num_samples); + } + } + else if (glopts.input_select == INPUT_SELECT_VLC) { + if (samplerate == 0) { + fprintf (stderr, "Samplerate not specified\n"); + exit (1); + } + *num_samples = MAX_U_32_NUM; + int channels = (header->mode == MPG_MD_MONO) ? 1 : 2; +#if defined(VLC_INPUT) + if (vlc_in_prepare(glopts.verbosity, samplerate, inPath, channels, *icy_file) != 0) { + fprintf(stderr, "VLC initialisation failed\n"); + exit(1); + } +#else + fprintf(stderr, "VLC input not compiled in\n"); + exit(1); +#endif + } + else { + fprintf(stderr, "INVALID INPUT\n"); + exit(1); + } + + + /* check for a valid bitrate */ + if (brate == 0) + brate = bitrate[header->version][10]; + + /* Check to see we have a sane value for the bitrate for this version */ + if ((header->bitrate_index = BitrateIndex (brate, header->version)) < 0) + err = 1; + + if (header->dab_extension) { + /* in 48 kHz (= MPEG-1) */ + /* if the bit rate per channel is less then 56 kbit/s, we have 2 scf-crc */ + /* else we have 4 scf-crc */ + /* in 24 kHz (= MPEG-2), we have 4 scf-crc */ + if (header->version == MPEG_AUDIO_ID && (brate / (header->mode == MPG_MD_MONO ? 1 : 2) < 56)) + header->dab_extension = 2; + } + + bs.zmq_framesize = 3 * brate; + + /* All options are hunky dory, open the input audio file and + return to the main drag */ + open_bit_stream_w (&bs, outPath, BUFFER_SIZE); +} + + +void smr_dump(double smr[2][SBLIMIT], int nch) { + int ch, sb; + + fprintf(stdout,"SMR:"); + for (ch = 0;ch<nch; ch++) { + if (ch==1) + fprintf(stdout," "); + for (sb=0;sb<SBLIMIT;sb++) + fprintf(stdout,"%3.0f ",smr[ch][sb]); + fprintf(stdout,"\n"); + } +} + diff --git a/libtoolame-dab/toolame.h b/libtoolame-dab/toolame.h new file mode 100644 index 0000000..4289ab5 --- /dev/null +++ b/libtoolame-dab/toolame.h @@ -0,0 +1,16 @@ + +void global_init (void); +void proginfo (void); +void short_usage (void); + +void obtain_parameters (frame_info *, int *, unsigned long *, + char[MAX_NAME_SIZE], char[MAX_NAME_SIZE]); +void parse_args (int, char **, frame_info *, int *, unsigned long *, + char[MAX_NAME_SIZE], char[MAX_NAME_SIZE], char**, char**); +void print_config (frame_info *, int *, + char[MAX_NAME_SIZE], char[MAX_NAME_SIZE]); +void usage (void); + + +void smr_dump(double smr[2][SBLIMIT], int nch); + diff --git a/libtoolame-dab/utils.c b/libtoolame-dab/utils.c new file mode 100644 index 0000000..a9aefbe --- /dev/null +++ b/libtoolame-dab/utils.c @@ -0,0 +1,33 @@ +#include "utils.h" +#include <unistd.h> +#include <stdint.h> +#include <math.h> + +/* Taken from sox */ +const char* level(int channel, int* peak) +{ + static char const * const text[][2] = { + /* White: 2dB steps */ + {"", ""}, {"-", "-"}, {"=", "="}, {"-=", "=-"}, + {"==", "=="}, {"-==", "==-"}, {"===", "==="}, {"-===", "===-"}, + {"====", "===="}, {"-====", "====-"}, {"=====", "====="}, + {"-=====", "=====-"}, {"======", "======"}, + /* Red: 1dB steps */ + {"!=====", "=====!"}, + }; + int const red = 1, white = NUMOF(text) - red; + + double linear = (double)(*peak) / INT16_MAX; + + int vu_dB = linear ? floor(2 * white + red + linear_to_dB(linear)) : 0; + + int index = vu_dB < 2 * white ? + MAX(vu_dB / 2, 0) : + MIN(vu_dB - white, red + white - 1); + + *peak = 0; + + return text[index][channel]; + +} + diff --git a/libtoolame-dab/utils.h b/libtoolame-dab/utils.h new file mode 100644 index 0000000..7d98ab6 --- /dev/null +++ b/libtoolame-dab/utils.h @@ -0,0 +1,20 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include <math.h> +#include <stdint.h> + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#define NUMOF(l) (sizeof(l) / sizeof(*l)) + +#define linear_to_dB(x) (log10(x) * 20) + +/* Calculate the little string containing a bargraph + * 'VU-meter' from the peak value measured + */ +const char* level(int channel, int* peak); + +#endif + diff --git a/libtoolame-dab/vlc_input.c b/libtoolame-dab/vlc_input.c new file mode 100644 index 0000000..11e04c7 --- /dev/null +++ b/libtoolame-dab/vlc_input.c @@ -0,0 +1,430 @@ +#include "vlc_input.h" + +#if defined(VLC_INPUT) +#include <stdlib.h> +#include <errno.h> +#include <pthread.h> +#include <semaphore.h> +#include <assert.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +int check_vlc_uses_size_t(); +struct vlc_buffer* vlc_buffer_new(); +void vlc_buffer_free(struct vlc_buffer* node); + +libvlc_instance_t *m_vlc; +libvlc_media_player_t *m_mp; + +unsigned int vlc_rate; +unsigned int vlc_channels; + +struct vlc_buffer *head_buffer; + +// now playing information can get written to +// a file. This writing happens in a separate thread +#define NOWPLAYING_LEN 512 +char vlc_nowplaying[NOWPLAYING_LEN]; +int vlc_nowplaying_running; +pthread_t vlc_nowplaying_thread; +const char* vlc_nowplaying_filename; + +struct icywriter_task_data { + char text[NOWPLAYING_LEN]; + int success; + sem_t sem; +}; + +struct icywriter_task_data icy_task_data; + + +pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER; + +struct vlc_buffer* vlc_buffer_new() +{ + struct vlc_buffer* node; + node = malloc(sizeof(struct vlc_buffer)); + memset(node, 0, sizeof(struct vlc_buffer)); + return node; +} + +void vlc_buffer_free(struct vlc_buffer* node) +{ + if (node->buf) { + free(node->buf); + } + + free(node); +} + +size_t vlc_buffer_totalsize(struct vlc_buffer* node) +{ + size_t totalsize = 0; + for (; node != NULL; node = node->next) { + totalsize += node->size; + } + + return totalsize; +} + +// VLC Audio prerender callback, we must allocate a buffer here +void prepareRender_size_t( + void* p_audio_data, + uint8_t** pp_pcm_buffer, + size_t size) +{ + *pp_pcm_buffer = malloc(size); +} + +void prepareRender( + void* p_audio_data, + uint8_t** pp_pcm_buffer, + unsigned int size) +{ + *pp_pcm_buffer = malloc(size); +} + + +// Audio postrender callback +void handleStream_size_t( + void* p_audio_data, + uint8_t* p_pcm_buffer, + unsigned int channels, + unsigned int rate, + unsigned int nb_samples, + unsigned int bits_per_sample, + size_t size, + int64_t pts) +{ + assert(channels == vlc_channels); + assert(rate == vlc_rate); + assert(bits_per_sample == 16); + + // 16 is a bit arbitrary, if it's too small we might enter + // a deadlock if toolame asks for too much data + const size_t max_length = 16 * size; + + for (;;) { + pthread_mutex_lock(&buffer_lock); + + if (vlc_buffer_totalsize(head_buffer) < max_length) { + struct vlc_buffer* newbuf = vlc_buffer_new(); + + newbuf->buf = p_pcm_buffer; + newbuf->size = size; + + // Append the new buffer to the end of the linked list + struct vlc_buffer* tail = head_buffer; + while (tail->next) { + tail = tail->next; + } + tail->next = newbuf; + + pthread_mutex_unlock(&buffer_lock); + return; + } + + pthread_mutex_unlock(&buffer_lock); + usleep(100); + } +} + +// convert from unsigned int size to size_t size +void handleStream( + void* p_audio_data, + uint8_t* p_pcm_buffer, + unsigned int channels, + unsigned int rate, + unsigned int nb_samples, + unsigned int bits_per_sample, + unsigned int size, + int64_t pts) +{ + handleStream_size_t( + p_audio_data, + p_pcm_buffer, + channels, + rate, + nb_samples, + bits_per_sample, + size, + pts); +} + +int vlc_in_prepare( + unsigned verbosity, + unsigned int rate, + const char* uri, + unsigned channels, + const char* icy_write_file + ) +{ + fprintf(stderr, "Initialising VLC...\n"); + + vlc_nowplaying_running = 0; + vlc_nowplaying_filename = icy_write_file; + + long long int handleStream_address; + long long int prepareRender_address; + + int vlc_version_check = check_vlc_uses_size_t(); + if (vlc_version_check == 0) { + fprintf(stderr, "You are using VLC with unsigned int size callbacks\n"); + + handleStream_address = (long long int)(intptr_t)(void*)&handleStream; + prepareRender_address = (long long int)(intptr_t)(void*)&prepareRender; + } + else if (vlc_version_check == 1) { + fprintf(stderr, "You are using VLC with size_t size callbacks\n"); + + handleStream_address = (long long int)(intptr_t)(void*)&handleStream_size_t; + prepareRender_address = (long long int)(intptr_t)(void*)&prepareRender_size_t; + } + else { + fprintf(stderr, "Error detecting VLC version!\n"); + fprintf(stderr, " you are using %s\n", libvlc_get_version()); + return -1; + } + + vlc_rate = rate; + vlc_channels = channels; + + // VLC options + char smem_options[512]; + snprintf(smem_options, sizeof(smem_options), + "#transcode{acodec=s16l,samplerate=%d}:" + // We are using transcode because smem only support raw audio and + // video formats + "smem{" + "audio-postrender-callback=%lld," + "audio-prerender-callback=%lld" + "}", + vlc_rate, + handleStream_address, + prepareRender_address); + + char verb_options[512]; + snprintf(verb_options, sizeof(verb_options), + "--verbose=%d", verbosity); + + const char * const vlc_args[] = { + verb_options, + "--sout", smem_options // Stream to memory + }; + + // Launch VLC + m_vlc = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); + + // Load the media + libvlc_media_t *m; + m = libvlc_media_new_location(m_vlc, uri); + m_mp = libvlc_media_player_new_from_media(m); + libvlc_media_release(m); + + // Allocate the list + head_buffer = vlc_buffer_new(); + + // Start playing + int ret = libvlc_media_player_play(m_mp); + + if (ret == 0) { + libvlc_media_t *media = libvlc_media_player_get_media(m_mp); + libvlc_state_t st; + + ret = -1; + + int timeout; + for (timeout = 0; timeout < 100; timeout++) { + st = libvlc_media_get_state(media); + usleep(10*1000); + if (st != libvlc_NothingSpecial) { + ret = 0; + break; + } + } + } + + return ret; +} + +ssize_t vlc_in_read(void *buf, size_t len) +{ + if (len == 0) { + return 0; + } + + assert(buf); + + size_t requested = len; + for (;;) { + pthread_mutex_lock(&buffer_lock); + + if (vlc_buffer_totalsize(head_buffer) >= len) { + while (len >= head_buffer->size) { + if (head_buffer->buf && head_buffer->size) { + // Get all the data from this list element + memcpy(buf, head_buffer->buf, head_buffer->size); + + buf += head_buffer->size; + len -= head_buffer->size; + } + + if (head_buffer->next) { + struct vlc_buffer *next_head = head_buffer->next; + vlc_buffer_free(head_buffer); + head_buffer = next_head; + } + else { + vlc_buffer_free(head_buffer); + head_buffer = vlc_buffer_new(); + break; + } + } + + if (len > 0) { + assert(len < head_buffer->size); + assert(head_buffer->buf); + + memcpy(buf, head_buffer->buf, len); + + // split the current head into two parts + size_t remaining = head_buffer->size - len; + uint8_t *newbuf = malloc(remaining); + + memcpy(newbuf, head_buffer->buf + len, remaining); + free(head_buffer->buf); + head_buffer->buf = newbuf; + head_buffer->size = remaining; + } + + pthread_mutex_unlock(&buffer_lock); + return requested; + } + + pthread_mutex_unlock(&buffer_lock); + usleep(100); + + libvlc_media_t *media = libvlc_media_player_get_media(m_mp); + libvlc_state_t st = libvlc_media_get_state(media); + if (!(st == libvlc_Opening || + st == libvlc_Buffering || + st == libvlc_Playing) ) { + return -1; + } + + char* nowplaying_sz = libvlc_media_get_meta(media, libvlc_meta_NowPlaying); + if (nowplaying_sz) { + snprintf(vlc_nowplaying, NOWPLAYING_LEN, "%s", nowplaying_sz); + free(nowplaying_sz); + } + } + + abort(); +} + +// This task is run in a separate thread +void* vlc_in_write_icy_task(void* arg) +{ + struct icywriter_task_data* data = arg; + + FILE* fd = fopen(vlc_nowplaying_filename, "wb"); + if (fd) { + int ret = fputs(data->text, fd); + fclose(fd); + + if (ret >= 0) { + data->success = 1; + } + } + else { + data->success = 0; + } + + sem_post(&data->sem); + return NULL; +} + +void vlc_in_write_icy(void) +{ + if (vlc_nowplaying_filename == NULL) { + return; + } + else if (vlc_nowplaying_running == 0) { + memcpy(icy_task_data.text, vlc_nowplaying, NOWPLAYING_LEN); + icy_task_data.success = 0; + + int ret = sem_init(&icy_task_data.sem, 0, 0); + if (ret == 0) { + ret = pthread_create(&vlc_nowplaying_thread, NULL, vlc_in_write_icy_task, &icy_task_data); + + if (ret == 0) { + vlc_nowplaying_running = 1; + } + else { + fprintf(stderr, "ICY Text writer: thread start failed: %s\n", strerror(ret)); + } + } + else { + fprintf(stderr, "ICY Text writer: semaphore init failed: %s\n", strerror(errno)); + } + + } + else { + int ret = sem_trywait(&icy_task_data.sem); + if (ret == -1 && errno == EAGAIN) { + return; + } + else if (ret == 0) { + ret = pthread_join(vlc_nowplaying_thread, NULL); + if (ret != 0) { + fprintf(stderr, "ICY Text writer: pthread_join error: %s\n", strerror(ret)); + } + + vlc_nowplaying_running = 0; + } + else { + fprintf(stderr, "ICY Text writer: semaphore trywait failed: %s\n", strerror(errno)); + } + } +} + + +/* VLC up to version 2.1.0 used a different callback function signature. + * VLC 2.2.0 uses size_t + * + * \return 1 if the callback with size_t size should be used. + * 0 if the callback with unsigned int size should be used. + * -1 if there was an error. + */ +int check_vlc_uses_size_t() +{ + int retval = -1; + + char libvlc_version[256]; + strncpy(libvlc_version, libvlc_get_version(), 255); + + char *space_position = strstr(libvlc_version, " "); + + if (space_position) { + *space_position = '\0'; + } + + char *saveptr; + char *major_ver_sz = strtok_r(libvlc_version, ".", &saveptr); + if (major_ver_sz) { + int major_ver = atoi(major_ver_sz); + + char *minor_ver_sz = strtok_r(NULL, ".", &saveptr); + if (minor_ver_sz) { + int minor_ver = atoi(minor_ver_sz); + + retval = (major_ver >= 2 && minor_ver >= 2) ? 1 : 0; + } + } + + return retval; +} + +#endif // defined(VLC_INPUT) + diff --git a/libtoolame-dab/vlc_input.h b/libtoolame-dab/vlc_input.h new file mode 100644 index 0000000..a2ecefa --- /dev/null +++ b/libtoolame-dab/vlc_input.h @@ -0,0 +1,34 @@ +#ifndef __VLC_INPUT_H_ +#define __VLC_INPUT_H_ + +# if defined(VLC_INPUT) + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> +#include <vlc/vlc.h> + + +// A linked list structure for the incoming buffers +struct vlc_buffer { + uint8_t *buf; + size_t size; + struct vlc_buffer *next; +}; + +// Open the VLC input +int vlc_in_prepare( + unsigned verbosity, + unsigned int rate, + const char* uri, + unsigned channels, + const char* icy_write_file); + +// Read len audio bytes into buf +ssize_t vlc_in_read(void *buf, size_t len); + +void vlc_in_write_icy(void); + +# endif // VLC_INPUT +#endif // __VLC_INPUT_H_ + diff --git a/libtoolame-dab/xpad.c b/libtoolame-dab/xpad.c new file mode 100644 index 0000000..6c97ea8 --- /dev/null +++ b/libtoolame-dab/xpad.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <assert.h> +#include <errno.h> + +#include "xpad.h" + +static int xpad_fd = 0; + +/* The F-PAD has to be: + uint16_t fpad = 0x2; // CI flag + + if (xpad_len()) { + fpad |= 1<<13; // variable length X-PAD + } + + which is included by mot-encoder in the file/fifo + it generates + */ + +/* Create and open the desired PAD input fifo + */ +int xpad_init(char* pad_fifo, int pad_len) +{ + if (mkfifo(pad_fifo, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) != 0) { + if (errno != EEXIST) { + fprintf(stderr, "Can't create pad file: %d!\n", errno); + return -1; + } + } + + xpad_fd = open(pad_fifo, O_RDONLY | O_NONBLOCK); + if (xpad_fd == -1) { + fprintf(stderr, "Can't open pad file!\n"); + return -1; + } + + int flags = fcntl(xpad_fd, F_GETFL, 0); + if (fcntl(xpad_fd, F_SETFL, flags | O_NONBLOCK)) { + fprintf(stderr, "Can't set non-blocking mode in pad file!\n"); + return -1; + } + + return 0; +} + +int xpad_read_len(uint8_t* buf, int len) +{ + if (xpad_fd == 0) return 0; + + ssize_t num_read = 0; + + while (num_read < len) { + ssize_t r = read(xpad_fd, buf + num_read, len - num_read); + + if(r < 0) { + if (errno == EAGAIN) { + return 0; + } + else { + perror("PAD input read error"); + return -1; + } + } + else if (r == 0) { + // reached end of data + return 0; + } + + num_read += r; + } + +#if XPAD_DEBUG + int i; + for (i = 0; i < len; i++) { + fprintf(stderr, "%02x ", buf[i]); + } + fprintf(stderr, "\n"); +#endif + + return num_read; +} + diff --git a/libtoolame-dab/xpad.h b/libtoolame-dab/xpad.h new file mode 100644 index 0000000..cd0a434 --- /dev/null +++ b/libtoolame-dab/xpad.h @@ -0,0 +1,28 @@ +#ifndef _XPAD_H_ +#define _XPAD_H_ + +#include <stdint.h> + +/* Initialise the xpad reader + * + * pad_fifo is the filename of the FIFO that will be created, and + * can be used with mot-encoder. + * + * pad_len is the XPAD length, that also has to be given + * to mot-encoder. + * + * returns 0 on success + * -1 on failure + */ +int xpad_init(char* pad_fifo, int pad_len); + +/* Get len bytes of x-pad data, write into buf + * returns either + * - len if the read was sucessful + * - 0 if there was no data + * - -1 if there was an error (errno will be set) + */ +int xpad_read_len(uint8_t* buf, int len); + +#endif + diff --git a/libtoolame-dab/zmqoutput.c b/libtoolame-dab/zmqoutput.c new file mode 100644 index 0000000..03007cc --- /dev/null +++ b/libtoolame-dab/zmqoutput.c @@ -0,0 +1,120 @@ +#include "zmqoutput.h" +#include <zmq.h> +#include <stdlib.h> +#include <string.h> +#include "common.h" + +static void *zmq_context; + +// Buffer containing at maximum one frame +unsigned char* zmqbuf; + +// The current data length (smaller than allocated +// buffer size) +size_t zmqbuf_len; + +static int zmq_peak_left = 0; +static int zmq_peak_right = 0; + +void zmqoutput_set_peaks(int left, int right) +{ + zmq_peak_left = left; + zmq_peak_right = right; +} + +int zmqoutput_open(Bit_stream_struc *bs, const char* uri_list) +{ + zmq_context = zmq_ctx_new(); + bs->zmq_sock = zmq_socket(zmq_context, ZMQ_PUB); + if (bs->zmq_sock == NULL) { + fprintf(stderr, "Error occurred during zmq_socket: %s\n", + zmq_strerror(errno)); + return -1; + } + + char* uris = strdup(uri_list); + char* saveptr = NULL; + + for (; ; uris = NULL) { + char* uri = strtok_r(uris, ";", &saveptr); + + + if (uri) { + fprintf(stderr, "Connecting ZMQ to %s\n", uri); + if (zmq_connect(bs->zmq_sock, uri) != 0) { + fprintf(stderr, "Error occurred during zmq_connect: %s\n", + zmq_strerror(errno)); + free(uris); + return -1; + } + } + else { + break; + } + } + + free(uris); + + zmqbuf = (unsigned char*)malloc(bs->zmq_framesize); + if (zmqbuf == NULL) { + fprintf(stderr, "Unable to allocate ZMQ buffer\n"); + exit(0); + } + zmqbuf_len = 0; + return 0; +} + +int zmqoutput_write_byte(Bit_stream_struc *bs, unsigned char data) +{ + zmqbuf[zmqbuf_len++] = data; + + if (zmqbuf_len == bs->zmq_framesize) { + + int frame_length = sizeof(struct zmq_frame_header) + zmqbuf_len; + + struct zmq_frame_header* header = + malloc(frame_length); + + uint8_t* txframe = ((uint8_t*)header) + sizeof(struct zmq_frame_header); + + header->version = 1; + header->encoder = ZMQ_ENCODER_TOOLAME; + header->datasize = zmqbuf_len; + header->audiolevel_left = zmq_peak_left; + header->audiolevel_right = zmq_peak_right; + + memcpy(txframe, zmqbuf, zmqbuf_len); + + int send_error = zmq_send(bs->zmq_sock, header, frame_length, + ZMQ_DONTWAIT); + + free(header); + header = NULL; + + if (send_error < 0) { + fprintf(stderr, "ZeroMQ send failed! %s\n", zmq_strerror(errno)); + } + + zmqbuf_len = 0; + + return bs->zmq_framesize; + } + + return 0; + +} + +void zmqoutput_close(Bit_stream_struc *bs) +{ + if (bs->zmq_sock) + zmq_close(bs->zmq_sock); + + if (zmq_context) + zmq_ctx_destroy(zmq_context); + + if (zmqbuf) { + free(zmqbuf); + zmqbuf = NULL; + } +} + diff --git a/libtoolame-dab/zmqoutput.h b/libtoolame-dab/zmqoutput.h new file mode 100644 index 0000000..7f4eb59 --- /dev/null +++ b/libtoolame-dab/zmqoutput.h @@ -0,0 +1,37 @@ +#ifndef _ZMQOUTPUT_H_ +#define _ZMQOUTPUT_H_ + +#include <stdint.h> +#include "common.h" + +#define ZMQ_ENCODER_TOOLAME 2 + +struct zmq_frame_header +{ + uint16_t version; // we support version=1 now + uint16_t encoder; // see ZMQ_ENCODER_XYZ + + /* length of the 'data' field */ + uint32_t datasize; + + /* Audio level, peak, linear PCM */ + int16_t audiolevel_left; + int16_t audiolevel_right; + + /* Data follows this header */ +} __attribute__ ((packed)); + + +/* Open the zmq socket and connect it to all URIs in the list. + * The URIs are semicolon delimited + */ +int zmqoutput_open(Bit_stream_struc * bs, const char* uri_list); + +int zmqoutput_write_byte(Bit_stream_struc *bs, unsigned char data); + +void zmqoutput_close(Bit_stream_struc *bs); + +void zmqoutput_set_peaks(int left, int right); + +#endif + |