diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/include/lame | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/include/lame')
70 files changed, 33139 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/COPYING b/Src/external_dependencies/openmpt-trunk/include/lame/COPYING new file mode 100644 index 00000000..f5030495 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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 Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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/Src/external_dependencies/openmpt-trunk/include/lame/OpenMPT.txt b/Src/external_dependencies/openmpt-trunk/include/lame/OpenMPT.txt new file mode 100644 index 00000000..a331acee --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/OpenMPT.txt @@ -0,0 +1,7 @@ +lame library version 3.100.
+The following changes have been made:
+ * Obviously, unnecessary folders and files have been removed.
+ * Forced library name in lame.def has been removed.
+ * All modifications have been marked with /* OpenMPT */.
+ * For building, premake is used to generate Visual Studio project files.
+ See ../build/premake/ for details.
diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/configMS.h b/Src/external_dependencies/openmpt-trunk/include/lame/configMS.h new file mode 100644 index 00000000..b533a1e4 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/configMS.h @@ -0,0 +1,120 @@ +#ifndef CONFIGMS_H_INCLUDED +#define CONFIGMS_H_INCLUDED + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a long double. */ +#define SIZEOF_LONG_DOUBLE 12 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +/* The number of bytes in a unsigned int. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The number of bytes in a unsigned long. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The number of bytes in a unsigned short. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS + +/* Define if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H + +/* Name of package */ +#define PACKAGE "lame" + +/* Define if compiler has function prototypes */ +#define PROTOTYPES 1 + +/* faster log implementation with less but enough precission */ +#define USE_FAST_LOG 1 + +#define HAVE_STRCHR +#define HAVE_MEMCPY + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#pragma warning( disable : 4305 ) + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + + typedef float float32_t; + typedef double float64_t; +#elif defined (__GNUC__) +#define __int8_t_defined +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned int +#define uint64_t unsigned long long + +#define int8_t signed char +#define int16_t signed short +#define int32_t signed int +#define int64_t signed long long +#endif + +typedef long double ieee854_float80_t; +typedef double ieee754_float64_t; +typedef float ieee754_float32_t; + +#ifdef HAVE_MPGLIB +# define DECODE_ON_THE_FLY 1 +#endif + +#ifdef LAME_ACM +/* memory hacking for driver purposes */ +#define calloc(x,y) acm_Calloc(x,y) +#define free(x) acm_Free(x) +#define malloc(x) acm_Malloc(x) + +#include <stddef.h> +void *acm_Calloc( size_t num, size_t size ); +void *acm_Malloc( size_t size ); +void acm_Free( void * mem); +#endif /* LAME_ACM */ + +#define LAME_LIBRARY_BUILD + + +#ifdef HAVE_NASM + #if (defined(__ICL) && (__ICL >= 450)) + #define HAVE_XMMINTRIN_H + #elif defined(_MSC_VER) + #include <malloc.h> + #ifdef _mm_malloc + #define HAVE_XMMINTRIN_H + #endif + #endif +#endif + +#if defined(_M_X64) && !defined(HAVE_XMMINTRIN_H) + #define HAVE_XMMINTRIN_H +#endif + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.def b/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.def new file mode 100644 index 00000000..92308b06 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.def @@ -0,0 +1,304 @@ +;OpenMPT +;LIBRARY libmp3lame.DLL +LIBRARY +EXPORTS + +lame_init @1 + +lame_set_num_samples @2 +lame_get_num_samples @3 + +lame_set_in_samplerate @4 +lame_get_in_samplerate @5 + +lame_set_num_channels @6 +lame_get_num_channels @7 + +lame_set_scale @8 +lame_get_scale @9 + +lame_set_scale_left @10 +lame_get_scale_left @11 + +lame_set_scale_right @12 +lame_get_scale_right @13 + +lame_set_out_samplerate @14 +lame_get_out_samplerate @15 + +lame_set_analysis @16 +lame_get_analysis @17 + +lame_set_bWriteVbrTag @18 +lame_get_bWriteVbrTag @19 + +lame_set_decode_only @20 +lame_get_decode_only @21 + +lame_set_quality @22 +lame_get_quality @23 + +lame_set_mode @24 +lame_get_mode @25 + +lame_set_force_ms @26 +lame_get_force_ms @27 + +lame_set_free_format @28 +lame_get_free_format @29 + + +lame_set_findReplayGain @30 +lame_get_findReplayGain @31 + +lame_set_decode_on_the_fly @32 +lame_get_decode_on_the_fly @33 + +lame_set_nogap_total @34 +lame_get_nogap_total @35 + +lame_set_nogap_currentindex @36 +lame_get_nogap_currentindex @37 + + +lame_set_errorf @38 +lame_set_debugf @39 +lame_set_msgf @40 + +lame_set_brate @41 +lame_get_brate @42 + +lame_set_compression_ratio @43 +lame_get_compression_ratio @44 + +lame_set_preset @45 + +lame_set_asm_optimizations @46 + + +lame_set_copyright @47 +lame_get_copyright @48 + +lame_set_original @49 +lame_get_original @50 + +lame_set_error_protection @51 +lame_get_error_protection @52 + +lame_set_padding_type @53 +lame_get_padding_type @54 + +lame_set_extension @55 +lame_get_extension @56 + +lame_set_strict_ISO @57 +lame_get_strict_ISO @58 + +lame_set_disable_reservoir @59 +lame_get_disable_reservoir @60 + +lame_set_quant_comp @61 +lame_get_quant_comp @62 +lame_set_quant_comp_short @63 +lame_get_quant_comp_short @64 + +lame_set_experimentalX @65 +lame_get_experimentalX @66 + +lame_set_experimentalY @67 +lame_get_experimentalY @68 + +lame_set_experimentalZ @69 +lame_get_experimentalZ @70 + +lame_set_exp_nspsytune @71 +lame_get_exp_nspsytune @72 + +lame_set_msfix @73 +lame_get_msfix @74 + +lame_set_VBR @75 +lame_get_VBR @76 + +lame_set_VBR_q @77 +lame_get_VBR_q @78 + +lame_set_VBR_mean_bitrate_kbps @79 +lame_get_VBR_mean_bitrate_kbps @80 + +lame_set_VBR_min_bitrate_kbps @81 +lame_get_VBR_min_bitrate_kbps @82 + +lame_set_VBR_max_bitrate_kbps @83 +lame_get_VBR_max_bitrate_kbps @84 + +lame_set_VBR_hard_min @85 +lame_get_VBR_hard_min @86 + +lame_set_preset_expopts @87 + +lame_set_lowpassfreq @88 +lame_get_lowpassfreq @89 + +lame_set_lowpasswidth @90 +lame_get_lowpasswidth @91 + +lame_set_highpassfreq @92 +lame_get_highpassfreq @93 + +lame_set_highpasswidth @94 +lame_get_highpasswidth @95 + +lame_set_ATHonly @96 +lame_get_ATHonly @97 + +lame_set_ATHshort @98 +lame_get_ATHshort @99 + +lame_set_noATH @100 +lame_get_noATH @101 + +lame_set_ATHtype @102 +lame_get_ATHtype @103 + +lame_set_ATHlower @104 +lame_get_ATHlower @105 + +lame_set_athaa_type @106 +lame_get_athaa_type @107 + +lame_set_athaa_loudapprox @108 +lame_get_athaa_loudapprox @109 + +lame_set_athaa_sensitivity @110 +lame_get_athaa_sensitivity @111 + +lame_set_cwlimit @112 +lame_get_cwlimit @113 + +lame_set_useTemporal @114 +lame_get_useTemporal @115 + +lame_set_interChRatio @116 +lame_get_interChRatio @117 + +lame_set_no_short_blocks @118 +lame_get_no_short_blocks @119 +lame_set_force_short_blocks @120 +lame_get_force_short_blocks @121 +lame_set_allow_diff_short @122 +lame_get_allow_diff_short @123 + +lame_set_emphasis @124 +lame_get_emphasis @125 + +lame_get_version @126 +lame_get_encoder_delay @127 +lame_get_encoder_padding @128 +lame_get_framesize @129 + +lame_get_mf_samples_to_encode @130 +lame_get_size_mp3buffer @131 +lame_get_frameNum @132 +lame_get_totalframes @133 + +lame_get_RadioGain @134 +lame_get_AudiophileGain @135 +lame_get_PeakSample @136 +lame_get_noclipGainChange @137 +lame_get_noclipScale @138 + +lame_init_params @139 + +get_lame_version @140 +get_lame_short_version @141 +get_lame_very_short_version @142 +get_psy_version @143 +get_lame_url @144 + +get_lame_version_numerical @145 + +lame_print_config @146 +lame_print_internals @147 + +lame_encode_buffer @148 +lame_encode_buffer_interleaved @149 +lame_encode_buffer_float @150 +lame_encode_buffer_long @151 +lame_encode_buffer_long2 @152 +lame_encode_buffer_int @153 +lame_encode_flush @154 +lame_encode_flush_nogap @155 + +lame_init_bitstream @156 + +lame_bitrate_hist @157 +lame_bitrate_kbps @158 +lame_stereo_mode_hist @159 +lame_bitrate_stereo_mode_hist @160 +lame_block_type_hist @161 +lame_bitrate_block_type_hist @162 +lame_mp3_tags_fid @163 +lame_close @164 +lame_get_lametag_frame @165 +get_lame_os_bitness @166 +lame_set_VBR_quality @167 +lame_get_VBR_quality @168 + +lame_encode_buffer_ieee_float @169 +lame_encode_buffer_interleaved_ieee_float @170 +lame_encode_buffer_ieee_double @171 +lame_encode_buffer_interleaved_ieee_double @172 +lame_encode_buffer_interleaved_int @173 + +lame_get_bitrate @502 +lame_get_samplerate @503 +lame_get_maximum_number_of_samples @504 + +lame_decode_init @1000 +lame_decode @1001 +lame_decode_headers @1002 +lame_decode1 @1003 +lame_decode1_headers @1004 +lame_decode1_headersB @1005 +lame_decode_exit @1006 + +hip_decode_init @1100 +hip_decode_exit @1101 +hip_decode @1102 +hip_decode_headers @1103 +hip_decode1 @1104 +hip_decode1_headers @1105 +hip_decode1_headersB @1106 +hip_set_debugf @1107 +hip_set_errorf @1108 +hip_set_msgf @1109 + +id3tag_genre_list @2000 +id3tag_init @2001 +id3tag_add_v2 @2002 +id3tag_v1_only @2003 +id3tag_v2_only @2004 +id3tag_space_v1 @2005 +id3tag_pad_v2 @2006 +id3tag_set_title @2007 +id3tag_set_artist @2008 +id3tag_set_album @2009 +id3tag_set_year @2010 +id3tag_set_comment @2011 +id3tag_set_track @2012 +id3tag_set_genre @2013 +id3tag_set_fieldvalue @2014 +id3tag_set_albumart @2015 +lame_get_id3v1_tag @2016 +lame_get_id3v2_tag @2017 +lame_set_write_id3tag_automatic @2018 +lame_get_write_id3tag_automatic @2019 +id3tag_set_pad @2020 +id3tag_set_comment_ucs2 @2021 +id3tag_set_textinfo_ucs2 @2022 +id3tag_set_fieldvalue_ucs2 @2023 +id3tag_set_comment_utf16 @2024 +id3tag_set_textinfo_utf16 @2025 +id3tag_set_fieldvalue_utf16 @2026 + diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.h b/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.h new file mode 100644 index 00000000..5196690f --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/include/lame.h @@ -0,0 +1,1342 @@ +/* + * Interface to MP3 LAME encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame.h,v 1.192 2017/08/31 14:14:46 robert Exp $ */ + +#ifndef LAME_LAME_H +#define LAME_LAME_H + +/* for size_t typedef */ +#include <stddef.h> +/* for va_list typedef */ +#include <stdarg.h> +/* for FILE typedef, TODO: remove when removing lame_mp3_tags_fid */ +#include <stdio.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef void (*lame_report_function)(const char *format, va_list ap); + +#if defined(WIN32) || defined(_WIN32) +#undef CDECL +#define CDECL __cdecl +#else +#define CDECL +#endif + +#define DEPRECATED_OR_OBSOLETE_CODE_REMOVED 1 + +typedef enum vbr_mode_e { + vbr_off=0, + vbr_mt, /* obsolete, same as vbr_mtrh */ + vbr_rh, + vbr_abr, + vbr_mtrh, + vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ + vbr_default=vbr_mtrh /* change this to change the default VBR mode of LAME */ +} vbr_mode; + + +/* MPEG modes */ +typedef enum MPEG_mode_e { + STEREO = 0, + JOINT_STEREO, + DUAL_CHANNEL, /* LAME doesn't supports this! */ + MONO, + NOT_SET, + MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} MPEG_mode; + +/* Padding types */ +typedef enum Padding_type_e { + PAD_NO = 0, + PAD_ALL, + PAD_ADJUST, + PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} Padding_type; + + + +/*presets*/ +typedef enum preset_mode_e { + /*values from 8 to 320 should be reserved for abr bitrates*/ + /*for abr I'd suggest to directly use the targeted bitrate as a value*/ + ABR_8 = 8, + ABR_320 = 320, + + V9 = 410, /*Vx to match Lame and VBR_xx to match FhG*/ + VBR_10 = 410, + V8 = 420, + VBR_20 = 420, + V7 = 430, + VBR_30 = 430, + V6 = 440, + VBR_40 = 440, + V5 = 450, + VBR_50 = 450, + V4 = 460, + VBR_60 = 460, + V3 = 470, + VBR_70 = 470, + V2 = 480, + VBR_80 = 480, + V1 = 490, + VBR_90 = 490, + V0 = 500, + VBR_100 = 500, + + + + /*still there for compatibility*/ + R3MIX = 1000, + STANDARD = 1001, + EXTREME = 1002, + INSANE = 1003, + STANDARD_FAST = 1004, + EXTREME_FAST = 1005, + MEDIUM = 1006, + MEDIUM_FAST = 1007 +} preset_mode; + + +/*asm optimizations*/ +typedef enum asm_optimizations_e { + MMX = 1, + AMD_3DNOW = 2, + SSE = 3 +} asm_optimizations; + + +/* psychoacoustic model */ +typedef enum Psy_model_e { + PSY_GPSYCHO = 1, + PSY_NSPSYTUNE = 2 +} Psy_model; + + +/* buffer considerations */ +typedef enum buffer_constraint_e { + MDB_DEFAULT=0, + MDB_STRICT_ISO=1, + MDB_MAXIMUM=2 +} buffer_constraint; + + +struct lame_global_struct; +typedef struct lame_global_struct lame_global_flags; +typedef lame_global_flags *lame_t; + + + + +/*********************************************************************** + * + * The LAME API + * These functions should be called, in this order, for each + * MP3 file to be encoded. See the file "API" for more documentation + * + ***********************************************************************/ + + +/* + * REQUIRED: + * initialize the encoder. sets default for all encoder parameters, + * returns NULL if some malloc()'s failed + * otherwise returns pointer to structure needed for all future + * API calls. + */ +lame_global_flags * CDECL lame_init(void); +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* obsolete version */ +int CDECL lame_init_old(lame_global_flags *); +#endif + +/* + * OPTIONAL: + * set as needed to override defaults + */ + +/******************************************************************** + * input stream description + ***********************************************************************/ +/* number of samples. default = 2^32-1 */ +int CDECL lame_set_num_samples(lame_global_flags *, unsigned long); +unsigned long CDECL lame_get_num_samples(const lame_global_flags *); + +/* input sample rate in Hz. default = 44100hz */ +int CDECL lame_set_in_samplerate(lame_global_flags *, int); +int CDECL lame_get_in_samplerate(const lame_global_flags *); + +/* number of channels in input stream. default=2 */ +int CDECL lame_set_num_channels(lame_global_flags *, int); +int CDECL lame_get_num_channels(const lame_global_flags *); + +/* + scale the input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale(lame_global_flags *, float); +float CDECL lame_get_scale(const lame_global_flags *); + +/* + scale the channel 0 (left) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale_left(lame_global_flags *, float); +float CDECL lame_get_scale_left(const lame_global_flags *); + +/* + scale the channel 1 (right) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale_right(lame_global_flags *, float); +float CDECL lame_get_scale_right(const lame_global_flags *); + +/* + output sample rate in Hz. default = 0, which means LAME picks best value + based on the amount of compression. MPEG only allows: + MPEG1 32, 44.1, 48khz + MPEG2 16, 22.05, 24 + MPEG2.5 8, 11.025, 12 + (not used by decoding routines) +*/ +int CDECL lame_set_out_samplerate(lame_global_flags *, int); +int CDECL lame_get_out_samplerate(const lame_global_flags *); + + +/******************************************************************** + * general control parameters + ***********************************************************************/ +/* 1=cause LAME to collect data for an MP3 frame analyzer. default=0 */ +int CDECL lame_set_analysis(lame_global_flags *, int); +int CDECL lame_get_analysis(const lame_global_flags *); + +/* + 1 = write a Xing VBR header frame. + default = 1 + this variable must have been added by a Hungarian notation Windows programmer :-) +*/ +int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); +int CDECL lame_get_bWriteVbrTag(const lame_global_flags *); + +/* 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 */ +int CDECL lame_set_decode_only(lame_global_flags *, int); +int CDECL lame_get_decode_only(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* 1=encode a Vorbis .ogg file. default=0 */ +/* DEPRECATED */ +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); +#endif + +/* + internal algorithm selection. True quality is determined by the bitrate + but this variable will effect quality by selecting expensive or cheap algorithms. + quality=0..9. 0=best (very slow). 9=worst. + recommended: 2 near-best quality, not too slow + 5 good quality, fast + 7 ok quality, really fast +*/ +int CDECL lame_set_quality(lame_global_flags *, int); +int CDECL lame_get_quality(const lame_global_flags *); + +/* + mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono + default: lame picks based on compression ration and input channels +*/ +int CDECL lame_set_mode(lame_global_flags *, MPEG_mode); +MPEG_mode CDECL lame_get_mode(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + mode_automs. Use a M/S mode with a switching threshold based on + compression ratio + DEPRECATED +*/ +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); +#endif + +/* + force_ms. Force M/S for all frames. For testing only. + default = 0 (disabled) +*/ +int CDECL lame_set_force_ms(lame_global_flags *, int); +int CDECL lame_get_force_ms(const lame_global_flags *); + +/* use free_format? default = 0 (disabled) */ +int CDECL lame_set_free_format(lame_global_flags *, int); +int CDECL lame_get_free_format(const lame_global_flags *); + +/* perform ReplayGain analysis? default = 0 (disabled) */ +int CDECL lame_set_findReplayGain(lame_global_flags *, int); +int CDECL lame_get_findReplayGain(const lame_global_flags *); + +/* decode on the fly. Search for the peak sample. If the ReplayGain + * analysis is enabled then perform the analysis on the decoded data + * stream. default = 0 (disabled) + * NOTE: if this option is set the build-in decoder should not be used */ +int CDECL lame_set_decode_on_the_fly(lame_global_flags *, int); +int CDECL lame_get_decode_on_the_fly(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* DEPRECATED: now does the same as lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_input(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_input(const lame_global_flags *); + +/* DEPRECATED: now does the same as + lame_set_decode_on_the_fly() && lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_decode(const lame_global_flags *); + +/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() + default = 0 (disabled) */ +int CDECL lame_set_findPeakSample(lame_global_flags *, int); +int CDECL lame_get_findPeakSample(const lame_global_flags *); +#endif + +/* counters for gapless encoding */ +int CDECL lame_set_nogap_total(lame_global_flags*, int); +int CDECL lame_get_nogap_total(const lame_global_flags*); + +int CDECL lame_set_nogap_currentindex(lame_global_flags* , int); +int CDECL lame_get_nogap_currentindex(const lame_global_flags*); + + +/* + * OPTIONAL: + * Set printf like error/debug/message reporting functions. + * The second argument has to be a pointer to a function which looks like + * void my_debugf(const char *format, va_list ap) + * { + * (void) vfprintf(stdout, format, ap); + * } + * If you use NULL as the value of the pointer in the set function, the + * lame buildin function will be used (prints to stderr). + * To quiet any output you have to replace the body of the example function + * with just "return;" and use it in the set function. + */ +int CDECL lame_set_errorf(lame_global_flags *, lame_report_function); +int CDECL lame_set_debugf(lame_global_flags *, lame_report_function); +int CDECL lame_set_msgf (lame_global_flags *, lame_report_function); + + + +/* set one of brate compression ratio. default is compression ratio of 11. */ +int CDECL lame_set_brate(lame_global_flags *, int); +int CDECL lame_get_brate(const lame_global_flags *); +int CDECL lame_set_compression_ratio(lame_global_flags *, float); +float CDECL lame_get_compression_ratio(const lame_global_flags *); + + +int CDECL lame_set_preset( lame_global_flags* gfp, int ); +int CDECL lame_set_asm_optimizations( lame_global_flags* gfp, int, int ); + + + +/******************************************************************** + * frame params + ***********************************************************************/ +/* mark as copyright. default=0 */ +int CDECL lame_set_copyright(lame_global_flags *, int); +int CDECL lame_get_copyright(const lame_global_flags *); + +/* mark as original. default=1 */ +int CDECL lame_set_original(lame_global_flags *, int); +int CDECL lame_get_original(const lame_global_flags *); + +/* error_protection. Use 2 bytes from each frame for CRC checksum. default=0 */ +int CDECL lame_set_error_protection(lame_global_flags *, int); +int CDECL lame_get_error_protection(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) */ +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); +#endif + +/* MP3 'private extension' bit Meaningless. default=0 */ +int CDECL lame_set_extension(lame_global_flags *, int); +int CDECL lame_get_extension(const lame_global_flags *); + +/* enforce strict ISO compliance. default=0 */ +int CDECL lame_set_strict_ISO(lame_global_flags *, int); +int CDECL lame_get_strict_ISO(const lame_global_flags *); + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* disable the bit reservoir. For testing only. default=0 */ +int CDECL lame_set_disable_reservoir(lame_global_flags *, int); +int CDECL lame_get_disable_reservoir(const lame_global_flags *); + +/* select a different "best quantization" function. default=0 */ +int CDECL lame_set_quant_comp(lame_global_flags *, int); +int CDECL lame_get_quant_comp(const lame_global_flags *); +int CDECL lame_set_quant_comp_short(lame_global_flags *, int); +int CDECL lame_get_quant_comp_short(const lame_global_flags *); + +int CDECL lame_set_experimentalX(lame_global_flags *, int); /* compatibility*/ +int CDECL lame_get_experimentalX(const lame_global_flags *); + +/* another experimental option. for testing only */ +int CDECL lame_set_experimentalY(lame_global_flags *, int); +int CDECL lame_get_experimentalY(const lame_global_flags *); + +/* another experimental option. for testing only */ +int CDECL lame_set_experimentalZ(lame_global_flags *, int); +int CDECL lame_get_experimentalZ(const lame_global_flags *); + +/* Naoki's psycho acoustic model. default=0 */ +int CDECL lame_set_exp_nspsytune(lame_global_flags *, int); +int CDECL lame_get_exp_nspsytune(const lame_global_flags *); + +void CDECL lame_set_msfix(lame_global_flags *, double); +float CDECL lame_get_msfix(const lame_global_flags *); + + +/******************************************************************** + * VBR control + ***********************************************************************/ +/* Types of VBR. default = vbr_off = CBR */ +int CDECL lame_set_VBR(lame_global_flags *, vbr_mode); +vbr_mode CDECL lame_get_VBR(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest */ +int CDECL lame_set_VBR_q(lame_global_flags *, int); +int CDECL lame_get_VBR_q(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest, Range [0,...,10[ */ +int CDECL lame_set_VBR_quality(lame_global_flags *, float); +float CDECL lame_get_VBR_quality(const lame_global_flags *); + +/* Ignored except for VBR=vbr_abr (ABR mode) */ +int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); + +/* + 1=strictly enforce VBR_min_bitrate. Normally it will be violated for + analog silence +*/ +int CDECL lame_set_VBR_hard_min(lame_global_flags *, int); +int CDECL lame_get_VBR_hard_min(const lame_global_flags *); + +/* for preset */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int CDECL lame_set_preset_expopts(lame_global_flags *, int); +#endif + +/******************************************************************** + * Filtering control + ***********************************************************************/ +/* freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled */ +int CDECL lame_set_lowpassfreq(lame_global_flags *, int); +int CDECL lame_get_lowpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int CDECL lame_set_lowpasswidth(lame_global_flags *, int); +int CDECL lame_get_lowpasswidth(const lame_global_flags *); + +/* freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled */ +int CDECL lame_set_highpassfreq(lame_global_flags *, int); +int CDECL lame_get_highpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int CDECL lame_set_highpasswidth(lame_global_flags *, int); +int CDECL lame_get_highpasswidth(const lame_global_flags *); + + +/******************************************************************** + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + ***********************************************************************/ + +/* only use ATH for masking */ +int CDECL lame_set_ATHonly(lame_global_flags *, int); +int CDECL lame_get_ATHonly(const lame_global_flags *); + +/* only use ATH for short blocks */ +int CDECL lame_set_ATHshort(lame_global_flags *, int); +int CDECL lame_get_ATHshort(const lame_global_flags *); + +/* disable ATH */ +int CDECL lame_set_noATH(lame_global_flags *, int); +int CDECL lame_get_noATH(const lame_global_flags *); + +/* select ATH formula */ +int CDECL lame_set_ATHtype(lame_global_flags *, int); +int CDECL lame_get_ATHtype(const lame_global_flags *); + +/* lower ATH by this many db */ +int CDECL lame_set_ATHlower(lame_global_flags *, float); +float CDECL lame_get_ATHlower(const lame_global_flags *); + +/* select ATH adaptive adjustment type */ +int CDECL lame_set_athaa_type( lame_global_flags *, int); +int CDECL lame_get_athaa_type( const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* select the loudness approximation used by the ATH adaptive auto-leveling */ +int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int); +int CDECL lame_get_athaa_loudapprox( const lame_global_flags *); +#endif + +/* adjust (in dB) the point below which adaptive ATH level adjustment occurs */ +int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float); +float CDECL lame_get_athaa_sensitivity( const lame_global_flags* ); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* OBSOLETE: predictability limit (ISO tonality formula) */ +int CDECL lame_set_cwlimit(lame_global_flags *, int); +int CDECL lame_get_cwlimit(const lame_global_flags *); +#endif + +/* + allow blocktypes to differ between channels? + default: 0 for jstereo, 1 for stereo +*/ +int CDECL lame_set_allow_diff_short(lame_global_flags *, int); +int CDECL lame_get_allow_diff_short(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int CDECL lame_set_useTemporal(lame_global_flags *, int); +int CDECL lame_get_useTemporal(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int CDECL lame_set_interChRatio(lame_global_flags *, float); +float CDECL lame_get_interChRatio(const lame_global_flags *); + +/* disable short blocks */ +int CDECL lame_set_no_short_blocks(lame_global_flags *, int); +int CDECL lame_get_no_short_blocks(const lame_global_flags *); + +/* force short blocks */ +int CDECL lame_set_force_short_blocks(lame_global_flags *, int); +int CDECL lame_get_force_short_blocks(const lame_global_flags *); + +/* Input PCM is emphased PCM (for instance from one of the rarely + emphased CDs), it is STRONGLY not recommended to use this, because + psycho does not take it into account, and last but not least many decoders + ignore these bits */ +int CDECL lame_set_emphasis(lame_global_flags *, int); +int CDECL lame_get_emphasis(const lame_global_flags *); + + + +/************************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/************************************************************************/ +/* version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) */ +int CDECL lame_get_version(const lame_global_flags *); + +/* encoder delay */ +int CDECL lame_get_encoder_delay(const lame_global_flags *); + +/* + padding appended to the input to make sure decoder can fully decode + all input. Note that this value can only be calculated during the + call to lame_encoder_flush(). Before lame_encoder_flush() has + been called, the value of encoder_padding = 0. +*/ +int CDECL lame_get_encoder_padding(const lame_global_flags *); + +/* size of MPEG frame */ +int CDECL lame_get_framesize(const lame_global_flags *); + +/* number of PCM samples buffered, but not yet encoded to mp3 data. */ +int CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); + +/* + size (bytes) of mp3 data buffered, but not yet encoded. + this is the number of bytes which would be output by a call to + lame_encode_flush_nogap. NOTE: lame_encode_flush() will return + more bytes than this because it will encode the reamining buffered + PCM samples before flushing the mp3 buffers. +*/ +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); + +/* number of frames encoded so far */ +int CDECL lame_get_frameNum(const lame_global_flags *); + +/* + lame's estimate of the total number of frames to be encoded + only valid if calling program set num_samples +*/ +int CDECL lame_get_totalframes(const lame_global_flags *); + +/* RadioGain value. Multiplied by 10 and rounded to the nearest. */ +int CDECL lame_get_RadioGain(const lame_global_flags *); + +/* AudiophileGain value. Multipled by 10 and rounded to the nearest. */ +int CDECL lame_get_AudiophileGain(const lame_global_flags *); + +/* the peak sample */ +float CDECL lame_get_PeakSample(const lame_global_flags *); + +/* Gain change required for preventing clipping. The value is correct only if + peak sample searching was enabled. If negative then the waveform + already does not clip. The value is multiplied by 10 and rounded up. */ +int CDECL lame_get_noclipGainChange(const lame_global_flags *); + +/* user-specified scale factor required for preventing clipping. Value is + correct only if peak sample searching was enabled and no user-specified + scaling was performed. If negative then either the waveform already does + not clip or the value cannot be determined */ +float CDECL lame_get_noclipScale(const lame_global_flags *); + +/* returns the limit of PCM samples, which one can pass in an encode call + under the constrain of a provided buffer of size buffer_size */ +int CDECL lame_get_maximum_number_of_samples(lame_t gfp, size_t buffer_size); + + + + +/* + * REQUIRED: + * sets more internal configuration based on data provided above. + * returns -1 if something failed. + */ +int CDECL lame_init_params(lame_global_flags *); + + +/* + * OPTIONAL: + * get the version number, in a string. of the form: + * "3.63 (beta)" or just "3.63". + */ +const char* CDECL get_lame_version ( void ); +const char* CDECL get_lame_short_version ( void ); +const char* CDECL get_lame_very_short_version ( void ); +const char* CDECL get_psy_version ( void ); +const char* CDECL get_lame_url ( void ); +const char* CDECL get_lame_os_bitness ( void ); + +/* + * OPTIONAL: + * get the version numbers in numerical form. + */ +typedef struct { + /* generic LAME version */ + int major; + int minor; + int alpha; /* 0 if not an alpha version */ + int beta; /* 0 if not a beta version */ + + /* version of the psy model */ + int psy_major; + int psy_minor; + int psy_alpha; /* 0 if not an alpha version */ + int psy_beta; /* 0 if not a beta version */ + + /* compile time features */ + const char *features; /* Don't make assumptions about the contents! */ +} lame_version_t; +void CDECL get_lame_version_numerical(lame_version_t *); + + +/* + * OPTIONAL: + * print internal lame configuration to message handler + */ +void CDECL lame_print_config(const lame_global_flags* gfp); + +void CDECL lame_print_internals( const lame_global_flags *gfp); + + +/* + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * + * return code number of bytes output in mp3buf. Can be 0 + * -1: mp3buf was too small + * -2: malloc() problem + * -3: lame_init_params() not called + * -4: psycho acoustic problems + * + * The required mp3buf_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buf_size in bytes = 1.25*num_samples + 7200 + * + * I think a tighter bound could be: (mt, March 2000) + * MPEG1: + * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 + * MPEG2: + * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 + * + * but test first if you use that! + * + * set mp3buf_size = 0 and LAME will not check if mp3buf_size is + * large enough. + * + * NOTE: + * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels + * will be averaged into the L channel before encoding only the L channel + * This will overwrite the data in buffer_l[] and buffer_r[]. + * +*/ +int CDECL lame_encode_buffer ( + lame_global_flags* gfp, /* global context handle */ + const short int buffer_l [], /* PCM data for left channel */ + const short int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but input has L & R channel data interleaved. + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int CDECL lame_encode_buffer_interleaved( + lame_global_flags* gfp, /* global context handlei */ + short int pcm[], /* PCM data for left and right + channel, interleaved */ + int num_samples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + */ +int CDECL lame_encode_buffer_float( + lame_global_flags* gfp, /* global context handle */ + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int CDECL lame_encode_buffer_ieee_float( + lame_t gfp, + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); +int CDECL lame_encode_buffer_interleaved_ieee_float( + lame_t gfp, + const float pcm[], /* PCM data for left and right + channel, interleaved */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); + +/* as lame_encode_buffer, but for 'double's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int CDECL lame_encode_buffer_ieee_double( + lame_t gfp, + const double pcm_l [], /* PCM data for left channel */ + const double pcm_r [], /* PCM data for right channel */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); +int CDECL lame_encode_buffer_interleaved_ieee_double( + lame_t gfp, + const double pcm[], /* PCM data for left and right + channel, interleaved */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); + +/* as lame_encode_buffer, but for long's + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + * + * This scaling was a mistake (doesn't allow one to exploit full + * precision of type 'long'. Use lame_encode_buffer_long2() instead. + * + */ +int CDECL lame_encode_buffer_long( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* Same as lame_encode_buffer_long(), but with correct scaling. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'long'. Data should be in the range: +/- 2^(8*size(long)-1) + * + */ +int CDECL lame_encode_buffer_long2( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for int's + * !! NOTE: !! input should be scaled to the maximum range of 'int' + * If int is 4 bytes, then the values should range from + * +/- 2147483648. + * + * This routine does not (and cannot, without loosing precision) use + * the same scaling as the rest of the lame_encode_buffer() routines. + * + */ +int CDECL lame_encode_buffer_int( + lame_global_flags* gfp, /* global context handle */ + const int buffer_l [], /* PCM data for left channel */ + const int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but for interleaved data. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'int32_t'. Data should be in the range: +/- 2^(8*size(int32_t)-1) + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int +lame_encode_buffer_interleaved_int( + lame_t gfp, + const int pcm [], /* PCM data for left and right + channel, interleaved */ + const int nsamples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + + +/* + * REQUIRED: + * lame_encode_flush will flush the intenal PCM buffers, padding with + * 0's to make sure the final frame is complete, and then flush + * the internal MP3 buffers, and thus may return a + * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * will also write id3v1 tags (if any) into the bitstream + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * lame_encode_flush_nogap will flush the internal mp3 buffers and pad + * the last frame with ancillary data so it is a complete mp3 frame. + * + * 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * After a call to this routine, the outputed mp3 data is complete, but + * you may continue to encode new PCM samples and write future mp3 data + * to a different file. The two mp3 files will play back with no gaps + * if they are concatenated together. + * + * This routine will NOT write id3v1 tags into the bitstream. + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush_nogap( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * Normally, this is called by lame_init_params(). It writes id3v2 and + * Xing headers into the front of the bitstream, and sets frame counters + * and bitrate histogram data to 0. You can also call this after + * lame_encode_flush_nogap(). + */ +int CDECL lame_init_bitstream( + lame_global_flags * gfp); /* global context handle */ + + + +/* + * OPTIONAL: some simple statistics + * a bitrate histogram to visualize the distribution of used frame sizes + * a stereo mode histogram to visualize the distribution of used stereo + * modes, useful in joint-stereo mode only + * 0: LR left-right encoded + * 1: LR-I left-right and intensity encoded (currently not supported) + * 2: MS mid-side encoded + * 3: MS-I mid-side and intensity encoded (currently not supported) + * + * attention: don't call them after lame_encode_finish + * suggested: lame_encode_flush -> lame_*_hist -> lame_close + */ + +void CDECL lame_bitrate_hist( + const lame_global_flags * gfp, + int bitrate_count[14] ); +void CDECL lame_bitrate_kbps( + const lame_global_flags * gfp, + int bitrate_kbps [14] ); +void CDECL lame_stereo_mode_hist( + const lame_global_flags * gfp, + int stereo_mode_count[4] ); + +void CDECL lame_bitrate_stereo_mode_hist ( + const lame_global_flags * gfp, + int bitrate_stmode_count[14][4] ); + +void CDECL lame_block_type_hist ( + const lame_global_flags * gfp, + int btype_count[6] ); + +void CDECL lame_bitrate_block_type_hist ( + const lame_global_flags * gfp, + int bitrate_btype_count[14][6] ); + +#if (DEPRECATED_OR_OBSOLETE_CODE_REMOVED && 0) +#else +/* + * OPTIONAL: + * lame_mp3_tags_fid will rewrite a Xing VBR tag to the mp3 file with file + * pointer fid. These calls perform forward and backwards seeks, so make + * sure fid is a real file. Make sure lame_encode_flush has been called, + * and all mp3 data has been written to the file before calling this + * function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME because + * the output is not a regular file, this call does nothing + * NOTE: + * LAME wants to read from the file to skip an optional ID3v2 tag, so + * make sure you opened the file for writing and reading. + * NOTE: + * You can call lame_get_lametag_frame instead, if you want to insert + * the lametag yourself. +*/ +void CDECL lame_mp3_tags_fid(lame_global_flags *, FILE* fid); +#endif + +/* + * OPTIONAL: + * lame_get_lametag_frame copies the final LAME-tag into 'buffer'. + * The function returns the number of bytes copied into buffer, or + * the required buffer size, if the provided buffer is too small. + * Function failed, if the return value is larger than 'size'! + * Make sure lame_encode flush has been called before calling this function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME, + * this call does nothing and returns 0. + * NOTE: + * LAME inserted an empty frame in the beginning of mp3 audio data, + * which you have to replace by the final LAME-tag frame after encoding. + * In case there is no ID3v2 tag, usually this frame will be the very first + * data in your mp3 file. If you put some other leading data into your + * file, you'll have to do some bookkeeping about where to write this buffer. + */ +size_t CDECL lame_get_lametag_frame( + const lame_global_flags *, unsigned char* buffer, size_t size); + +/* + * REQUIRED: + * final call to free all remaining buffers + */ +int CDECL lame_close (lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + * OBSOLETE: + * lame_encode_finish combines lame_encode_flush() and lame_close() in + * one call. However, once this call is made, the statistics routines + * will no longer work because the data will have been cleared, and + * lame_mp3_tags_fid() cannot be called to add data to the VBR header + */ +int CDECL lame_encode_finish( + lame_global_flags* gfp, + unsigned char* mp3buf, + int size ); +#endif + + + + + + +/********************************************************************* + * + * decoding + * + * a simple interface to mpglib, part of mpg123, is also included if + * libmp3lame is compiled with HAVE_MPGLIB + * + *********************************************************************/ + +struct hip_global_struct; +typedef struct hip_global_struct hip_global_flags; +typedef hip_global_flags *hip_t; + + +typedef struct { + int header_parsed; /* 1 if header was parsed and following data was + computed */ + int stereo; /* number of channels */ + int samplerate; /* sample rate */ + int bitrate; /* bitrate */ + int mode; /* mp3 frame type */ + int mode_ext; /* mp3 frame type */ + int framesize; /* number of samples per mp3 frame */ + + /* this data is only computed if mpglib detects a Xing VBR header */ + unsigned long nsamp; /* number of samples in mp3 file. */ + int totalframes; /* total number of frames in mp3 file */ + + /* this data is not currently computed by the mpglib routines */ + int framenum; /* frames decoded counter */ +} mp3data_struct; + +/* required call to initialize decoder */ +hip_t CDECL hip_decode_init(void); + +/* cleanup call to exit decoder */ +int CDECL hip_decode_exit(hip_t gfp); + +/* HIP reporting functions */ +void CDECL hip_set_errorf(hip_t gfp, lame_report_function f); +void CDECL hip_set_debugf(hip_t gfp, lame_report_function f); +void CDECL hip_set_msgf (hip_t gfp, lame_report_function f); + +/********************************************************************* + * input 1 mp3 frame, output (maybe) pcm data. + * + * nout = hip_decode(hip, mp3buf,len,pcm_l,pcm_r); + * + * input: + * len : number of bytes of mp3 data in mp3buf + * mp3buf[len] : mp3 data to be decoded + * + * output: + * nout: -1 : decoding error + * 0 : need more data before we can complete the decode + * >0 : returned 'nout' samples worth of data in pcm_l,pcm_r + * pcm_l[nout] : left channel data + * pcm_r[nout] : right channel data + * + *********************************************************************/ +int CDECL hip_decode( hip_t gfp + , unsigned char * mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode, and also returns mp3 header data */ +int CDECL hip_decode_headers( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode, but returns at most one frame */ +int CDECL hip_decode1( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode1, but returns at most one frame and mp3 header data */ +int CDECL hip_decode1_headers( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode1_headers, but also returns enc_delay and enc_padding + from VBR Info tag, (-1 if no info tag was found) */ +int CDECL hip_decode1_headersB( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + , int *enc_delay + , int *enc_padding + ); + + + +/* OBSOLETE: + * lame_decode... functions are there to keep old code working + * but it is strongly recommended to replace calls by hip_decode... + * function calls, see above. + */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int CDECL lame_decode_init(void); +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); +int CDECL lame_decode_exit(void); + +#endif /* obsolete lame_decode API calls */ + + +/********************************************************************* + * + * id3tag stuff + * + *********************************************************************/ + +/* + * id3tag.h -- Interface to write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +/* utility to obtain alphabetically sorted list of genre names with numbers */ +void CDECL id3tag_genre_list( + void (*handler)(int, const char *, void *), + void* cookie); + +void CDECL id3tag_init (lame_t gfp); + +/* force addition of version 2 tag */ +void CDECL id3tag_add_v2 (lame_t gfp); + +/* add only a version 1 tag */ +void CDECL id3tag_v1_only (lame_t gfp); + +/* add only a version 2 tag */ +void CDECL id3tag_v2_only (lame_t gfp); + +/* pad version 1 tag with spaces instead of nulls */ +void CDECL id3tag_space_v1 (lame_t gfp); + +/* pad version 2 tag with extra 128 bytes */ +void CDECL id3tag_pad_v2 (lame_t gfp); + +/* pad version 2 tag with extra n bytes */ +void CDECL id3tag_set_pad (lame_t gfp, size_t n); + +void CDECL id3tag_set_title(lame_t gfp, const char* title); +void CDECL id3tag_set_artist(lame_t gfp, const char* artist); +void CDECL id3tag_set_album(lame_t gfp, const char* album); +void CDECL id3tag_set_year(lame_t gfp, const char* year); +void CDECL id3tag_set_comment(lame_t gfp, const char* comment); + +/* return -1 result if track number is out of ID3v1 range + and ignored for ID3v1 */ +int CDECL id3tag_set_track(lame_t gfp, const char* track); + +/* return non-zero result if genre name or number is invalid + result 0: OK + result -1: genre number out of range + result -2: no valid ID3v1 genre name, mapped to ID3v1 'Other' + but taken as-is for ID3v2 genre tag */ +int CDECL id3tag_set_genre(lame_t gfp, const char* genre); + +/* return non-zero result if field name is invalid */ +int CDECL id3tag_set_fieldvalue(lame_t gfp, const char* fieldvalue); + +/* return non-zero result if image type is invalid */ +int CDECL id3tag_set_albumart(lame_t gfp, const char* image, size_t size); + +/* lame_get_id3v1_tag copies ID3v1 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v1 tag. + */ +size_t CDECL lame_get_id3v1_tag(lame_t gfp, unsigned char* buffer, size_t size); + +/* lame_get_id3v2_tag copies ID3v2 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v2 tag. + */ +size_t CDECL lame_get_id3v2_tag(lame_t gfp, unsigned char* buffer, size_t size); + +/* normaly lame_init_param writes ID3v2 tags into the audio stream + * Call lame_set_write_id3tag_automatic(gfp, 0) before lame_init_param + * to turn off this behaviour and get ID3v2 tag with above function + * write it yourself into your file. + */ +void CDECL lame_set_write_id3tag_automatic(lame_global_flags * gfp, int); +int CDECL lame_get_write_id3tag_automatic(lame_global_flags const* gfp); + +/* experimental */ +int CDECL id3tag_set_textinfo_latin1(lame_t gfp, char const *id, char const *text); + +/* experimental */ +int CDECL id3tag_set_comment_latin1(lame_t gfp, char const *lang, char const *desc, char const *text); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* experimental */ +int CDECL id3tag_set_textinfo_ucs2(lame_t gfp, char const *id, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_comment_ucs2(lame_t gfp, char const *lang, + unsigned short const *desc, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue); +#endif + +/* experimental */ +int CDECL id3tag_set_fieldvalue_utf16(lame_t gfp, const unsigned short *fieldvalue); + +/* experimental */ +int CDECL id3tag_set_textinfo_utf16(lame_t gfp, char const *id, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_comment_utf16(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text); + + +/*********************************************************************** +* +* list of valid bitrates [kbps] & sample frequencies [Hz]. +* first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) +* 1: MPEG-1 values (sample frequencies 32...48 kHz) +* 2: MPEG-2.5 values (sample frequencies 8...12 kHz) +***********************************************************************/ + +extern const int bitrate_table [3][16]; +extern const int samplerate_table [3][ 4]; + +/* access functions for use in DLL, global vars are not exported */ +int CDECL lame_get_bitrate(int mpeg_version, int table_index); +int CDECL lame_get_samplerate(int mpeg_version, int table_index); + + +/* maximum size of albumart image (128KB), which affects LAME_MAXMP3BUFFER + as well since lame_encode_buffer() also returns ID3v2 tag data */ +#define LAME_MAXALBUMART (128 * 1024) + +/* maximum size of mp3buffer needed if you encode at most 1152 samples for + each call to lame_encode_buffer. see lame_encode_buffer() below + (LAME_MAXMP3BUFFER is now obsolete) */ +#define LAME_MAXMP3BUFFER (16384 + LAME_MAXALBUMART) + + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82 + +} lame_errorcodes_t; + +#if defined(__cplusplus) +} +#endif +#endif /* LAME_LAME_H */ + diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.c new file mode 100644 index 00000000..5800a44c --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.c @@ -0,0 +1,1082 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * Copyright (c) 2001 Jonathan Dee + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: VbrTag.c,v 1.106 2017/08/06 18:15:47 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "bitstream.h" +#include "VbrTag.h" +#include "lame_global_flags.h" +#include "tables.h" + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + + +#ifdef _DEBUG +/* #define DEBUG_VBRTAG */ +#endif + +/* + * 4 bytes for Header Tag + * 4 bytes for Header Flags + * 100 bytes for entry (NUMTOCENTRIES) + * 4 bytes for FRAME SIZE + * 4 bytes for STREAM_SIZE + * 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst + * 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)" + * ___________ + * 140 bytes +*/ +#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4) + +#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2) + +/* the size of the Xing header (MPEG1 and MPEG2) in kbps */ +#define XING_BITRATE1 128 +#define XING_BITRATE2 64 +#define XING_BITRATE25 32 + +extern const char* get_lame_tag_encoder_short_version(void); + +static const char VBRTag0[] = { "Xing" }; +static const char VBRTag1[] = { "Info" }; + + + + +/* Lookup table for fast CRC computation + * See 'CRC_update_lookup' + * Uses the polynomial x^16+x^15+x^2+1 */ + +static const unsigned int crc16_lookup[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + + + + + +/*********************************************************************** + * Robert Hegemann 2001-01-17 + ***********************************************************************/ + +static void +addVbr(VBR_seek_info_t * v, int bitrate) +{ + int i; + + v->nVbrNumFrames++; + v->sum += bitrate; + v->seen++; + + if (v->seen < v->want) { + return; + } + + if (v->pos < v->size) { + v->bag[v->pos] = v->sum; + v->pos++; + v->seen = 0; + } + if (v->pos == v->size) { + for (i = 1; i < v->size; i += 2) { + v->bag[i / 2] = v->bag[i]; + } + v->want *= 2; + v->pos /= 2; + } +} + +static void +Xing_seek_table(VBR_seek_info_t const* v, unsigned char *t) +{ + int i, indx; + int seek_point; + + if (v->pos <= 0) + return; + + for (i = 1; i < NUMTOCENTRIES; ++i) { + float j = i / (float) NUMTOCENTRIES, act, sum; + indx = (int) (floor(j * v->pos)); + if (indx > v->pos - 1) + indx = v->pos - 1; + act = v->bag[indx]; + sum = v->sum; + seek_point = (int) (256. * act / sum); + if (seek_point > 255) + seek_point = 255; + t[i] = seek_point; + } +} + +#ifdef DEBUG_VBR_SEEKING_TABLE +static void +print_seeking(unsigned char *t) +{ + int i; + + printf("seeking table "); + for (i = 0; i < NUMTOCENTRIES; ++i) { + printf(" %d ", t[i]); + } + printf("\n"); +} +#endif + + +/**************************************************************************** + * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries + * Paramters: + * nStreamPos: how many bytes did we write to the bitstream so far + * (in Bytes NOT Bits) + **************************************************************************** +*/ +void +AddVbrFrame(lame_internal_flags * gfc) +{ + int kbps = bitrate_table[gfc->cfg.version][gfc->ov_enc.bitrate_index]; + assert(gfc->VBR_seek_table.bag); + addVbr(&gfc->VBR_seek_table, kbps); +} + + +/*-------------------------------------------------------------*/ +static int +ExtractI4(const unsigned char *buf) +{ + int x; + /* big endian extract */ + x = buf[0]; + x <<= 8; + x |= buf[1]; + x <<= 8; + x |= buf[2]; + x <<= 8; + x |= buf[3]; + return x; +} + +static void +CreateI4(unsigned char *buf, uint32_t nValue) +{ + /* big endian create */ + buf[0] = (nValue >> 24) & 0xff; + buf[1] = (nValue >> 16) & 0xff; + buf[2] = (nValue >> 8) & 0xff; + buf[3] = (nValue) & 0xff; +} + + + +static void +CreateI2(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0] = (nValue >> 8) & 0xff; + buf[1] = (nValue) & 0xff; +} + +/* check for magic strings*/ +static int +IsVbrTag(const unsigned char *buf) +{ + int isTag0, isTag1; + + isTag0 = ((buf[0] == VBRTag0[0]) && (buf[1] == VBRTag0[1]) && (buf[2] == VBRTag0[2]) + && (buf[3] == VBRTag0[3])); + isTag1 = ((buf[0] == VBRTag1[0]) && (buf[1] == VBRTag1[1]) && (buf[2] == VBRTag1[2]) + && (buf[3] == VBRTag1[3])); + + return (isTag0 || isTag1); +} + +#define SHIFT_IN_BITS_VALUE(x,n,v) ( x = (x << (n)) | ( (v) & ~(-1 << (n)) ) ) + +static void +setLameTagFrameHeader(lame_internal_flags const *gfc, unsigned char *buffer) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + char abyte, bbyte; + + SHIFT_IN_BITS_VALUE(buffer[0], 8u, 0xffu); + + SHIFT_IN_BITS_VALUE(buffer[1], 3u, 7); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, (cfg->samplerate_out < 16000) ? 0 : 1); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, cfg->version); + SHIFT_IN_BITS_VALUE(buffer[1], 2u, 4 - 3); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, (!cfg->error_protection) ? 1 : 0); + + SHIFT_IN_BITS_VALUE(buffer[2], 4u, eov->bitrate_index); + SHIFT_IN_BITS_VALUE(buffer[2], 2u, cfg->samplerate_index); + SHIFT_IN_BITS_VALUE(buffer[2], 1u, 0); + SHIFT_IN_BITS_VALUE(buffer[2], 1u, cfg->extension); + + SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->mode); + SHIFT_IN_BITS_VALUE(buffer[3], 2u, eov->mode_ext); + SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->copyright); + SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->original); + SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->emphasis); + + /* the default VBR header. 48 kbps layer III, no padding, no crc */ + /* but sampling freq, mode andy copyright/copy protection taken */ + /* from first valid frame */ + buffer[0] = (uint8_t) 0xff; + abyte = (buffer[1] & (unsigned char) 0xf1); + { + int bitrate; + if (1 == cfg->version) { + bitrate = XING_BITRATE1; + } + else { + if (cfg->samplerate_out < 16000) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (cfg->vbr == vbr_off) + bitrate = cfg->avg_bitrate; + + if (cfg->free_format) + bbyte = 0x00; + else + bbyte = 16 * BitrateIndex(bitrate, cfg->version, cfg->samplerate_out); + } + + /* Use as much of the info from the real frames in the + * Xing header: samplerate, channels, crc, etc... + */ + if (cfg->version == 1) { + /* MPEG1 */ + buffer[1] = abyte | (char) 0x0a; /* was 0x0b; */ + abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */ + buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG1 frame */ + } + else { + /* MPEG2 */ + buffer[1] = abyte | (char) 0x02; /* was 0x03; */ + abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */ + buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG2 frame */ + } +} + +#if 0 +static int CheckVbrTag(unsigned char *buf); + +/*-------------------------------------------------------------*/ +/* Same as GetVbrTag below, but only checks for the Xing tag. + requires buf to contain only 40 bytes */ +/*-------------------------------------------------------------*/ +int +CheckVbrTag(unsigned char *buf) +{ + int h_id, h_mode; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_mode = (buf[3] >> 6) & 3; + + /* determine offset of header */ + if (h_id) { + /* mpeg1 */ + if (h_mode != 3) + buf += (32 + 4); + else + buf += (17 + 4); + } + else { + /* mpeg2 */ + if (h_mode != 3) + buf += (17 + 4); + else + buf += (9 + 4); + } + + return IsVbrTag(buf); +} +#endif + +int +GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf) +{ + int i, head_flags; + int h_bitrate, h_id, h_mode, h_sr_index, h_layer; + int enc_delay, enc_padding; + + /* get Vbr header data */ + pTagData->flags = 0; + + /* get selected MPEG header data */ + h_layer = (buf[1] >> 1) & 3; + if ( h_layer != 0x01 ) { + /* the following code assumes Layer-3, so give up here */ + return 0; + } + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + h_bitrate = ((buf[2] >> 4) & 0xf); + h_bitrate = bitrate_table[h_id][h_bitrate]; + + /* check for FFE syncword */ + if ((buf[1] >> 4) == 0xE) + pTagData->samprate = samplerate_table[2][h_sr_index]; + else + pTagData->samprate = samplerate_table[h_id][h_sr_index]; + /* if( h_id == 0 ) */ + /* pTagData->samprate >>= 1; */ + + + + /* determine offset of header */ + if (h_id) { + /* mpeg1 */ + if (h_mode != 3) + buf += (32 + 4); + else + buf += (17 + 4); + } + else { + /* mpeg2 */ + if (h_mode != 3) + buf += (17 + 4); + else + buf += (9 + 4); + } + + if (!IsVbrTag(buf)) + return 0; + + buf += 4; + + pTagData->h_id = h_id; + + head_flags = pTagData->flags = ExtractI4(buf); + buf += 4; /* get flags */ + + if (head_flags & FRAMES_FLAG) { + pTagData->frames = ExtractI4(buf); + buf += 4; + } + + if (head_flags & BYTES_FLAG) { + pTagData->bytes = ExtractI4(buf); + buf += 4; + } + + if (head_flags & TOC_FLAG) { + if (pTagData->toc != NULL) { + for (i = 0; i < NUMTOCENTRIES; i++) + pTagData->toc[i] = buf[i]; + } + buf += NUMTOCENTRIES; + } + + pTagData->vbr_scale = -1; + + if (head_flags & VBR_SCALE_FLAG) { + pTagData->vbr_scale = ExtractI4(buf); + buf += 4; + } + + pTagData->headersize = ((h_id + 1) * 72000 * h_bitrate) / pTagData->samprate; + + buf += 21; + enc_delay = buf[0] << 4; + enc_delay += buf[1] >> 4; + enc_padding = (buf[1] & 0x0F) << 8; + enc_padding += buf[2]; + /* check for reasonable values (this may be an old Xing header, */ + /* not a INFO tag) */ + if (enc_delay < 0 || enc_delay > 3000) + enc_delay = -1; + if (enc_padding < 0 || enc_padding > 3000) + enc_padding = -1; + + pTagData->enc_delay = enc_delay; + pTagData->enc_padding = enc_padding; + +#ifdef DEBUG_VBRTAG + fprintf(stderr, "\n\n********************* VBR TAG INFO *****************\n"); + fprintf(stderr, "tag :%s\n", VBRTag); + fprintf(stderr, "head_flags :%d\n", head_flags); + fprintf(stderr, "bytes :%d\n", pTagData->bytes); + fprintf(stderr, "frames :%d\n", pTagData->frames); + fprintf(stderr, "VBR Scale :%d\n", pTagData->vbr_scale); + fprintf(stderr, "enc_delay = %i \n", enc_delay); + fprintf(stderr, "enc_padding= %i \n", enc_padding); + fprintf(stderr, "toc:\n"); + if (pTagData->toc != NULL) { + for (i = 0; i < NUMTOCENTRIES; i++) { + if ((i % 10) == 0) + fprintf(stderr, "\n"); + fprintf(stderr, " %3d", (int) (pTagData->toc[i])); + } + } + fprintf(stderr, "\n***************** END OF VBR TAG INFO ***************\n"); +#endif + return 1; /* success */ +} + + +/**************************************************************************** + * InitVbrTag: Initializes the header, and write empty frame to stream + * Paramters: + * fpStream: pointer to output file stream + * nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO + **************************************************************************** +*/ +int +InitVbrTag(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + int kbps_header; + +#define MAXFRAMESIZE 2880 /* or 0xB40, the max freeformat 640 32kHz framesize */ + + /* + * Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz). + * (at 48kHz they use 56kbs since 48kbs frame not big enough for + * table of contents) + * let's always embed Xing header inside a 64kbs layer III frame. + * this gives us enough room for a LAME version string too. + * size determined by sampling frequency (MPEG1) + * 32kHz: 216 bytes@48kbs 288bytes@ 64kbs + * 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1) + * 48kHz: 144 bytes 192 + * + * MPEG 2 values are the same since the framesize and samplerate + * are each reduced by a factor of 2. + */ + + + if (1 == cfg->version) { + kbps_header = XING_BITRATE1; + } + else { + if (cfg->samplerate_out < 16000) + kbps_header = XING_BITRATE25; + else + kbps_header = XING_BITRATE2; + } + + if (cfg->vbr == vbr_off) + kbps_header = cfg->avg_bitrate; + + /** make sure LAME Header fits into Frame + */ + { + int total_frame_size = ((cfg->version + 1) * 72000 * kbps_header) / cfg->samplerate_out; + int header_size = (cfg->sideinfo_len + LAMEHEADERSIZE); + gfc->VBR_seek_table.TotalFrameSize = total_frame_size; + if (total_frame_size < header_size || total_frame_size > MAXFRAMESIZE) { + /* disable tag, it wont fit */ + gfc->cfg.write_lame_tag = 0; + return 0; + } + } + + gfc->VBR_seek_table.nVbrNumFrames = 0; + gfc->VBR_seek_table.nBytesWritten = 0; + gfc->VBR_seek_table.sum = 0; + + gfc->VBR_seek_table.seen = 0; + gfc->VBR_seek_table.want = 1; + gfc->VBR_seek_table.pos = 0; + + if (gfc->VBR_seek_table.bag == NULL) { + gfc->VBR_seek_table.bag = lame_calloc(int, 400); + if (gfc->VBR_seek_table.bag != NULL) { + gfc->VBR_seek_table.size = 400; + } + else { + gfc->VBR_seek_table.size = 0; + ERRORF(gfc, "Error: can't allocate VbrFrames buffer\n"); + gfc->cfg.write_lame_tag = 0; + return -1; + } + } + + /* write dummy VBR tag of all 0's into bitstream */ + { + uint8_t buffer[MAXFRAMESIZE]; + size_t i, n; + + memset(buffer, 0, sizeof(buffer)); + setLameTagFrameHeader(gfc, buffer); + n = gfc->VBR_seek_table.TotalFrameSize; + for (i = 0; i < n; ++i) { + add_dummy_byte(gfc, buffer[i], 1); + } + } + /* Success */ + return 0; +} + + + +/* fast CRC-16 computation - uses table crc16_lookup 8*/ +static uint16_t +CRC_update_lookup(uint16_t value, uint16_t crc) +{ + uint16_t tmp; + tmp = crc ^ value; + crc = (crc >> 8) ^ crc16_lookup[tmp & 0xff]; + return crc; +} + +void +UpdateMusicCRC(uint16_t * crc, unsigned char const *buffer, int size) +{ + int i; + for (i = 0; i < size; ++i) + *crc = CRC_update_lookup(buffer[i], *crc); +} + + + + + +/**************************************************************************** + * Jonathan Dee 2001/08/31 + * + * PutLameVBR: Write LAME info: mini version + info on various switches used + * Paramters: + * pbtStreamBuffer : pointer to output buffer + * id3v2size : size of id3v2 tag in bytes + * crc : computation of crc-16 of Lame Tag so far (starting at frame sync) + * + **************************************************************************** +*/ +static int +PutLameVBR(lame_global_flags const *gfp, size_t nMusicLength, uint8_t * pbtStreamBuffer, uint16_t crc) +{ + lame_internal_flags const *gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + + int nBytesWritten = 0; + int i; + + int enc_delay = gfc->ov_enc.encoder_delay; /* encoder delay */ + int enc_padding = gfc->ov_enc.encoder_padding; /* encoder padding */ + + /*recall: cfg->vbr_q is for example set by the switch -V */ + /* gfp->quality by -q, -h, -f, etc */ + + int nQuality = (100 - 10 * gfp->VBR_q - gfp->quality); + + + /* + NOTE: + Even though the specification for the LAME VBR tag + did explicitly mention other encoders than LAME, + many SW/HW decoder seem to be able to make use of + this tag only, if the encoder version starts with LAME. + To be compatible with such decoders, ANY encoder will + be forced to write a fake LAME version string! + As a result, the encoder version info becomes worthless. + */ + const char *szVersion = get_lame_tag_encoder_short_version(); + uint8_t nVBR; + uint8_t nRevision = 0x00; + uint8_t nRevMethod; + uint8_t vbr_type_translator[] = { 1, 5, 3, 2, 4, 0, 3 }; /*numbering different in vbr_mode vs. Lame tag */ + + uint8_t nLowpass = + (((cfg->lowpassfreq / 100.0) + .5) > 255 ? 255 : (cfg->lowpassfreq / 100.0) + .5); + + uint32_t nPeakSignalAmplitude = 0; + + uint16_t nRadioReplayGain = 0; + uint16_t nAudiophileReplayGain = 0; + + uint8_t nNoiseShaping = cfg->noise_shaping; + uint8_t nStereoMode = 0; + int bNonOptimal = 0; + uint8_t nSourceFreq = 0; + uint8_t nMisc = 0; + uint16_t nMusicCRC = 0; + + /*psy model type: Gpsycho or NsPsytune */ + unsigned char bExpNPsyTune = 1; /* only NsPsytune */ + unsigned char bSafeJoint = (cfg->use_safe_joint_stereo) != 0; + + unsigned char bNoGapMore = 0; + unsigned char bNoGapPrevious = 0; + + int nNoGapCount = gfp->nogap_total; + int nNoGapCurr = gfp->nogap_current; + + + uint8_t nAthType = cfg->ATHtype; /*4 bits. */ + + uint8_t nFlags = 0; + + /* if ABR, {store bitrate <=255} else { store "-b"} */ + int nABRBitrate; + switch (cfg->vbr) { + case vbr_abr:{ + nABRBitrate = cfg->vbr_avg_bitrate_kbps; + break; + } + case vbr_off:{ + nABRBitrate = cfg->avg_bitrate; + break; + } + default:{ /*vbr modes */ + nABRBitrate = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index];; + } + } + + + /*revision and vbr method */ + if (cfg->vbr < sizeof(vbr_type_translator)) + nVBR = vbr_type_translator[cfg->vbr]; + else + nVBR = 0x00; /*unknown. */ + + nRevMethod = 0x10 * nRevision + nVBR; + + + /* ReplayGain */ + if (cfg->findReplayGain) { + int RadioGain = gfc->ov_rpg.RadioGain; + if (RadioGain > 0x1FE) + RadioGain = 0x1FE; + if (RadioGain < -0x1FE) + RadioGain = -0x1FE; + + nRadioReplayGain = 0x2000; /* set name code */ + nRadioReplayGain |= 0xC00; /* set originator code to `determined automatically' */ + + if (RadioGain >= 0) + nRadioReplayGain |= RadioGain; /* set gain adjustment */ + else { + nRadioReplayGain |= 0x200; /* set the sign bit */ + nRadioReplayGain |= -RadioGain; /* set gain adjustment */ + } + } + + /* peak sample */ + if (cfg->findPeakSample) + nPeakSignalAmplitude = + abs((int) ((((FLOAT) gfc->ov_rpg.PeakSample) / 32767.0) * pow(2, 23) + .5)); + + /*nogap */ + if (nNoGapCount != -1) { + if (nNoGapCurr > 0) + bNoGapPrevious = 1; + + if (nNoGapCurr < nNoGapCount - 1) + bNoGapMore = 1; + } + + /*flags */ + + nFlags = nAthType + (bExpNPsyTune << 4) + + (bSafeJoint << 5) + + (bNoGapMore << 6) + + (bNoGapPrevious << 7); + + + if (nQuality < 0) + nQuality = 0; + + /*stereo mode field... a bit ugly. */ + + switch (cfg->mode) { + case MONO: + nStereoMode = 0; + break; + case STEREO: + nStereoMode = 1; + break; + case DUAL_CHANNEL: + nStereoMode = 2; + break; + case JOINT_STEREO: + if (cfg->force_ms) + nStereoMode = 4; + else + nStereoMode = 3; + break; + case NOT_SET: + /* FALLTHROUGH */ + default: + nStereoMode = 7; + break; + } + + /*Intensity stereo : nStereoMode = 6. IS is not implemented */ + + if (cfg->samplerate_in <= 32000) + nSourceFreq = 0x00; + else if (cfg->samplerate_in == 48000) + nSourceFreq = 0x02; + else if (cfg->samplerate_in > 48000) + nSourceFreq = 0x03; + else + nSourceFreq = 0x01; /*default is 44100Hz. */ + + + /*Check if the user overrided the default LAME behaviour with some nasty options */ + + if (cfg->short_blocks == short_block_forced || cfg->short_blocks == short_block_dispensed || ((cfg->lowpassfreq == -1) && (cfg->highpassfreq == -1)) || /* "-k" */ + (cfg->disable_reservoir && cfg->avg_bitrate < 320) || + cfg->noATH || cfg->ATHonly || (nAthType == 0) || cfg->samplerate_in <= 32000) + bNonOptimal = 1; + + nMisc = nNoiseShaping + (nStereoMode << 2) + + (bNonOptimal << 5) + + (nSourceFreq << 6); + + + nMusicCRC = gfc->nMusicCRC; + + + /*Write all this information into the stream */ + CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality); + nBytesWritten += 4; + + strncpy((char *) &pbtStreamBuffer[nBytesWritten], szVersion, 9); + nBytesWritten += 9; + + pbtStreamBuffer[nBytesWritten] = nRevMethod; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = nLowpass; + nBytesWritten++; + + CreateI4(&pbtStreamBuffer[nBytesWritten], nPeakSignalAmplitude); + nBytesWritten += 4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nRadioReplayGain); + nBytesWritten += 2; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nAudiophileReplayGain); + nBytesWritten += 2; + + pbtStreamBuffer[nBytesWritten] = nFlags; + nBytesWritten++; + + if (nABRBitrate >= 255) + pbtStreamBuffer[nBytesWritten] = 0xFF; + else + pbtStreamBuffer[nBytesWritten] = nABRBitrate; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = enc_delay >> 4; /* works for win32, does it for unix? */ + pbtStreamBuffer[nBytesWritten + 1] = (enc_delay << 4) + (enc_padding >> 8); + pbtStreamBuffer[nBytesWritten + 2] = enc_padding; + + nBytesWritten += 3; + + pbtStreamBuffer[nBytesWritten] = nMisc; + nBytesWritten++; + + + pbtStreamBuffer[nBytesWritten++] = 0; /*unused in rev0 */ + + CreateI2(&pbtStreamBuffer[nBytesWritten], cfg->preset); + nBytesWritten += 2; + + CreateI4(&pbtStreamBuffer[nBytesWritten], (int) nMusicLength); + nBytesWritten += 4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC); + nBytesWritten += 2; + + /*Calculate tag CRC.... must be done here, since it includes + *previous information*/ + + for (i = 0; i < nBytesWritten; i++) + crc = CRC_update_lookup(pbtStreamBuffer[i], crc); + + CreateI2(&pbtStreamBuffer[nBytesWritten], crc); + nBytesWritten += 2; + + return nBytesWritten; +} + +static long +skipId3v2(FILE * fpStream) +{ + size_t nbytes; + long id3v2TagSize; + unsigned char id3v2Header[10]; + + /* seek to the beginning of the stream */ + if (fseek(fpStream, 0, SEEK_SET) != 0) { + return -2; /* not seekable, abort */ + } + /* read 10 bytes in case there's an ID3 version 2 header here */ + nbytes = fread(id3v2Header, 1, sizeof(id3v2Header), fpStream); + if (nbytes != sizeof(id3v2Header)) { + return -3; /* not readable, maybe opened Write-Only */ + } + /* does the stream begin with the ID3 version 2 file identifier? */ + if (!strncmp((char *) id3v2Header, "ID3", 3)) { + /* the tag size (minus the 10-byte header) is encoded into four + * bytes where the most significant bit is clear in each byte */ + id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21) + | ((id3v2Header[7] & 0x7f) << 14) + | ((id3v2Header[8] & 0x7f) << 7) + | (id3v2Header[9] & 0x7f)) + + sizeof id3v2Header; + } + else { + /* no ID3 version 2 tag in this stream */ + id3v2TagSize = 0; + } + return id3v2TagSize; +} + + + +size_t +lame_get_lametag_frame(lame_global_flags const *gfp, unsigned char *buffer, size_t size) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + unsigned long stream_size; + unsigned int nStreamIndex; + uint8_t btToc[NUMTOCENTRIES]; + + if (gfp == 0) { + return 0; + } + gfc = gfp->internal_flags; + if (gfc == 0) { + return 0; + } + if (!is_lame_internal_flags_valid(gfc)) { + return 0; + } + cfg = &gfc->cfg; + if (cfg->write_lame_tag == 0) { + return 0; + } + if (gfc->VBR_seek_table.pos <= 0) { + return 0; + } + if (size < gfc->VBR_seek_table.TotalFrameSize) { + return gfc->VBR_seek_table.TotalFrameSize; + } + if (buffer == 0) { + return 0; + } + + memset(buffer, 0, gfc->VBR_seek_table.TotalFrameSize); + + /* 4 bytes frame header */ + + setLameTagFrameHeader(gfc, buffer); + + /* Clear all TOC entries */ + memset(btToc, 0, sizeof(btToc)); + + if (cfg->free_format) { + int i; + for (i = 1; i < NUMTOCENTRIES; ++i) + btToc[i] = 255 * i / 100; + } + else { + Xing_seek_table(&gfc->VBR_seek_table, btToc); + } +#ifdef DEBUG_VBR_SEEKING_TABLE + print_seeking(btToc); +#endif + + /* Start writing the tag after the zero frame */ + nStreamIndex = cfg->sideinfo_len; + /* note! Xing header specifies that Xing data goes in the + * ancillary data with NO ERROR PROTECTION. If error protecton + * in enabled, the Xing data still starts at the same offset, + * and now it is in sideinfo data block, and thus will not + * decode correctly by non-Xing tag aware players */ + if (cfg->error_protection) + nStreamIndex -= 2; + + /* Put Vbr tag */ + if (cfg->vbr == vbr_off) { + buffer[nStreamIndex++] = VBRTag1[0]; + buffer[nStreamIndex++] = VBRTag1[1]; + buffer[nStreamIndex++] = VBRTag1[2]; + buffer[nStreamIndex++] = VBRTag1[3]; + + } + else { + buffer[nStreamIndex++] = VBRTag0[0]; + buffer[nStreamIndex++] = VBRTag0[1]; + buffer[nStreamIndex++] = VBRTag0[2]; + buffer[nStreamIndex++] = VBRTag0[3]; + } + + /* Put header flags */ + CreateI4(&buffer[nStreamIndex], FRAMES_FLAG + BYTES_FLAG + TOC_FLAG + VBR_SCALE_FLAG); + nStreamIndex += 4; + + /* Put Total Number of frames */ + CreateI4(&buffer[nStreamIndex], gfc->VBR_seek_table.nVbrNumFrames); + nStreamIndex += 4; + + /* Put total audio stream size, including Xing/LAME Header */ + stream_size = gfc->VBR_seek_table.nBytesWritten + gfc->VBR_seek_table.TotalFrameSize; + CreateI4(&buffer[nStreamIndex], stream_size); + nStreamIndex += 4; + + /* Put TOC */ + memcpy(&buffer[nStreamIndex], btToc, sizeof(btToc)); + nStreamIndex += sizeof(btToc); + + + if (cfg->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, (char *) buffer); + } + { + /*work out CRC so far: initially crc = 0 */ + uint16_t crc = 0x00; + unsigned int i; + for (i = 0; i < nStreamIndex; i++) + crc = CRC_update_lookup(buffer[i], crc); + /*Put LAME VBR info */ + nStreamIndex += PutLameVBR(gfp, stream_size, buffer + nStreamIndex, crc); + } + +#ifdef DEBUG_VBRTAG + { + VBRTAGDATA TestHeader; + GetVbrTag(&TestHeader, buffer); + } +#endif + + return gfc->VBR_seek_table.TotalFrameSize; +} + +/*********************************************************************** + * + * PutVbrTag: Write final VBR tag to the file + * Paramters: + * lpszFileName: filename of MP3 bit stream + * nVbrScale : encoder quality indicator (0..100) + **************************************************************************** + */ + +int +PutVbrTag(lame_global_flags const *gfp, FILE * fpStream) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + long lFileSize; + long id3v2TagSize; + size_t nbytes; + uint8_t buffer[MAXFRAMESIZE]; + + if (gfc->VBR_seek_table.pos <= 0) + return -1; + + /* Seek to end of file */ + fseek(fpStream, 0, SEEK_END); + + /* Get file size */ + lFileSize = ftell(fpStream); + + /* Abort if file has zero length. Yes, it can happen :) */ + if (lFileSize == 0) + return -1; + + /* + * The VBR tag may NOT be located at the beginning of the stream. + * If an ID3 version 2 tag was added, then it must be skipped to write + * the VBR tag data. + */ + + id3v2TagSize = skipId3v2(fpStream); + + if (id3v2TagSize < 0) { + return id3v2TagSize; + } + + /*Seek to the beginning of the stream */ + fseek(fpStream, id3v2TagSize, SEEK_SET); + + nbytes = lame_get_lametag_frame(gfp, buffer, sizeof(buffer)); + if (nbytes > sizeof(buffer)) { + return -1; + } + + if (nbytes < 1) { + return 0; + } + + /* Put it all to disk again */ + if (fwrite(buffer, nbytes, 1, fpStream) != 1) { + return -1; + } + + return 0; /* success */ +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.h new file mode 100644 index 00000000..406af366 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/VbrTag.h @@ -0,0 +1,79 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_VRBTAG_H +#define LAME_VRBTAG_H + + +/* ----------------------------------------------------------- + * A Vbr header may be present in the ancillary + * data field of the first frame of an mp3 bitstream + * The Vbr header (optionally) contains + * frames total number of audio frames in the bitstream + * bytes total number of bytes in the bitstream + * toc table of contents + + * toc (table of contents) gives seek points + * for random access + * the ith entry determines the seek point for + * i-percent duration + * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes + * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes + */ + + +#define FRAMES_FLAG 0x0001 +#define BYTES_FLAG 0x0002 +#define TOC_FLAG 0x0004 +#define VBR_SCALE_FLAG 0x0008 + +#define NUMTOCENTRIES 100 + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + + +/*structure to receive extracted header */ +/* toc may be NULL*/ +typedef struct { + int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */ + int samprate; /* determined from MPEG header */ + int flags; /* from Vbr header data */ + int frames; /* total bit stream frames from Vbr header data */ + int bytes; /* total bit stream bytes from Vbr header data */ + int vbr_scale; /* encoded vbr scale from Vbr header data */ + unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired */ + int headersize; /* size of VBR header, in bytes */ + int enc_delay; /* encoder delay */ + int enc_padding; /* encoder paddign added at end of stream */ +} VBRTAGDATA; + +int GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf); + +int InitVbrTag(lame_global_flags * gfp); +int PutVbrTag(lame_global_flags const *gfp, FILE * fid); +void AddVbrFrame(lame_internal_flags * gfc); +void UpdateMusicCRC(uint16_t * crc, const unsigned char *buffer, int size); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.c new file mode 100644 index 00000000..aa359150 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.c @@ -0,0 +1,1111 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 1999-2002 Takehiro Tominaga + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Id: bitstream.c,v 1.99 2017/08/31 14:14:46 robert Exp $ + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "tables.h" +#include "quantize_pvt.h" +#include "lame_global_flags.h" +#include "gain_analysis.h" +#include "VbrTag.h" +#include "bitstream.h" +#include "tables.h" + + + +/* unsigned int is at least this large: */ +/* we work with ints, so when doing bit manipulation, we limit + * ourselves to MAX_LENGTH-2 just to be on the safe side */ +#define MAX_LENGTH 32 + + + +#ifdef DEBUG +static int hogege; +#endif + + + +static int +calcFrameLength(SessionConfig_t const *const cfg, int kbps, int pad) +{ + return 8 * ((cfg->version + 1) * 72000 * kbps / cfg->samplerate_out + pad); +} + + +/*********************************************************************** + * compute bitsperframe and mean_bits for a layer III frame + **********************************************************************/ +int +getframebits(const lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int bit_rate; + + /* get bitrate in kbps [?] */ + if (eov->bitrate_index) + bit_rate = bitrate_table[cfg->version][eov->bitrate_index]; + else + bit_rate = cfg->avg_bitrate; + /*assert(bit_rate <= 550); */ + assert(8 <= bit_rate && bit_rate <= 640); + + /* main encoding routine toggles padding on and off */ + /* one Layer3 Slot consists of 8 bits */ + return calcFrameLength(cfg, bit_rate, eov->padding); +} + +int +get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint) +{ + int maxmp3buf = 0; + if (cfg->avg_bitrate > 320) { + /* in freeformat the buffer is constant */ + if (constraint == MDB_STRICT_ISO) { + maxmp3buf = calcFrameLength(cfg, cfg->avg_bitrate, 0); + } + else { + /* maximum allowed bits per granule are 7680 */ + maxmp3buf = 7680 * (cfg->version + 1); + } + } + else { + int max_kbps; + if (cfg->samplerate_out < 16000) { + max_kbps = bitrate_table[cfg->version][8]; /* default: allow 64 kbps (MPEG-2.5) */ + } + else { + max_kbps = bitrate_table[cfg->version][14]; + } + switch (constraint) + { + default: + case MDB_DEFAULT: + /* Bouvigne suggests this more lax interpretation of the ISO doc instead of using 8*960. */ + /* All mp3 decoders should have enough buffer to handle this value: size of a 320kbps 32kHz frame */ + maxmp3buf = 8 * 1440; + break; + case MDB_STRICT_ISO: + maxmp3buf = calcFrameLength(cfg, max_kbps, 0); + break; + case MDB_MAXIMUM: + maxmp3buf = 7680 * (cfg->version + 1); + break; + } + } + return maxmp3buf; +} + + +static void +putheader_bits(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + Bit_stream_struc *bs = &gfc->bs; +#ifdef DEBUG + hogege += cfg->sideinfo_len * 8; +#endif + memcpy(&bs->buf[bs->buf_byte_idx], esv->header[esv->w_ptr].buf, cfg->sideinfo_len); + bs->buf_byte_idx += cfg->sideinfo_len; + bs->totbit += cfg->sideinfo_len * 8; + esv->w_ptr = (esv->w_ptr + 1) & (MAX_HEADER_BUF - 1); +} + + + + +/*write j bits into the bit stream */ +inline static void +putbits2(lame_internal_flags * gfc, int val, int j) +{ + EncStateVar_t const *const esv = &gfc->sv_enc; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH - 2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + assert(esv->header[esv->w_ptr].write_timing >= bs->totbit); + if (esv->header[esv->w_ptr].write_timing == bs->totbit) { + putheader_bits(gfc); + } + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert(bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + +/*write j bits into the bit stream, ignoring frame headers */ +inline static void +putbits_noheaders(lame_internal_flags * gfc, int val, int j) +{ + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH - 2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert(bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + + +/* + Some combinations of bitrate, Fs, and stereo make it impossible to stuff + out a frame using just main_data, due to the limited number of bits to + indicate main_data_length. In these situations, we put stuffing bits into + the ancillary data... +*/ + +inline static void +drain_into_ancillary(lame_internal_flags * gfc, int remainingBits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int i; + assert(remainingBits >= 0); + + if (remainingBits >= 8) { + putbits2(gfc, 0x4c, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x41, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x4d, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x45, 8); + remainingBits -= 8; + } + + if (remainingBits >= 32) { + const char *const version = get_lame_short_version(); + if (remainingBits >= 32) + for (i = 0; i < (int) strlen(version) && remainingBits >= 8; ++i) { + remainingBits -= 8; + putbits2(gfc, version[i], 8); + } + } + + for (; remainingBits >= 1; remainingBits -= 1) { + putbits2(gfc, esv->ancillary_flag, 1); + esv->ancillary_flag ^= !cfg->disable_reservoir; + } + + assert(remainingBits == 0); + +} + +/*write N bits into the header */ +inline static void +writeheader(lame_internal_flags * gfc, int val, int j) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + int ptr = esv->header[esv->h_ptr].ptr; + + while (j > 0) { + int const k = Min(j, 8 - (ptr & 7)); + j -= k; + assert(j < MAX_LENGTH); /* >> 32 too large for 32 bit machines */ + esv->header[esv->h_ptr].buf[ptr >> 3] + |= ((val >> j)) << (8 - (ptr & 7) - k); + ptr += k; + } + esv->header[esv->h_ptr].ptr = ptr; +} + + +static int +CRC_update(int value, int crc) +{ + int i; + value <<= 8; + for (i = 0; i < 8; i++) { + value <<= 1; + crc <<= 1; + + if (((crc ^ value) & 0x10000)) + crc ^= CRC16_POLYNOMIAL; + } + return crc; +} + + +void +CRC_writeheader(lame_internal_flags const *gfc, char *header) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int crc = 0xffff; /* (jo) init crc16 for error_protection */ + int i; + + crc = CRC_update(((unsigned char *) header)[2], crc); + crc = CRC_update(((unsigned char *) header)[3], crc); + for (i = 6; i < cfg->sideinfo_len; i++) { + crc = CRC_update(((unsigned char *) header)[i], crc); + } + + header[4] = crc >> 8; + header[5] = crc & 255; +} + +inline static void +encodeSideInfo2(lame_internal_flags * gfc, int bitsPerFrame) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *l3_side; + int gr, ch; + + l3_side = &gfc->l3_side; + esv->header[esv->h_ptr].ptr = 0; + memset(esv->header[esv->h_ptr].buf, 0, cfg->sideinfo_len); + if (cfg->samplerate_out < 16000) + writeheader(gfc, 0xffe, 12); + else + writeheader(gfc, 0xfff, 12); + writeheader(gfc, (cfg->version), 1); + writeheader(gfc, 4 - 3, 2); + writeheader(gfc, (!cfg->error_protection), 1); + writeheader(gfc, (eov->bitrate_index), 4); + writeheader(gfc, (cfg->samplerate_index), 2); + writeheader(gfc, (eov->padding), 1); + writeheader(gfc, (cfg->extension), 1); + writeheader(gfc, (cfg->mode), 2); + writeheader(gfc, (eov->mode_ext), 2); + writeheader(gfc, (cfg->copyright), 1); + writeheader(gfc, (cfg->original), 1); + writeheader(gfc, (cfg->emphasis), 2); + if (cfg->error_protection) { + writeheader(gfc, 0, 16); /* dummy */ + } + + if (cfg->version == 1) { + /* MPEG1 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc, (l3_side->main_data_begin), 9); + + if (cfg->channels_out == 2) + writeheader(gfc, l3_side->private_bits, 3); + else + writeheader(gfc, l3_side->private_bits, 5); + + for (ch = 0; ch < cfg->channels_out; ch++) { + int band; + for (band = 0; band < 4; band++) { + writeheader(gfc, l3_side->scfsi[ch][band], 1); + } + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const gi = &l3_side->tt[gr][ch]; + writeheader(gfc, gi->part2_3_length + gi->part2_length, 12); + writeheader(gfc, gi->big_values / 2, 9); + writeheader(gfc, gi->global_gain, 8); + writeheader(gfc, gi->scalefac_compress, 4); + + if (gi->block_type != NORM_TYPE) { + writeheader(gfc, 1, 1); /* window_switching_flag */ + writeheader(gfc, gi->block_type, 2); + writeheader(gfc, gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + + writeheader(gfc, gi->subblock_gain[0], 3); + writeheader(gfc, gi->subblock_gain[1], 3); + writeheader(gfc, gi->subblock_gain[2], 3); + } + else { + writeheader(gfc, 0, 1); /* window_switching_flag */ + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc, gi->table_select[2], 5); + + assert(0 <= gi->region0_count && gi->region0_count < 16); + assert(0 <= gi->region1_count && gi->region1_count < 8); + writeheader(gfc, gi->region0_count, 4); + writeheader(gfc, gi->region1_count, 3); + } + writeheader(gfc, gi->preflag, 1); + writeheader(gfc, gi->scalefac_scale, 1); + writeheader(gfc, gi->count1table_select, 1); + } + } + } + else { + /* MPEG2 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc, (l3_side->main_data_begin), 8); + writeheader(gfc, l3_side->private_bits, cfg->channels_out); + + gr = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const gi = &l3_side->tt[gr][ch]; + writeheader(gfc, gi->part2_3_length + gi->part2_length, 12); + writeheader(gfc, gi->big_values / 2, 9); + writeheader(gfc, gi->global_gain, 8); + writeheader(gfc, gi->scalefac_compress, 9); + + if (gi->block_type != NORM_TYPE) { + writeheader(gfc, 1, 1); /* window_switching_flag */ + writeheader(gfc, gi->block_type, 2); + writeheader(gfc, gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + + writeheader(gfc, gi->subblock_gain[0], 3); + writeheader(gfc, gi->subblock_gain[1], 3); + writeheader(gfc, gi->subblock_gain[2], 3); + } + else { + writeheader(gfc, 0, 1); /* window_switching_flag */ + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc, gi->table_select[2], 5); + + assert(0 <= gi->region0_count && gi->region0_count < 16); + assert(0 <= gi->region1_count && gi->region1_count < 8); + writeheader(gfc, gi->region0_count, 4); + writeheader(gfc, gi->region1_count, 3); + } + + writeheader(gfc, gi->scalefac_scale, 1); + writeheader(gfc, gi->count1table_select, 1); + } + } + + if (cfg->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, esv->header[esv->h_ptr].buf); + } + + { + int const old = esv->h_ptr; + assert(esv->header[old].ptr == cfg->sideinfo_len * 8); + + esv->h_ptr = (old + 1) & (MAX_HEADER_BUF - 1); + esv->header[esv->h_ptr].write_timing = esv->header[old].write_timing + bitsPerFrame; + + if (esv->h_ptr == esv->w_ptr) { + /* yikes! we are out of header buffer space */ + ERRORF(gfc, "Error: MAX_HEADER_BUF too small in bitstream.c \n"); + } + + } +} + + +inline static int +huffman_coder_count1(lame_internal_flags * gfc, gr_info const *gi) +{ + /* Write count1 area */ + struct huffcodetab const *const h = &ht[gi->count1table_select + 32]; + int i, bits = 0; +#ifdef DEBUG + int gegebo = gfc->bs.totbit; +#endif + + int const *ix = &gi->l3_enc[gi->big_values]; + FLOAT const *xr = &gi->xr[gi->big_values]; + assert(gi->count1table_select < 2); + + for (i = (gi->count1 - gi->big_values) / 4; i > 0; --i) { + int huffbits = 0; + int p = 0, v; + + v = ix[0]; + if (v) { + p += 8; + if (xr[0] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[1]; + if (v) { + p += 4; + huffbits *= 2; + if (xr[1] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[2]; + if (v) { + p += 2; + huffbits *= 2; + if (xr[2] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[3]; + if (v) { + p++; + huffbits *= 2; + if (xr[3] < 0.0f) + huffbits++; + assert(v <= 1); + } + + ix += 4; + xr += 4; + putbits2(gfc, huffbits + h->table[p], h->hlen[p]); + bits += h->hlen[p]; + } +#ifdef DEBUG + DEBUGF(gfc, "count1: real: %ld counted:%d (bigv %d count1len %d)\n", + gfc->bs.totbit - gegebo, gi->count1bits, gi->big_values, gi->count1); +#endif + return bits; +} + + + +/* + Implements the pseudocode of page 98 of the IS + */ +inline static int +Huffmancode(lame_internal_flags * const gfc, const unsigned int tableindex, + int start, int end, gr_info const *gi) +{ + struct huffcodetab const *const h = &ht[tableindex]; + unsigned int const linbits = h->xlen; + int i, bits = 0; + + assert(tableindex < 32u); + if (!tableindex) + return bits; + + for (i = start; i < end; i += 2) { + int16_t cbits = 0; + uint16_t xbits = 0; + unsigned int xlen = h->xlen; + unsigned int ext = 0; + unsigned int x1 = gi->l3_enc[i]; + unsigned int x2 = gi->l3_enc[i + 1]; + + assert(gi->l3_enc[i] >= 0); + assert(gi->l3_enc[i+1] >= 0); + + if (x1 != 0u) { + if (gi->xr[i] < 0.0f) + ext++; + cbits--; + } + + if (tableindex > 15u) { + /* use ESC-words */ + if (x1 >= 15u) { + uint16_t const linbits_x1 = x1 - 15u; + assert(linbits_x1 <= h->linmax); + ext |= linbits_x1 << 1u; + xbits = linbits; + x1 = 15u; + } + + if (x2 >= 15u) { + uint16_t const linbits_x2 = x2 - 15u; + assert(linbits_x2 <= h->linmax); + ext <<= linbits; + ext |= linbits_x2; + xbits += linbits; + x2 = 15u; + } + xlen = 16; + } + + if (x2 != 0u) { + ext <<= 1; + if (gi->xr[i + 1] < 0.0f) + ext++; + cbits--; + } + + assert((x1 | x2) < 16u); + + x1 = x1 * xlen + x2; + xbits -= cbits; + cbits += h->hlen[x1]; + + assert(cbits <= MAX_LENGTH); + assert(xbits <= MAX_LENGTH); + + putbits2(gfc, h->table[x1], cbits); + putbits2(gfc, (int)ext, xbits); + bits += cbits + xbits; + } + return bits; +} + +/* + Note the discussion of huffmancodebits() on pages 28 + and 29 of the IS, as well as the definitions of the side + information on pages 26 and 27. + */ +static int +ShortHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi) +{ + int bits; + int region1Start; + + region1Start = 3 * gfc->scalefac_band.s[3]; + if (region1Start > gi->big_values) + region1Start = gi->big_values; + + /* short blocks do not have a region2 */ + bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi); + bits += Huffmancode(gfc, gi->table_select[1], region1Start, gi->big_values, gi); + return bits; +} + +static int +LongHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi) +{ + unsigned int i; + int bigvalues, bits; + int region1Start, region2Start; + + bigvalues = gi->big_values; + assert(0 <= bigvalues && bigvalues <= 576); + + assert(gi->region0_count >= -1); + assert(gi->region1_count >= -1); + i = gi->region0_count + 1; + assert((size_t) i < dimension_of(gfc->scalefac_band.l)); + region1Start = gfc->scalefac_band.l[i]; + i += gi->region1_count + 1; + assert((size_t) i < dimension_of(gfc->scalefac_band.l)); + region2Start = gfc->scalefac_band.l[i]; + + if (region1Start > bigvalues) + region1Start = bigvalues; + + if (region2Start > bigvalues) + region2Start = bigvalues; + + bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi); + bits += Huffmancode(gfc, gi->table_select[1], region1Start, region2Start, gi); + bits += Huffmancode(gfc, gi->table_select[2], region2Start, bigvalues, gi); + return bits; +} + +inline static int +writeMainData(lame_internal_flags * const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t const *const l3_side = &gfc->l3_side; + int gr, ch, sfb, data_bits, tot_bits = 0; + + if (cfg->version == 1) { + /* MPEG 1 */ + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &l3_side->tt[gr][ch]; + int const slen1 = slen1_tab[gi->scalefac_compress]; + int const slen2 = slen2_tab[gi->scalefac_compress]; + data_bits = 0; +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + for (sfb = 0; sfb < gi->sfbdivide; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; /* scfsi is used */ + putbits2(gfc, gi->scalefac[sfb], slen1); + data_bits += slen1; + } + for (; sfb < gi->sfbmax; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; /* scfsi is used */ + putbits2(gfc, gi->scalefac[sfb], slen2); + data_bits += slen2; + } + assert(data_bits == gi->part2_length); + + if (gi->block_type == SHORT_TYPE) { + data_bits += ShortHuffmancodebits(gfc, gi); + } + else { + data_bits += LongHuffmancodebits(gfc, gi); + } + data_bits += huffman_coder_count1(gfc, gi); +#ifdef DEBUG + DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count? */ + assert(data_bits == gi->part2_3_length + gi->part2_length); + tot_bits += data_bits; + } /* for ch */ + } /* for gr */ + } + else { + /* MPEG 2 */ + gr = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &l3_side->tt[gr][ch]; + int i, sfb_partition, scale_bits = 0; + assert(gi->sfb_partition_table); + data_bits = 0; +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + sfb = 0; + sfb_partition = 0; + + if (gi->block_type == SHORT_TYPE) { + for (; sfb_partition < 4; sfb_partition++) { + int const sfbs = gi->sfb_partition_table[sfb_partition] / 3; + int const slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 0], 0), slen); + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 1], 0), slen); + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 2], 0), slen); + scale_bits += 3 * slen; + } + } + data_bits += ShortHuffmancodebits(gfc, gi); + } + else { + for (; sfb_partition < 4; sfb_partition++) { + int const sfbs = gi->sfb_partition_table[sfb_partition]; + int const slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfc, Max(gi->scalefac[sfb], 0), slen); + scale_bits += slen; + } + } + data_bits += LongHuffmancodebits(gfc, gi); + } + data_bits += huffman_coder_count1(gfc, gi); +#ifdef DEBUG + DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count? */ + assert(data_bits == gi->part2_3_length); + assert(scale_bits == gi->part2_length); + tot_bits += scale_bits + data_bits; + } /* for ch */ + } /* for gf */ + return tot_bits; +} /* main_data */ + + + +/* compute the number of bits required to flush all mp3 frames + currently in the buffer. This should be the same as the + reservoir size. Only call this routine between frames - i.e. + only after all headers and data have been added to the buffer + by format_bitstream(). + + Also compute total_bits_output = + size of mp3 buffer (including frame headers which may not + have yet been send to the mp3 buffer) + + number of bits needed to flush all mp3 frames. + + total_bytes_output is the size of the mp3 output buffer if + lame_encode_flush_nogap() was called right now. + + */ +int +compute_flushbits(const lame_internal_flags * gfc, int *total_bytes_output) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t const *const esv = &gfc->sv_enc; + int flushbits, remaining_headers; + int bitsPerFrame; + int last_ptr, first_ptr; + first_ptr = esv->w_ptr; /* first header to add to bitstream */ + last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr == -1) + last_ptr = MAX_HEADER_BUF - 1; + + /* add this many bits to bitstream so we can flush all headers */ + flushbits = esv->header[last_ptr].write_timing - gfc->bs.totbit; + *total_bytes_output = flushbits; + + if (flushbits >= 0) { + /* if flushbits >= 0, some headers have not yet been written */ + /* reduce flushbits by the size of the headers */ + remaining_headers = 1 + last_ptr - first_ptr; + if (last_ptr < first_ptr) + remaining_headers = 1 + last_ptr - first_ptr + MAX_HEADER_BUF; + flushbits -= remaining_headers * 8 * cfg->sideinfo_len; + } + + + /* finally, add some bits so that the last frame is complete + * these bits are not necessary to decode the last frame, but + * some decoders will ignore last frame if these bits are missing + */ + bitsPerFrame = getframebits(gfc); + flushbits += bitsPerFrame; + *total_bytes_output += bitsPerFrame; + /* round up: */ + if (*total_bytes_output % 8) + *total_bytes_output = 1 + (*total_bytes_output / 8); + else + *total_bytes_output = (*total_bytes_output / 8); + *total_bytes_output += gfc->bs.buf_byte_idx + 1; + + + if (flushbits < 0) { +#if 0 + /* if flushbits < 0, this would mean that the buffer looks like: + * (data...) last_header (data...) (extra data that should not be here...) + */ + DEBUGF(gfc, "last header write_timing = %i \n", esv->header[last_ptr].write_timing); + DEBUGF(gfc, "first header write_timing = %i \n", esv->header[first_ptr].write_timing); + DEBUGF(gfc, "bs.totbit: %i \n", gfc->bs.totbit); + DEBUGF(gfc, "first_ptr, last_ptr %i %i \n", first_ptr, last_ptr); + DEBUGF(gfc, "remaining_headers = %i \n", remaining_headers); + DEBUGF(gfc, "bitsperframe: %i \n", bitsPerFrame); + DEBUGF(gfc, "sidelen: %i \n", cfg->sideinfo_len); +#endif + ERRORF(gfc, "strange error flushing buffer ... \n"); + } + return flushbits; +} + + +void +flush_bitstream(lame_internal_flags * gfc) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *l3_side; + int nbytes; + int flushbits; + int last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr == -1) + last_ptr = MAX_HEADER_BUF - 1; + l3_side = &gfc->l3_side; + + + if ((flushbits = compute_flushbits(gfc, &nbytes)) < 0) + return; + drain_into_ancillary(gfc, flushbits); + + /* check that the 100% of the last frame has been written to bitstream */ + assert(esv->header[last_ptr].write_timing + getframebits(gfc) + == gfc->bs.totbit); + + /* we have padded out all frames with ancillary data, which is the + same as filling the bitreservoir with ancillary data, so : */ + esv->ResvSize = 0; + l3_side->main_data_begin = 0; +} + + + + +void +add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + int i; + + while (n-- > 0u) { + putbits_noheaders(gfc, val, 8); + + for (i = 0; i < MAX_HEADER_BUF; ++i) + esv->header[i].write_timing += 8; + } +} + + +/* + format_bitstream() + + This is called after a frame of audio has been quantized and coded. + It will write the encoded audio to the bitstream. Note that + from a layer3 encoder's perspective the bit stream is primarily + a series of main_data() blocks, with header and side information + inserted at the proper locations to maintain framing. (See Figure A.7 + in the IS). + */ +int +format_bitstream(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int bits, nbytes; + III_side_info_t *l3_side; + int bitsPerFrame; + l3_side = &gfc->l3_side; + + bitsPerFrame = getframebits(gfc); + drain_into_ancillary(gfc, l3_side->resvDrain_pre); + + encodeSideInfo2(gfc, bitsPerFrame); + bits = 8 * cfg->sideinfo_len; + bits += writeMainData(gfc); + drain_into_ancillary(gfc, l3_side->resvDrain_post); + bits += l3_side->resvDrain_post; + + l3_side->main_data_begin += (bitsPerFrame - bits) / 8; + + /* compare number of bits needed to clear all buffered mp3 frames + * with what we think the resvsize is: */ + if (compute_flushbits(gfc, &nbytes) != esv->ResvSize) { + ERRORF(gfc, "Internal buffer inconsistency. flushbits <> ResvSize"); + } + + + /* compare main_data_begin for the next frame with what we + * think the resvsize is: */ + if ((l3_side->main_data_begin * 8) != esv->ResvSize) { + ERRORF(gfc, "bit reservoir error: \n" + "l3_side->main_data_begin: %i \n" + "Resvoir size: %i \n" + "resv drain (post) %i \n" + "resv drain (pre) %i \n" + "header and sideinfo: %i \n" + "data bits: %i \n" + "total bits: %i (remainder: %i) \n" + "bitsperframe: %i \n", + 8 * l3_side->main_data_begin, + esv->ResvSize, + l3_side->resvDrain_post, + l3_side->resvDrain_pre, + 8 * cfg->sideinfo_len, + bits - l3_side->resvDrain_post - 8 * cfg->sideinfo_len, + bits, bits % 8, bitsPerFrame); + + ERRORF(gfc, "This is a fatal error. It has several possible causes:"); + ERRORF(gfc, "90%% LAME compiled with buggy version of gcc using advanced optimizations"); + ERRORF(gfc, " 9%% Your system is overclocked"); + ERRORF(gfc, " 1%% bug in LAME encoding library"); + + esv->ResvSize = l3_side->main_data_begin * 8; + }; + assert(gfc->bs.totbit % 8 == 0); + + if (gfc->bs.totbit > 1000000000) { + /* to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset bit counter */ + int i; + for (i = 0; i < MAX_HEADER_BUF; ++i) + esv->header[i].write_timing -= gfc->bs.totbit; + gfc->bs.totbit = 0; + } + + + return 0; +} + + +static int +do_gain_analysis(lame_internal_flags * gfc, unsigned char* buffer, int minimum) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + RpgStateVar_t const *const rsv = &gfc->sv_rpg; + RpgResult_t *const rov = &gfc->ov_rpg; +#ifdef DECODE_ON_THE_FLY + if (cfg->decode_on_the_fly) { /* decode the frame */ + sample_t pcm_buf[2][1152]; + int mp3_in = minimum; + int samples_out = -1; + + /* re-synthesis to pcm. Repeat until we get a samples_out=0 */ + while (samples_out != 0) { + + samples_out = hip_decode1_unclipped(gfc->hip, buffer, mp3_in, pcm_buf[0], pcm_buf[1]); + /* samples_out = 0: need more data to decode + * samples_out = -1: error. Lets assume 0 pcm output + * samples_out = number of samples output */ + + /* set the lenght of the mp3 input buffer to zero, so that in the + * next iteration of the loop we will be querying mpglib about + * buffered data */ + mp3_in = 0; + + if (samples_out == -1) { + /* error decoding. Not fatal, but might screw up + * the ReplayGain tag. What should we do? Ignore for now */ + samples_out = 0; + } + if (samples_out > 0) { + /* process the PCM data */ + + /* this should not be possible, and indicates we have + * overflown the pcm_buf buffer */ + assert(samples_out <= 1152); + + if (cfg->findPeakSample) { + int i; + /* FIXME: is this correct? maybe Max(fabs(pcm),PeakSample) */ + for (i = 0; i < samples_out; i++) { + if (pcm_buf[0][i] > rov->PeakSample) + rov->PeakSample = pcm_buf[0][i]; + else if (-pcm_buf[0][i] > rov->PeakSample) + rov->PeakSample = -pcm_buf[0][i]; + } + if (cfg->channels_out > 1) + for (i = 0; i < samples_out; i++) { + if (pcm_buf[1][i] > rov->PeakSample) + rov->PeakSample = pcm_buf[1][i]; + else if (-pcm_buf[1][i] > rov->PeakSample) + rov->PeakSample = -pcm_buf[1][i]; + } + } + + if (cfg->findReplayGain) + if (AnalyzeSamples + (rsv->rgdata, pcm_buf[0], pcm_buf[1], samples_out, + cfg->channels_out) == GAIN_ANALYSIS_ERROR) + return -6; + + } /* if (samples_out>0) */ + } /* while (samples_out!=0) */ + } /* if (gfc->decode_on_the_fly) */ +#endif + return minimum; +} + +static int +do_copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size) +{ + Bit_stream_struc *const bs = &gfc->bs; + int const minimum = bs->buf_byte_idx + 1; + if (minimum <= 0) + return 0; + if (minimum > size) + return -1; /* buffer is too small */ + memcpy(buffer, bs->buf, minimum); + bs->buf_byte_idx = -1; + bs->buf_bit_idx = 0; + return minimum; +} + +/* copy data out of the internal MP3 bit buffer into a user supplied + unsigned char buffer. + + mp3data=0 indicates data in buffer is an id3tags and VBR tags + mp3data=1 data is real mp3 frame data. + + +*/ +int +copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size, int mp3data) +{ + int const minimum = do_copy_buffer(gfc, buffer, size); + if (minimum > 0 && mp3data) { + UpdateMusicCRC(&gfc->nMusicCRC, buffer, minimum); + + /** sum number of bytes belonging to the mp3 stream + * this info will be written into the Xing/LAME header for seeking + */ + gfc->VBR_seek_table.nBytesWritten += minimum; + + return do_gain_analysis(gfc, buffer, minimum); + } /* if (mp3data) */ + return minimum; +} + + +void +init_bit_stream_w(lame_internal_flags * gfc) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + + esv->h_ptr = esv->w_ptr = 0; + esv->header[esv->h_ptr].write_timing = 0; + + gfc->bs.buf = lame_calloc(unsigned char, BUFFER_SIZE); + gfc->bs.buf_size = BUFFER_SIZE; + gfc->bs.buf_byte_idx = -1; + gfc->bs.buf_bit_idx = 0; + gfc->bs.totbit = 0; +} + +/* end of bitstream.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.h new file mode 100644 index 00000000..3ae48d02 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/bitstream.h @@ -0,0 +1,40 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_BITSTREAM_H +#define LAME_BITSTREAM_H + +int getframebits(const lame_internal_flags * gfc); + +int format_bitstream(lame_internal_flags * gfc); + +void flush_bitstream(lame_internal_flags * gfc); +void add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n); + +int copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int buffer_size, + int update_crc); +void init_bit_stream_w(lame_internal_flags * gfc); +void CRC_writeheader(lame_internal_flags const *gfc, char *buffer); +int compute_flushbits(const lame_internal_flags * gfp, int *nbytes); + +int get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.c new file mode 100644 index 00000000..48f46c7b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.c @@ -0,0 +1,574 @@ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * Copyright (c) 2000-2002 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2001 Gabriel Bouvigne + * Copyright (c) 2001 John Dahlstrom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: encoder.c,v 1.114 2017/08/26 10:54:57 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" +#include "newmdct.h" +#include "psymodel.h" +#include "lame-analysis.h" +#include "bitstream.h" +#include "VbrTag.h" +#include "quantize.h" +#include "quantize_pvt.h" + + + +/* + * auto-adjust of ATH, useful for low volume + * Gabriel Bouvigne 3 feb 2001 + * + * modifies some values in + * gfp->internal_flags->ATH + * (gfc->ATH) + */ +static void +adjust_ATH(lame_internal_flags const *const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT gr2_max, max_pow; + + if (gfc->ATH->use_adjust == 0) { + gfc->ATH->adjust_factor = 1.0; /* no adjustment */ + return; + } + + /* jd - 2001 mar 12, 27, jun 30 */ + /* loudness based on equal loudness curve; */ + /* use granule with maximum combined loudness */ + max_pow = gfc->ov_psy.loudness_sq[0][0]; + gr2_max = gfc->ov_psy.loudness_sq[1][0]; + if (cfg->channels_out == 2) { + max_pow += gfc->ov_psy.loudness_sq[0][1]; + gr2_max += gfc->ov_psy.loudness_sq[1][1]; + } + else { + max_pow += max_pow; + gr2_max += gr2_max; + } + if (cfg->mode_gr == 2) { + max_pow = Max(max_pow, gr2_max); + } + max_pow *= 0.5; /* max_pow approaches 1.0 for full band noise */ + + /* jd - 2001 mar 31, jun 30 */ + /* user tuning of ATH adjustment region */ + max_pow *= gfc->ATH->aa_sensitivity_p; + + /* adjust ATH depending on range of maximum value + */ + + /* jd - 2001 feb27, mar12,20, jun30, jul22 */ + /* continuous curves based on approximation */ + /* to GB's original values. */ + /* For an increase in approximate loudness, */ + /* set ATH adjust to adjust_limit immediately */ + /* after a delay of one frame. */ + /* For a loudness decrease, reduce ATH adjust */ + /* towards adjust_limit gradually. */ + /* max_pow is a loudness squared or a power. */ + if (max_pow > 0.03125) { /* ((1 - 0.000625)/ 31.98) from curve below */ + if (gfc->ATH->adjust_factor >= 1.0) { + gfc->ATH->adjust_factor = 1.0; + } + else { + /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + /* in case there is leading low volume */ + if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) { + gfc->ATH->adjust_factor = gfc->ATH->adjust_limit; + } + } + gfc->ATH->adjust_limit = 1.0; + } + else { /* adjustment curve */ + /* about 32 dB maximum adjust (0.000625) */ + FLOAT const adj_lim_new = 31.98 * max_pow + 0.000625; + if (gfc->ATH->adjust_factor >= adj_lim_new) { /* descend gradually */ + gfc->ATH->adjust_factor *= adj_lim_new * 0.075 + 0.925; + if (gfc->ATH->adjust_factor < adj_lim_new) { /* stop descent */ + gfc->ATH->adjust_factor = adj_lim_new; + } + } + else { /* ascend */ + if (gfc->ATH->adjust_limit >= adj_lim_new) { + gfc->ATH->adjust_factor = adj_lim_new; + } + else { /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) { + gfc->ATH->adjust_factor = gfc->ATH->adjust_limit; + } + } + } + gfc->ATH->adjust_limit = adj_lim_new; + } +} + +/*********************************************************************** + * + * some simple statistics + * + * bitrate index 0: free bitrate -> not allowed in VBR mode + * : bitrates, kbps depending on MPEG version + * bitrate index 15: forbidden + * + * mode_ext: + * 0: LR + * 1: LR-i + * 2: MS + * 3: MS-i + * + ***********************************************************************/ + +static void +updateStats(lame_internal_flags * const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *eov = &gfc->ov_enc; + int gr, ch; + assert(0 <= eov->bitrate_index && eov->bitrate_index < 16); + assert(0 <= eov->mode_ext && eov->mode_ext < 4); + + /* count bitrate indices */ + eov->bitrate_channelmode_hist[eov->bitrate_index][4]++; + eov->bitrate_channelmode_hist[15][4]++; + + /* count 'em for every mode extension in case of 2 channel encoding */ + if (cfg->channels_out == 2) { + eov->bitrate_channelmode_hist[eov->bitrate_index][eov->mode_ext]++; + eov->bitrate_channelmode_hist[15][eov->mode_ext]++; + } + for (gr = 0; gr < cfg->mode_gr; ++gr) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + int bt = gfc->l3_side.tt[gr][ch].block_type; + if (gfc->l3_side.tt[gr][ch].mixed_block_flag) + bt = 4; + eov->bitrate_blocktype_hist[eov->bitrate_index][bt]++; + eov->bitrate_blocktype_hist[eov->bitrate_index][5]++; + eov->bitrate_blocktype_hist[15][bt]++; + eov->bitrate_blocktype_hist[15][5]++; + } + } +} + + + + +static void +lame_encode_frame_init(lame_internal_flags * gfc, const sample_t *const inbuf[2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + + int ch, gr; + + if (gfc->lame_encode_frame_init == 0) { + sample_t primebuff0[286 + 1152 + 576]; + sample_t primebuff1[286 + 1152 + 576]; + int const framesize = 576 * cfg->mode_gr; + /* prime the MDCT/polyphase filterbank with a short block */ + int i, j; + gfc->lame_encode_frame_init = 1; + memset(primebuff0, 0, sizeof(primebuff0)); + memset(primebuff1, 0, sizeof(primebuff1)); + for (i = 0, j = 0; i < 286 + 576 * (1 + cfg->mode_gr); ++i) { + if (i < framesize) { + primebuff0[i] = 0; + if (cfg->channels_out == 2) + primebuff1[i] = 0; + } + else { + primebuff0[i] = inbuf[0][j]; + if (cfg->channels_out == 2) + primebuff1[i] = inbuf[1][j]; + ++j; + } + } + /* polyphase filtering / mdct */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gfc->l3_side.tt[gr][ch].block_type = SHORT_TYPE; + } + } + mdct_sub48(gfc, primebuff0, primebuff1); + + /* check FFT will not use a negative starting offset */ +#if 576 < FFTOFFSET +# error FFTOFFSET greater than 576: FFT uses a negative offset +#endif + /* check if we have enough data for FFT */ + assert(gfc->sv_enc.mf_size >= (BLKSIZE + framesize - FFTOFFSET)); + /* check if we have enough data for polyphase filterbank */ + assert(gfc->sv_enc.mf_size >= (512 + framesize - 32)); + } + +} + + + + + + + +/************************************************************************ +* +* encodeframe() Layer 3 +* +* encode a single frame +* +************************************************************************ +lame_encode_frame() + + + gr 0 gr 1 +inbuf: |--------------|--------------|--------------| + + +Polyphase (18 windows, each shifted 32) +gr 0: +window1 <----512----> +window18 <----512----> + +gr 1: +window1 <----512----> +window18 <----512----> + + + +MDCT output: |--------------|--------------|--------------| + +FFT's <---------1024----------> + <---------1024--------> + + + + inbuf = buffer of PCM data size=MP3 framesize + encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY + so the MDCT coefficints are from inbuf[ch][-MDCTDELAY] + + psy-model FFT has a 1 granule delay, so we feed it data for the + next granule. + FFT is centered over granule: 224+576+224 + So FFT starts at: 576-224-MDCTDELAY + + MPEG2: FFT ends at: BLKSIZE+576-224-MDCTDELAY (1328) + MPEG1: FFT ends at: BLKSIZE+2*576-224-MDCTDELAY (1904) + + MPEG2: polyphase first window: [0..511] + 18th window: [544..1055] (1056) + MPEG1: 36th window: [1120..1631] (1632) + data needed: 512+framesize-32 + + A close look newmdct.c shows that the polyphase filterbank + only uses data from [0..510] for each window. Perhaps because the window + used by the filterbank is zero for the last point, so Takehiro's + code doesn't bother to compute with it. + + FFT starts at 576-224-MDCTDELAY (304) = 576-FFTOFFSET + +*/ + +typedef FLOAT chgrdata[2][2]; + + +int +lame_encode_mp3_frame( /* Output */ + lame_internal_flags * gfc, /* Context */ + sample_t const *inbuf_l, /* Input */ + sample_t const *inbuf_r, /* Input */ + unsigned char *mp3buf, /* Output */ + int mp3buf_size) +{ /* Output */ + SessionConfig_t const *const cfg = &gfc->cfg; + int mp3count; + III_psy_ratio masking_LR[2][2]; /*LR masking & energy */ + III_psy_ratio masking_MS[2][2]; /*MS masking & energy */ + const III_psy_ratio (*masking)[2]; /*pointer to selected maskings */ + const sample_t *inbuf[2]; + + FLOAT tot_ener[2][4]; + FLOAT ms_ener_ratio[2] = { .5, .5 }; + FLOAT pe[2][2] = { {0., 0.}, {0., 0.} }, pe_MS[2][2] = { { + 0., 0.}, { + 0., 0.}}; + FLOAT (*pe_use)[2]; + + int ch, gr; + + inbuf[0] = inbuf_l; + inbuf[1] = inbuf_r; + + if (gfc->lame_encode_frame_init == 0) { + /*first run? */ + lame_encode_frame_init(gfc, inbuf); + + } + + + /********************** padding *****************************/ + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert Hegemann 2000-06-22 + */ + gfc->ov_enc.padding = FALSE; + if ((gfc->sv_enc.slot_lag -= gfc->sv_enc.frac_SpF) < 0) { + gfc->sv_enc.slot_lag += cfg->samplerate_out; + gfc->ov_enc.padding = TRUE; + } + + + + /**************************************** + * Stage 1: psychoacoustic model * + ****************************************/ + + { + /* psychoacoustic model + * psy model has a 1 granule (576) delay that we must compensate for + * (mt 6/99). + */ + int ret; + const sample_t *bufp[2] = {0, 0}; /* address of beginning of left & right granule */ + int blocktype[2]; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + + for (ch = 0; ch < cfg->channels_out; ch++) { + bufp[ch] = &inbuf[ch][576 + gr * 576 - FFTOFFSET]; + } + ret = L3psycho_anal_vbr(gfc, bufp, gr, + masking_LR, masking_MS, + pe[gr], pe_MS[gr], tot_ener[gr], blocktype); + if (ret != 0) + return -4; + + if (cfg->mode == JOINT_STEREO) { + ms_ener_ratio[gr] = tot_ener[gr][2] + tot_ener[gr][3]; + if (ms_ener_ratio[gr] > 0) + ms_ener_ratio[gr] = tot_ener[gr][3] / ms_ener_ratio[gr]; + } + + /* block type flags */ + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + cod_info->block_type = blocktype[ch]; + cod_info->mixed_block_flag = 0; + } + } + } + + + /* auto-adjust of ATH, useful for low volume */ + adjust_ATH(gfc); + + + /**************************************** + * Stage 2: MDCT * + ****************************************/ + + /* polyphase filtering / mdct */ + mdct_sub48(gfc, inbuf[0], inbuf[1]); + + + /**************************************** + * Stage 3: MS/LR decision * + ****************************************/ + + /* Here will be selected MS or LR coding of the 2 stereo channels */ + gfc->ov_enc.mode_ext = MPG_MD_LR_LR; + + if (cfg->force_ms) { + gfc->ov_enc.mode_ext = MPG_MD_MS_LR; + } + else if (cfg->mode == JOINT_STEREO) { + /* ms_ratio = is scaled, for historical reasons, to look like + a ratio of side_channel / total. + 0 = signal is 100% mono + .5 = L & R uncorrelated + */ + + /* [0] and [1] are the results for the two granules in MPEG-1, + * in MPEG-2 it's only a faked averaging of the same value + * _prev is the value of the last granule of the previous frame + * _next is the value of the first granule of the next frame + */ + + FLOAT sum_pe_MS = 0; + FLOAT sum_pe_LR = 0; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + sum_pe_MS += pe_MS[gr][ch]; + sum_pe_LR += pe[gr][ch]; + } + } + + /* based on PE: M/S coding would not use much more bits than L/R */ + if (sum_pe_MS <= 1.00 * sum_pe_LR) { + + gr_info const *const gi0 = &gfc->l3_side.tt[0][0]; + gr_info const *const gi1 = &gfc->l3_side.tt[cfg->mode_gr - 1][0]; + + if (gi0[0].block_type == gi0[1].block_type && gi1[0].block_type == gi1[1].block_type) { + + gfc->ov_enc.mode_ext = MPG_MD_MS_LR; + } + } + } + + /* bit and noise allocation */ + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + masking = (const III_psy_ratio (*)[2])masking_MS; /* use MS masking */ + pe_use = pe_MS; + } + else { + masking = (const III_psy_ratio (*)[2])masking_LR; /* use LR masking */ + pe_use = pe; + } + + + /* copy data for MP3 frame analyzer */ + if (cfg->analysis && gfc->pinfo != NULL) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gfc->pinfo->ms_ratio[gr] = 0; + gfc->pinfo->ms_ener_ratio[gr] = ms_ener_ratio[gr]; + gfc->pinfo->blocktype[gr][ch] = gfc->l3_side.tt[gr][ch].block_type; + gfc->pinfo->pe[gr][ch] = pe_use[gr][ch]; + memcpy(gfc->pinfo->xr[gr][ch], &gfc->l3_side.tt[gr][ch].xr[0], sizeof(FLOAT) * 576); + /* in psymodel, LR and MS data was stored in pinfo. + switch to MS data: */ + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + gfc->pinfo->ers[gr][ch] = gfc->pinfo->ers[gr][ch + 2]; + memcpy(gfc->pinfo->energy[gr][ch], gfc->pinfo->energy[gr][ch + 2], + sizeof(gfc->pinfo->energy[gr][ch])); + } + } + } + } + + + /**************************************** + * Stage 4: quantization loop * + ****************************************/ + + if (cfg->vbr == vbr_off || cfg->vbr == vbr_abr) { + static FLOAT const fircoef[9] = { + -0.0207887 * 5, -0.0378413 * 5, -0.0432472 * 5, -0.031183 * 5, + 7.79609e-18 * 5, 0.0467745 * 5, 0.10091 * 5, 0.151365 * 5, + 0.187098 * 5 + }; + + int i; + FLOAT f; + + for (i = 0; i < 18; i++) + gfc->sv_enc.pefirbuf[i] = gfc->sv_enc.pefirbuf[i + 1]; + + f = 0.0; + for (gr = 0; gr < cfg->mode_gr; gr++) + for (ch = 0; ch < cfg->channels_out; ch++) + f += pe_use[gr][ch]; + gfc->sv_enc.pefirbuf[18] = f; + + f = gfc->sv_enc.pefirbuf[9]; + for (i = 0; i < 9; i++) + f += (gfc->sv_enc.pefirbuf[i] + gfc->sv_enc.pefirbuf[18 - i]) * fircoef[i]; + + f = (670 * 5 * cfg->mode_gr * cfg->channels_out) / f; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + pe_use[gr][ch] *= f; + } + } + } + switch (cfg->vbr) + { + default: + case vbr_off: + CBR_iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking); + break; + case vbr_abr: + ABR_iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking); + break; + case vbr_rh: + VBR_old_iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking); + break; + case vbr_mt: + case vbr_mtrh: + VBR_new_iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking); + break; + } + + + /**************************************** + * Stage 5: bitstream formatting * + ****************************************/ + + + /* write the frame to the bitstream */ + (void) format_bitstream(gfc); + + /* copy mp3 bit buffer into array */ + mp3count = copy_buffer(gfc, mp3buf, mp3buf_size, 1); + + + if (cfg->write_lame_tag) { + AddVbrFrame(gfc); + } + + if (cfg->analysis && gfc->pinfo != NULL) { + int framesize = 576 * cfg->mode_gr; + for (ch = 0; ch < cfg->channels_out; ch++) { + int j; + for (j = 0; j < FFTOFFSET; j++) + gfc->pinfo->pcmdata[ch][j] = gfc->pinfo->pcmdata[ch][j + framesize]; + for (j = FFTOFFSET; j < 1600; j++) { + gfc->pinfo->pcmdata[ch][j] = inbuf[ch][j - FFTOFFSET]; + } + } + gfc->sv_qnt.masking_lower = 1.0; + + set_frame_pinfo(gfc, masking); + } + + ++gfc->ov_enc.frame_number; + + updateStats(gfc); + + return mp3count; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.h new file mode 100644 index 00000000..b06a7c64 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/encoder.h @@ -0,0 +1,156 @@ +/* + * encoder.h include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifndef LAME_ENCODER_H +#define LAME_ENCODER_H + +/*********************************************************************** +* +* encoder and decoder delays +* +***********************************************************************/ + +/* + * layer III enc->dec delay: 1056 (1057?) (observed) + * layer II enc->dec delay: 480 (481?) (observed) + * + * polyphase 256-16 (dec or enc) = 240 + * mdct 256+32 (9*32) (dec or enc) = 288 + * total: 512+16 + * + * My guess is that delay of polyphase filterbank is actualy 240.5 + * (there are technical reasons for this, see postings in mp3encoder). + * So total Encode+Decode delay = ENCDELAY + 528 + 1 + */ + +/* + * ENCDELAY The encoder delay. + * + * Minimum allowed is MDCTDELAY (see below) + * + * The first 96 samples will be attenuated, so using a value less than 96 + * will result in corrupt data for the first 96-ENCDELAY samples. + * + * suggested: 576 + * set to 1160 to sync with FhG. + */ + +#define ENCDELAY 576 + + + +/* + * make sure there is at least one complete frame after the + * last frame containing real data + * + * Using a value of 288 would be sufficient for a + * a very sophisticated decoder that can decode granule-by-granule instead + * of frame by frame. But lets not assume this, and assume the decoder + * will not decode frame N unless it also has data for frame N+1 + * + */ +/*#define POSTDELAY 288*/ +#define POSTDELAY 1152 + + + +/* + * delay of the MDCT used in mdct.c + * original ISO routines had a delay of 528! + * Takehiro's routines: + */ + +#define MDCTDELAY 48 +#define FFTOFFSET (224+MDCTDELAY) + +/* + * Most decoders, including the one we use, have a delay of 528 samples. + */ + +#define DECDELAY 528 + + +/* number of subbands */ +#define SBLIMIT 32 + +/* parition bands bands */ +#define CBANDS 64 + +/* number of critical bands/scale factor bands where masking is computed*/ +#define SBPSY_l 21 +#define SBPSY_s 12 + +/* total number of scalefactor bands encoded */ +#define SBMAX_l 22 +#define SBMAX_s 13 +#define PSFB21 6 +#define PSFB12 6 + + + +/* FFT sizes */ +#define BLKSIZE 1024 +#define HBLKSIZE (BLKSIZE/2 + 1) +#define BLKSIZE_s 256 +#define HBLKSIZE_s (BLKSIZE_s/2 + 1) + + +/* #define switch_pe 1800 */ +#define NORM_TYPE 0 +#define START_TYPE 1 +#define SHORT_TYPE 2 +#define STOP_TYPE 3 + +/* + * Mode Extention: + * When we are in stereo mode, there are 4 possible methods to store these + * two channels. The stereo modes -m? are using a subset of them. + * + * -ms: MPG_MD_LR_LR + * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR + * -mf: MPG_MD_MS_LR + * -mi: all + */ +#if 0 +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 +#endif +enum MPEGChannelMode +{ MPG_MD_LR_LR = 0 +, MPG_MD_LR_I = 1 +, MPG_MD_MS_LR = 2 +, MPG_MD_MS_I = 3 +}; + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + +int lame_encode_mp3_frame(lame_internal_flags * gfc, + sample_t const *inbuf_l, + sample_t const *inbuf_r, unsigned char *mp3buf, int mp3buf_size); + +#endif /* LAME_ENCODER_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.c new file mode 100644 index 00000000..4eea1adb --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.c @@ -0,0 +1,339 @@ +/* +** FFT and FHT routines +** Copyright 1988, 1993; Ron Mayer +** Copyright (c) 1999-2000 Takehiro Tominaga +** +** 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 +** and added some optimization by +** Mather - idea of using lookup table +** Takehiro - some dirty hack for speed up +*/ + +/* $Id: fft.c,v 1.39 2017/09/06 15:07:29 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "fft.h" + +#include "vector/lame_intrin.h" + + + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ + +/* fft.c */ + +static const FLOAT costab[TRI_SIZE * 2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + +static void +fht(FLOAT * fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *gi; + FLOAT const *fn; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0, f1, f2, f3; + 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; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fi < fn); + c1 = tri[0]; + s1 = tri[1]; + for (i = 1; i < kx; i++) { + FLOAT c2, s2; + c2 = 1 - (2 * s1) * s1; + s2 = (2 * s1) * c1; + 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); + c2 = c1; + c1 = c2 * tri[0] - s1 * tri[1]; + s1 = c2 * tri[1] + s1 * tri[0]; + } + tri += 2; + } while (k4 < n); +} + + +static const unsigned char rv_tbl[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe +}; + +#define ch01(index) (buffer[chn][index]) + +#define ml00(f) (window[i ] * f(i)) +#define ml10(f) (window[i + 0x200] * f(i + 0x200)) +#define ml20(f) (window[i + 0x100] * f(i + 0x100)) +#define ml30(f) (window[i + 0x300] * f(i + 0x300)) + +#define ml01(f) (window[i + 0x001] * f(i + 0x001)) +#define ml11(f) (window[i + 0x201] * f(i + 0x201)) +#define ml21(f) (window[i + 0x101] * f(i + 0x101)) +#define ml31(f) (window[i + 0x301] * f(i + 0x301)) + +#define ms00(f) (window_s[i ] * f(i + k)) +#define ms10(f) (window_s[0x7f - i] * f(i + k + 0x80)) +#define ms20(f) (window_s[i + 0x40] * f(i + k + 0x40)) +#define ms30(f) (window_s[0x3f - i] * f(i + k + 0xc0)) + +#define ms01(f) (window_s[i + 0x01] * f(i + k + 0x01)) +#define ms11(f) (window_s[0x7e - i] * f(i + k + 0x81)) +#define ms21(f) (window_s[i + 0x41] * f(i + k + 0x41)) +#define ms31(f) (window_s[0x3e - i] * f(i + k + 0xc1)) + +void +fft_short(lame_internal_flags const *const gfc, + FLOAT x_real[3][BLKSIZE_s], int chn, const sample_t *const buffer[2]) +{ + int i; + int j; + int b; + +#define window_s gfc->cd_psy->window_s +#define window gfc->cd_psy->window + + for (b = 0; b < 3; b++) { + FLOAT *x = &x_real[b][BLKSIZE_s / 2]; + short const k = (576 / 3) * (b + 1); + j = BLKSIZE_s / 8 - 1; + do { + FLOAT f0, f1, f2, f3, w; + + i = rv_tbl[j << 2]; + + f0 = ms00(ch01); + w = ms10(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ms20(ch01); + w = ms30(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ms01(ch01); + w = ms11(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ms21(ch01); + w = ms31(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x[BLKSIZE_s / 2 + 0] = f0 + f2; + x[BLKSIZE_s / 2 + 2] = f0 - f2; + x[BLKSIZE_s / 2 + 1] = f1 + f3; + x[BLKSIZE_s / 2 + 3] = f1 - f3; + } while (--j >= 0); + +#undef window +#undef window_s + + gfc->fft_fht(x, BLKSIZE_s / 2); + /* BLKSIZE_s/2 because of 3DNow! ASM routine */ + } +} + +void +fft_long(lame_internal_flags const *const gfc, + FLOAT x[BLKSIZE], int chn, const sample_t *const buffer[2]) +{ + int i; + int jj = BLKSIZE / 8 - 1; + x += BLKSIZE / 2; + +#define window_s gfc->cd_psy->window_s +#define window gfc->cd_psy->window + + do { + FLOAT f0, f1, f2, f3, w; + + i = rv_tbl[jj]; + f0 = ml00(ch01); + w = ml10(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ml20(ch01); + w = ml30(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ml01(ch01); + w = ml11(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ml21(ch01); + w = ml31(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x[BLKSIZE / 2 + 0] = f0 + f2; + x[BLKSIZE / 2 + 2] = f0 - f2; + x[BLKSIZE / 2 + 1] = f1 + f3; + x[BLKSIZE / 2 + 3] = f1 - f3; + } while (--jj >= 0); + +#undef window +#undef window_s + + gfc->fft_fht(x, BLKSIZE / 2); + /* BLKSIZE/2 because of 3DNow! ASM routine */ +} + +#ifdef HAVE_NASM +extern void fht_3DN(FLOAT * fz, int n); +extern void fht_SSE(FLOAT * fz, int n); +#endif + +void +init_fft(lame_internal_flags * const gfc) +{ + int i; + + /* The type of window used here will make no real difference, but */ + /* in the interest of merging nspsytune stuff - switch to blackman window */ + for (i = 0; i < BLKSIZE; i++) + /* blackman window */ + gfc->cd_psy->window[i] = 0.42 - 0.5 * cos(2 * PI * (i + .5) / BLKSIZE) + + 0.08 * cos(4 * PI * (i + .5) / BLKSIZE); + + for (i = 0; i < BLKSIZE_s / 2; i++) + gfc->cd_psy->window_s[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE_s)); + + gfc->fft_fht = fht; +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + gfc->fft_fht = fht_3DN; + } + else if (gfc->CPU_features.SSE) { + gfc->fft_fht = fht_SSE; + } + else { + gfc->fft_fht = fht; + } +#else +#ifdef HAVE_XMMINTRIN_H +#ifdef MIN_ARCH_SSE + gfc->fft_fht = fht_SSE2; +#endif +#endif +#endif +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.h new file mode 100644 index 00000000..258df887 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/fft.h @@ -0,0 +1,35 @@ +/* + * Fast Fourier Transform include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_FFT_H +#define LAME_FFT_H + +void fft_long(lame_internal_flags const *const gfc, FLOAT x_real[BLKSIZE], + int chn, const sample_t *const data[2]); + +void fft_short(lame_internal_flags const *const gfc, FLOAT x_real[3][BLKSIZE_s], + int chn, const sample_t *const data[2]); + +void init_fft(lame_internal_flags * const gfc); + +#endif + +/* End of fft.h */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.c new file mode 100644 index 00000000..c94db780 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.c @@ -0,0 +1,476 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * Improvements and optimizations added by Frank Klemm, and by Marcel Muller + * + * 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 + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * original coding by Glen Sawyer (mp3gain@hotmail.com) + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * + * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ ) + * -- credit him for all the _good_ programming ;) + * + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +/* + * Here's the deal. Call + * + * InitGainAnalysis ( long samplefreq ); + * + * to initialize everything. Call + * + * AnalyzeSamples ( const Float_t* left_samples, + * const Float_t* right_samples, + * size_t num_samples, + * int num_channels ); + * + * as many times as you want, with as many or as few samples as you want. + * If mono, pass the sample buffer in through left_samples, leave + * right_samples NULL, and make sure num_channels = 1. + * + * GetTitleGain() + * + * will return the recommended dB level change for all samples analyzed + * SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis(). + * + * GetAlbumGain() + * + * will return the recommended dB level change for all samples analyzed + * since InitGainAnalysis() was called and finalized with GetTitleGain(). + * + * Pseudo-code to process an album: + * + * Float_t l_samples [4096]; + * Float_t r_samples [4096]; + * size_t num_samples; + * unsigned int num_songs; + * unsigned int i; + * + * InitGainAnalysis ( 44100 ); + * for ( i = 1; i <= num_songs; i++ ) { + * while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 ) + * AnalyzeSamples ( left_samples, right_samples, num_samples, 2 ); + * fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() ); + * } + * fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() ); + */ + +/* + * So here's the main source of potential code confusion: + * + * The filters applied to the incoming samples are IIR filters, + * meaning they rely on up to <filter order> number of previous samples + * AND up to <filter order> number of previous filtered samples. + * + * I set up the AnalyzeSamples routine to minimize memory usage and interface + * complexity. The speed isn't compromised too much (I don't think), but the + * internal complexity is higher than it should be for such a relatively + * simple routine. + * + * Optimization/clarity suggestions are welcome. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "lame.h" +#include "machine.h" +#include "gain_analysis.h" + +/* for each filter: */ +/* [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */ + +#ifdef WIN32 +#pragma warning ( disable : 4305 ) +#endif + + +/*lint -save -e736 loss of precision */ +static const Float_t ABYule[9][multiple_of(4, 2 * YULE_ORDER + 1)] = { + /* 20 18 16 14 12 10 8 6 4 2 0 19 17 15 13 11 9 7 5 3 1 */ + { 0.00288463683916, 0.00012025322027, 0.00306428023191, 0.00594298065125, -0.02074045215285, 0.02161526843274, -0.01655260341619, -0.00009291677959, -0.00123395316851, -0.02160367184185, 0.03857599435200, 0.13919314567432, -0.86984376593551, 2.75465861874613, -5.87257861775999, 9.48293806319790,-12.28759895145294, 13.05504219327545,-11.34170355132042, 7.81501653005538, -3.84664617118067}, + {-0.00187763777362, 0.00674613682247, -0.00240879051584, 0.01624864962975, -0.02596338512915, 0.02245293253339, -0.00834990904936, -0.00851165645469, -0.00848709379851, -0.02911007808948, 0.05418656406430, 0.13149317958808, -0.75104302451432, 2.19611684890774, -4.39470996079559, 6.85401540936998, -8.81498681370155, 9.47693607801280, -8.54751527471874, 6.36317777566148, -3.47845948550071}, + {-0.00881362733839, 0.00651420667831, -0.01390589421898, 0.03174092540049, 0.00222312597743, 0.04781476674921, -0.05588393329856, 0.02163541888798, -0.06247880153653, -0.09331049056315, 0.15457299681924, 0.02347897407020, -0.05032077717131, 0.16378164858596, -0.45953458054983, 1.00595954808547, -1.67148153367602, 2.23697657451713, -2.64577170229825, 2.84868151156327, -2.37898834973084}, + {-0.02950134983287, 0.00205861885564, -0.00000828086748, 0.06276101321749, -0.00584456039913, -0.02364141202522, -0.00915702933434, 0.03282930172664, -0.08587323730772, -0.22613988682123, 0.30296907319327, 0.00302439095741, 0.02005851806501, 0.04500235387352, -0.22138138954925, 0.39120800788284, -0.22638893773906, -0.16276719120440, -0.25656257754070, 1.07977492259970, -1.61273165137247}, + {-0.01760176568150, -0.01635381384540, 0.00832043980773, 0.05724228140351, -0.00589500224440, -0.00469977914380, -0.07834489609479, 0.11921148675203, -0.11828570177555, -0.25572241425570, 0.33642304856132, 0.02977207319925, -0.04237348025746, 0.08333755284107, -0.04067510197014, -0.12453458140019, 0.47854794562326, -0.80774944671438, 0.12205022308084, 0.87350271418188, -1.49858979367799}, + { 0.00541907748707, -0.03193428438915, -0.01863887810927, 0.10478503600251, 0.04097565135648, -0.12398163381748, 0.04078262797139, -0.01419140100551, -0.22784394429749, -0.14351757464547, 0.44915256608450, 0.03222754072173, 0.05784820375801, 0.06747620744683, 0.00613424350682, 0.22199650564824, -0.42029820170918, 0.00213767857124, -0.37256372942400, 0.29661783706366, -0.62820619233671}, + {-0.00588215443421, -0.03788984554840, 0.08647503780351, 0.00647310677246, -0.27562961986224, 0.30931782841830, -0.18901604199609, 0.16744243493672, 0.16242137742230, -0.75464456939302, 0.56619470757641, 0.01807364323573, 0.01639907836189, -0.04784254229033, 0.06739368333110, -0.33032403314006, 0.45054734505008, 0.00819999645858, -0.26806001042947, 0.29156311971249, -1.04800335126349}, + {-0.00749618797172, -0.03721611395801, 0.06920467763959, 0.01628462406333, -0.25344790059353, 0.15558449135573, 0.02377945217615, 0.17520704835522, -0.14289799034253, -0.53174909058578, 0.58100494960553, 0.01818801111503, 0.02442357316099, -0.02505961724053, -0.05246019024463, -0.23313271880868, 0.38952639978999, 0.14728154134330, -0.20256413484477, -0.31863563325245, -0.51035327095184}, + {-0.02217936801134, 0.04788665548180, -0.04060034127000, -0.11202315195388, -0.02459864859345, 0.14590772289388, -0.10214864179676, 0.04267842219415, -0.00275953611929, -0.42163034350696, 0.53648789255105, 0.04704409688120, 0.05477720428674, -0.18823009262115, -0.17556493366449, 0.15113130533216, 0.26408300200955, -0.04678328784242, -0.03424681017675, -0.43193942311114, -0.25049871956020} +}; + +static const Float_t ABButter[9][multiple_of(4, 2 * BUTTER_ORDER + 1)] = { + /* 5 4 3 2 1 */ + {0.98621192462708, 0.97261396931306, -1.97242384925416, -1.97223372919527, 0.98621192462708}, + {0.98500175787242, 0.97022847566350, -1.97000351574484, -1.96977855582618, 0.98500175787242}, + {0.97938932735214, 0.95920349965459, -1.95877865470428, -1.95835380975398, 0.97938932735214}, + {0.97531843204928, 0.95124613669835, -1.95063686409857, -1.95002759149878, 0.97531843204928}, + {0.97316523498161, 0.94705070426118, -1.94633046996323, -1.94561023566527, 0.97316523498161}, + {0.96454515552826, 0.93034775234268, -1.92909031105652, -1.92783286977036, 0.96454515552826}, + {0.96009142950541, 0.92177618768381, -1.92018285901082, -1.91858953033784, 0.96009142950541}, + {0.95856916599601, 0.91885558323625, -1.91713833199203, -1.91542108074780, 0.95856916599601}, + {0.94597685600279, 0.89487434461664, -1.89195371200558, -1.88903307939452, 0.94597685600279} +}; + +/*lint -restore */ + +#ifdef WIN32 +#pragma warning ( default : 4305 ) +#endif + +/* When calling this procedure, make sure that ip[-order] and op[-order] point to real data! */ + +static void +filterYule(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel) +{ + while (nSamples--) { + Float_t y0 = input[-10] * kernel[ 0]; + Float_t y2 = input[ -9] * kernel[ 1]; + Float_t y4 = input[ -8] * kernel[ 2]; + Float_t y6 = input[ -7] * kernel[ 3]; + Float_t s00 = y0 + y2 + y4 + y6; + Float_t y8 = input[ -6] * kernel[ 4]; + Float_t yA = input[ -5] * kernel[ 5]; + Float_t yC = input[ -4] * kernel[ 6]; + Float_t yE = input[ -3] * kernel[ 7]; + Float_t s01 = y8 + yA + yC + yE; + Float_t yG = input[ -2] * kernel[ 8] + input[ -1] * kernel[ 9]; + Float_t yK = input[ 0] * kernel[10]; + + Float_t s1 = s00 + s01 + yG + yK; + + Float_t x1 = output[-10] * kernel[11] + output[ -9] * kernel[12]; + Float_t x5 = output[ -8] * kernel[13] + output[ -7] * kernel[14]; + Float_t x9 = output[ -6] * kernel[15] + output[ -5] * kernel[16]; + Float_t xD = output[ -4] * kernel[17] + output[ -3] * kernel[18]; + Float_t xH = output[ -2] * kernel[19] + output[ -1] * kernel[20]; + + Float_t s2 = x1 + x5 + x9 + xD + xH; + + output[0] = (Float_t)(s1 - s2); + + ++output; + ++input; + } +} + +static void +filterButter(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel) +{ + while (nSamples--) { + Float_t s1 = input[-2] * kernel[0] + input[-1] * kernel[2] + input[ 0] * kernel[4]; + Float_t s2 = output[-2] * kernel[1] + output[-1] * kernel[3]; + output[0] = (Float_t)(s1 - s2); + ++output; + ++input; + } +} + + + +static int ResetSampleFrequency(replaygain_t * rgData, long samplefreq); + +/* returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not */ + +int +ResetSampleFrequency(replaygain_t * rgData, long samplefreq) +{ + /* zero out initial values, only first MAX_ORDER values */ + memset(rgData->linprebuf, 0, MAX_ORDER * sizeof(*rgData->linprebuf)); + memset(rgData->rinprebuf, 0, MAX_ORDER * sizeof(*rgData->rinprebuf)); + memset(rgData->lstepbuf, 0, MAX_ORDER * sizeof(*rgData->lstepbuf)); + memset(rgData->rstepbuf, 0, MAX_ORDER * sizeof(*rgData->rstepbuf)); + memset(rgData->loutbuf, 0, MAX_ORDER * sizeof(*rgData->loutbuf)); + memset(rgData->routbuf, 0, MAX_ORDER * sizeof(*rgData->routbuf)); + + switch ((int) (samplefreq)) { + case 48000: + rgData->freqindex = 0; + break; + case 44100: + rgData->freqindex = 1; + break; + case 32000: + rgData->freqindex = 2; + break; + case 24000: + rgData->freqindex = 3; + break; + case 22050: + rgData->freqindex = 4; + break; + case 16000: + rgData->freqindex = 5; + break; + case 12000: + rgData->freqindex = 6; + break; + case 11025: + rgData->freqindex = 7; + break; + case 8000: + rgData->freqindex = 8; + break; + default: + return INIT_GAIN_ANALYSIS_ERROR; + } + + rgData->sampleWindow = + (samplefreq * RMS_WINDOW_TIME_NUMERATOR + RMS_WINDOW_TIME_DENOMINATOR - + 1) / RMS_WINDOW_TIME_DENOMINATOR; + + rgData->lsum = 0.; + rgData->rsum = 0.; + rgData->totsamp = 0; + + memset(rgData->A, 0, sizeof(rgData->A)); + + return INIT_GAIN_ANALYSIS_OK; +} + +int +InitGainAnalysis(replaygain_t * rgData, long samplefreq) +{ + if (ResetSampleFrequency(rgData, samplefreq) != INIT_GAIN_ANALYSIS_OK) { + return INIT_GAIN_ANALYSIS_ERROR; + } + + rgData->linpre = rgData->linprebuf + MAX_ORDER; + rgData->rinpre = rgData->rinprebuf + MAX_ORDER; + rgData->lstep = rgData->lstepbuf + MAX_ORDER; + rgData->rstep = rgData->rstepbuf + MAX_ORDER; + rgData->lout = rgData->loutbuf + MAX_ORDER; + rgData->rout = rgData->routbuf + MAX_ORDER; + + memset(rgData->B, 0, sizeof(rgData->B)); + + return INIT_GAIN_ANALYSIS_OK; +} + +/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */ + +int +AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, const Float_t * right_samples, + size_t num_samples, int num_channels) +{ + const Float_t *curleft; + const Float_t *curright; + long batchsamples; + long cursamples; + long cursamplepos; + int i; + Float_t sum_l, sum_r; + + if (num_samples == 0) + return GAIN_ANALYSIS_OK; + + cursamplepos = 0; + batchsamples = (long) num_samples; + + switch (num_channels) { + case 1: + right_samples = left_samples; + break; + case 2: + break; + default: + return GAIN_ANALYSIS_ERROR; + } + + if (num_samples < MAX_ORDER) { + memcpy(rgData->linprebuf + MAX_ORDER, left_samples, num_samples * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t)); + } + else { + memcpy(rgData->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t)); + } + + while (batchsamples > 0) { + cursamples = batchsamples > rgData->sampleWindow - rgData->totsamp ? + rgData->sampleWindow - rgData->totsamp : batchsamples; + if (cursamplepos < MAX_ORDER) { + curleft = rgData->linpre + cursamplepos; + curright = rgData->rinpre + cursamplepos; + if (cursamples > MAX_ORDER - cursamplepos) + cursamples = MAX_ORDER - cursamplepos; + } + else { + curleft = left_samples + cursamplepos; + curright = right_samples + cursamplepos; + } + + YULE_FILTER(curleft, rgData->lstep + rgData->totsamp, cursamples, + ABYule[rgData->freqindex]); + YULE_FILTER(curright, rgData->rstep + rgData->totsamp, cursamples, + ABYule[rgData->freqindex]); + + BUTTER_FILTER(rgData->lstep + rgData->totsamp, rgData->lout + rgData->totsamp, cursamples, + ABButter[rgData->freqindex]); + BUTTER_FILTER(rgData->rstep + rgData->totsamp, rgData->rout + rgData->totsamp, cursamples, + ABButter[rgData->freqindex]); + + curleft = rgData->lout + rgData->totsamp; /* Get the squared values */ + curright = rgData->rout + rgData->totsamp; + + sum_l = 0; + sum_r = 0; + i = cursamples & 0x03; + while (i--) { + Float_t const l = *curleft++; + Float_t const r = *curright++; + sum_l += l * l; + sum_r += r * r; + } + i = cursamples / 4; + while (i--) { + Float_t l0 = curleft[0] * curleft[0]; + Float_t l1 = curleft[1] * curleft[1]; + Float_t l2 = curleft[2] * curleft[2]; + Float_t l3 = curleft[3] * curleft[3]; + Float_t sl = l0 + l1 + l2 + l3; + Float_t r0 = curright[0] * curright[0]; + Float_t r1 = curright[1] * curright[1]; + Float_t r2 = curright[2] * curright[2]; + Float_t r3 = curright[3] * curright[3]; + Float_t sr = r0 + r1 + r2 + r3; + sum_l += sl; + curleft += 4; + sum_r += sr; + curright += 4; + } + rgData->lsum += sum_l; + rgData->rsum += sum_r; + + batchsamples -= cursamples; + cursamplepos += cursamples; + rgData->totsamp += cursamples; + if (rgData->totsamp == rgData->sampleWindow) { /* Get the Root Mean Square (RMS) for this set of samples */ + double const val = + STEPS_per_dB * 10. * log10((rgData->lsum + rgData->rsum) / rgData->totsamp * 0.5 + + 1.e-37); + size_t ival = (val <= 0) ? 0 : (size_t) val; + if (ival >= sizeof(rgData->A) / sizeof(*(rgData->A))) + ival = sizeof(rgData->A) / sizeof(*(rgData->A)) - 1; + rgData->A[ival]++; + rgData->lsum = rgData->rsum = 0.; + memmove(rgData->loutbuf, rgData->loutbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->routbuf, rgData->routbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->lstepbuf, rgData->lstepbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->rstepbuf, rgData->rstepbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + rgData->totsamp = 0; + } + if (rgData->totsamp > rgData->sampleWindow) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */ + return GAIN_ANALYSIS_ERROR; + } + if (num_samples < MAX_ORDER) { + memmove(rgData->linprebuf, rgData->linprebuf + num_samples, + (MAX_ORDER - num_samples) * sizeof(Float_t)); + memmove(rgData->rinprebuf, rgData->rinprebuf + num_samples, + (MAX_ORDER - num_samples) * sizeof(Float_t)); + memcpy(rgData->linprebuf + MAX_ORDER - num_samples, left_samples, + num_samples * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER - num_samples, right_samples, + num_samples * sizeof(Float_t)); + } + else { + memcpy(rgData->linprebuf, left_samples + num_samples - MAX_ORDER, + MAX_ORDER * sizeof(Float_t)); + memcpy(rgData->rinprebuf, right_samples + num_samples - MAX_ORDER, + MAX_ORDER * sizeof(Float_t)); + } + + return GAIN_ANALYSIS_OK; +} + + +static Float_t +analyzeResult(uint32_t const *Array, size_t len) +{ + uint32_t elems; + uint32_t upper; + uint32_t sum; + size_t i; + + elems = 0; + for (i = 0; i < len; i++) + elems += Array[i]; + if (elems == 0) + return GAIN_NOT_ENOUGH_SAMPLES; + + upper = (uint32_t) ceil(elems * (1. - RMS_PERCENTILE)); + sum = 0; + for (i = len; i-- > 0;) { + sum += Array[i]; + if (sum >= upper) { + break; + } + } + + return (Float_t) ((Float_t) PINK_REF - (Float_t) i / (Float_t) STEPS_per_dB); +} + + +Float_t +GetTitleGain(replaygain_t * rgData) +{ + Float_t retval; + unsigned int i; + + retval = analyzeResult(rgData->A, sizeof(rgData->A) / sizeof(*(rgData->A))); + + for (i = 0; i < sizeof(rgData->A) / sizeof(*(rgData->A)); i++) { + rgData->B[i] += rgData->A[i]; + rgData->A[i] = 0; + } + + for (i = 0; i < MAX_ORDER; i++) + rgData->linprebuf[i] = rgData->lstepbuf[i] + = rgData->loutbuf[i] + = rgData->rinprebuf[i] + = rgData->rstepbuf[i] + = rgData->routbuf[i] = 0.f; + + rgData->totsamp = 0; + rgData->lsum = rgData->rsum = 0.; + return retval; +} + +#if 0 +static Float_t GetAlbumGain(replaygain_t const* rgData); + +Float_t +GetAlbumGain(replaygain_t const* rgData) +{ + return analyzeResult(rgData->B, sizeof(rgData->B) / sizeof(*(rgData->B))); +} +#endif + +/* end of gain_analysis.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.h new file mode 100644 index 00000000..a6b56ab3 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/gain_analysis.h @@ -0,0 +1,109 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * + * 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 + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +#ifndef GAIN_ANALYSIS_H +#define GAIN_ANALYSIS_H + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#else +# ifdef HAVE_STDINT_H +# include <stdint.h> +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + typedef sample_t Float_t; /* Type used for filtering */ + + +#define PINK_REF 64.82 /* 298640883795 */ /* calibration value for 89dB */ + + +#define YULE_ORDER 10 +#define BUTTER_ORDER 2 +#define YULE_FILTER filterYule +#define BUTTER_FILTER filterButter +#define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */ +#define MAX_SAMP_FREQ 48000L /* maximum allowed sample frequency [Hz] */ +#define RMS_WINDOW_TIME_NUMERATOR 1L +#define RMS_WINDOW_TIME_DENOMINATOR 20L /* numerator / denominator = time slice size [s] */ +#define STEPS_per_dB 100 /* Table entries per dB */ +#define MAX_dB 120 /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */ + + enum { GAIN_NOT_ENOUGH_SAMPLES = -24601, GAIN_ANALYSIS_ERROR = 0, GAIN_ANALYSIS_OK = + 1, INIT_GAIN_ANALYSIS_ERROR = 0, INIT_GAIN_ANALYSIS_OK = 1 + }; + + enum { MAX_ORDER = (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER) + , MAX_SAMPLES_PER_WINDOW = ((MAX_SAMP_FREQ * RMS_WINDOW_TIME_NUMERATOR) / RMS_WINDOW_TIME_DENOMINATOR + 1) /* max. Samples per Time slice */ + }; + + struct replaygain_data { + Float_t linprebuf[MAX_ORDER * 2]; + Float_t *linpre; /* left input samples, with pre-buffer */ + Float_t lstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *lstep; /* left "first step" (i.e. post first filter) samples */ + Float_t loutbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *lout; /* left "out" (i.e. post second filter) samples */ + Float_t rinprebuf[MAX_ORDER * 2]; + Float_t *rinpre; /* right input samples ... */ + Float_t rstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *rstep; + Float_t routbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *rout; + long sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */ + long totsamp; + double lsum; + double rsum; + int freqindex; + int first; + uint32_t A[STEPS_per_dB * MAX_dB]; + uint32_t B[STEPS_per_dB * MAX_dB]; + + }; +#ifndef replaygain_data_defined +#define replaygain_data_defined + typedef struct replaygain_data replaygain_t; +#endif + + + + + int InitGainAnalysis(replaygain_t * rgData, long samplefreq); + int AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, + const Float_t * right_samples, size_t num_samples, int num_channels); + Float_t GetTitleGain(replaygain_t * rgData); + + +#ifdef __cplusplus +} +#endif +#endif /* GAIN_ANALYSIS_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.c new file mode 100644 index 00000000..ac485103 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.c @@ -0,0 +1,1926 @@ +/* + * id3tag.c -- Write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton + * Copyright (C) 2011-2017 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +/* + * HISTORY: This source file is part of LAME (see http://www.mp3dev.org) + * and was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au> + * from mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1 + * tags. Don Melton <don@blivet.com> COMPLETELY rewrote it to support version + * 2 tags and be more conformant to other standards while remaining flexible. + * + * NOTE: See http://id3.org/ for more information about ID3 tag formats. + */ + +/* $Id: id3tag.c,v 1.80 2017/08/28 15:39:51 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef STDC_HEADERS +# include <stddef.h> +# include <stdlib.h> +# include <string.h> +# include <ctype.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "id3tag.h" +#include "lame_global_flags.h" +#include "util.h" +#include "bitstream.h" + + +static const char *const genre_names[] = { + /* + * NOTE: The spelling of these genre names is identical to those found in + * Winamp and mp3info. + */ + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", + "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", + "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", + "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", + "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", + "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock", + "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", + "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", + "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", + "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", + "Native US", "Cabaret", "New Wave", "Psychedelic", "Rave", + "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", + "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", + "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", + "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", + "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", + "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", + "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", + "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", + "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta", + "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "SynthPop" +}; + +#define GENRE_NAME_COUNT \ + ((int)(sizeof genre_names / sizeof (const char *const))) + +static const int genre_alpha_map[] = { + 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0, + 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2, + 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84, + 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35, + 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64, + 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92, + 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21, + 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130, + 144, 60, 70, 31, 72, 27, 28 +}; + +#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int))) + +#define GENRE_INDEX_OTHER 12 + + +#define FRAME_ID(a, b, c, d) \ + ( ((unsigned long)(a) << 24) \ + | ((unsigned long)(b) << 16) \ + | ((unsigned long)(c) << 8) \ + | ((unsigned long)(d) << 0) ) + +typedef enum UsualStringIDs { ID_TITLE = FRAME_ID('T', 'I', 'T', '2') + , ID_ARTIST = FRAME_ID('T', 'P', 'E', '1') + , ID_ALBUM = FRAME_ID('T', 'A', 'L', 'B') + , ID_GENRE = FRAME_ID('T', 'C', 'O', 'N') + , ID_ENCODER = FRAME_ID('T', 'S', 'S', 'E') + , ID_PLAYLENGTH = FRAME_ID('T', 'L', 'E', 'N') + , ID_COMMENT = FRAME_ID('C', 'O', 'M', 'M') /* full text string */ +} UsualStringIDs; + +typedef enum NumericStringIDs { ID_DATE = FRAME_ID('T', 'D', 'A', 'T') /* "ddMM" */ + , ID_TIME = FRAME_ID('T', 'I', 'M', 'E') /* "hhmm" */ + , ID_TPOS = FRAME_ID('T', 'P', 'O', 'S') /* '0'-'9' and '/' allowed */ + , ID_TRACK = FRAME_ID('T', 'R', 'C', 'K') /* '0'-'9' and '/' allowed */ + , ID_YEAR = FRAME_ID('T', 'Y', 'E', 'R') /* "yyyy" */ +} NumericStringIDs; + +typedef enum MiscIDs { ID_TXXX = FRAME_ID('T', 'X', 'X', 'X') + , ID_WXXX = FRAME_ID('W', 'X', 'X', 'X') + , ID_SYLT = FRAME_ID('S', 'Y', 'L', 'T') + , ID_APIC = FRAME_ID('A', 'P', 'I', 'C') + , ID_GEOB = FRAME_ID('G', 'E', 'O', 'B') + , ID_PCNT = FRAME_ID('P', 'C', 'N', 'T') + , ID_AENC = FRAME_ID('A', 'E', 'N', 'C') + , ID_LINK = FRAME_ID('L', 'I', 'N', 'K') + , ID_ENCR = FRAME_ID('E', 'N', 'C', 'R') + , ID_GRID = FRAME_ID('G', 'R', 'I', 'D') + , ID_PRIV = FRAME_ID('P', 'R', 'I', 'V') + , ID_USLT = FRAME_ID('U', 'S', 'L', 'T') /* full text string */ + , ID_USER = FRAME_ID('U', 'S', 'E', 'R') /* full text string */ + , ID_PCST = FRAME_ID('P', 'C', 'S', 'T') /* iTunes Podcast indicator, only presence important */ + , ID_WFED = FRAME_ID('W', 'F', 'E', 'D') /* iTunes Podcast URL as TEXT FRAME !!! violates standard */ +} MiscIDs; + + +static int +frame_id_matches(int id, int mask) +{ + int result = 0, i, window = 0xff; + for (i = 0; i < 4; ++i, window <<= 8) { + int const mw = (mask & window); + int const iw = (id & window); + if (mw != 0 && mw != iw) { + result |= iw; + } + } + return result; +} + +static int +isFrameIdMatching(int id, int mask) +{ + return frame_id_matches(id, mask) == 0 ? 1 : 0; +} + +static int +test_tag_spec_flags(lame_internal_flags const *gfc, unsigned int tst) +{ + return (gfc->tag_spec.flags & tst) != 0u ? 1 : 0; +} + +#if 0 +static void +debug_tag_spec_flags(lame_internal_flags * gfc, const char* info) +{ + MSGF(gfc, "%s\n", info); + MSGF(gfc, "CHANGED_FLAG : %d\n", test_tag_spec_flags(gfc, CHANGED_FLAG )); + MSGF(gfc, "ADD_V2_FLAG : %d\n", test_tag_spec_flags(gfc, ADD_V2_FLAG )); + MSGF(gfc, "V1_ONLY_FLAG : %d\n", test_tag_spec_flags(gfc, V1_ONLY_FLAG )); + MSGF(gfc, "V2_ONLY_FLAG : %d\n", test_tag_spec_flags(gfc, V2_ONLY_FLAG )); + MSGF(gfc, "SPACE_V1_FLAG : %d\n", test_tag_spec_flags(gfc, SPACE_V1_FLAG)); + MSGF(gfc, "PAD_V2_FLAG : %d\n", test_tag_spec_flags(gfc, PAD_V2_FLAG )); +} +#endif + +static int +is_lame_internal_flags_null(lame_t gfp) +{ + return (gfp && gfp->internal_flags) ? 0 : 1; +} + +static int +id3v2_add_ucs2_lng(lame_t gfp, uint32_t frame_id, unsigned short const *desc, unsigned short const *text); +static int +id3v2_add_latin1_lng(lame_t gfp, uint32_t frame_id, char const *desc, char const *text); + + +static void +copyV1ToV2(lame_t gfp, int frame_id, char const *s) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc != 0) { + unsigned int flags = gfc->tag_spec.flags; + id3v2_add_latin1_lng(gfp, frame_id, 0, s); + gfc->tag_spec.flags = flags; +#if 0 + debug_tag_spec_flags(gfc, "copyV1ToV2"); +#endif + } +} + + +static void +id3v2AddLameVersion(lame_t gfp) +{ + char buffer[1024]; + const char *b = get_lame_os_bitness(); + const char *v = get_lame_version(); + const char *u = get_lame_url(); + const size_t lenb = strlen(b); + + if (lenb > 0) { + sprintf(buffer, "LAME %s version %s (%s)", b, v, u); + } + else { + sprintf(buffer, "LAME version %s (%s)", v, u); + } + copyV1ToV2(gfp, ID_ENCODER, buffer); +} + +static void +id3v2AddAudioDuration(lame_t gfp, double ms) +{ + SessionConfig_t const *const cfg = &gfp->internal_flags->cfg; /* caller checked pointers */ + char buffer[1024]; + double const max_ulong = MAX_U_32_NUM; + unsigned long playlength_ms; + + ms *= 1000; + ms /= cfg->samplerate_in; + if (ms > max_ulong) { + playlength_ms = max_ulong; + } + else if (ms < 0) { + playlength_ms = 0; + } + else { + playlength_ms = ms; + } + sprintf(buffer, "%lu", playlength_ms); + copyV1ToV2(gfp, ID_PLAYLENGTH, buffer); +} + +void +id3tag_genre_list(void (*handler) (int, const char *, void *), void *cookie) +{ + if (handler) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (i < GENRE_ALPHA_COUNT) { + int j = genre_alpha_map[i]; + handler(j, genre_names[j], cookie); + } + } + } +} + +#define GENRE_NUM_UNKNOWN 255 + + + +void +id3tag_init(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + free_id3tag(gfc); + memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec); + gfc->tag_spec.genre_id3v1 = GENRE_NUM_UNKNOWN; + gfc->tag_spec.padding_size = 128; + id3v2AddLameVersion(gfp); +} + + + +void +id3tag_add_v2(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; +} + +void +id3tag_v1_only(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG); + gfc->tag_spec.flags |= V1_ONLY_FLAG; +} + +void +id3tag_v2_only(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= V2_ONLY_FLAG; +} + +void +id3tag_space_v1(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V2_ONLY_FLAG; + gfc->tag_spec.flags |= SPACE_V1_FLAG; +} + +void +id3tag_pad_v2(lame_t gfp) +{ + id3tag_set_pad(gfp, 128); +} + +void +id3tag_set_pad(lame_t gfp, size_t n) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return; + } + gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= PAD_V2_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; + gfc->tag_spec.padding_size = (unsigned int)n; +} + +static int +hasUcs2ByteOrderMarker(unsigned short bom) +{ + if (bom == 0xFFFEu || bom == 0xFEFFu) { + return 1; + } + return 0; +} + + +static unsigned short +swap_bytes(unsigned short w) +{ + return (0xff00u & (w << 8)) | (0x00ffu & (w >> 8)); +} + + +static unsigned short +toLittleEndian(unsigned short bom, unsigned short c) +{ + if (bom == 0xFFFEu) { + return swap_bytes(c); + } + return c; +} + +static unsigned short +fromLatin1Char(const unsigned short* s, unsigned short c) +{ + if (s[0] == 0xFFFEu) { + return swap_bytes(c); + } + return c; +} + + +static size_t +local_strdup(char **dst, const char *src) +{ + if (dst == 0) { + return 0; + } + free(*dst); + *dst = 0; + if (src != 0) { + size_t n; + for (n = 0; src[n] != 0; ++n) { /* calc src string length */ + } + if (n > 0) { /* string length without zero termination */ + assert(sizeof(*src) == sizeof(**dst)); + *dst = lame_calloc(char, n + 1); + if (*dst != 0) { + memcpy(*dst, src, n * sizeof(**dst)); + (*dst)[n] = 0; + return n; + } + } + } + return 0; +} + +static size_t +local_ucs2_strdup(unsigned short **dst, unsigned short const *src) +{ + if (dst == 0) { + return 0; + } + free(*dst); /* free old string pointer */ + *dst = 0; + if (src != 0) { + size_t n; + for (n = 0; src[n] != 0; ++n) { /* calc src string length */ + } + if (n > 0) { /* string length without zero termination */ + assert(sizeof(*src) >= 2); + assert(sizeof(*src) == sizeof(**dst)); + *dst = lame_calloc(unsigned short, n + 1); + if (*dst != 0) { + memcpy(*dst, src, n * sizeof(**dst)); + (*dst)[n] = 0; + return n; + } + } + } + return 0; +} + + +static size_t +local_ucs2_strlen(unsigned short const *s) +{ + size_t n = 0; + if (s != 0) { + while (*s++) { + ++n; + } + } + return n; +} + + +static size_t +local_ucs2_substr(unsigned short** dst, unsigned short const* src, size_t start, size_t end) +{ + size_t const len = 1 + 1 + ((start < end) ? (end - start) : 0); + size_t n = 0; + unsigned short *ptr = lame_calloc(unsigned short, len); + *dst = ptr; + if (ptr == 0 || src == 0) { + return 0; + } + if (hasUcs2ByteOrderMarker(src[0])) { + ptr[n++] = src[0]; + if (start == 0) { + ++start; + } + } + while (start < end) { + ptr[n++] = src[start++]; + } + ptr[n] = 0; + return n; +} + +static int +local_ucs2_pos(unsigned short const* str, unsigned short c) +{ + int i; + for (i = 0; str != 0 && str[i] != 0; ++i) { + if (str[i] == c) { + return i; + } + } + return -1; +} + +static int +local_char_pos(char const* str, char c) +{ + int i; + for (i = 0; str != 0 && str[i] != 0; ++i) { + if (str[i] == c) { + return i; + } + } + return -1; +} + +static int +maybeLatin1(unsigned short const* text) +{ + if (text) { + unsigned short bom = *text++; + while (*text) { + unsigned short c = toLittleEndian(bom, *text++); + if (c > 0x00fe) return 0; + } + } + return 1; +} + +static int searchGenre(char const* genre); +static int sloppySearchGenre(char const* genre); + +static int +lookupGenre(char const* genre) +{ + char *str; + int num = strtol(genre, &str, 10); + /* is the input a string or a valid number? */ + if (*str) { + num = searchGenre(genre); + if (num == GENRE_NAME_COUNT) { + num = sloppySearchGenre(genre); + } + if (num == GENRE_NAME_COUNT) { + return -2; /* no common genre text found */ + } + } + else { + if ((num < 0) || (num >= GENRE_NAME_COUNT)) { + return -1; /* number unknown */ + } + } + return num; +} + +static unsigned char * +writeLoBytes(unsigned char *frame, unsigned short const *str, size_t n); + +static char* +local_strdup_utf16_to_latin1(unsigned short const* utf16) +{ + size_t len = local_ucs2_strlen(utf16); + unsigned char* latin1 = lame_calloc(unsigned char, len+1); + writeLoBytes(latin1, utf16, len); + return (char*)latin1; +} + + +static int +id3tag_set_genre_utf16(lame_t gfp, unsigned short const* text) +{ + lame_internal_flags* gfc = gfp->internal_flags; + int ret; + if (text == 0) { + return -3; + } + if (!hasUcs2ByteOrderMarker(text[0])) { + return -3; + } + if (maybeLatin1(text)) { + char* latin1 = local_strdup_utf16_to_latin1(text); + int num = lookupGenre(latin1); + free(latin1); + if (num == -1) return -1; /* number out of range */ + if (num >= 0) { /* common genre found */ + gfc->tag_spec.flags |= CHANGED_FLAG; + gfc->tag_spec.genre_id3v1 = num; + copyV1ToV2(gfp, ID_GENRE, genre_names[num]); + return 0; + } + } + ret = id3v2_add_ucs2_lng(gfp, ID_GENRE, 0, text); + if (ret == 0) { + gfc->tag_spec.flags |= CHANGED_FLAG; + gfc->tag_spec.genre_id3v1 = GENRE_INDEX_OTHER; + } + return ret; +} + +/* +Some existing options for ID3 tag can be specified by --tv option +as follows. +--tt <value>, --tv TIT2=value +--ta <value>, --tv TPE1=value +--tl <value>, --tv TALB=value +--ty <value>, --tv TYER=value +--tn <value>, --tv TRCK=value +--tg <value>, --tv TCON=value +(although some are not exactly same)*/ + +int +id3tag_set_albumart(lame_t gfp, const char *image, size_t size) +{ + int mimetype = MIMETYPE_NONE; + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + gfc = gfp->internal_flags; + + if (image != 0) { + unsigned char const *data = (unsigned char const *) image; + /* determine MIME type from the actual image data */ + if (2 < size && data[0] == 0xFF && data[1] == 0xD8) { + mimetype = MIMETYPE_JPEG; + } + else if (4 < size && data[0] == 0x89 && strncmp((const char *) &data[1], "PNG", 3) == 0) { + mimetype = MIMETYPE_PNG; + } + else if (4 < size && strncmp((const char *) data, "GIF8", 4) == 0) { + mimetype = MIMETYPE_GIF; + } + else { + return -1; + } + } + if (gfc->tag_spec.albumart != 0) { + free(gfc->tag_spec.albumart); + gfc->tag_spec.albumart = 0; + gfc->tag_spec.albumart_size = 0; + gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE; + } + if (size < 1 || mimetype == MIMETYPE_NONE) { + return 0; + } + gfc->tag_spec.albumart = lame_calloc(unsigned char, size); + if (gfc->tag_spec.albumart != 0) { + memcpy(gfc->tag_spec.albumart, image, size); + gfc->tag_spec.albumart_size = (unsigned int)size; + gfc->tag_spec.albumart_mimetype = mimetype; + gfc->tag_spec.flags |= CHANGED_FLAG; + id3tag_add_v2(gfp); + } + return 0; +} + +static unsigned char * +set_4_byte_value(unsigned char *bytes, uint32_t value) +{ + int i; + for (i = 3; i >= 0; --i) { + bytes[i] = value & 0xffUL; + value >>= 8; + } + return bytes + 4; +} + +static uint32_t +toID3v2TagId(char const *s) +{ + unsigned int i, x = 0; + if (s == 0) { + return 0; + } + for (i = 0; i < 4 && s[i] != 0; ++i) { + char const c = s[i]; + unsigned int const u = 0x0ff & c; + x <<= 8; + x |= u; + if (c < 'A' || 'Z' < c) { + if (c < '0' || '9' < c) { + return 0; + } + } + } + return x; +} + +static uint32_t +toID3v2TagId_ucs2(unsigned short const *s) +{ + unsigned int i, x = 0; + unsigned short bom = 0; + if (s == 0) { + return 0; + } + bom = s[0]; + if (hasUcs2ByteOrderMarker(bom)) { + ++s; + } + for (i = 0; i < 4 && s[i] != 0; ++i) { + unsigned short const c = toLittleEndian(bom, s[i]); + if (c < 'A' || 'Z' < c) { + if (c < '0' || '9' < c) { + return 0; + } + } + x <<= 8; + x |= c; + } + return x; +} + +#if 0 +static int +isNumericString(uint32_t frame_id) +{ + switch (frame_id) { + case ID_DATE: + case ID_TIME: + case ID_TPOS: + case ID_TRACK: + case ID_YEAR: + return 1; + } + return 0; +} +#endif + +static int +isMultiFrame(uint32_t frame_id) +{ + switch (frame_id) { + case ID_TXXX: + case ID_WXXX: + case ID_COMMENT: + case ID_SYLT: + case ID_APIC: + case ID_GEOB: + case ID_PCNT: + case ID_AENC: + case ID_LINK: + case ID_ENCR: + case ID_GRID: + case ID_PRIV: + return 1; + } + return 0; +} + +#if 0 +static int +isFullTextString(int frame_id) +{ + switch (frame_id) { + case ID_VSLT: + case ID_COMMENT: + return 1; + } + return 0; +} +#endif + +static FrameDataNode * +findNode(id3tag_spec const *tag, uint32_t frame_id, FrameDataNode const *last) +{ + FrameDataNode *node = last ? last->nxt : tag->v2_head; + while (node != 0) { + if (node->fid == frame_id) { + return node; + } + node = node->nxt; + } + return 0; +} + +static void +appendNode(id3tag_spec * tag, FrameDataNode * node) +{ + if (tag->v2_tail == 0 || tag->v2_head == 0) { + tag->v2_head = node; + tag->v2_tail = node; + } + else { + tag->v2_tail->nxt = node; + tag->v2_tail = node; + } +} + +static void +setLang(char *dst, char const *src) +{ + int i; + if (src == 0 || src[0] == 0) { + dst[0] = 'e'; + dst[1] = 'n'; + dst[2] = 'g'; + } + else { + for (i = 0; i < 3 && src && *src; ++i) { + dst[i] = src[i]; + } + for (; i < 3; ++i) { + dst[i] = ' '; + } + } +} + +static int +isSameLang(char const *l1, char const *l2) +{ + char d[3]; + int i; + setLang(d, l2); + for (i = 0; i < 3; ++i) { + char a = tolower(l1[i]); + char b = tolower(d[i]); + if (a < ' ') + a = ' '; + if (b < ' ') + b = ' '; + if (a != b) { + return 0; + } + } + return 1; +} + +static int +isSameDescriptor(FrameDataNode const *node, char const *dsc) +{ + size_t i; + if (node->dsc.enc == 1 && node->dsc.dim > 0) { + return 0; + } + for (i = 0; i < node->dsc.dim; ++i) { + if (!dsc || node->dsc.ptr.l[i] != dsc[i]) { + return 0; + } + } + return 1; +} + +static int +isSameDescriptorUcs2(FrameDataNode const *node, unsigned short const *dsc) +{ + size_t i; + if (node->dsc.enc != 1 && node->dsc.dim > 0) { + return 0; + } + for (i = 0; i < node->dsc.dim; ++i) { + if (!dsc || node->dsc.ptr.u[i] != dsc[i]) { + return 0; + } + } + return 1; +} + +static int +id3v2_add_ucs2(lame_t gfp, uint32_t frame_id, char const *lng, unsigned short const *desc, unsigned short const *text) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc != 0) { + FrameDataNode *node = findNode(&gfc->tag_spec, frame_id, 0); + char lang[4]; + setLang(lang, lng); + if (isMultiFrame(frame_id)) { + while (node) { + if (isSameLang(node->lng, lang)) { + if (isSameDescriptorUcs2(node, desc)) { + break; + } + } + node = findNode(&gfc->tag_spec, frame_id, node); + } + } + if (node == 0) { + node = lame_calloc(FrameDataNode, 1); + if (node == 0) { + return -254; /* memory problem */ + } + appendNode(&gfc->tag_spec, node); + } + node->fid = frame_id; + setLang(node->lng, lang); + node->dsc.dim = local_ucs2_strdup(&node->dsc.ptr.u, desc); + node->dsc.enc = 1; + node->txt.dim = local_ucs2_strdup(&node->txt.ptr.u, text); + node->txt.enc = 1; + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + return 0; + } + return -255; +} + +static int +id3v2_add_latin1(lame_t gfp, uint32_t frame_id, char const *lng, char const *desc, char const *text) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc != 0) { + FrameDataNode *node = findNode(&gfc->tag_spec, frame_id, 0); + char lang[4]; + setLang(lang, lng); + if (isMultiFrame(frame_id)) { + while (node) { + if (isSameLang(node->lng, lang)) { + if (isSameDescriptor(node, desc)) { + break; + } + } + node = findNode(&gfc->tag_spec, frame_id, node); + } + } + if (node == 0) { + node = lame_calloc(FrameDataNode, 1); + if (node == 0) { + return -254; /* memory problem */ + } + appendNode(&gfc->tag_spec, node); + } + node->fid = frame_id; + setLang(node->lng, lang); + node->dsc.dim = local_strdup(&node->dsc.ptr.l, desc); + node->dsc.enc = 0; + node->txt.dim = local_strdup(&node->txt.ptr.l, text); + node->txt.enc = 0; + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + return 0; + } + return -255; +} + +static char const* +id3v2_get_language(lame_t gfp) +{ + lame_internal_flags const* gfc = gfp ? gfp->internal_flags : 0; + if (gfc) return gfc->tag_spec.language; + return 0; +} + +static int +id3v2_add_ucs2_lng(lame_t gfp, uint32_t frame_id, unsigned short const *desc, unsigned short const *text) +{ + char const* lang = id3v2_get_language(gfp); + return id3v2_add_ucs2(gfp, frame_id, lang, desc, text); +} + +static int +id3v2_add_latin1_lng(lame_t gfp, uint32_t frame_id, char const *desc, char const *text) +{ + char const* lang = id3v2_get_language(gfp); + return id3v2_add_latin1(gfp, frame_id, lang, desc, text); +} + +static int +id3tag_set_userinfo_latin1(lame_t gfp, uint32_t id, char const *fieldvalue) +{ + char const separator = '='; + int rc = -7; + int a = local_char_pos(fieldvalue, separator); + if (a >= 0) { + char* dup = 0; + local_strdup(&dup, fieldvalue); + dup[a] = 0; + rc = id3v2_add_latin1_lng(gfp, id, dup, dup+a+1); + free(dup); + } + return rc; +} + +static int +id3tag_set_userinfo_ucs2(lame_t gfp, uint32_t id, unsigned short const *fieldvalue) +{ + unsigned short const separator = fromLatin1Char(fieldvalue,'='); + int rc = -7; + size_t b = local_ucs2_strlen(fieldvalue); + int a = local_ucs2_pos(fieldvalue, separator); + if (a >= 0) { + unsigned short* dsc = 0, *val = 0; + local_ucs2_substr(&dsc, fieldvalue, 0, a); + local_ucs2_substr(&val, fieldvalue, a+1, b); + rc = id3v2_add_ucs2_lng(gfp, id, dsc, val); + free(dsc); + free(val); + } + return rc; +} + +int +id3tag_set_textinfo_utf16(lame_t gfp, char const *id, unsigned short const *text) +{ + uint32_t const frame_id = toID3v2TagId(id); + if (frame_id == 0) { + return -1; + } + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + if (text == 0) { + return 0; + } + if (!hasUcs2ByteOrderMarker(text[0])) { + return -3; /* BOM missing */ + } + if (frame_id == ID_TXXX || frame_id == ID_WXXX || frame_id == ID_COMMENT) { + return id3tag_set_userinfo_ucs2(gfp, frame_id, text); + } + if (frame_id == ID_GENRE) { + return id3tag_set_genre_utf16(gfp, text); + } + if (frame_id == ID_PCST) { + return id3v2_add_ucs2_lng(gfp, frame_id, 0, text); + } + if (frame_id == ID_USER) { + return id3v2_add_ucs2_lng(gfp, frame_id, text, 0); + } + if (frame_id == ID_WFED) { + return id3v2_add_ucs2_lng(gfp, frame_id, text, 0); /* iTunes expects WFED to be a text frame */ + } + if (isFrameIdMatching(frame_id, FRAME_ID('T', 0, 0, 0)) + ||isFrameIdMatching(frame_id, FRAME_ID('W', 0, 0, 0))) { +#if 0 + if (isNumericString(frame_id)) { + return -2; /* must be Latin-1 encoded */ + } +#endif + return id3v2_add_ucs2_lng(gfp, frame_id, 0, text); + } + return -255; /* not supported by now */ +} + +extern int +id3tag_set_textinfo_ucs2(lame_t gfp, char const *id, unsigned short const *text); + +int +id3tag_set_textinfo_ucs2(lame_t gfp, char const *id, unsigned short const *text) +{ + return id3tag_set_textinfo_utf16(gfp, id, text); +} + +int +id3tag_set_textinfo_latin1(lame_t gfp, char const *id, char const *text) +{ + uint32_t const frame_id = toID3v2TagId(id); + if (frame_id == 0) { + return -1; + } + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + if (text == 0) { + return 0; + } + if (frame_id == ID_TXXX || frame_id == ID_WXXX || frame_id == ID_COMMENT) { + return id3tag_set_userinfo_latin1(gfp, frame_id, text); + } + if (frame_id == ID_GENRE) { + return id3tag_set_genre(gfp, text); + } + if (frame_id == ID_PCST) { + return id3v2_add_latin1_lng(gfp, frame_id, 0, text); + } + if (frame_id == ID_USER) { + return id3v2_add_latin1_lng(gfp, frame_id, text, 0); + } + if (frame_id == ID_WFED) { + return id3v2_add_latin1_lng(gfp, frame_id, text, 0); /* iTunes expects WFED to be a text frame */ + } + if (isFrameIdMatching(frame_id, FRAME_ID('T', 0, 0, 0)) + ||isFrameIdMatching(frame_id, FRAME_ID('W', 0, 0, 0))) { + return id3v2_add_latin1_lng(gfp, frame_id, 0, text); + } + return -255; /* not supported by now */ +} + + +int +id3tag_set_comment_latin1(lame_t gfp, char const *lang, char const *desc, char const *text) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + return id3v2_add_latin1(gfp, ID_COMMENT, lang, desc, text); +} + + +int +id3tag_set_comment_utf16(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + return id3v2_add_ucs2(gfp, ID_COMMENT, lang, desc, text); +} + +extern int +id3tag_set_comment_ucs2(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text); + + +int +id3tag_set_comment_ucs2(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + return id3tag_set_comment_utf16(gfp, lang, desc, text); +} + + +void +id3tag_set_title(lame_t gfp, const char *title) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc && title && *title) { + local_strdup(&gfc->tag_spec.title, title); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfp, ID_TITLE, title); + } +} + +void +id3tag_set_artist(lame_t gfp, const char *artist) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc && artist && *artist) { + local_strdup(&gfc->tag_spec.artist, artist); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfp, ID_ARTIST, artist); + } +} + +void +id3tag_set_album(lame_t gfp, const char *album) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc && album && *album) { + local_strdup(&gfc->tag_spec.album, album); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfp, ID_ALBUM, album); + } +} + +void +id3tag_set_year(lame_t gfp, const char *year) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc && year && *year) { + int num = atoi(year); + if (num < 0) { + num = 0; + } + /* limit a year to 4 digits so it fits in a version 1 tag */ + if (num > 9999) { + num = 9999; + } + if (num) { + gfc->tag_spec.year = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + copyV1ToV2(gfp, ID_YEAR, year); + } +} + +void +id3tag_set_comment(lame_t gfp, const char *comment) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + if (gfc && comment && *comment) { + local_strdup(&gfc->tag_spec.comment, comment); + gfc->tag_spec.flags |= CHANGED_FLAG; + { + uint32_t const flags = gfc->tag_spec.flags; + id3v2_add_latin1_lng(gfp, ID_COMMENT, "", comment); + gfc->tag_spec.flags = flags; + } + } +} + +int +id3tag_set_track(lame_t gfp, const char *track) +{ + char const *trackcount; + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + int ret = 0; + + if (gfc && track && *track) { + int num = atoi(track); + /* check for valid ID3v1 track number range */ + if (num < 1 || num > 255) { + num = 0; + ret = -1; /* track number out of ID3v1 range, ignored for ID3v1 */ + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + if (num) { + gfc->tag_spec.track_id3v1 = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + /* Look for the total track count after a "/", same restrictions */ + trackcount = strchr(track, '/'); + if (trackcount && *trackcount) { + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + copyV1ToV2(gfp, ID_TRACK, track); + } + return ret; +} + +/* would use real "strcasecmp" but it isn't portable */ +static int +local_strcasecmp(const char *s1, const char *s2) +{ + unsigned char c1; + unsigned char c2; + do { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + } while (c1 == c2); + return c1 - c2; +} + + +static +const char* nextUpperAlpha(const char* p, char x) +{ + char c; + for(c = toupper(*p); *p != 0; c = toupper(*++p)) { + if ('A' <= c && c <= 'Z') { + if (c != x) { + return p; + } + } + } + return p; +} + + +static int +sloppyCompared(const char* p, const char* q) +{ + char cp, cq; + p = nextUpperAlpha(p, 0); + q = nextUpperAlpha(q, 0); + cp = toupper(*p); + cq = toupper(*q); + while (cp == cq) { + if (cp == 0) { + return 1; + } + if (p[1] == '.') { /* some abbrevation */ + while (*q && *q++ != ' ') { + } + } + p = nextUpperAlpha(p, cp); + q = nextUpperAlpha(q, cq); + cp = toupper(*p); + cq = toupper(*q); + } + return 0; +} + + +static int +sloppySearchGenre(const char *genre) +{ + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (sloppyCompared(genre, genre_names[i])) { + return i; + } + } + return GENRE_NAME_COUNT; +} + + +static int +searchGenre(const char* genre) +{ + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (!local_strcasecmp(genre, genre_names[i])) { + return i; + } + } + return GENRE_NAME_COUNT; +} + + +int +id3tag_set_genre(lame_t gfp, const char *genre) +{ + lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0; + int ret = 0; + if (gfc && genre && *genre) { + int const num = lookupGenre(genre); + if (num == -1) return num; + gfc->tag_spec.flags |= CHANGED_FLAG; + if (num >= 0) { + gfc->tag_spec.genre_id3v1 = num; + genre = genre_names[num]; + } + else { + gfc->tag_spec.genre_id3v1 = GENRE_INDEX_OTHER; + gfc->tag_spec.flags |= ADD_V2_FLAG; + } + copyV1ToV2(gfp, ID_GENRE, genre); + } + return ret; +} + + +static size_t +sizeOfNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + n += 1; /* text encoding flag */ + switch (node->txt.enc) { + default: + case 0: + if (node->dsc.dim > 0) { + n += node->dsc.dim + 1; + } + n += node->txt.dim; + break; + case 1: + if (node->dsc.dim > 0) { + n += (node->dsc.dim+1) * 2; + } + n += node->txt.dim * 2; + break; + } + } + return n; +} + +static size_t +sizeOfCommentNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + n += 1; /* text encoding flag */ + n += 3; /* language */ + switch (node->dsc.enc) { + default: + case 0: + n += 1 + node->dsc.dim; + break; + case 1: + n += 2 + node->dsc.dim * 2; + break; + } + switch (node->txt.enc) { + default: + case 0: + n += node->txt.dim; + break; + case 1: + n += node->txt.dim * 2; + break; + } + } + return n; +} + +static size_t +sizeOfWxxxNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + if (node->dsc.dim > 0) { + n += 1; /* text encoding flag */ + switch (node->dsc.enc) { + default: + case 0: + n += 1 + node->dsc.dim; + break; + case 1: + n += 2 + node->dsc.dim * 2; + break; + } + } + if (node->txt.dim > 0) { + switch (node->txt.enc) { + default: + case 0: + n += node->txt.dim; + break; + case 1: + n += node->txt.dim - 1; /* UCS2 -> Latin1, skip BOM */ + break; + } + } + } + return n; +} + +static unsigned char * +writeChars(unsigned char *frame, char const *str, size_t n) +{ + while (n--) { + *frame++ = *str++; + } + return frame; +} + +static unsigned char * +writeUcs2s(unsigned char *frame, unsigned short const *str, size_t n) +{ + if (n > 0) { + unsigned short const bom = *str; + while (n--) { + unsigned short const c = toLittleEndian(bom, *str++); + *frame++ = 0x00ffu & c; + *frame++ = 0x00ffu & (c >> 8); + } + } + return frame; +} + +static unsigned char * +writeLoBytes(unsigned char *frame, unsigned short const *str, size_t n) +{ + if (n > 0) { + unsigned short const bom = *str; + if (hasUcs2ByteOrderMarker(bom)) { + str++; n--; /* skip BOM */ + } + while (n--) { + unsigned short const c = toLittleEndian(bom, *str++); + if (c < 0x0020u || 0x00ffu < c) { + *frame++ = 0x0020; /* blank */ + } + else { + *frame++ = c; + } + } + } + return frame; +} + +static unsigned char * +set_frame_comment(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfCommentNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (uint32_t) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* encoding descriptor byte */ + *frame++ = node->txt.enc == 1 ? 1 : 0; + /* 3 bytes language */ + *frame++ = node->lng[0]; + *frame++ = node->lng[1]; + *frame++ = node->lng[2]; + /* descriptor with zero byte(s) separator */ + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + /* comment full text */ + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeUcs2s(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_custom2(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (unsigned long) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = node->txt.enc == 1 ? 1 : 0; + if (node->dsc.dim > 0) { + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + } + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeUcs2s(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_wxxx(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfWxxxNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (unsigned long) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + if (node->dsc.dim > 0) { + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = node->dsc.enc == 1 ? 1 : 0; + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + } + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeLoBytes(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_apic(unsigned char *frame, const char *mimetype, const unsigned char *data, size_t size) +{ + /* ID3v2.3 standard APIC frame: + * <Header for 'Attached picture', ID: "APIC"> + * Text encoding $xx + * MIME type <text string> $00 + * Picture type $xx + * Description <text string according to encoding> $00 (00) + * Picture data <binary data> + */ + if (mimetype && data && size) { + frame = set_4_byte_value(frame, FRAME_ID('A', 'P', 'I', 'C')); + frame = set_4_byte_value(frame, (unsigned long) (4 + strlen(mimetype) + size)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = 0; + /* copy mime_type */ + while (*mimetype) { + *frame++ = *mimetype++; + } + *frame++ = 0; + /* set picture type to 0 */ + *frame++ = 0; + /* empty description field */ + *frame++ = 0; + /* copy the image data */ + while (size--) { + *frame++ = *data++; + } + } + return frame; +} + +int +id3tag_set_fieldvalue(lame_t gfp, const char *fieldvalue) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + if (fieldvalue && *fieldvalue) { + if (strlen(fieldvalue) < 5 || fieldvalue[4] != '=') { + return -1; + } + return id3tag_set_textinfo_latin1(gfp, fieldvalue, &fieldvalue[5]); + } + return 0; +} + +int +id3tag_set_fieldvalue_utf16(lame_t gfp, const unsigned short *fieldvalue) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + if (fieldvalue && *fieldvalue) { + size_t dx = hasUcs2ByteOrderMarker(fieldvalue[0]); + unsigned short const separator = fromLatin1Char(fieldvalue, '='); + char fid[5] = {0,0,0,0,0}; + uint32_t const frame_id = toID3v2TagId_ucs2(fieldvalue); + if (local_ucs2_strlen(fieldvalue) < (5+dx) || fieldvalue[4+dx] != separator) { + return -1; + } + fid[0] = (frame_id >> 24) & 0x0ff; + fid[1] = (frame_id >> 16) & 0x0ff; + fid[2] = (frame_id >> 8) & 0x0ff; + fid[3] = frame_id & 0x0ff; + if (frame_id != 0) { + unsigned short* txt = 0; + int rc; + local_ucs2_substr(&txt, fieldvalue, dx+5, local_ucs2_strlen(fieldvalue)); + rc = id3tag_set_textinfo_utf16(gfp, fid, txt); + free(txt); + return rc; + } + } + return -1; +} + +extern int +id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue); + +int +id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue) +{ + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + return id3tag_set_fieldvalue_utf16(gfp, fieldvalue); +} + +size_t +lame_get_id3v2_tag(lame_t gfp, unsigned char *buffer, size_t size) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + gfc = gfp->internal_flags; + if (test_tag_spec_flags(gfc, V1_ONLY_FLAG)) { + return 0; + } +#if 0 + debug_tag_spec_flags(gfc, "lame_get_id3v2_tag"); +#endif + { + int usev2 = test_tag_spec_flags(gfc, ADD_V2_FLAG | V2_ONLY_FLAG); + /* calculate length of four fields which may not fit in verion 1 tag */ + size_t title_length = gfc->tag_spec.title ? strlen(gfc->tag_spec.title) : 0; + size_t artist_length = gfc->tag_spec.artist ? strlen(gfc->tag_spec.artist) : 0; + size_t album_length = gfc->tag_spec.album ? strlen(gfc->tag_spec.album) : 0; + size_t comment_length = gfc->tag_spec.comment ? strlen(gfc->tag_spec.comment) : 0; + /* write tag if explicitly requested or if fields overflow */ + if ((title_length > 30) + || (artist_length > 30) + || (album_length > 30) + || (comment_length > 30) + || (gfc->tag_spec.track_id3v1 && (comment_length > 28))) { + usev2 = 1; + } + if (usev2) { + size_t tag_size; + unsigned char *p; + size_t adjusted_tag_size; + const char *albumart_mime = NULL; + static const char *mime_jpeg = "image/jpeg"; + static const char *mime_png = "image/png"; + static const char *mime_gif = "image/gif"; + + if (gfp->num_samples != MAX_U_32_NUM) { + id3v2AddAudioDuration(gfp, gfp->num_samples); + } + + /* calulate size of tag starting with 10-byte tag header */ + tag_size = 10; + if (gfc->tag_spec.albumart && gfc->tag_spec.albumart_size) { + switch (gfc->tag_spec.albumart_mimetype) { + case MIMETYPE_JPEG: + albumart_mime = mime_jpeg; + break; + case MIMETYPE_PNG: + albumart_mime = mime_png; + break; + case MIMETYPE_GIF: + albumart_mime = mime_gif; + break; + } + if (albumart_mime) { + tag_size += 10 + 4 + strlen(albumart_mime) + gfc->tag_spec.albumart_size; + } + } + { + id3tag_spec *tag = &gfc->tag_spec; + if (tag->v2_head != 0) { + FrameDataNode *node; + for (node = tag->v2_head; node != 0; node = node->nxt) { + if (node->fid == ID_COMMENT || node->fid == ID_USER) { + tag_size += sizeOfCommentNode(node); + } + else if (isFrameIdMatching(node->fid, FRAME_ID('W',0,0,0))) { + tag_size += sizeOfWxxxNode(node); + } + else { + tag_size += sizeOfNode(node); + } + } + } + } + if (test_tag_spec_flags(gfc, PAD_V2_FLAG)) { + /* add some bytes of padding */ + tag_size += gfc->tag_spec.padding_size; + } + if (size < tag_size) { + return tag_size; + } + if (buffer == 0) { + return 0; + } + p = buffer; + /* set tag header starting with file identifier */ + *p++ = 'I'; + *p++ = 'D'; + *p++ = '3'; + /* set version number word */ + *p++ = 3; + *p++ = 0; + /* clear flags byte */ + *p++ = 0; + /* calculate and set tag size = total size - header size */ + adjusted_tag_size = tag_size - 10; + /* encode adjusted size into four bytes where most significant + * bit is clear in each byte, for 28-bit total */ + *p++ = (unsigned char) ((adjusted_tag_size >> 21) & 0x7fu); + *p++ = (unsigned char) ((adjusted_tag_size >> 14) & 0x7fu); + *p++ = (unsigned char) ((adjusted_tag_size >> 7) & 0x7fu); + *p++ = (unsigned char) (adjusted_tag_size & 0x7fu); + + /* + * NOTE: The remainder of the tag (frames and padding, if any) + * are not "unsynchronized" to prevent false MPEG audio headers + * from appearing in the bitstream. Why? Well, most players + * and utilities know how to skip the ID3 version 2 tag by now + * even if they don't read its contents, and it's actually + * very unlikely that such a false "sync" pattern would occur + * in just the simple text frames added here. + */ + + /* set each frame in tag */ + { + id3tag_spec *tag = &gfc->tag_spec; + if (tag->v2_head != 0) { + FrameDataNode *node; + for (node = tag->v2_head; node != 0; node = node->nxt) { + if (node->fid == ID_COMMENT || node->fid == ID_USER) { + p = set_frame_comment(p, node); + } + else if (isFrameIdMatching(node->fid,FRAME_ID('W',0,0,0))) { + p = set_frame_wxxx(p, node); + } + else { + p = set_frame_custom2(p, node); + } + } + } + } + if (albumart_mime) { + p = set_frame_apic(p, albumart_mime, gfc->tag_spec.albumart, + gfc->tag_spec.albumart_size); + } + /* clear any padding bytes */ + memset(p, 0, tag_size - (p - buffer)); + return tag_size; + } + } + return 0; +} + +int +id3tag_write_v2(lame_t gfp) +{ + lame_internal_flags *gfc = 0; + + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + gfc = gfp->internal_flags; +#if 0 + debug_tag_spec_flags(gfc, "write v2"); +#endif + if (test_tag_spec_flags(gfc, V1_ONLY_FLAG)) { + return 0; + } + if (test_tag_spec_flags(gfc, CHANGED_FLAG)) { + unsigned char *tag = 0; + size_t tag_size, n; + + n = lame_get_id3v2_tag(gfp, 0, 0); + tag = lame_calloc(unsigned char, n); + if (tag == 0) { + return -1; + } + tag_size = lame_get_id3v2_tag(gfp, tag, n); + if (tag_size > n) { + free(tag); + return -1; + } + else { + size_t i; + /* write tag directly into bitstream at current position */ + for (i = 0; i < tag_size; ++i) { + add_dummy_byte(gfc, tag[i], 1); + } + } + free(tag); + return (int) tag_size; /* ok, tag should not exceed 2GB */ + } + return 0; +} + +static unsigned char * +set_text_field(unsigned char *field, const char *text, size_t size, int pad) +{ + while (size--) { + if (text && *text) { + *field++ = *text++; + } + else { + *field++ = pad; + } + } + return field; +} + +size_t +lame_get_id3v1_tag(lame_t gfp, unsigned char *buffer, size_t size) +{ + size_t const tag_size = 128; + lame_internal_flags *gfc; + + if (gfp == 0) { + return 0; + } + if (size < tag_size) { + return tag_size; + } + gfc = gfp->internal_flags; + if (gfc == 0) { + return 0; + } + if (buffer == 0) { + return 0; + } + if (test_tag_spec_flags(gfc, V2_ONLY_FLAG)) { + return 0; + } + if (test_tag_spec_flags(gfc, CHANGED_FLAG)) { + unsigned char *p = buffer; + int pad = test_tag_spec_flags(gfc, SPACE_V1_FLAG) ? ' ' : 0; + char year[5]; + + /* set tag identifier */ + *p++ = 'T'; + *p++ = 'A'; + *p++ = 'G'; + /* set each field in tag */ + p = set_text_field(p, gfc->tag_spec.title, 30, pad); + p = set_text_field(p, gfc->tag_spec.artist, 30, pad); + p = set_text_field(p, gfc->tag_spec.album, 30, pad); + sprintf(year, "%d", gfc->tag_spec.year); + p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad); + /* limit comment field to 28 bytes if a track is specified */ + p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track_id3v1 ? 28 : 30, pad); + if (gfc->tag_spec.track_id3v1) { + /* clear the next byte to indicate a version 1.1 tag */ + *p++ = 0; + *p++ = gfc->tag_spec.track_id3v1; + } + *p++ = gfc->tag_spec.genre_id3v1; + return tag_size; + } + return 0; +} + +int +id3tag_write_v1(lame_t gfp) +{ + lame_internal_flags* gfc = 0; + size_t i, n, m; + unsigned char tag[128]; + + if (is_lame_internal_flags_null(gfp)) { + return 0; + } + gfc = gfp->internal_flags; + + m = sizeof(tag); + n = lame_get_id3v1_tag(gfp, tag, m); + if (n > m) { + return 0; + } + /* write tag directly into bitstream at current position */ + for (i = 0; i < n; ++i) { + add_dummy_byte(gfc, tag[i], 1); + } + return (int) n; /* ok, tag has fixed size of 128 bytes, well below 2GB */ +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.h new file mode 100644 index 00000000..9cd9ad9b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/id3tag.h @@ -0,0 +1,64 @@ + +#ifndef LAME_ID3_H +#define LAME_ID3_H + + +#define CHANGED_FLAG (1U << 0) +#define ADD_V2_FLAG (1U << 1) +#define V1_ONLY_FLAG (1U << 2) +#define V2_ONLY_FLAG (1U << 3) +#define SPACE_V1_FLAG (1U << 4) +#define PAD_V2_FLAG (1U << 5) + +enum { + MIMETYPE_NONE = 0, + MIMETYPE_JPEG, + MIMETYPE_PNG, + MIMETYPE_GIF +}; + +typedef struct FrameDataNode { + struct FrameDataNode *nxt; + uint32_t fid; /* Frame Identifier */ + char lng[4]; /* 3-character language descriptor */ + struct { + union { + char *l; /* ptr to Latin-1 chars */ + unsigned short *u; /* ptr to UCS-2 text */ + unsigned char *b; /* ptr to raw bytes */ + } ptr; + size_t dim; + int enc; /* 0:Latin-1, 1:UCS-2, 2:RAW */ + } dsc , txt; +} FrameDataNode; + + +typedef struct id3tag_spec { + /* private data members */ + unsigned int flags; + int year; + char *title; + char *artist; + char *album; + char *comment; + int track_id3v1; + int genre_id3v1; + unsigned char *albumart; + unsigned int albumart_size; + unsigned int padding_size; + int albumart_mimetype; + char language[4]; /* the language of the frame's content, according to ISO-639-2 */ + FrameDataNode *v2_head, *v2_tail; +} id3tag_spec; + + +/* write tag into stream at current position */ +extern int id3tag_write_v2(lame_global_flags * gfp); +extern int id3tag_write_v1(lame_global_flags * gfp); +/* + * NOTE: A version 2 tag will NOT be added unless one of the text fields won't + * fit in a version 1 tag (e.g. the title string is longer than 30 characters), + * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used. + */ + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/l3side.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/l3side.h new file mode 100644 index 00000000..f65bbedd --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/l3side.h @@ -0,0 +1,95 @@ +/* + * Layer 3 side include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_L3SIDE_H +#define LAME_L3SIDE_H + +/* max scalefactor band, max(SBMAX_l, SBMAX_s*3, (SBMAX_s-3)*3+8) */ +#define SFBMAX (SBMAX_s*3) + +/* Layer III side information. */ +typedef struct { + int l[1 + SBMAX_l]; + int s[1 + SBMAX_s]; + int psfb21[1 + PSFB21]; + int psfb12[1 + PSFB12]; +} scalefac_struct; + + +typedef struct { + FLOAT l[SBMAX_l]; + FLOAT s[SBMAX_s][3]; +} III_psy_xmin; + +typedef struct { + III_psy_xmin thm; + III_psy_xmin en; +} III_psy_ratio; + +typedef struct { + FLOAT xr[576]; + int l3_enc[576]; + int scalefac[SFBMAX]; + FLOAT xrpow_max; + + int part2_3_length; + int big_values; + int count1; + int global_gain; + int scalefac_compress; + int block_type; + int mixed_block_flag; + int table_select[3]; + int subblock_gain[3 + 1]; + int region0_count; + int region1_count; + int preflag; + int scalefac_scale; + int count1table_select; + + int part2_length; + int sfb_lmax; + int sfb_smin; + int psy_lmax; + int sfbmax; + int psymax; + int sfbdivide; + int width[SFBMAX]; + int window[SFBMAX]; + int count1bits; + /* added for LSF */ + const int *sfb_partition_table; + int slen[4]; + + int max_nonzero_coeff; + char energy_above_cutoff[SFBMAX]; +} gr_info; + +typedef struct { + gr_info tt[2][2]; + int main_data_begin; + int private_bits; + int resvDrain_pre; + int resvDrain_post; + int scfsi[2][4]; +} III_side_info_t; + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame-analysis.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame-analysis.h new file mode 100644 index 00000000..5055a603 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame-analysis.h @@ -0,0 +1,96 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_GTKANAL_H +#define LAME_GTKANAL_H + + +#define READ_AHEAD 40 /* number of frames to read ahead */ +#define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this + we have to stop */ +#define NUMBACK 6 /* number of frames we can back up */ +#define NUMPINFO (NUMBACK+READ_AHEAD+1) + + + +struct plotting_data { + int frameNum; /* current frame number */ + int frameNum123; + int num_samples; /* number of pcm samples read for this frame */ + double frametime; /* starting time of frame, in seconds */ + double pcmdata[2][1600]; + double pcmdata2[2][1152 + 1152 - DECDELAY]; + double xr[2][2][576]; + double mpg123xr[2][2][576]; + double ms_ratio[2]; + double ms_ener_ratio[2]; + + /* L,R, M and S values */ + double energy_save[4][BLKSIZE]; /* psymodel is one ahead */ + double energy[2][4][BLKSIZE]; + double pe[2][4]; + double thr[2][4][SBMAX_l]; + double en[2][4][SBMAX_l]; + double thr_s[2][4][3 * SBMAX_s]; + double en_s[2][4][3 * SBMAX_s]; + double ers_save[4]; /* psymodel is one ahead */ + double ers[2][4]; + + double sfb[2][2][SBMAX_l]; + double sfb_s[2][2][3 * SBMAX_s]; + double LAMEsfb[2][2][SBMAX_l]; + double LAMEsfb_s[2][2][3 * SBMAX_s]; + + int LAMEqss[2][2]; + int qss[2][2]; + int big_values[2][2]; + int sub_gain[2][2][3]; + + double xfsf[2][2][SBMAX_l]; + double xfsf_s[2][2][3 * SBMAX_s]; + + int over[2][2]; + double tot_noise[2][2]; + double max_noise[2][2]; + double over_noise[2][2]; + int over_SSD[2][2]; + int blocktype[2][2]; + int scalefac_scale[2][2]; + int preflag[2][2]; + int mpg123blocktype[2][2]; + int mixed[2][2]; + int mainbits[2][2]; + int sfbits[2][2]; + int LAMEmainbits[2][2]; + int LAMEsfbits[2][2]; + int framesize, stereo, js, ms_stereo, i_stereo, emph, bitrate, sampfreq, maindata; + int crc, padding; + int scfsi[2], mean_bits, resvsize; + int totbits; +}; +#ifndef plotting_data_defined +#define plotting_data_defined +typedef struct plotting_data plotting_data; +#endif +#if 0 +extern plotting_data *pinfo; +#endif +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.c new file mode 100644 index 00000000..cb82225a --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.c @@ -0,0 +1,2665 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2000-2005 Takehiro Tominaga + * Copyright (c) 2000-2017 Robert Hegemann + * Copyright (c) 2000-2005 Gabriel Bouvigne + * Copyright (c) 2000-2004 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame.c,v 1.377 2017/09/26 12:14:02 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" + +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" +#include "gain_analysis.h" +#include "bitstream.h" +#include "quantize_pvt.h" +#include "set_get.h" +#include "quantize.h" +#include "psymodel.h" +#include "version.h" +#include "VbrTag.h" +#include "tables.h" + + +#if defined(__FreeBSD__) && !defined(__alpha__) +#include <floatingpoint.h> +#endif +#ifdef __riscos__ +#include "asmstuff.h" +#endif + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + + +#define LAME_DEFAULT_QUALITY 3 + + + +int +is_lame_global_flags_valid(const lame_global_flags * gfp) +{ + if (gfp == NULL) + return 0; + if (gfp->class_id != LAME_ID) + return 0; + return 1; +} + + +int +is_lame_internal_flags_valid(const lame_internal_flags * gfc) +{ + if (gfc == NULL) + return 0; + if (gfc->class_id != LAME_ID) + return 0; + if (gfc->lame_init_params_successful <=0) + return 0; + return 1; +} + + + +static FLOAT +filter_coef(FLOAT x) +{ + if (x > 1.0) + return 0.0; + if (x <= 0.0) + return 1.0; + + return cos(PI / 2 * x); +} + +static void +lame_init_params_ppflt(lame_internal_flags * gfc) +{ + SessionConfig_t *const cfg = &gfc->cfg; + + /***************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /***************************************************************/ + + int band, maxband, minband; + FLOAT freq; + int lowpass_band = 32; + int highpass_band = -1; + + if (cfg->lowpass1 > 0) { + minband = 999; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + /* this band and above will be zeroed: */ + if (freq >= cfg->lowpass2) { + lowpass_band = Min(lowpass_band, band); + } + if (cfg->lowpass1 < freq && freq < cfg->lowpass2) { + minband = Min(minband, band); + } + } + + /* compute the *actual* transition band implemented by + * the polyphase filter */ + if (minband == 999) { + cfg->lowpass1 = (lowpass_band - .75) / 31.0; + } + else { + cfg->lowpass1 = (minband - .75) / 31.0; + } + cfg->lowpass2 = lowpass_band / 31.0; + } + + /* make sure highpass filter is within 90% of what the effective + * highpass frequency will be */ + if (cfg->highpass2 > 0) { + if (cfg->highpass2 < .9 * (.75 / 31.0)) { + cfg->highpass1 = 0; + cfg->highpass2 = 0; + MSGF(gfc, "Warning: highpass filter disabled. " "highpass frequency too small\n"); + } + } + + if (cfg->highpass2 > 0) { + maxband = -1; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + /* this band and below will be zereod */ + if (freq <= cfg->highpass1) { + highpass_band = Max(highpass_band, band); + } + if (cfg->highpass1 < freq && freq < cfg->highpass2) { + maxband = Max(maxband, band); + } + } + /* compute the *actual* transition band implemented by + * the polyphase filter */ + cfg->highpass1 = highpass_band / 31.0; + if (maxband == -1) { + cfg->highpass2 = (highpass_band + .75) / 31.0; + } + else { + cfg->highpass2 = (maxband + .75) / 31.0; + } + } + + for (band = 0; band < 32; band++) { + FLOAT fc1, fc2; + freq = band / 31.0f; + if (cfg->highpass2 > cfg->highpass1) { + fc1 = filter_coef((cfg->highpass2 - freq) / (cfg->highpass2 - cfg->highpass1 + 1e-20)); + } + else { + fc1 = 1.0f; + } + if (cfg->lowpass2 > cfg->lowpass1) { + fc2 = filter_coef((freq - cfg->lowpass1) / (cfg->lowpass2 - cfg->lowpass1 + 1e-20)); + } + else { + fc2 = 1.0f; + } + gfc->sv_enc.amp_filter[band] = fc1 * fc2; + } +} + + +static void +optimum_bandwidth(double *const lowerlimit, double *const upperlimit, const unsigned bitrate) +{ +/* + * Input: + * bitrate total bitrate in kbps + * + * Output: + * lowerlimit: best lowpass frequency limit for input filter in Hz + * upperlimit: best highpass frequency limit for input filter in Hz + */ + int table_index; + + typedef struct { + int bitrate; /* only indicative value */ + int lowpass; + } band_pass_t; + + const band_pass_t freq_map[] = { + {8, 2000}, + {16, 3700}, + {24, 3900}, + {32, 5500}, + {40, 7000}, + {48, 7500}, + {56, 10000}, + {64, 11000}, + {80, 13500}, + {96, 15100}, + {112, 15600}, + {128, 17000}, + {160, 17500}, + {192, 18600}, + {224, 19400}, + {256, 19700}, + {320, 20500} + }; + + + table_index = nearestBitrateFullIndex(bitrate); + + (void) freq_map[table_index].bitrate; + *lowerlimit = freq_map[table_index].lowpass; + + +/* + * Now we try to choose a good high pass filtering frequency. + * This value is currently not used. + * For fu < 16 kHz: sqrt(fu*fl) = 560 Hz + * For fu = 18 kHz: no high pass filtering + * This gives: + * + * 2 kHz => 160 Hz + * 3 kHz => 107 Hz + * 4 kHz => 80 Hz + * 8 kHz => 40 Hz + * 16 kHz => 20 Hz + * 17 kHz => 10 Hz + * 18 kHz => 0 Hz + * + * These are ad hoc values and these can be optimized if a high pass is available. + */ +/* if (f_low <= 16000) + f_high = 16000. * 20. / f_low; + else if (f_low <= 18000) + f_high = 180. - 0.01 * f_low; + else + f_high = 0.;*/ + + /* + * When we sometimes have a good highpass filter, we can add the highpass + * frequency to the lowpass frequency + */ + + /*if (upperlimit != NULL) + *upperlimit = f_high;*/ + (void) upperlimit; +} + + +static int +optimum_samplefreq(int lowpassfreq, int input_samplefreq) +{ +/* + * Rules: + * - if possible, sfb21 should NOT be used + * + */ + int suggested_samplefreq = 44100; + + if (input_samplefreq >= 48000) + suggested_samplefreq = 48000; + else if (input_samplefreq >= 44100) + suggested_samplefreq = 44100; + else if (input_samplefreq >= 32000) + suggested_samplefreq = 32000; + else if (input_samplefreq >= 24000) + suggested_samplefreq = 24000; + else if (input_samplefreq >= 22050) + suggested_samplefreq = 22050; + else if (input_samplefreq >= 16000) + suggested_samplefreq = 16000; + else if (input_samplefreq >= 12000) + suggested_samplefreq = 12000; + else if (input_samplefreq >= 11025) + suggested_samplefreq = 11025; + else if (input_samplefreq >= 8000) + suggested_samplefreq = 8000; + + if (lowpassfreq == -1) + return suggested_samplefreq; + + if (lowpassfreq <= 15960) + suggested_samplefreq = 44100; + if (lowpassfreq <= 15250) + suggested_samplefreq = 32000; + if (lowpassfreq <= 11220) + suggested_samplefreq = 24000; + if (lowpassfreq <= 9970) + suggested_samplefreq = 22050; + if (lowpassfreq <= 7230) + suggested_samplefreq = 16000; + if (lowpassfreq <= 5420) + suggested_samplefreq = 12000; + if (lowpassfreq <= 4510) + suggested_samplefreq = 11025; + if (lowpassfreq <= 3970) + suggested_samplefreq = 8000; + + if (input_samplefreq < suggested_samplefreq) { + /* choose a valid MPEG sample frequency above the input sample frequency + to avoid SFB21/12 bitrate bloat + rh 061115 + */ + if (input_samplefreq > 44100) { + return 48000; + } + if (input_samplefreq > 32000) { + return 44100; + } + if (input_samplefreq > 24000) { + return 32000; + } + if (input_samplefreq > 22050) { + return 24000; + } + if (input_samplefreq > 16000) { + return 22050; + } + if (input_samplefreq > 12000) { + return 16000; + } + if (input_samplefreq > 11025) { + return 12000; + } + if (input_samplefreq > 8000) { + return 11025; + } + return 8000; + } + return suggested_samplefreq; +} + + + + + +/* set internal feature flags. USER should not access these since + * some combinations will produce strange results */ +static void +lame_init_qval(lame_global_flags * gfp) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + SessionConfig_t *const cfg = &gfc->cfg; + + switch (gfp->quality) { + default: + case 9: /* no psymodel, no noise shaping */ + cfg->noise_shaping = 0; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 8: + gfp->quality = 7; + /*lint --fallthrough */ + case 7: /* use psymodel (for short block and m/s switching), but no noise shapping */ + cfg->noise_shaping = 0; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + if (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) { + cfg->full_outer_loop = -1; + } + break; + + case 6: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 5: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 4: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 3: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 1; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 2: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 1; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; /* inner loop */ + cfg->full_outer_loop = 0; + break; + + case 1: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 2; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 0: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 2; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; /*type 2 disabled because of it slowness, + in favor of full outer loop search */ + cfg->full_outer_loop = 1; + break; + } + +} + + + +static double +linear_int(double a, double b, double m) +{ + return a + m * (b - a); +} + + + +/******************************************************************** + * initialize internal params based on data in gf + * (globalflags struct filled in by calling program) + * + * OUTLINE: + * + * We first have some complex code to determine bitrate, + * output samplerate and mode. It is complicated by the fact + * that we allow the user to set some or all of these parameters, + * and need to determine best possible values for the rest of them: + * + * 1. set some CPU related flags + * 2. check if we are mono->mono, stereo->mono or stereo->stereo + * 3. compute bitrate and output samplerate: + * user may have set compression ratio + * user may have set a bitrate + * user may have set a output samplerate + * 4. set some options which depend on output samplerate + * 5. compute the actual compression ratio + * 6. set mode based on compression ratio + * + * The remaining code is much simpler - it just sets options + * based on the mode & compression ratio: + * + * set allow_diff_short based on mode + * select lowpass filter based on compression ratio & mode + * set the bitrate index, and min/max bitrates for VBR modes + * disable VBR tag if it is not appropriate + * initialize the bitstream + * initialize scalefac_band data + * set sideinfo_len (based on channels, CRC, out_samplerate) + * write an id3v2 tag into the bitstream + * write VBR tag into the bitstream + * set mpeg1/2 flag + * estimate the number of frames (based on a lot of data) + * + * now we set more flags: + * nspsytune: + * see code + * VBR modes + * see code + * CBR/ABR + * see code + * + * Finally, we set the algorithm flags based on the gfp->quality value + * lame_init_qval(gfp); + * + ********************************************************************/ +int +lame_init_params(lame_global_flags * gfp) +{ + + int i; + int j; + lame_internal_flags *gfc; + SessionConfig_t *cfg; + + if (!is_lame_global_flags_valid(gfp)) + return -1; + + gfc = gfp->internal_flags; + if (gfc == 0) + return -1; + + if (is_lame_internal_flags_valid(gfc)) + return -1; /* already initialized */ + + /* start updating lame internal flags */ + gfc->class_id = LAME_ID; + gfc->lame_init_params_successful = 0; /* will be set to one, when we get through until the end */ + + if (gfp->samplerate_in < 1) + return -1; /* input sample rate makes no sense */ + if (gfp->num_channels < 1 || 2 < gfp->num_channels) + return -1; /* number of input channels makes no sense */ + if (gfp->samplerate_out != 0) { + int v=0; + if (SmpFrqIndex(gfp->samplerate_out, &v) < 0) + return -1; /* output sample rate makes no sense */ + } + + cfg = &gfc->cfg; + + cfg->enforce_min_bitrate = gfp->VBR_hard_min; + cfg->analysis = gfp->analysis; + if (cfg->analysis) + gfp->write_lame_tag = 0; + + /* some file options not allowed if output is: not specified or stdout */ + if (gfc->pinfo != NULL) + gfp->write_lame_tag = 0; /* disable Xing VBR tag */ + + /* report functions */ + gfc->report_msg = gfp->report.msgf; + gfc->report_dbg = gfp->report.debugf; + gfc->report_err = gfp->report.errorf; + + if (gfp->asm_optimizations.amd3dnow) + gfc->CPU_features.AMD_3DNow = has_3DNow(); + else + gfc->CPU_features.AMD_3DNow = 0; + + if (gfp->asm_optimizations.mmx) + gfc->CPU_features.MMX = has_MMX(); + else + gfc->CPU_features.MMX = 0; + + if (gfp->asm_optimizations.sse) { + gfc->CPU_features.SSE = has_SSE(); + gfc->CPU_features.SSE2 = has_SSE2(); + } + else { + gfc->CPU_features.SSE = 0; + gfc->CPU_features.SSE2 = 0; + } + + + cfg->vbr = gfp->VBR; + cfg->error_protection = gfp->error_protection; + cfg->copyright = gfp->copyright; + cfg->original = gfp->original; + cfg->extension = gfp->extension; + cfg->emphasis = gfp->emphasis; + + cfg->channels_in = gfp->num_channels; + if (cfg->channels_in == 1) + gfp->mode = MONO; + cfg->channels_out = (gfp->mode == MONO) ? 1 : 2; + if (gfp->mode != JOINT_STEREO) + gfp->force_ms = 0; /* forced mid/side stereo for j-stereo only */ + cfg->force_ms = gfp->force_ms; + + if (cfg->vbr == vbr_off && gfp->VBR_mean_bitrate_kbps != 128 && gfp->brate == 0) + gfp->brate = gfp->VBR_mean_bitrate_kbps; + + switch (cfg->vbr) { + case vbr_off: + case vbr_mtrh: + case vbr_mt: + /* these modes can handle free format condition */ + break; + default: + gfp->free_format = 0; /* mode can't be mixed with free format */ + break; + } + + cfg->free_format = gfp->free_format; + + if (cfg->vbr == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use 11.025 */ + if (EQ(gfp->compression_ratio, 0)) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + /* find bitrate if user specify a compression ratio */ + if (cfg->vbr == vbr_off && gfp->compression_ratio > 0) { + + if (gfp->samplerate_out == 0) + gfp->samplerate_out = map2MP3Frequency((int) (0.97 * gfp->samplerate_in)); /* round up with a margin of 3% */ + + /* choose a bitrate for the output samplerate which achieves + * specified compression ratio + */ + gfp->brate = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->compression_ratio); + + /* we need the version for the bitrate table look up */ + cfg->samplerate_index = SmpFrqIndex(gfp->samplerate_out, &cfg->version); + assert(cfg->samplerate_index >=0); + + if (!cfg->free_format) /* for non Free Format find the nearest allowed bitrate */ + gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, gfp->samplerate_out); + } + if (gfp->samplerate_out) { + if (gfp->samplerate_out < 16000) { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 64); + } + else if (gfp->samplerate_out < 32000) { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 160); + } + else { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 32); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 320); + } + } + /* WORK IN PROGRESS */ + /* mapping VBR scale to internal VBR quality settings */ + if (gfp->samplerate_out == 0 && (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh)) { + float const qval = gfp->VBR_q + gfp->VBR_q_frac; + struct q_map { int sr_a; float qa, qb, ta, tb; int lp; }; + struct q_map const m[9] + = { {48000, 0.0,6.5, 0.0,6.5, 23700} + , {44100, 0.0,6.5, 0.0,6.5, 21780} + , {32000, 6.5,8.0, 5.2,6.5, 15800} + , {24000, 8.0,8.5, 5.2,6.0, 11850} + , {22050, 8.5,9.01, 5.2,6.5, 10892} + , {16000, 9.01,9.4, 4.9,6.5, 7903} + , {12000, 9.4,9.6, 4.5,6.0, 5928} + , {11025, 9.6,9.9, 5.1,6.5, 5446} + , { 8000, 9.9,10., 4.9,6.5, 3952} + }; + for (i = 2; i < 9; ++i) { + if (gfp->samplerate_in == m[i].sr_a) { + if (qval < m[i].qa) { + double d = qval / m[i].qa; + d = d * m[i].ta; + gfp->VBR_q = (int)d; + gfp->VBR_q_frac = d - gfp->VBR_q; + } + } + if (gfp->samplerate_in >= m[i].sr_a) { + if (m[i].qa <= qval && qval < m[i].qb) { + float const q_ = m[i].qb-m[i].qa; + float const t_ = m[i].tb-m[i].ta; + double d = m[i].ta + t_ * (qval-m[i].qa) / q_; + gfp->VBR_q = (int)d; + gfp->VBR_q_frac = d - gfp->VBR_q; + gfp->samplerate_out = m[i].sr_a; + if (gfp->lowpassfreq == 0) { + gfp->lowpassfreq = -1; + } + break; + } + } + } + } + + /****************************************************************/ + /* if a filter has not been enabled, see if we should add one: */ + /****************************************************************/ + if (gfp->lowpassfreq == 0) { + double lowpass = 16000; + double highpass; + + switch (cfg->vbr) { + case vbr_off:{ + optimum_bandwidth(&lowpass, &highpass, gfp->brate); + break; + } + case vbr_abr:{ + optimum_bandwidth(&lowpass, &highpass, gfp->VBR_mean_bitrate_kbps); + break; + } + case vbr_rh:{ + int const x[11] = { + 19500, 19000, 18600, 18000, 17500, 16000, 15600, 14900, 12500, 10000, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 19500; + } + break; + } + case vbr_mtrh: + case vbr_mt:{ + int const x[11] = { + 24000, 19500, 18500, 18000, 17500, 17000, 16500, 15600, 15200, 7230, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 21500; + } + break; + } + default:{ + int const x[11] = { + 19500, 19000, 18500, 18000, 17500, 16500, 15500, 14500, 12500, 9500, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 19500; + } + } + } + + if (gfp->mode == MONO && (cfg->vbr == vbr_off || cfg->vbr == vbr_abr)) + lowpass *= 1.5; + + gfp->lowpassfreq = lowpass; + } + + if (gfp->samplerate_out == 0) { + if (2 * gfp->lowpassfreq > gfp->samplerate_in) { + gfp->lowpassfreq = gfp->samplerate_in / 2; + } + gfp->samplerate_out = optimum_samplefreq((int) gfp->lowpassfreq, gfp->samplerate_in); + } + if (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) { + gfp->lowpassfreq = Min(24000, gfp->lowpassfreq); + } + else { + gfp->lowpassfreq = Min(20500, gfp->lowpassfreq); + } + gfp->lowpassfreq = Min(gfp->samplerate_out / 2, gfp->lowpassfreq); + + if (cfg->vbr == vbr_off) { + gfp->compression_ratio = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->brate); + } + if (cfg->vbr == vbr_abr) { + gfp->compression_ratio = + gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps); + } + + cfg->disable_reservoir = gfp->disable_reservoir; + cfg->lowpassfreq = gfp->lowpassfreq; + cfg->highpassfreq = gfp->highpassfreq; + cfg->samplerate_in = gfp->samplerate_in; + cfg->samplerate_out = gfp->samplerate_out; + cfg->mode_gr = cfg->samplerate_out <= 24000 ? 1 : 2; /* Number of granules per frame */ + + + /* + * sample freq bitrate compression ratio + * [kHz] [kbps/channel] for 16 bit input + * 44.1 56 12.6 + * 44.1 64 11.025 + * 44.1 80 8.82 + * 22.05 24 14.7 + * 22.05 32 11.025 + * 22.05 40 8.82 + * 16 16 16.0 + * 16 24 10.667 + * + */ + /* + * For VBR, take a guess at the compression_ratio. + * For example: + * + * VBR_q compression like + * - 4.4 320 kbps/44 kHz + * 0...1 5.5 256 kbps/44 kHz + * 2 7.3 192 kbps/44 kHz + * 4 8.8 160 kbps/44 kHz + * 6 11 128 kbps/44 kHz + * 9 14.7 96 kbps + * + * for lower bitrates, downsample with --resample + */ + + switch (cfg->vbr) { + case vbr_mt: + case vbr_rh: + case vbr_mtrh: + { + /*numbers are a bit strange, but they determine the lowpass value */ + FLOAT const cmp[] = { 5.7, 6.5, 7.3, 8.2, 10, 11.9, 13, 14, 15, 16.5 }; + gfp->compression_ratio = cmp[gfp->VBR_q]; + } + break; + case vbr_abr: + gfp->compression_ratio = + cfg->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps); + break; + default: + gfp->compression_ratio = cfg->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->brate); + break; + } + + + /* mode = -1 (not set by user) or + * mode = MONO (because of only 1 input channel). + * If mode has not been set, then select J-STEREO + */ + if (gfp->mode == NOT_SET) { + gfp->mode = JOINT_STEREO; + } + + cfg->mode = gfp->mode; + + + /* apply user driven high pass filter */ + if (cfg->highpassfreq > 0) { + cfg->highpass1 = 2. * cfg->highpassfreq; + + if (gfp->highpasswidth >= 0) + cfg->highpass2 = 2. * (cfg->highpassfreq + gfp->highpasswidth); + else /* 0% above on default */ + cfg->highpass2 = (1 + 0.00) * 2. * cfg->highpassfreq; + + cfg->highpass1 /= cfg->samplerate_out; + cfg->highpass2 /= cfg->samplerate_out; + } + else { + cfg->highpass1 = 0; + cfg->highpass2 = 0; + } + /* apply user driven low pass filter */ + cfg->lowpass1 = 0; + cfg->lowpass2 = 0; + if (cfg->lowpassfreq > 0 && cfg->lowpassfreq < (cfg->samplerate_out / 2) ) { + cfg->lowpass2 = 2. * cfg->lowpassfreq; + if (gfp->lowpasswidth >= 0) { + cfg->lowpass1 = 2. * (cfg->lowpassfreq - gfp->lowpasswidth); + if (cfg->lowpass1 < 0) /* has to be >= 0 */ + cfg->lowpass1 = 0; + } + else { /* 0% below on default */ + cfg->lowpass1 = (1 - 0.00) * 2. * cfg->lowpassfreq; + } + cfg->lowpass1 /= cfg->samplerate_out; + cfg->lowpass2 /= cfg->samplerate_out; + } + + + + + /**********************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /**********************************************************************/ + lame_init_params_ppflt(gfc); + + + /******************************************************* + * samplerate and bitrate index + *******************************************************/ + cfg->samplerate_index = SmpFrqIndex(cfg->samplerate_out, &cfg->version); + assert(cfg->samplerate_index >= 0); + + if (cfg->vbr == vbr_off) { + if (cfg->free_format) { + gfc->ov_enc.bitrate_index = 0; + } + else { + gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, cfg->samplerate_out); + gfc->ov_enc.bitrate_index = BitrateIndex(gfp->brate, cfg->version, cfg->samplerate_out); + if (gfc->ov_enc.bitrate_index <= 0) { + /* This never happens, because of preceding FindNearestBitrate! + * But, set a sane value, just in case + */ + assert(0); + gfc->ov_enc.bitrate_index = 8; + } + } + } + else { + gfc->ov_enc.bitrate_index = 1; + } + + init_bit_stream_w(gfc); + + j = cfg->samplerate_index + (3 * cfg->version) + 6 * (cfg->samplerate_out < 16000); + for (i = 0; i < SBMAX_l + 1; i++) + gfc->scalefac_band.l[i] = sfBandIndex[j].l[i]; + + for (i = 0; i < PSFB21 + 1; i++) { + int const size = (gfc->scalefac_band.l[22] - gfc->scalefac_band.l[21]) / PSFB21; + int const start = gfc->scalefac_band.l[21] + i * size; + gfc->scalefac_band.psfb21[i] = start; + } + gfc->scalefac_band.psfb21[PSFB21] = 576; + + for (i = 0; i < SBMAX_s + 1; i++) + gfc->scalefac_band.s[i] = sfBandIndex[j].s[i]; + + for (i = 0; i < PSFB12 + 1; i++) { + int const size = (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]) / PSFB12; + int const start = gfc->scalefac_band.s[12] + i * size; + gfc->scalefac_band.psfb12[i] = start; + } + gfc->scalefac_band.psfb12[PSFB12] = 192; + + /* determine the mean bitrate for main data */ + if (cfg->mode_gr == 2) /* MPEG 1 */ + cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 17 : 4 + 32; + else /* MPEG 2 */ + cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 9 : 4 + 17; + + if (cfg->error_protection) + cfg->sideinfo_len += 2; + + { + int k; + + for (k = 0; k < 19; k++) + gfc->sv_enc.pefirbuf[k] = 700 * cfg->mode_gr * cfg->channels_out; + + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + } + + assert(gfp->VBR_q <= 9); + assert(gfp->VBR_q >= 0); + + switch (cfg->vbr) { + + case vbr_mt: + case vbr_mtrh:{ + if (gfp->strict_ISO < 0) { + gfp->strict_ISO = MDB_MAXIMUM; + } + if (gfp->useTemporal < 0) { + gfp->useTemporal = 0; /* off by default for this VBR mode */ + } + + (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0); + /* The newer VBR code supports only a limited + subset of quality levels: + 9-5=5 are the same, uses x^3/4 quantization + 4-0=0 are the same 5 plus best huffman divide code + */ + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + if (gfp->quality < 5) + gfp->quality = 0; + if (gfp->quality > 7) + gfp->quality = 7; + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if (gfp->experimentalY) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000); + + break; + + } + case vbr_rh:{ + + (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0); + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if (gfp->experimentalY) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000); + + /* VBR needs at least the output of GPSYCHO, + * so we have to garantee that by setting a minimum + * quality level, actually level 6 does it. + * down to level 6 + */ + if (gfp->quality > 6) + gfp->quality = 6; + + + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + + break; + } + + default: /* cbr/abr */ { + + /* no sfb21 extra with CBR code + */ + gfc->sv_qnt.sfb21_extra = 0; + + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + + + if (cfg->vbr == vbr_off) + (void) lame_set_VBR_mean_bitrate_kbps(gfp, gfp->brate); + /* second, set parameters depending on bitrate */ + (void) apply_preset(gfp, gfp->VBR_mean_bitrate_kbps, 0); + gfp->VBR = cfg->vbr; + + break; + } + } + + /*initialize default values common for all modes */ + + gfc->sv_qnt.mask_adjust = gfp->maskingadjust; + gfc->sv_qnt.mask_adjust_short = gfp->maskingadjust_short; + + /* just another daily changing developer switch */ + if (gfp->tune) { + gfc->sv_qnt.mask_adjust += gfp->tune_value_a; + gfc->sv_qnt.mask_adjust_short += gfp->tune_value_a; + } + + + if (cfg->vbr != vbr_off) { /* choose a min/max bitrate for VBR */ + /* if the user didn't specify VBR_max_bitrate: */ + cfg->vbr_min_bitrate_index = 1; /* default: allow 8 kbps (MPEG-2) or 32 kbps (MPEG-1) */ + cfg->vbr_max_bitrate_index = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */ + if (cfg->samplerate_out < 16000) + cfg->vbr_max_bitrate_index = 8; /* default: allow 64 kbps (MPEG-2.5) */ + if (gfp->VBR_min_bitrate_kbps) { + gfp->VBR_min_bitrate_kbps = + FindNearestBitrate(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out); + cfg->vbr_min_bitrate_index = + BitrateIndex(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out); + if (cfg->vbr_min_bitrate_index < 0) { + /* This never happens, because of preceding FindNearestBitrate! + * But, set a sane value, just in case + */ + assert(0); + cfg->vbr_min_bitrate_index = 1; + } + } + if (gfp->VBR_max_bitrate_kbps) { + gfp->VBR_max_bitrate_kbps = + FindNearestBitrate(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out); + cfg->vbr_max_bitrate_index = + BitrateIndex(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out); + if (cfg->vbr_max_bitrate_index < 0) { + /* This never happens, because of preceding FindNearestBitrate! + * But, set a sane value, just in case + */ + assert(0); + cfg->vbr_max_bitrate_index = cfg->samplerate_out < 16000 ? 8 : 14; + } + } + gfp->VBR_min_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index]; + gfp->VBR_max_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_max_bitrate_index]; + gfp->VBR_mean_bitrate_kbps = + Min(bitrate_table[cfg->version][cfg->vbr_max_bitrate_index], + gfp->VBR_mean_bitrate_kbps); + gfp->VBR_mean_bitrate_kbps = + Max(bitrate_table[cfg->version][cfg->vbr_min_bitrate_index], + gfp->VBR_mean_bitrate_kbps); + } + + cfg->preset = gfp->preset; + cfg->write_lame_tag = gfp->write_lame_tag; + gfc->sv_qnt.substep_shaping = gfp->substep_shaping; + cfg->noise_shaping = gfp->noise_shaping; + cfg->subblock_gain = gfp->subblock_gain; + cfg->use_best_huffman = gfp->use_best_huffman; + cfg->avg_bitrate = gfp->brate; + cfg->vbr_avg_bitrate_kbps = gfp->VBR_mean_bitrate_kbps; + cfg->compression_ratio = gfp->compression_ratio; + + /* initialize internal qval settings */ + lame_init_qval(gfp); + + + /* automatic ATH adjustment on + */ + if (gfp->athaa_type < 0) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + + /* initialize internal adaptive ATH settings -jd */ + gfc->ATH->aa_sensitivity_p = pow(10.0, gfp->athaa_sensitivity / -10.0); + + + if (gfp->short_blocks == short_block_not_set) { + gfp->short_blocks = short_block_allowed; + } + + /*Note Jan/2003: Many hardware decoders cannot handle short blocks in regular + stereo mode unless they are coupled (same type in both channels) + it is a rare event (1 frame per min. or so) that LAME would use + uncoupled short blocks, so lets turn them off until we decide + how to handle this. No other encoders allow uncoupled short blocks, + even though it is in the standard. */ + /* rh 20040217: coupling makes no sense for mono and dual-mono streams + */ + if (gfp->short_blocks == short_block_allowed + && (cfg->mode == JOINT_STEREO || cfg->mode == STEREO)) { + gfp->short_blocks = short_block_coupled; + } + + cfg->short_blocks = gfp->short_blocks; + + + if (lame_get_quant_comp(gfp) < 0) + (void) lame_set_quant_comp(gfp, 1); + if (lame_get_quant_comp_short(gfp) < 0) + (void) lame_set_quant_comp_short(gfp, 0); + + if (lame_get_msfix(gfp) < 0) + lame_set_msfix(gfp, 0); + + /* select psychoacoustic model */ + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + + if (gfp->ATHtype < 0) + gfp->ATHtype = 4; + + if (gfp->ATHcurve < 0) + gfp->ATHcurve = 4; + + if (gfp->interChRatio < 0) + gfp->interChRatio = 0; + + if (gfp->useTemporal < 0) + gfp->useTemporal = 1; /* on by default */ + + + cfg->interChRatio = gfp->interChRatio; + cfg->msfix = gfp->msfix; + cfg->ATH_offset_db = 0-gfp->ATH_lower_db; + cfg->ATH_offset_factor = powf(10.f, cfg->ATH_offset_db * 0.1f); + cfg->ATHcurve = gfp->ATHcurve; + cfg->ATHtype = gfp->ATHtype; + cfg->ATHonly = gfp->ATHonly; + cfg->ATHshort = gfp->ATHshort; + cfg->noATH = gfp->noATH; + + cfg->quant_comp = gfp->quant_comp; + cfg->quant_comp_short = gfp->quant_comp_short; + + cfg->use_temporal_masking_effect = gfp->useTemporal; + if (cfg->mode == JOINT_STEREO) { + cfg->use_safe_joint_stereo = gfp->exp_nspsytune & 2; + } + else { + cfg->use_safe_joint_stereo = 0; + } + { + cfg->adjust_bass_db = (gfp->exp_nspsytune >> 2) & 63; + if (cfg->adjust_bass_db >= 32.f) + cfg->adjust_bass_db -= 64.f; + cfg->adjust_bass_db *= 0.25f; + + cfg->adjust_alto_db = (gfp->exp_nspsytune >> 8) & 63; + if (cfg->adjust_alto_db >= 32.f) + cfg->adjust_alto_db -= 64.f; + cfg->adjust_alto_db *= 0.25f; + + cfg->adjust_treble_db = (gfp->exp_nspsytune >> 14) & 63; + if (cfg->adjust_treble_db >= 32.f) + cfg->adjust_treble_db -= 64.f; + cfg->adjust_treble_db *= 0.25f; + + /* to be compatible with Naoki's original code, the next 6 bits + * define only the amount of changing treble for sfb21 */ + cfg->adjust_sfb21_db = (gfp->exp_nspsytune >> 20) & 63; + if (cfg->adjust_sfb21_db >= 32.f) + cfg->adjust_sfb21_db -= 64.f; + cfg->adjust_sfb21_db *= 0.25f; + cfg->adjust_sfb21_db += cfg->adjust_treble_db; + } + + /* Setting up the PCM input data transform matrix, to apply + * user defined re-scaling, and or two-to-one channel downmix. + */ + { + FLOAT m[2][2] = { {1.0f, 0.0f}, {0.0f, 1.0f} }; + + /* user selected scaling of the samples */ + m[0][0] *= gfp->scale; + m[0][1] *= gfp->scale; + m[1][0] *= gfp->scale; + m[1][1] *= gfp->scale; + /* user selected scaling of the channel 0 (left) samples */ + m[0][0] *= gfp->scale_left; + m[0][1] *= gfp->scale_left; + /* user selected scaling of the channel 1 (right) samples */ + m[1][0] *= gfp->scale_right; + m[1][1] *= gfp->scale_right; + /* Downsample to Mono if 2 channels in and 1 channel out */ + if (cfg->channels_in == 2 && cfg->channels_out == 1) { + m[0][0] = 0.5f * (m[0][0] + m[1][0]); + m[0][1] = 0.5f * (m[0][1] + m[1][1]); + m[1][0] = 0; + m[1][1] = 0; + } + cfg->pcm_transform[0][0] = m[0][0]; + cfg->pcm_transform[0][1] = m[0][1]; + cfg->pcm_transform[1][0] = m[1][0]; + cfg->pcm_transform[1][1] = m[1][1]; + } + + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert Hegemann 2000-06-22 + */ + gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF = 0; + if (cfg->vbr == vbr_off) + gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF + = ((cfg->version + 1) * 72000L * cfg->avg_bitrate) % cfg->samplerate_out; + + (void) lame_init_bitstream(gfp); + + iteration_init(gfc); + (void) psymodel_init(gfp); + + cfg->buffer_constraint = get_max_frame_buffer_size_by_constraint(cfg, gfp->strict_ISO); + + + cfg->findReplayGain = gfp->findReplayGain; + cfg->decode_on_the_fly = gfp->decode_on_the_fly; + + if (cfg->decode_on_the_fly) + cfg->findPeakSample = 1; + + if (cfg->findReplayGain) { + if (InitGainAnalysis(gfc->sv_rpg.rgdata, cfg->samplerate_out) == INIT_GAIN_ANALYSIS_ERROR) { + /* Actually this never happens, our samplerates are the ones RG accepts! + * But just in case, turn RG off + */ + assert(0); + cfg->findReplayGain = 0; + } + } + +#ifdef DECODE_ON_THE_FLY + if (cfg->decode_on_the_fly && !gfp->decode_only) { + if (gfc->hip) { + hip_decode_exit(gfc->hip); + } + gfc->hip = hip_decode_init(); + /* report functions */ + hip_set_errorf(gfc->hip, gfp->report.errorf); + hip_set_debugf(gfc->hip, gfp->report.debugf); + hip_set_msgf(gfc->hip, gfp->report.msgf); + } +#endif + /* updating lame internal flags finished successful */ + gfc->lame_init_params_successful = 1; + return 0; +} + +static void +concatSep(char* dest, char const* sep, char const* str) +{ + if (*dest != 0) strcat(dest, sep); + strcat(dest, str); +} + +/* + * print_config + * + * Prints some selected information about the coding parameters via + * the macro command MSGF(), which is currently mapped to lame_errorf + * (reports via a error function?), which is a printf-like function + * for <stderr>. + */ + +void +lame_print_config(const lame_global_flags * gfp) +{ + lame_internal_flags const *const gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + double const out_samplerate = cfg->samplerate_out; + double const in_samplerate = cfg->samplerate_in; + + MSGF(gfc, "LAME %s %s (%s)\n", get_lame_version(), get_lame_os_bitness(), get_lame_url()); + +#if (LAME_ALPHA_VERSION) + MSGF(gfc, "warning: alpha versions should be used for testing only\n"); +#endif + if (gfc->CPU_features.MMX + || gfc->CPU_features.AMD_3DNow || gfc->CPU_features.SSE || gfc->CPU_features.SSE2) { + char text[256] = { 0 }; + int fft_asm_used = 0; +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + fft_asm_used = 1; + } + else if (gfc->CPU_features.SSE) { + fft_asm_used = 2; + } +#else +# if defined( HAVE_XMMINTRIN_H ) && defined( MIN_ARCH_SSE ) + { + fft_asm_used = 3; + } +# endif +#endif + if (gfc->CPU_features.MMX) { +#ifdef MMX_choose_table + concatSep(text, ", ", "MMX (ASM used)"); +#else + concatSep(text, ", ", "MMX"); +#endif + } + if (gfc->CPU_features.AMD_3DNow) { + concatSep(text, ", ", (fft_asm_used == 1) ? "3DNow! (ASM used)" : "3DNow!"); + } + if (gfc->CPU_features.SSE) { +#if defined(HAVE_XMMINTRIN_H) + concatSep(text, ", ", "SSE (ASM used)"); +#else + concatSep(text, ", ", (fft_asm_used == 2) ? "SSE (ASM used)" : "SSE"); +#endif + } + if (gfc->CPU_features.SSE2) { + concatSep(text, ", ", (fft_asm_used == 3) ? "SSE2 (ASM used)" : "SSE2"); + } + MSGF(gfc, "CPU features: %s\n", text); + } + + if (cfg->channels_in == 2 && cfg->channels_out == 1 /* mono */ ) { + MSGF(gfc, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n"); + } + + if (isResamplingNecessary(cfg)) { + MSGF(gfc, "Resampling: input %g kHz output %g kHz\n", + 1.e-3 * in_samplerate, 1.e-3 * out_samplerate); + } + + if (cfg->highpass2 > 0.) + MSGF(gfc, + "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * cfg->highpass1 * out_samplerate, 0.5 * cfg->highpass2 * out_samplerate); + if (0. < cfg->lowpass1 || 0. < cfg->lowpass2) { + MSGF(gfc, + "Using polyphase lowpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * cfg->lowpass1 * out_samplerate, 0.5 * cfg->lowpass2 * out_samplerate); + } + else { + MSGF(gfc, "polyphase lowpass filter disabled\n"); + } + + if (cfg->free_format) { + MSGF(gfc, "Warning: many decoders cannot handle free format bitstreams\n"); + if (cfg->avg_bitrate > 320) { + MSGF(gfc, + "Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation)\n"); + } + } +} + + +/** rh: + * some pretty printing is very welcome at this point! + * so, if someone is willing to do so, please do it! + * add more, if you see more... + */ +void +lame_print_internals(const lame_global_flags * gfp) +{ + lame_internal_flags const *const gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + const char *pc = ""; + + /* compiler/processor optimizations, operational, etc. + */ + MSGF(gfc, "\nmisc:\n\n"); + + MSGF(gfc, "\tscaling: %g\n", gfp->scale); + MSGF(gfc, "\tch0 (left) scaling: %g\n", gfp->scale_left); + MSGF(gfc, "\tch1 (right) scaling: %g\n", gfp->scale_right); + switch (cfg->use_best_huffman) { + default: + pc = "normal"; + break; + case 1: + pc = "best (outside loop)"; + break; + case 2: + pc = "best (inside loop, slow)"; + break; + } + MSGF(gfc, "\thuffman search: %s\n", pc); + MSGF(gfc, "\texperimental Y=%d\n", gfp->experimentalY); + MSGF(gfc, "\t...\n"); + + /* everything controlling the stream format + */ + MSGF(gfc, "\nstream format:\n\n"); + switch (cfg->version) { + case 0: + pc = "2.5"; + break; + case 1: + pc = "1"; + break; + case 2: + pc = "2"; + break; + default: + pc = "?"; + break; + } + MSGF(gfc, "\tMPEG-%s Layer 3\n", pc); + switch (cfg->mode) { + case JOINT_STEREO: + pc = "joint stereo"; + break; + case STEREO: + pc = "stereo"; + break; + case DUAL_CHANNEL: + pc = "dual channel"; + break; + case MONO: + pc = "mono"; + break; + case NOT_SET: + pc = "not set (error)"; + break; + default: + pc = "unknown (error)"; + break; + } + MSGF(gfc, "\t%d channel - %s\n", cfg->channels_out, pc); + + switch (cfg->vbr) { + case vbr_off: + pc = "off"; + break; + default: + pc = "all"; + break; + } + MSGF(gfc, "\tpadding: %s\n", pc); + + if (vbr_default == cfg->vbr) + pc = "(default)"; + else if (cfg->free_format) + pc = "(free format)"; + else + pc = ""; + switch (cfg->vbr) { + case vbr_off: + MSGF(gfc, "\tconstant bitrate - CBR %s\n", pc); + break; + case vbr_abr: + MSGF(gfc, "\tvariable bitrate - ABR %s\n", pc); + break; + case vbr_rh: + MSGF(gfc, "\tvariable bitrate - VBR rh %s\n", pc); + break; + case vbr_mt: + MSGF(gfc, "\tvariable bitrate - VBR mt %s\n", pc); + break; + case vbr_mtrh: + MSGF(gfc, "\tvariable bitrate - VBR mtrh %s\n", pc); + break; + default: + MSGF(gfc, "\t ?? oops, some new one ?? \n"); + break; + } + if (cfg->write_lame_tag) + MSGF(gfc, "\tusing LAME Tag\n"); + MSGF(gfc, "\t...\n"); + + /* everything controlling psychoacoustic settings, like ATH, etc. + */ + MSGF(gfc, "\npsychoacoustic:\n\n"); + + switch (cfg->short_blocks) { + default: + case short_block_not_set: + pc = "?"; + break; + case short_block_allowed: + pc = "allowed"; + break; + case short_block_coupled: + pc = "channel coupled"; + break; + case short_block_dispensed: + pc = "dispensed"; + break; + case short_block_forced: + pc = "forced"; + break; + } + MSGF(gfc, "\tusing short blocks: %s\n", pc); + MSGF(gfc, "\tsubblock gain: %d\n", cfg->subblock_gain); + MSGF(gfc, "\tadjust masking: %g dB\n", gfc->sv_qnt.mask_adjust); + MSGF(gfc, "\tadjust masking short: %g dB\n", gfc->sv_qnt.mask_adjust_short); + MSGF(gfc, "\tquantization comparison: %d\n", cfg->quant_comp); + MSGF(gfc, "\t ^ comparison short blocks: %d\n", cfg->quant_comp_short); + MSGF(gfc, "\tnoise shaping: %d\n", cfg->noise_shaping); + MSGF(gfc, "\t ^ amplification: %d\n", cfg->noise_shaping_amp); + MSGF(gfc, "\t ^ stopping: %d\n", cfg->noise_shaping_stop); + + pc = "using"; + if (cfg->ATHshort) + pc = "the only masking for short blocks"; + if (cfg->ATHonly) + pc = "the only masking"; + if (cfg->noATH) + pc = "not used"; + MSGF(gfc, "\tATH: %s\n", pc); + MSGF(gfc, "\t ^ type: %d\n", cfg->ATHtype); + MSGF(gfc, "\t ^ shape: %g%s\n", cfg->ATHcurve, " (only for type 4)"); + MSGF(gfc, "\t ^ level adjustement: %g dB\n", cfg->ATH_offset_db); + MSGF(gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust); + MSGF(gfc, "\t ^ adjust sensitivity power: %f\n", gfc->ATH->aa_sensitivity_p); + + MSGF(gfc, "\texperimental psy tunings by Naoki Shibata\n"); + MSGF(gfc, "\t adjust masking bass=%g dB, alto=%g dB, treble=%g dB, sfb21=%g dB\n", + 10 * log10(gfc->sv_qnt.longfact[0]), + 10 * log10(gfc->sv_qnt.longfact[7]), + 10 * log10(gfc->sv_qnt.longfact[14]), 10 * log10(gfc->sv_qnt.longfact[21])); + + pc = cfg->use_temporal_masking_effect ? "yes" : "no"; + MSGF(gfc, "\tusing temporal masking effect: %s\n", pc); + MSGF(gfc, "\tinterchannel masking ratio: %g\n", cfg->interChRatio); + MSGF(gfc, "\t...\n"); + + /* that's all ? + */ + MSGF(gfc, "\n"); + return; +} + + +static void +save_gain_values(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + RpgStateVar_t const *const rsv = &gfc->sv_rpg; + RpgResult_t *const rov = &gfc->ov_rpg; + /* save the ReplayGain value */ + if (cfg->findReplayGain) { + FLOAT const RadioGain = (FLOAT) GetTitleGain(rsv->rgdata); + if (NEQ(RadioGain, GAIN_NOT_ENOUGH_SAMPLES)) { + rov->RadioGain = (int) floor(RadioGain * 10.0 + 0.5); /* round to nearest */ + } + else { + rov->RadioGain = 0; + } + } + + /* find the gain and scale change required for no clipping */ + if (cfg->findPeakSample) { + rov->noclipGainChange = (int) ceil(log10(rov->PeakSample / 32767.0) * 20.0 * 10.0); /* round up */ + + if (rov->noclipGainChange > 0) { /* clipping occurs */ + rov->noclipScale = floor((32767.0f / rov->PeakSample) * 100.0f) / 100.0f; /* round down */ + } + else /* no clipping */ + rov->noclipScale = -1.0f; + } +} + + + +static int +update_inbuffer_size(lame_internal_flags * gfc, const int nsamples) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + if (esv->in_buffer_0 == 0 || esv->in_buffer_nsamples < nsamples) { + if (esv->in_buffer_0) { + free(esv->in_buffer_0); + } + if (esv->in_buffer_1) { + free(esv->in_buffer_1); + } + esv->in_buffer_0 = lame_calloc(sample_t, nsamples); + esv->in_buffer_1 = lame_calloc(sample_t, nsamples); + esv->in_buffer_nsamples = nsamples; + } + if (esv->in_buffer_0 == NULL || esv->in_buffer_1 == NULL) { + if (esv->in_buffer_0) { + free(esv->in_buffer_0); + } + if (esv->in_buffer_1) { + free(esv->in_buffer_1); + } + esv->in_buffer_0 = 0; + esv->in_buffer_1 = 0; + esv->in_buffer_nsamples = 0; + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + return 0; +} + + +static int +calcNeeded(SessionConfig_t const * cfg) +{ + int mf_needed; + int pcm_samples_per_frame = 576 * cfg->mode_gr; + + /* some sanity checks */ +#if ENCDELAY < MDCTDELAY +# error ENCDELAY is less than MDCTDELAY, see encoder.h +#endif +#if FFTOFFSET > BLKSIZE +# error FFTOFFSET is greater than BLKSIZE, see encoder.h +#endif + + mf_needed = BLKSIZE + pcm_samples_per_frame - FFTOFFSET; /* amount needed for FFT */ + /*mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); */ + mf_needed = Max(mf_needed, 512 + pcm_samples_per_frame - 32); + + assert(MFSIZE >= mf_needed); + + return mf_needed; +} + + +/* + * THE MAIN LAME ENCODING INTERFACE + * mt 3/00 + * + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * The required mp3buffer_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buffer_size in bytes = 1.25*num_samples + 7200 + * + * return code = number of bytes output in mp3buffer. can be 0 + * + * NOTE: this routine uses LAME's internal PCM data representation, + * 'sample_t'. It should not be used by any application. + * applications should use lame_encode_buffer(), + * lame_encode_buffer_float() + * lame_encode_buffer_int() + * etc... depending on what type of data they are working with. +*/ +static int +lame_encode_buffer_sample_t(lame_internal_flags * gfc, + int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int pcm_samples_per_frame = 576 * cfg->mode_gr; + int mp3size = 0, ret, i, ch, mf_needed; + int mp3out; + sample_t *mfbuf[2]; + sample_t *in_buffer[2]; + + if (gfc->class_id != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + /* copy out any tags that may have been written into bitstream */ + { /* if user specifed buffer size = 0, dont check size */ + int const buf_size = mp3buf_size == 0 ? INT_MAX : mp3buf_size; + mp3out = copy_buffer(gfc, mp3buf, buf_size, 0); + } + if (mp3out < 0) + return mp3out; /* not enough buffer space */ + mp3buf += mp3out; + mp3size += mp3out; + + in_buffer[0] = esv->in_buffer_0; + in_buffer[1] = esv->in_buffer_1; + + mf_needed = calcNeeded(cfg); + + mfbuf[0] = esv->mfbuf[0]; + mfbuf[1] = esv->mfbuf[1]; + + while (nsamples > 0) { + sample_t const *in_buffer_ptr[2]; + int n_in = 0; /* number of input samples processed with fill_buffer */ + int n_out = 0; /* number of samples output with fill_buffer */ + /* n_in <> n_out if we are resampling */ + + in_buffer_ptr[0] = in_buffer[0]; + in_buffer_ptr[1] = in_buffer[1]; + /* copy in new samples into mfbuf, with resampling */ + fill_buffer(gfc, mfbuf, &in_buffer_ptr[0], nsamples, &n_in, &n_out); + + /* compute ReplayGain of resampled input if requested */ + if (cfg->findReplayGain && !cfg->decode_on_the_fly) + if (AnalyzeSamples + (gfc->sv_rpg.rgdata, &mfbuf[0][esv->mf_size], &mfbuf[1][esv->mf_size], n_out, + cfg->channels_out) == GAIN_ANALYSIS_ERROR) + return -6; + + + + /* update in_buffer counters */ + nsamples -= n_in; + in_buffer[0] += n_in; + if (cfg->channels_out == 2) + in_buffer[1] += n_in; + + /* update mfbuf[] counters */ + esv->mf_size += n_out; + assert(esv->mf_size <= MFSIZE); + + /* lame_encode_flush may have set gfc->mf_sample_to_encode to 0 + * so we have to reinitialize it here when that happened. + */ + if (esv->mf_samples_to_encode < 1) { + esv->mf_samples_to_encode = ENCDELAY + POSTDELAY; + } + esv->mf_samples_to_encode += n_out; + + + if (esv->mf_size >= mf_needed) { + /* encode the frame. */ + /* mp3buf = pointer to current location in buffer */ + /* mp3buf_size = size of original mp3 output buffer */ + /* = 0 if we should not worry about the */ + /* buffer size because calling program is */ + /* to lazy to compute it */ + /* mp3size = size of data written to buffer so far */ + /* mp3buf_size-mp3size = amount of space avalable */ + + int buf_size = mp3buf_size - mp3size; + if (mp3buf_size == 0) + buf_size = INT_MAX; + + ret = lame_encode_mp3_frame(gfc, mfbuf[0], mfbuf[1], mp3buf, buf_size); + + if (ret < 0) + return ret; + mp3buf += ret; + mp3size += ret; + + /* shift out old samples */ + esv->mf_size -= pcm_samples_per_frame; + esv->mf_samples_to_encode -= pcm_samples_per_frame; + for (ch = 0; ch < cfg->channels_out; ch++) + for (i = 0; i < esv->mf_size; i++) + mfbuf[ch][i] = mfbuf[ch][i + pcm_samples_per_frame]; + } + } + assert(nsamples == 0); + + return mp3size; +} + +enum PCMSampleType +{ pcm_short_type +, pcm_int_type +, pcm_long_type +, pcm_float_type +, pcm_double_type +}; + +static void +lame_copy_inbuffer(lame_internal_flags* gfc, + void const* l, void const* r, int nsamples, + enum PCMSampleType pcm_type, int jump, FLOAT s) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + sample_t* ib0 = esv->in_buffer_0; + sample_t* ib1 = esv->in_buffer_1; + FLOAT m[2][2]; + + /* Apply user defined re-scaling */ + m[0][0] = s * cfg->pcm_transform[0][0]; + m[0][1] = s * cfg->pcm_transform[0][1]; + m[1][0] = s * cfg->pcm_transform[1][0]; + m[1][1] = s * cfg->pcm_transform[1][1]; + + /* make a copy of input buffer, changing type to sample_t */ +#define COPY_AND_TRANSFORM(T) \ +{ \ + T const *bl = l, *br = r; \ + int i; \ + for (i = 0; i < nsamples; i++) { \ + sample_t const xl = *bl; \ + sample_t const xr = *br; \ + sample_t const u = xl * m[0][0] + xr * m[0][1]; \ + sample_t const v = xl * m[1][0] + xr * m[1][1]; \ + ib0[i] = u; \ + ib1[i] = v; \ + bl += jump; \ + br += jump; \ + } \ +} + switch ( pcm_type ) { + case pcm_short_type: + COPY_AND_TRANSFORM(short int); + break; + case pcm_int_type: + COPY_AND_TRANSFORM(int); + break; + case pcm_long_type: + COPY_AND_TRANSFORM(long int); + break; + case pcm_float_type: + COPY_AND_TRANSFORM(float); + break; + case pcm_double_type: + COPY_AND_TRANSFORM(double); + break; + } +} + + +static int +lame_encode_buffer_template(lame_global_flags * gfp, + void const* buffer_l, void const* buffer_r, const int nsamples, + unsigned char *mp3buf, const int mp3buf_size, enum PCMSampleType pcm_type, int aa, FLOAT norm) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + + if (nsamples == 0) + return 0; + + if (update_inbuffer_size(gfc, nsamples) != 0) { + return -2; + } + /* make a copy of input buffer, changing type to sample_t */ + if (cfg->channels_in > 1) { + if (buffer_l == 0 || buffer_r == 0) { + return 0; + } + lame_copy_inbuffer(gfc, buffer_l, buffer_r, nsamples, pcm_type, aa, norm); + } + else { + if (buffer_l == 0) { + return 0; + } + lame_copy_inbuffer(gfc, buffer_l, buffer_l, nsamples, pcm_type, aa, norm); + } + + return lame_encode_buffer_sample_t(gfc, nsamples, mp3buf, mp3buf_size); + } + } + return -3; +} + +int +lame_encode_buffer(lame_global_flags * gfp, + const short int pcm_l[], const short int pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_short_type, 1, 1.0); +} + + +int +lame_encode_buffer_float(lame_global_flags * gfp, + const float pcm_l[], const float pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 32768 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 1.0); +} + + +int +lame_encode_buffer_ieee_float(lame_t gfp, + const float pcm_l[], const float pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 32767.0); +} + + +int +lame_encode_buffer_interleaved_ieee_float(lame_t gfp, + const float pcm[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_float_type, 2, 32767.0); +} + + +int +lame_encode_buffer_ieee_double(lame_t gfp, + const double pcm_l[], const double pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_double_type, 1, 32767.0); +} + + +int +lame_encode_buffer_interleaved_ieee_double(lame_t gfp, + const double pcm[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_double_type, 2, 32767.0); +} + + +int +lame_encode_buffer_int(lame_global_flags * gfp, + const int pcm_l[], const int pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_INT for full scale */ + FLOAT const norm = (1.0 / (1L << (8 * sizeof(int) - 16))); + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_int_type, 1, norm); +} + + +int +lame_encode_buffer_long2(lame_global_flags * gfp, + const long pcm_l[], const long pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_LONG for full scale */ + FLOAT const norm = (1.0 / (1L << (8 * sizeof(long) - 16))); + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, norm); +} + + +int +lame_encode_buffer_long(lame_global_flags * gfp, + const long pcm_l[], const long pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 32768 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, 1.0); +} + + + +int +lame_encode_buffer_interleaved(lame_global_flags * gfp, + short int pcm[], int nsamples, + unsigned char *mp3buf, int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_SHORT for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_short_type, 2, 1.0); +} + + +int +lame_encode_buffer_interleaved_int(lame_t gfp, + const int pcm[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX(int) for full scale */ + FLOAT const norm = (1.0 / (1L << (8 * sizeof(int)-16))); + return lame_encode_buffer_template(gfp, pcm, pcm + 1, nsamples, mp3buf, mp3buf_size, pcm_int_type, 2, norm); +} + + + + +/***************************************************************** + Flush mp3 buffer, pad with ancillary data so last frame is complete. + Reset reservoir size to 0 + but keep all PCM samples and MDCT data in memory + This option is used to break a large file into several mp3 files + that when concatenated together will decode with no gaps + Because we set the reservoir=0, they will also decode seperately + with no errors. +*********************************************************************/ +int +lame_encode_flush_nogap(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + int rc = -3; + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + flush_bitstream(gfc); + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size = INT_MAX; + rc = copy_buffer(gfc, mp3buffer, mp3buffer_size, 1); + save_gain_values(gfc); + } + } + return rc; +} + + +/* called by lame_init_params. You can also call this after flush_nogap + if you want to write new id3v2 and Xing VBR tags into the bitstream */ +int +lame_init_bitstream(lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (gfc != 0) { + gfc->ov_enc.frame_number = 0; + + if (gfp->write_id3tag_automatic) { + (void) id3tag_write_v2(gfp); + } + /* initialize histogram data optionally used by frontend */ + memset(gfc->ov_enc.bitrate_channelmode_hist, 0, + sizeof(gfc->ov_enc.bitrate_channelmode_hist)); + memset(gfc->ov_enc.bitrate_blocktype_hist, 0, + sizeof(gfc->ov_enc.bitrate_blocktype_hist)); + + gfc->ov_rpg.PeakSample = 0.0; + + /* Write initial VBR Header to bitstream and init VBR data */ + if (gfc->cfg.write_lame_tag) + (void) InitVbrTag(gfp); + + + return 0; + } + } + return -3; +} + + +/*****************************************************************/ +/* flush internal PCM sample buffers, then mp3 buffers */ +/* then write id3 v1 tags into bitstream. */ +/*****************************************************************/ + +int +lame_encode_flush(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + EncStateVar_t *esv; + short int buffer[2][1152]; + int imp3 = 0, mp3count, mp3buffer_size_remaining; + + /* we always add POSTDELAY=288 padding to make sure granule with real + * data can be complety decoded (because of 50% overlap with next granule */ + int end_padding; + int frames_left; + int samples_to_encode; + int pcm_samples_per_frame; + int mf_needed; + int is_resampling_necessary; + double resample_ratio = 1; + + if (!is_lame_global_flags_valid(gfp)) { + return -3; + } + gfc = gfp->internal_flags; + if (!is_lame_internal_flags_valid(gfc)) { + return -3; + } + cfg = &gfc->cfg; + esv = &gfc->sv_enc; + + /* Was flush already called? */ + if (esv->mf_samples_to_encode < 1) { + return 0; + } + pcm_samples_per_frame = 576 * cfg->mode_gr; + mf_needed = calcNeeded(cfg); + + samples_to_encode = esv->mf_samples_to_encode - POSTDELAY; + + memset(buffer, 0, sizeof(buffer)); + mp3count = 0; + + is_resampling_necessary = isResamplingNecessary(cfg); + if (is_resampling_necessary) { + resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out; + /* delay due to resampling; needs to be fixed, if resampling code gets changed */ + samples_to_encode += 16. / resample_ratio; + } + end_padding = pcm_samples_per_frame - (samples_to_encode % pcm_samples_per_frame); + if (end_padding < 576) + end_padding += pcm_samples_per_frame; + gfc->ov_enc.encoder_padding = end_padding; + + frames_left = (samples_to_encode + end_padding) / pcm_samples_per_frame; + while (frames_left > 0 && imp3 >= 0) { + int const frame_num = gfc->ov_enc.frame_number; + int bunch = mf_needed - esv->mf_size; + + bunch *= resample_ratio; + if (bunch > 1152) bunch = 1152; + if (bunch < 1) bunch = 1; + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + /* send in a frame of 0 padding until all internal sample buffers + * are flushed + */ + imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], bunch, + mp3buffer, mp3buffer_size_remaining); + + mp3buffer += imp3; + mp3count += imp3; + { /* even a single pcm sample can produce several frames! + * for example: 1 Hz input file resampled to 8 kHz mpeg2.5 + */ + int const new_frames = gfc->ov_enc.frame_number - frame_num; + if (new_frames > 0) + frames_left -= new_frames; + } + } + /* Set esv->mf_samples_to_encode to 0, so we may detect + * and break loops calling it more than once in a row. + */ + esv->mf_samples_to_encode = 0; + + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = INT_MAX; + + /* mp3 related stuff. bit buffer might still contain some mp3 data */ + flush_bitstream(gfc); + imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 1); + save_gain_values(gfc); + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = INT_MAX; + + if (gfp->write_id3tag_automatic) { + /* write a id3 tag to the bitstream */ + (void) id3tag_write_v1(gfp); + + imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 0); + + if (imp3 < 0) { + return imp3; + } + mp3count += imp3; + } +#if 0 + { + int const ed = gfc->ov_enc.encoder_delay; + int const ep = gfc->ov_enc.encoder_padding; + int const ns = (gfc->ov_enc.frame_number * pcm_samples_per_frame) - (ed + ep); + double duration = ns; + duration /= cfg->samplerate_out; + MSGF(gfc, "frames=%d\n", gfc->ov_enc.frame_number); + MSGF(gfc, "pcm_samples_per_frame=%d\n", pcm_samples_per_frame); + MSGF(gfc, "encoder delay=%d\n", ed); + MSGF(gfc, "encoder padding=%d\n", ep); + MSGF(gfc, "sample count=%d (%g)\n", ns, cfg->samplerate_in * duration); + MSGF(gfc, "duration=%g sec\n", duration); + } +#endif + return mp3count; +} + +/*********************************************************************** + * + * lame_close () + * + * frees internal buffers + * + ***********************************************************************/ + +int +lame_close(lame_global_flags * gfp) +{ + int ret = 0; + if (gfp && gfp->class_id == LAME_ID) { + lame_internal_flags *const gfc = gfp->internal_flags; + gfp->class_id = 0; + if (NULL == gfc || gfc->class_id != LAME_ID) { + ret = -3; + } + if (NULL != gfc) { + gfc->lame_init_params_successful = 0; + gfc->class_id = 0; + /* this routine will free all malloc'd data in gfc, and then free gfc: */ + freegfc(gfc); + gfp->internal_flags = NULL; + } + if (gfp->lame_allocated_gfp) { + gfp->lame_allocated_gfp = 0; + free(gfp); + } + } + return ret; +} + +/*****************************************************************/ +/* flush internal mp3 buffers, and free internal buffers */ +/*****************************************************************/ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL +lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size); +#else +#endif + +int +lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + int const ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size); + + (void) lame_close(gfp); + + return ret; +} + +/*****************************************************************/ +/* write VBR Xing header, and ID3 version 1 tag, if asked for */ +/*****************************************************************/ +void lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream); + +void +lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + if (!is_lame_global_flags_valid(gfp)) { + return; + } + gfc = gfp->internal_flags; + if (!is_lame_internal_flags_valid(gfc)) { + return; + } + cfg = &gfc->cfg; + if (!cfg->write_lame_tag) { + return; + } + /* Write Xing header again */ + if (fpStream && !fseek(fpStream, 0, SEEK_SET)) { + int rc = PutVbrTag(gfp, fpStream); + switch (rc) { + default: + /* OK */ + break; + + case -1: + ERRORF(gfc, "Error: could not update LAME tag.\n"); + break; + + case -2: + ERRORF(gfc, "Error: could not update LAME tag, file not seekable.\n"); + break; + + case -3: + ERRORF(gfc, "Error: could not update LAME tag, file not readable.\n"); + break; + } + } +} + + +static int +lame_init_internal_flags(lame_internal_flags* gfc) +{ + if (NULL == gfc) + return -1; + + gfc->cfg.vbr_min_bitrate_index = 1; /* not 0 ????? */ + gfc->cfg.vbr_max_bitrate_index = 13; /* not 14 ????? */ + gfc->cfg.decode_on_the_fly = 0; + gfc->cfg.findReplayGain = 0; + gfc->cfg.findPeakSample = 0; + + gfc->sv_qnt.OldValue[0] = 180; + gfc->sv_qnt.OldValue[1] = 180; + gfc->sv_qnt.CurrentStep[0] = 4; + gfc->sv_qnt.CurrentStep[1] = 4; + gfc->sv_qnt.masking_lower = 1; + + /* The reason for + * int mf_samples_to_encode = ENCDELAY + POSTDELAY; + * ENCDELAY = internal encoder delay. And then we have to add POSTDELAY=288 + * because of the 50% MDCT overlap. A 576 MDCT granule decodes to + * 1152 samples. To synthesize the 576 samples centered under this granule + * we need the previous granule for the first 288 samples (no problem), and + * the next granule for the next 288 samples (not possible if this is last + * granule). So we need to pad with 288 samples to make sure we can + * encode the 576 samples we are interested in. + */ + gfc->sv_enc.mf_samples_to_encode = ENCDELAY + POSTDELAY; + gfc->sv_enc.mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */ + gfc->ov_enc.encoder_padding = 0; + gfc->ov_enc.encoder_delay = ENCDELAY; + + gfc->ov_rpg.RadioGain = 0; + gfc->ov_rpg.noclipGainChange = 0; + gfc->ov_rpg.noclipScale = -1.0; + + gfc->ATH = lame_calloc(ATH_t, 1); + if (NULL == gfc->ATH) + return -2; /* maybe error codes should be enumerated in lame.h ?? */ + + gfc->sv_rpg.rgdata = lame_calloc(replaygain_t, 1); + if (NULL == gfc->sv_rpg.rgdata) { + return -2; + } + return 0; +} + +/* initialize mp3 encoder */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +static +#else +#endif +int +lame_init_old(lame_global_flags * gfp) +{ + disable_FPE(); /* disable floating point exceptions */ + + memset(gfp, 0, sizeof(lame_global_flags)); + + gfp->class_id = LAME_ID; + + /* Global flags. set defaults here for non-zero values */ + /* see lame.h for description */ + /* set integer values to -1 to mean that LAME will compute the + * best value, UNLESS the calling program as set it + * (and the value is no longer -1) + */ + gfp->strict_ISO = MDB_MAXIMUM; + + gfp->mode = NOT_SET; + gfp->original = 1; + gfp->samplerate_in = 44100; + gfp->num_channels = 2; + gfp->num_samples = MAX_U_32_NUM; + + gfp->write_lame_tag = 1; + gfp->quality = -1; + gfp->short_blocks = short_block_not_set; + gfp->subblock_gain = -1; + + gfp->lowpassfreq = 0; + gfp->highpassfreq = 0; + gfp->lowpasswidth = -1; + gfp->highpasswidth = -1; + + gfp->VBR = vbr_off; + gfp->VBR_q = 4; + gfp->VBR_mean_bitrate_kbps = 128; + gfp->VBR_min_bitrate_kbps = 0; + gfp->VBR_max_bitrate_kbps = 0; + gfp->VBR_hard_min = 0; + + gfp->quant_comp = -1; + gfp->quant_comp_short = -1; + + gfp->msfix = -1; + + gfp->attackthre = -1; + gfp->attackthre_s = -1; + + gfp->scale = 1; + gfp->scale_left = 1; + gfp->scale_right = 1; + + gfp->ATHcurve = -1; + gfp->ATHtype = -1; /* default = -1 = set in lame_init_params */ + /* 2 = equal loudness curve */ + gfp->athaa_sensitivity = 0.0; /* no offset */ + gfp->athaa_type = -1; + gfp->useTemporal = -1; + gfp->interChRatio = -1; + + gfp->findReplayGain = 0; + gfp->decode_on_the_fly = 0; + + gfp->asm_optimizations.mmx = 1; + gfp->asm_optimizations.amd3dnow = 1; + gfp->asm_optimizations.sse = 1; + + gfp->preset = 0; + + gfp->write_id3tag_automatic = 1; + + gfp->report.debugf = &lame_report_def; + gfp->report.errorf = &lame_report_def; + gfp->report.msgf = &lame_report_def; + + gfp->internal_flags = lame_calloc(lame_internal_flags, 1); + + if (lame_init_internal_flags(gfp->internal_flags) < 0) { + freegfc(gfp->internal_flags); + gfp->internal_flags = 0; + return -1; + } + return 0; +} + + +lame_global_flags * +lame_init(void) +{ + lame_global_flags *gfp; + int ret; + + init_log_table(); + + gfp = lame_calloc(lame_global_flags, 1); + if (gfp == NULL) + return NULL; + + ret = lame_init_old(gfp); + if (ret != 0) { + free(gfp); + return NULL; + } + + gfp->lame_allocated_gfp = 1; + return gfp; +} + + +/*********************************************************************** + * + * some simple statistics + * + * Robert Hegemann 2000-10-11 + * + ***********************************************************************/ + +/* histogram of used bitrate indexes: + * One has to weight them to calculate the average bitrate in kbps + * + * bitrate indices: + * there are 14 possible bitrate indices, 0 has the special meaning + * "free format" which is not possible to mix with VBR and 15 is forbidden + * anyway. + * + * stereo modes: + * 0: LR number of left-right encoded frames + * 1: LR-I number of left-right and intensity encoded frames + * 2: MS number of mid-side encoded frames + * 3: MS-I number of mid-side and intensity encoded frames + * + * 4: number of encoded frames + * + */ + +void +lame_bitrate_kbps(const lame_global_flags * gfp, int bitrate_kbps[14]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + int i; + if (cfg->free_format) { + for (i = 0; i < 14; i++) + bitrate_kbps[i] = -1; + bitrate_kbps[0] = cfg->avg_bitrate; + } + else { + for (i = 0; i < 14; i++) + bitrate_kbps[i] = bitrate_table[cfg->version][i + 1]; + } + } + } +} + + +void +lame_bitrate_hist(const lame_global_flags * gfp, int bitrate_count[14]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + if (cfg->free_format) { + for (i = 0; i < 14; i++) { + bitrate_count[i] = 0; + } + bitrate_count[0] = eov->bitrate_channelmode_hist[0][4]; + } + else { + for (i = 0; i < 14; i++) { + bitrate_count[i] = eov->bitrate_channelmode_hist[i + 1][4]; + } + } + } + } +} + + +void +lame_stereo_mode_hist(const lame_global_flags * gfp, int stmode_count[4]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + for (i = 0; i < 4; i++) { + stmode_count[i] = eov->bitrate_channelmode_hist[15][i]; + } + } + } +} + + + +void +lame_bitrate_stereo_mode_hist(const lame_global_flags * gfp, int bitrate_stmode_count[14][4]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i; + int j; + + if (cfg->free_format) { + for (j = 0; j < 14; j++) + for (i = 0; i < 4; i++) { + bitrate_stmode_count[j][i] = 0; + } + for (i = 0; i < 4; i++) { + bitrate_stmode_count[0][i] = eov->bitrate_channelmode_hist[0][i]; + } + } + else { + for (j = 0; j < 14; j++) { + for (i = 0; i < 4; i++) { + bitrate_stmode_count[j][i] = eov->bitrate_channelmode_hist[j + 1][i]; + } + } + } + } + } +} + + +void +lame_block_type_hist(const lame_global_flags * gfp, int btype_count[6]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + for (i = 0; i < 6; ++i) { + btype_count[i] = eov->bitrate_blocktype_hist[15][i]; + } + } + } +} + + + +void +lame_bitrate_block_type_hist(const lame_global_flags * gfp, int bitrate_btype_count[14][6]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i, j; + + if (cfg->free_format) { + for (j = 0; j < 14; ++j) { + for (i = 0; i < 6; ++i) { + bitrate_btype_count[j][i] = 0; + } + } + for (i = 0; i < 6; ++i) { + bitrate_btype_count[0][i] = eov->bitrate_blocktype_hist[0][i]; + } + } + else { + for (j = 0; j < 14; ++j) { + for (i = 0; i < 6; ++i) { + bitrate_btype_count[j][i] = eov->bitrate_blocktype_hist[j + 1][i]; + } + } + } + } + } +} + +/* end of lame.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.rc b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.rc new file mode 100644 index 00000000..12d0193e --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame.rc @@ -0,0 +1,50 @@ +#include <winver.h> +#include "version.h" + +#ifdef _DLL +IDI_ICON1 ICON DISCARDABLE "logoe.ico" +#else +IDI_ICON1 ICON DISCARDABLE "logoe.ico" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION LAME_MAJOR_VERSION,LAME_MINOR_VERSION,LAME_TYPE_VERSION,LAME_PATCH_VERSION + PRODUCTVERSION LAME_MAJOR_VERSION,LAME_MINOR_VERSION,LAME_TYPE_VERSION,LAME_PATCH_VERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 +#ifdef _DLL + FILETYPE VFT_DLL +#else + FILETYPE VFT_APP +#endif + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + BEGIN + VALUE "CompanyName", LAME_URL "\0" + VALUE "FileDescription", "MP3 Encoder.\0" + VALUE "FileVersion", LAME_VERSION_STRING "\0" + VALUE "LegalCopyright", "Copyright (C) 1999-2011 The L.A.M.E. Team\0" +#ifdef _DLL + VALUE "OriginalFilename", STR(_DLL) "\0" +#else + VALUE "OriginalFilename", STR(_APP) "\0" +#endif + VALUE "ProductName", "L.A.M.E.\0" + VALUE "ProductVersion", LAME_VERSION_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 // mandatory by convention + END + END +/* End of Version info */ + diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame_global_flags.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame_global_flags.h new file mode 100644 index 00000000..ad9e677d --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lame_global_flags.h @@ -0,0 +1,184 @@ +#ifndef LAME_GLOBAL_FLAGS_H +#define LAME_GLOBAL_FLAGS_H + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + + +typedef enum short_block_e { + short_block_not_set = -1, /* allow LAME to decide */ + short_block_allowed = 0, /* LAME may use them, even different block types for L/R */ + short_block_coupled, /* LAME may use them, but always same block types in L/R */ + short_block_dispensed, /* LAME will not use short blocks, long blocks only */ + short_block_forced /* LAME will not use long blocks, short blocks only */ +} short_block_t; + +/*********************************************************************** +* +* Control Parameters set by User. These parameters are here for +* backwards compatibility with the old, non-shared lib API. +* Please use the lame_set_variablename() functions below +* +* +***********************************************************************/ +struct lame_global_struct { + unsigned int class_id; + + /* input description */ + unsigned long num_samples; /* number of samples. default=2^32-1 */ + int num_channels; /* input number of channels. default=2 */ + int samplerate_in; /* input_samp_rate in Hz. default=44.1 kHz */ + int samplerate_out; /* output_samp_rate. + default: LAME picks best value + at least not used for MP3 decoding: + Remember 44.1 kHz MP3s and AC97 */ + float scale; /* scale input by this amount before encoding + at least not used for MP3 decoding */ + float scale_left; /* scale input of channel 0 (left) by this + amount before encoding */ + float scale_right; /* scale input of channel 1 (right) by this + amount before encoding */ + + /* general control params */ + int analysis; /* collect data for a MP3 frame analyzer? */ + int write_lame_tag; /* add Xing VBR tag? */ + int decode_only; /* use lame/mpglib to convert mp3 to wav */ + int quality; /* quality setting 0=best, 9=worst default=5 */ + MPEG_mode mode; /* see enum in lame.h + default = LAME picks best value */ + int force_ms; /* force M/S mode. requires mode=1 */ + int free_format; /* use free format? default=0 */ + int findReplayGain; /* find the RG value? default=0 */ + int decode_on_the_fly; /* decode on the fly? default=0 */ + int write_id3tag_automatic; /* 1 (default) writes ID3 tags, 0 not */ + + int nogap_total; + int nogap_current; + + int substep_shaping; + int noise_shaping; + int subblock_gain; /* 0 = no, 1 = yes */ + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + + /* + * set either brate>0 or compression_ratio>0, LAME will compute + * the value of the variable not set. + * Default is compression_ratio = 11.025 + */ + int brate; /* bitrate */ + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + + /* frame params */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int extension; /* the MP3 'private extension' bit. + Meaningless */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + int error_protection; /* use 2 bytes per frame for a CRC + checksum. default=0 */ + int strict_ISO; /* enforce ISO spec as much as possible */ + + int disable_reservoir; /* use bit reservoir? */ + + /* quantization/noise shaping */ + int quant_comp; + int quant_comp_short; + int experimentalY; + int experimentalZ; + int exp_nspsytune; + + int preset; + + /* VBR control */ + vbr_mode VBR; + float VBR_q_frac; /* Range [0,...,1[ */ + int VBR_q; /* Range [0,...,9] */ + int VBR_mean_bitrate_kbps; + int VBR_min_bitrate_kbps; + int VBR_max_bitrate_kbps; + int VBR_hard_min; /* strictly enforce VBR_min_bitrate + normaly, it will be violated for analog + silence */ + + + /* resampling and filtering */ + int lowpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int highpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int lowpasswidth; /* freq width of filter, in Hz + (default=15%) */ + int highpasswidth; /* freq width of filter, in Hz + (default=15%) */ + + + + /* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + float maskingadjust; + float maskingadjust_short; + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + int ATHtype; /* select ATH formula */ + float ATHcurve; /* change ATH formula 4 shape */ + float ATH_lower_db; /* lower ATH by this many db */ + int athaa_type; /* select ATH auto-adjust scheme */ + float athaa_sensitivity; /* dB, tune active region of auto-level */ + short_block_t short_blocks; + int useTemporal; /* use temporal masking effect */ + float interChRatio; + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + + int tune; /* 0 off, 1 on */ + float tune_value_a; /* used to pass values for debugging and stuff */ + + float attackthre; /* attack threshold for L/R/M channel */ + float attackthre_s; /* attack threshold for S channel */ + + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf) (const char *format, va_list ap); + void (*errorf) (const char *format, va_list ap); + } report; + + /************************************************************************/ + /* internal variables, do not set... */ + /* provided because they may be of use to calling application */ + /************************************************************************/ + + int lame_allocated_gfp; /* is this struct owned by calling + program or lame? */ + + + + /**************************************************************************/ + /* more internal variables are stored in this structure: */ + /**************************************************************************/ + lame_internal_flags *internal_flags; + + + struct { + int mmx; + int amd3dnow; + int sse; + + } asm_optimizations; +}; + +int is_lame_global_flags_valid(const lame_global_flags * gfp); + +#endif /* LAME_GLOBAL_FLAGS_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lameerror.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lameerror.h new file mode 100644 index 00000000..7d9216bc --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/lameerror.h @@ -0,0 +1,26 @@ +/* + * A collection of LAME Error Codes + * + * Please use the constants defined here instead of some arbitrary + * values. Currently the values starting at -10 to avoid intersection + * with the -1, -2, -3 and -4 used in the current code. + * + * May be this should be a part of the include/lame.h. + */ + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82, + +} lame_errorcodes_t; + +/* end of lameerror.h */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/machine.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/machine.h new file mode 100644 index 00000000..bf6fff21 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/machine.h @@ -0,0 +1,189 @@ +/* + * Machine dependent defines/includes for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_MACHINE_H +#define LAME_MACHINE_H + +#include "version.h" + +#include <stdio.h> +#include <assert.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +# include "ymath.h" +#else +# include <math.h> +#endif +#include <limits.h> + +#include <ctype.h> + +#ifdef HAVE_ERRNO_H +# include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#if defined(macintosh) +# include <types.h> +# include <stat.h> +#else +# include <sys/types.h> +# include <sys/stat.h> +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#else +# ifdef HAVE_STDINT_H +# include <stdint.h> +# endif +#endif + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +/* + * 3 different types of pow() functions: + * - table lookup + * - pow() + * - exp() on some machines this is claimed to be faster than pow() + */ + +#define POW20(x) (assert(0 <= (x+Q_MAX2) && x < Q_MAX), pow20[x+Q_MAX2]) +/*#define POW20(x) pow(2.0,((double)(x)-210)*.25) */ +/*#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) */ + +#define IPOW20(x) (assert(0 <= x && x < Q_MAX), ipow20[x]) +/*#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) */ +/*#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) */ + +/* in case this is used without configure */ +#ifndef inline +# define inline +#endif + +#if defined(_MSC_VER) +# undef inline +# define inline _inline +#elif defined(__SASC) || defined(__GNUC__) || defined(__ICC) || defined(__ECC) +/* if __GNUC__ we always want to inline, not only if the user requests it */ +# undef inline +# define inline __inline +#endif + +#if defined(_MSC_VER) +# pragma warning( disable : 4244 ) +/*# pragma warning( disable : 4305 ) */ +#endif + +/* + * FLOAT for variables which require at least 32 bits + * FLOAT8 for variables which require at least 64 bits + * + * On some machines, 64 bit will be faster than 32 bit. Also, some math + * routines require 64 bit float, so setting FLOAT=float will result in a + * lot of conversions. + */ + +#if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) ) +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include <float.h> +# define FLOAT_MAX FLT_MAX +#else +# ifndef FLOAT +typedef float FLOAT; +# ifdef FLT_MAX +# define FLOAT_MAX FLT_MAX +# else +# define FLOAT_MAX 1e37 /* approx */ +# endif +# endif +#endif + +#ifndef FLOAT8 +typedef double FLOAT8; +# ifdef DBL_MAX +# define FLOAT8_MAX DBL_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#else +# ifdef FLT_MAX +# define FLOAT8_MAX FLT_MAX +# else +# define FLOAT8_MAX 1e37 /* approx */ +# endif +#endif + +/* sample_t must be floating point, at least 32 bits */ +typedef FLOAT sample_t; + +#define dimension_of(array) (sizeof(array)/sizeof(array[0])) +#define beyond(array) (array+dimension_of(array)) +#define compiletime_assert(expression) enum{static_assert_##FILE##_##LINE = 1/((expression)?1:0)} +#define lame_calloc(TYPE, COUNT) ((TYPE*)calloc(COUNT, sizeof(TYPE))) +#define multiple_of(CHUNK, COUNT) (\ + ( (COUNT) < 1 || (CHUNK) < 1 || (COUNT) % (CHUNK) == 0 ) \ + ? (COUNT) \ + : ((COUNT) + (CHUNK) - (COUNT) % (CHUNK)) \ + ) + +#if 1 +#define EQ(a,b) (\ +(fabs(a) > fabs(b)) \ + ? (fabs((a)-(b)) <= (fabs(a) * 1e-6f)) \ + : (fabs((a)-(b)) <= (fabs(b) * 1e-6f))) +#else +#define EQ(a,b) (fabs((a)-(b))<1E-37) +#endif + +#define NEQ(a,b) (!EQ(a,b)) + +#ifdef _MSC_VER +# if _MSC_VER < 1400 +# define fabsf fabs +# define powf pow +# define log10f log10 +# endif +#endif + +#endif + +/* end of machine.h */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/mpglib_interface.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/mpglib_interface.c new file mode 100644 index 00000000..d0f0b1d5 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/mpglib_interface.c @@ -0,0 +1,477 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2003 Olcios + * Copyright (c) 2008 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: mpglib_interface.c,v 1.44 2012/02/18 13:09:00 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_MPGLIB +#define hip_global_struct mpstr_tag +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "interface.h" + +#include "util.h" + + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* + * OBSOLETE: + * - kept to let it link + * - forward declaration to silence compiler + */ +int CDECL lame_decode_init(void); +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); +int CDECL lame_decode_exit(void); +#endif + + +static MPSTR mp; + +int +lame_decode_exit(void) +{ + ExitMP3(&mp); + return 0; +} + + +int +lame_decode_init(void) +{ + (void) InitMP3(&mp); + return 0; +} + + + + +/* copy mono samples */ +#define COPY_MONO(DST_TYPE, SRC_TYPE) \ + DST_TYPE *pcm_l = (DST_TYPE *)pcm_l_raw; \ + SRC_TYPE const *p_samples = (SRC_TYPE const *)p; \ + for (i = 0; i < processed_samples; i++) \ + *pcm_l++ = (DST_TYPE)(*p_samples++); + +/* copy stereo samples */ +#define COPY_STEREO(DST_TYPE, SRC_TYPE) \ + DST_TYPE *pcm_l = (DST_TYPE *)pcm_l_raw, *pcm_r = (DST_TYPE *)pcm_r_raw; \ + SRC_TYPE const *p_samples = (SRC_TYPE const *)p; \ + for (i = 0; i < processed_samples; i++) { \ + *pcm_l++ = (DST_TYPE)(*p_samples++); \ + *pcm_r++ = (DST_TYPE)(*p_samples++); \ + } + + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. either 576 or 1152 depending on MP3 file. + */ + +static int +decode1_headersB_clipchoice(PMPSTR pmp, unsigned char *buffer, size_t len, + char pcm_l_raw[], char pcm_r_raw[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding, + char *p, size_t psize, int decoded_sample_size, + int (*decodeMP3_ptr) (PMPSTR, unsigned char *, int, char *, int, + int *)) +{ + static const int smpls[2][4] = { + /* Layer I II III */ + {0, 384, 1152, 1152}, /* MPEG-1 */ + {0, 384, 1152, 576} /* MPEG-2(.5) */ + }; + + int processed_bytes; + int processed_samples; /* processed samples per channel */ + int ret; + int i; + int const len_l = len < INT_MAX ? (int) len : INT_MAX; + int const psize_l = psize < INT_MAX ? (int) psize : INT_MAX; + + mp3data->header_parsed = 0; + ret = (*decodeMP3_ptr) (pmp, buffer, len_l, p, psize_l, &processed_bytes); + /* three cases: + * 1. headers parsed, but data not complete + * pmp->header_parsed==1 + * pmp->framesize=0 + * pmp->fsizeold=size of last frame, or 0 if this is first frame + * + * 2. headers, data parsed, but ancillary data not complete + * pmp->header_parsed==1 + * pmp->framesize=size of frame + * pmp->fsizeold=size of last frame, or 0 if this is first frame + * + * 3. frame fully decoded: + * pmp->header_parsed==0 + * pmp->framesize=0 + * pmp->fsizeold=size of frame (which is now the last frame) + * + */ + if (pmp->header_parsed || pmp->fsizeold > 0 || pmp->framesize > 0) { + mp3data->header_parsed = 1; + mp3data->stereo = pmp->fr.stereo; + mp3data->samplerate = freqs[pmp->fr.sampling_frequency]; + mp3data->mode = pmp->fr.mode; + mp3data->mode_ext = pmp->fr.mode_ext; + mp3data->framesize = smpls[pmp->fr.lsf][pmp->fr.lay]; + + /* free format, we need the entire frame before we can determine + * the bitrate. If we haven't gotten the entire frame, bitrate=0 */ + if (pmp->fsizeold > 0) /* works for free format and fixed, no overrun, temporal results are < 400.e6 */ + mp3data->bitrate = 8 * (4 + pmp->fsizeold) * mp3data->samplerate / + (1.e3 * mp3data->framesize) + 0.5; + else if (pmp->framesize > 0) + mp3data->bitrate = 8 * (4 + pmp->framesize) * mp3data->samplerate / + (1.e3 * mp3data->framesize) + 0.5; + else + mp3data->bitrate = tabsel_123[pmp->fr.lsf][pmp->fr.lay - 1][pmp->fr.bitrate_index]; + + + + if (pmp->num_frames > 0) { + /* Xing VBR header found and num_frames was set */ + mp3data->totalframes = pmp->num_frames; + mp3data->nsamp = mp3data->framesize * pmp->num_frames; + *enc_delay = pmp->enc_delay; + *enc_padding = pmp->enc_padding; + } + } + + switch (ret) { + case MP3_OK: + switch (pmp->fr.stereo) { + case 1: + processed_samples = processed_bytes / decoded_sample_size; + if (decoded_sample_size == sizeof(short)) { + COPY_MONO(short, short) + } + else { + COPY_MONO(sample_t, FLOAT) + } + break; + case 2: + processed_samples = (processed_bytes / decoded_sample_size) >> 1; + if (decoded_sample_size == sizeof(short)) { + COPY_STEREO(short, short) + } + else { + COPY_STEREO(sample_t, FLOAT) + } + break; + default: + processed_samples = -1; + assert(0); + break; + } + break; + + case MP3_NEED_MORE: + processed_samples = 0; + break; + + case MP3_ERR: + processed_samples = -1; + break; + + default: + processed_samples = -1; + assert(0); + break; + } + + /*fprintf(stderr,"ok, more, err: %i %i %i\n", MP3_OK, MP3_NEED_MORE, MP3_ERR ); */ + /*fprintf(stderr,"ret = %i out=%i\n", ret, processed_samples ); */ + return processed_samples; +} + + +#define OUTSIZE_CLIPPED (4096*sizeof(short)) + +int +lame_decode1_headersB(unsigned char *buffer, + int len, + short pcm_l[], short pcm_r[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding) +{ + static char out[OUTSIZE_CLIPPED]; + + return decode1_headersB_clipchoice(&mp, buffer, len, (char *) pcm_l, (char *) pcm_r, mp3data, + enc_delay, enc_padding, out, OUTSIZE_CLIPPED, + sizeof(short), decodeMP3); +} + + + + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. Will be at most one frame of + * MPEG data. + */ + +int +lame_decode1_headers(unsigned char *buffer, + int len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int enc_delay, enc_padding; + return lame_decode1_headersB(buffer, len, pcm_l, pcm_r, mp3data, &enc_delay, &enc_padding); +} + + +int +lame_decode1(unsigned char *buffer, int len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + + return lame_decode1_headers(buffer, len, pcm_l, pcm_r, &mp3data); +} + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. a multiple of 576 or 1152 depending on MP3 file. + */ + +int +lame_decode_headers(unsigned char *buffer, + int len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int ret; + int totsize = 0; /* number of decoded samples per channel */ + + for (;;) { + switch (ret = lame_decode1_headers(buffer, len, pcm_l + totsize, pcm_r + totsize, mp3data)) { + case -1: + return ret; + case 0: + return totsize; + default: + totsize += ret; + len = 0; /* future calls to decodeMP3 are just to flush buffers */ + break; + } + } +} + + +int +lame_decode(unsigned char *buffer, int len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + + return lame_decode_headers(buffer, len, pcm_l, pcm_r, &mp3data); +} + + + + +hip_t hip_decode_init(void) +{ + hip_t hip = lame_calloc(hip_global_flags, 1); + InitMP3(hip); + return hip; +} + + +int hip_decode_exit(hip_t hip) +{ + if (hip) { + ExitMP3(hip); + free(hip); + } + return 0; +} + + +/* we forbid input with more than 1152 samples per channel for output in the unclipped mode */ +#define OUTSIZE_UNCLIPPED (1152*2*sizeof(FLOAT)) + +int +hip_decode1_unclipped(hip_t hip, unsigned char *buffer, size_t len, sample_t pcm_l[], sample_t pcm_r[]) +{ + static char out[OUTSIZE_UNCLIPPED]; + mp3data_struct mp3data; + int enc_delay, enc_padding; + + if (hip) { + return decode1_headersB_clipchoice(hip, buffer, len, (char *) pcm_l, (char *) pcm_r, &mp3data, + &enc_delay, &enc_padding, out, OUTSIZE_UNCLIPPED, + sizeof(FLOAT), decodeMP3_unclipped); + } + return 0; +} + +/* + * For hip_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. Will be at most one frame of + * MPEG data. + */ + +int +hip_decode1_headers(hip_t hip, unsigned char *buffer, + size_t len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int enc_delay, enc_padding; + return hip_decode1_headersB(hip, buffer, len, pcm_l, pcm_r, mp3data, &enc_delay, &enc_padding); +} + + +int +hip_decode1(hip_t hip, unsigned char *buffer, size_t len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + return hip_decode1_headers(hip, buffer, len, pcm_l, pcm_r, &mp3data); +} + + +/* + * For hip_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. a multiple of 576 or 1152 depending on MP3 file. + */ + +int +hip_decode_headers(hip_t hip, unsigned char *buffer, + size_t len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int ret; + int totsize = 0; /* number of decoded samples per channel */ + + for (;;) { + switch (ret = hip_decode1_headers(hip, buffer, len, pcm_l + totsize, pcm_r + totsize, mp3data)) { + case -1: + return ret; + case 0: + return totsize; + default: + totsize += ret; + len = 0; /* future calls to decodeMP3 are just to flush buffers */ + break; + } + } +} + + +int +hip_decode(hip_t hip, unsigned char *buffer, size_t len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + return hip_decode_headers(hip, buffer, len, pcm_l, pcm_r, &mp3data); +} + + +int +hip_decode1_headersB(hip_t hip, unsigned char *buffer, + size_t len, + short pcm_l[], short pcm_r[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding) +{ + static char out[OUTSIZE_CLIPPED]; + if (hip) { + return decode1_headersB_clipchoice(hip, buffer, len, (char *) pcm_l, (char *) pcm_r, mp3data, + enc_delay, enc_padding, out, OUTSIZE_CLIPPED, + sizeof(short), decodeMP3); + } + return -1; +} + + +void hip_set_pinfo(hip_t hip, plotting_data* pinfo) +{ + if (hip) { + hip->pinfo = pinfo; + } +} + + + +void hip_set_errorf(hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_err = func; + } +} + +void hip_set_debugf(hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_dbg = func; + } +} + +void hip_set_msgf (hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_msg = func; + } +} + +#endif + +/* end of mpglib_interface.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.c new file mode 100644 index 00000000..596cac91 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.c @@ -0,0 +1,1039 @@ +/* + * MP3 window subband -> subband filtering -> mdct routine + * + * Copyright (c) 1999-2000 Takehiro Tominaga + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +/* + * Special Thanks to Patrick De Smet for your advices. + */ + +/* $Id: newmdct.c,v 1.39 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "newmdct.h" + + + +#ifndef USE_GOGO_SUBBAND +static const FLOAT enwindow[] = { + -4.77e-07 * 0.740951125354959 / 2.384e-06, 1.03951e-04 * 0.740951125354959 / 2.384e-06, + 9.53674e-04 * 0.740951125354959 / 2.384e-06, 2.841473e-03 * 0.740951125354959 / 2.384e-06, + 3.5758972e-02 * 0.740951125354959 / 2.384e-06, 3.401756e-03 * 0.740951125354959 / 2.384e-06, 9.83715e-04 * 0.740951125354959 / 2.384e-06, 9.9182e-05 * 0.740951125354959 / 2.384e-06, /* 15 */ + 1.2398e-05 * 0.740951125354959 / 2.384e-06, 1.91212e-04 * 0.740951125354959 / 2.384e-06, + 2.283096e-03 * 0.740951125354959 / 2.384e-06, 1.6994476e-02 * 0.740951125354959 / 2.384e-06, + -1.8756866e-02 * 0.740951125354959 / 2.384e-06, -2.630711e-03 * 0.740951125354959 / 2.384e-06, + -2.47478e-04 * 0.740951125354959 / 2.384e-06, -1.4782e-05 * 0.740951125354959 / 2.384e-06, + 9.063471690191471e-01, + 1.960342806591213e-01, + + + -4.77e-07 * 0.773010453362737 / 2.384e-06, 1.05858e-04 * 0.773010453362737 / 2.384e-06, + 9.30786e-04 * 0.773010453362737 / 2.384e-06, 2.521515e-03 * 0.773010453362737 / 2.384e-06, + 3.5694122e-02 * 0.773010453362737 / 2.384e-06, 3.643036e-03 * 0.773010453362737 / 2.384e-06, 9.91821e-04 * 0.773010453362737 / 2.384e-06, 9.6321e-05 * 0.773010453362737 / 2.384e-06, /* 14 */ + 1.1444e-05 * 0.773010453362737 / 2.384e-06, 1.65462e-04 * 0.773010453362737 / 2.384e-06, + 2.110004e-03 * 0.773010453362737 / 2.384e-06, 1.6112804e-02 * 0.773010453362737 / 2.384e-06, + -1.9634247e-02 * 0.773010453362737 / 2.384e-06, -2.803326e-03 * 0.773010453362737 / 2.384e-06, + -2.77042e-04 * 0.773010453362737 / 2.384e-06, -1.6689e-05 * 0.773010453362737 / 2.384e-06, + 8.206787908286602e-01, + 3.901806440322567e-01, + + + -4.77e-07 * 0.803207531480645 / 2.384e-06, 1.07288e-04 * 0.803207531480645 / 2.384e-06, + 9.02653e-04 * 0.803207531480645 / 2.384e-06, 2.174854e-03 * 0.803207531480645 / 2.384e-06, + 3.5586357e-02 * 0.803207531480645 / 2.384e-06, 3.858566e-03 * 0.803207531480645 / 2.384e-06, 9.95159e-04 * 0.803207531480645 / 2.384e-06, 9.3460e-05 * 0.803207531480645 / 2.384e-06, /* 13 */ + 1.0014e-05 * 0.803207531480645 / 2.384e-06, 1.40190e-04 * 0.803207531480645 / 2.384e-06, + 1.937389e-03 * 0.803207531480645 / 2.384e-06, 1.5233517e-02 * 0.803207531480645 / 2.384e-06, + -2.0506859e-02 * 0.803207531480645 / 2.384e-06, -2.974033e-03 * 0.803207531480645 / 2.384e-06, + -3.07560e-04 * 0.803207531480645 / 2.384e-06, -1.8120e-05 * 0.803207531480645 / 2.384e-06, + 7.416505462720353e-01, + 5.805693545089249e-01, + + + -4.77e-07 * 0.831469612302545 / 2.384e-06, 1.08242e-04 * 0.831469612302545 / 2.384e-06, + 8.68797e-04 * 0.831469612302545 / 2.384e-06, 1.800537e-03 * 0.831469612302545 / 2.384e-06, + 3.5435200e-02 * 0.831469612302545 / 2.384e-06, 4.049301e-03 * 0.831469612302545 / 2.384e-06, 9.94205e-04 * 0.831469612302545 / 2.384e-06, 9.0599e-05 * 0.831469612302545 / 2.384e-06, /* 12 */ + 9.060e-06 * 0.831469612302545 / 2.384e-06, 1.16348e-04 * 0.831469612302545 / 2.384e-06, + 1.766682e-03 * 0.831469612302545 / 2.384e-06, 1.4358521e-02 * 0.831469612302545 / 2.384e-06, + -2.1372318e-02 * 0.831469612302545 / 2.384e-06, -3.14188e-03 * 0.831469612302545 / 2.384e-06, + -3.39031e-04 * 0.831469612302545 / 2.384e-06, -1.9550e-05 * 0.831469612302545 / 2.384e-06, + 6.681786379192989e-01, + 7.653668647301797e-01, + + + -4.77e-07 * 0.857728610000272 / 2.384e-06, 1.08719e-04 * 0.857728610000272 / 2.384e-06, + 8.29220e-04 * 0.857728610000272 / 2.384e-06, 1.399517e-03 * 0.857728610000272 / 2.384e-06, + 3.5242081e-02 * 0.857728610000272 / 2.384e-06, 4.215240e-03 * 0.857728610000272 / 2.384e-06, 9.89437e-04 * 0.857728610000272 / 2.384e-06, 8.7261e-05 * 0.857728610000272 / 2.384e-06, /* 11 */ + 8.106e-06 * 0.857728610000272 / 2.384e-06, 9.3937e-05 * 0.857728610000272 / 2.384e-06, + 1.597881e-03 * 0.857728610000272 / 2.384e-06, 1.3489246e-02 * 0.857728610000272 / 2.384e-06, + -2.2228718e-02 * 0.857728610000272 / 2.384e-06, -3.306866e-03 * 0.857728610000272 / 2.384e-06, + -3.71456e-04 * 0.857728610000272 / 2.384e-06, -2.1458e-05 * 0.857728610000272 / 2.384e-06, + 5.993769336819237e-01, + 9.427934736519954e-01, + + + -4.77e-07 * 0.881921264348355 / 2.384e-06, 1.08719e-04 * 0.881921264348355 / 2.384e-06, + 7.8392e-04 * 0.881921264348355 / 2.384e-06, 9.71317e-04 * 0.881921264348355 / 2.384e-06, + 3.5007000e-02 * 0.881921264348355 / 2.384e-06, 4.357815e-03 * 0.881921264348355 / 2.384e-06, 9.80854e-04 * 0.881921264348355 / 2.384e-06, 8.3923e-05 * 0.881921264348355 / 2.384e-06, /* 10 */ + 7.629e-06 * 0.881921264348355 / 2.384e-06, 7.2956e-05 * 0.881921264348355 / 2.384e-06, + 1.432419e-03 * 0.881921264348355 / 2.384e-06, 1.2627602e-02 * 0.881921264348355 / 2.384e-06, + -2.3074150e-02 * 0.881921264348355 / 2.384e-06, -3.467083e-03 * 0.881921264348355 / 2.384e-06, + -4.04358e-04 * 0.881921264348355 / 2.384e-06, -2.3365e-05 * 0.881921264348355 / 2.384e-06, + 5.345111359507916e-01, + 1.111140466039205e+00, + + + -9.54e-07 * 0.903989293123443 / 2.384e-06, 1.08242e-04 * 0.903989293123443 / 2.384e-06, + 7.31945e-04 * 0.903989293123443 / 2.384e-06, 5.15938e-04 * 0.903989293123443 / 2.384e-06, + 3.4730434e-02 * 0.903989293123443 / 2.384e-06, 4.477024e-03 * 0.903989293123443 / 2.384e-06, 9.68933e-04 * 0.903989293123443 / 2.384e-06, 8.0585e-05 * 0.903989293123443 / 2.384e-06, /* 9 */ + 6.676e-06 * 0.903989293123443 / 2.384e-06, 5.2929e-05 * 0.903989293123443 / 2.384e-06, + 1.269817e-03 * 0.903989293123443 / 2.384e-06, 1.1775017e-02 * 0.903989293123443 / 2.384e-06, + -2.3907185e-02 * 0.903989293123443 / 2.384e-06, -3.622532e-03 * 0.903989293123443 / 2.384e-06, + -4.38213e-04 * 0.903989293123443 / 2.384e-06, -2.5272e-05 * 0.903989293123443 / 2.384e-06, + 4.729647758913199e-01, + 1.268786568327291e+00, + + + -9.54e-07 * 0.92387953251128675613 / 2.384e-06, + 1.06812e-04 * 0.92387953251128675613 / 2.384e-06, + 6.74248e-04 * 0.92387953251128675613 / 2.384e-06, + 3.3379e-05 * 0.92387953251128675613 / 2.384e-06, + 3.4412861e-02 * 0.92387953251128675613 / 2.384e-06, + 4.573822e-03 * 0.92387953251128675613 / 2.384e-06, + 9.54151e-04 * 0.92387953251128675613 / 2.384e-06, + 7.6771e-05 * 0.92387953251128675613 / 2.384e-06, + 6.199e-06 * 0.92387953251128675613 / 2.384e-06, 3.4332e-05 * 0.92387953251128675613 / 2.384e-06, + 1.111031e-03 * 0.92387953251128675613 / 2.384e-06, + 1.0933399e-02 * 0.92387953251128675613 / 2.384e-06, + -2.4725437e-02 * 0.92387953251128675613 / 2.384e-06, + -3.771782e-03 * 0.92387953251128675613 / 2.384e-06, + -4.72546e-04 * 0.92387953251128675613 / 2.384e-06, + -2.7657e-05 * 0.92387953251128675613 / 2.384e-06, + 4.1421356237309504879e-01, /* tan(PI/8) */ + 1.414213562373095e+00, + + + -9.54e-07 * 0.941544065183021 / 2.384e-06, 1.05381e-04 * 0.941544065183021 / 2.384e-06, + 6.10352e-04 * 0.941544065183021 / 2.384e-06, -4.75883e-04 * 0.941544065183021 / 2.384e-06, + 3.4055710e-02 * 0.941544065183021 / 2.384e-06, 4.649162e-03 * 0.941544065183021 / 2.384e-06, 9.35555e-04 * 0.941544065183021 / 2.384e-06, 7.3433e-05 * 0.941544065183021 / 2.384e-06, /* 7 */ + 5.245e-06 * 0.941544065183021 / 2.384e-06, 1.7166e-05 * 0.941544065183021 / 2.384e-06, + 9.56535e-04 * 0.941544065183021 / 2.384e-06, 1.0103703e-02 * 0.941544065183021 / 2.384e-06, + -2.5527000e-02 * 0.941544065183021 / 2.384e-06, -3.914356e-03 * 0.941544065183021 / 2.384e-06, + -5.07355e-04 * 0.941544065183021 / 2.384e-06, -3.0041e-05 * 0.941544065183021 / 2.384e-06, + 3.578057213145241e-01, + 1.546020906725474e+00, + + + -9.54e-07 * 0.956940335732209 / 2.384e-06, 1.02520e-04 * 0.956940335732209 / 2.384e-06, + 5.39303e-04 * 0.956940335732209 / 2.384e-06, -1.011848e-03 * 0.956940335732209 / 2.384e-06, + 3.3659935e-02 * 0.956940335732209 / 2.384e-06, 4.703045e-03 * 0.956940335732209 / 2.384e-06, 9.15051e-04 * 0.956940335732209 / 2.384e-06, 7.0095e-05 * 0.956940335732209 / 2.384e-06, /* 6 */ + 4.768e-06 * 0.956940335732209 / 2.384e-06, 9.54e-07 * 0.956940335732209 / 2.384e-06, + 8.06808e-04 * 0.956940335732209 / 2.384e-06, 9.287834e-03 * 0.956940335732209 / 2.384e-06, + -2.6310921e-02 * 0.956940335732209 / 2.384e-06, -4.048824e-03 * 0.956940335732209 / 2.384e-06, + -5.42164e-04 * 0.956940335732209 / 2.384e-06, -3.2425e-05 * 0.956940335732209 / 2.384e-06, + 3.033466836073424e-01, + 1.662939224605090e+00, + + + -1.431e-06 * 0.970031253194544 / 2.384e-06, 9.9182e-05 * 0.970031253194544 / 2.384e-06, + 4.62532e-04 * 0.970031253194544 / 2.384e-06, -1.573563e-03 * 0.970031253194544 / 2.384e-06, + 3.3225536e-02 * 0.970031253194544 / 2.384e-06, 4.737377e-03 * 0.970031253194544 / 2.384e-06, 8.91685e-04 * 0.970031253194544 / 2.384e-06, 6.6280e-05 * 0.970031253194544 / 2.384e-06, /* 5 */ + 4.292e-06 * 0.970031253194544 / 2.384e-06, -1.3828e-05 * 0.970031253194544 / 2.384e-06, + 6.61850e-04 * 0.970031253194544 / 2.384e-06, 8.487225e-03 * 0.970031253194544 / 2.384e-06, + -2.7073860e-02 * 0.970031253194544 / 2.384e-06, -4.174709e-03 * 0.970031253194544 / 2.384e-06, + -5.76973e-04 * 0.970031253194544 / 2.384e-06, -3.4809e-05 * 0.970031253194544 / 2.384e-06, + 2.504869601913055e-01, + 1.763842528696710e+00, + + + -1.431e-06 * 0.98078528040323 / 2.384e-06, 9.5367e-05 * 0.98078528040323 / 2.384e-06, + 3.78609e-04 * 0.98078528040323 / 2.384e-06, -2.161503e-03 * 0.98078528040323 / 2.384e-06, + 3.2754898e-02 * 0.98078528040323 / 2.384e-06, 4.752159e-03 * 0.98078528040323 / 2.384e-06, 8.66413e-04 * 0.98078528040323 / 2.384e-06, 6.2943e-05 * 0.98078528040323 / 2.384e-06, /* 4 */ + 3.815e-06 * 0.98078528040323 / 2.384e-06, -2.718e-05 * 0.98078528040323 / 2.384e-06, + 5.22137e-04 * 0.98078528040323 / 2.384e-06, 7.703304e-03 * 0.98078528040323 / 2.384e-06, + -2.7815342e-02 * 0.98078528040323 / 2.384e-06, -4.290581e-03 * 0.98078528040323 / 2.384e-06, + -6.11782e-04 * 0.98078528040323 / 2.384e-06, -3.7670e-05 * 0.98078528040323 / 2.384e-06, + 1.989123673796580e-01, + 1.847759065022573e+00, + + + -1.907e-06 * 0.989176509964781 / 2.384e-06, 9.0122e-05 * 0.989176509964781 / 2.384e-06, + 2.88486e-04 * 0.989176509964781 / 2.384e-06, -2.774239e-03 * 0.989176509964781 / 2.384e-06, + 3.2248020e-02 * 0.989176509964781 / 2.384e-06, 4.748821e-03 * 0.989176509964781 / 2.384e-06, 8.38757e-04 * 0.989176509964781 / 2.384e-06, 5.9605e-05 * 0.989176509964781 / 2.384e-06, /* 3 */ + 3.338e-06 * 0.989176509964781 / 2.384e-06, -3.9577e-05 * 0.989176509964781 / 2.384e-06, + 3.88145e-04 * 0.989176509964781 / 2.384e-06, 6.937027e-03 * 0.989176509964781 / 2.384e-06, + -2.8532982e-02 * 0.989176509964781 / 2.384e-06, -4.395962e-03 * 0.989176509964781 / 2.384e-06, + -6.46591e-04 * 0.989176509964781 / 2.384e-06, -4.0531e-05 * 0.989176509964781 / 2.384e-06, + 1.483359875383474e-01, + 1.913880671464418e+00, + + + -1.907e-06 * 0.995184726672197 / 2.384e-06, 8.4400e-05 * 0.995184726672197 / 2.384e-06, + 1.91689e-04 * 0.995184726672197 / 2.384e-06, -3.411293e-03 * 0.995184726672197 / 2.384e-06, + 3.1706810e-02 * 0.995184726672197 / 2.384e-06, 4.728317e-03 * 0.995184726672197 / 2.384e-06, + 8.09669e-04 * 0.995184726672197 / 2.384e-06, 5.579e-05 * 0.995184726672197 / 2.384e-06, + 3.338e-06 * 0.995184726672197 / 2.384e-06, -5.0545e-05 * 0.995184726672197 / 2.384e-06, + 2.59876e-04 * 0.995184726672197 / 2.384e-06, 6.189346e-03 * 0.995184726672197 / 2.384e-06, + -2.9224873e-02 * 0.995184726672197 / 2.384e-06, -4.489899e-03 * 0.995184726672197 / 2.384e-06, + -6.80923e-04 * 0.995184726672197 / 2.384e-06, -4.3392e-05 * 0.995184726672197 / 2.384e-06, + 9.849140335716425e-02, + 1.961570560806461e+00, + + + -2.384e-06 * 0.998795456205172 / 2.384e-06, 7.7724e-05 * 0.998795456205172 / 2.384e-06, + 8.8215e-05 * 0.998795456205172 / 2.384e-06, -4.072189e-03 * 0.998795456205172 / 2.384e-06, + 3.1132698e-02 * 0.998795456205172 / 2.384e-06, 4.691124e-03 * 0.998795456205172 / 2.384e-06, + 7.79152e-04 * 0.998795456205172 / 2.384e-06, 5.2929e-05 * 0.998795456205172 / 2.384e-06, + 2.861e-06 * 0.998795456205172 / 2.384e-06, -6.0558e-05 * 0.998795456205172 / 2.384e-06, + 1.37329e-04 * 0.998795456205172 / 2.384e-06, 5.462170e-03 * 0.998795456205172 / 2.384e-06, + -2.9890060e-02 * 0.998795456205172 / 2.384e-06, -4.570484e-03 * 0.998795456205172 / 2.384e-06, + -7.14302e-04 * 0.998795456205172 / 2.384e-06, -4.6253e-05 * 0.998795456205172 / 2.384e-06, + 4.912684976946725e-02, + 1.990369453344394e+00, + + + 3.5780907e-02 * SQRT2 * 0.5 / 2.384e-06, 1.7876148e-02 * SQRT2 * 0.5 / 2.384e-06, + 3.134727e-03 * SQRT2 * 0.5 / 2.384e-06, 2.457142e-03 * SQRT2 * 0.5 / 2.384e-06, + 9.71317e-04 * SQRT2 * 0.5 / 2.384e-06, 2.18868e-04 * SQRT2 * 0.5 / 2.384e-06, + 1.01566e-04 * SQRT2 * 0.5 / 2.384e-06, 1.3828e-05 * SQRT2 * 0.5 / 2.384e-06, + + 3.0526638e-02 / 2.384e-06, 4.638195e-03 / 2.384e-06, 7.47204e-04 / 2.384e-06, + 4.9591e-05 / 2.384e-06, + 4.756451e-03 / 2.384e-06, 2.1458e-05 / 2.384e-06, -6.9618e-05 / 2.384e-06, /* 2.384e-06/2.384e-06 */ +}; +#endif + + +#define NS 12 +#define NL 36 + +static const FLOAT win[4][NL] = { + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049690e-13, + 6.423305872147839e-13, + 2.382191739347918e-13, + + 5.456116108943412e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758252e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558783e-12, + 8.371015190102974e-13, + 2.599706096327376e-13, + + -5.456116108943412e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758252e-12, + -2.858043359288076e-12, + -2.156177623817898e-12, + -1.475637723558783e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347923e-13, + -6.423305872147843e-13, + -9.400849094049696e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049694e-13, + -6.423305872147840e-13, + -2.382191739347918e-13, + }, + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049688e-13, + 6.423305872147841e-13, + 2.382191739347918e-13, + + 5.456116108943413e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758253e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558782e-12, + 8.371015190102975e-13, + 2.599706096327376e-13, + + -5.461314069809755e-12, + -4.921085770524055e-12, + -4.343405037091838e-12, + -3.732668368707687e-12, + -3.093523840190885e-12, + -2.430835727329465e-12, + -1.734679010007751e-12, + -9.748253656609281e-13, + -2.797435120168326e-13, + + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + -2.283748241799531e-13, + -4.037858874020686e-13, + -2.146547464825323e-13, + }, + { + 1.316524975873958e-01, /* win[SHORT_TYPE] */ + 4.142135623730950e-01, + 7.673269879789602e-01, + + 1.091308501069271e+00, /* tantab_l */ + 1.303225372841206e+00, + 1.569685577117490e+00, + 1.920982126971166e+00, + 2.414213562373094e+00, + 3.171594802363212e+00, + 4.510708503662055e+00, + 7.595754112725146e+00, + 2.290376554843115e+01, + + 0.98480775301220802032, /* cx */ + 0.64278760968653936292, + 0.34202014332566882393, + 0.93969262078590842791, + -0.17364817766693030343, + -0.76604444311897790243, + 0.86602540378443870761, + 0.500000000000000e+00, + + -5.144957554275265e-01, /* ca */ + -4.717319685649723e-01, + -3.133774542039019e-01, + -1.819131996109812e-01, + -9.457419252642064e-02, + -4.096558288530405e-02, + -1.419856857247115e-02, + -3.699974673760037e-03, + + 8.574929257125442e-01, /* cs */ + 8.817419973177052e-01, + 9.496286491027329e-01, + 9.833145924917901e-01, + 9.955178160675857e-01, + 9.991605581781475e-01, + 9.998991952444470e-01, + 9.999931550702802e-01, + }, + { + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 2.283748241799531e-13, + 4.037858874020686e-13, + 2.146547464825323e-13, + + 5.461314069809755e-12, + 4.921085770524055e-12, + 4.343405037091838e-12, + 3.732668368707687e-12, + 3.093523840190885e-12, + 2.430835727329466e-12, + 1.734679010007751e-12, + 9.748253656609281e-13, + 2.797435120168326e-13, + + -5.456116108943413e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758253e-12, + -2.858043359288075e-12, + -2.156177623817898e-12, + -1.475637723558782e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347913e-13, + -6.423305872147834e-13, + -9.400849094049688e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049688e-13, + -6.423305872147841e-13, + -2.382191739347918e-13, + } +}; + +#define tantab_l (win[SHORT_TYPE]+3) +#define cx (win[SHORT_TYPE]+12) +#define ca (win[SHORT_TYPE]+20) +#define cs (win[SHORT_TYPE]+28) + +/************************************************************************ +* +* 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# +* +************************************************************************/ + +/* + * new IDCT routine written by Takehiro TOMINAGA + */ +static const int order[] = { + 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29, + 2, 3, 18, 19, 10, 11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 +}; + + +/* returns sum_j=0^31 a[j]*cos(PI*j*(k+1/2)/32), 0<=k<32 */ +inline static void +window_subband(const sample_t * x1, FLOAT a[SBLIMIT]) +{ + int i; + FLOAT const *wp = enwindow + 10; + + const sample_t *x2 = &x1[238 - 14 - 286]; + + for (i = -15; i < 0; i++) { + FLOAT w, s, t; + + w = wp[-10]; + s = x2[-224] * w; + t = x1[224] * w; + w = wp[-9]; + s += x2[-160] * w; + t += x1[160] * w; + w = wp[-8]; + s += x2[-96] * w; + t += x1[96] * w; + w = wp[-7]; + s += x2[-32] * w; + t += x1[32] * w; + w = wp[-6]; + s += x2[32] * w; + t += x1[-32] * w; + w = wp[-5]; + s += x2[96] * w; + t += x1[-96] * w; + w = wp[-4]; + s += x2[160] * w; + t += x1[-160] * w; + w = wp[-3]; + s += x2[224] * w; + t += x1[-224] * w; + + w = wp[-2]; + s += x1[-256] * w; + t -= x2[256] * w; + w = wp[-1]; + s += x1[-192] * w; + t -= x2[192] * w; + w = wp[0]; + s += x1[-128] * w; + t -= x2[128] * w; + w = wp[1]; + s += x1[-64] * w; + t -= x2[64] * w; + w = wp[2]; + s += x1[0] * w; + t -= x2[0] * w; + w = wp[3]; + s += x1[64] * w; + t -= x2[-64] * w; + w = wp[4]; + s += x1[128] * w; + t -= x2[-128] * w; + w = wp[5]; + s += x1[192] * w; + t -= x2[-192] * w; + + /* + * this multiplyer could be removed, but it needs more 256 FLOAT data. + * thinking about the data cache performance, I think we should not + * use such a huge table. tt 2000/Oct/25 + */ + s *= wp[6]; + w = t - s; + a[30 + i * 2] = t + s; + a[31 + i * 2] = wp[7] * w; + wp += 18; + x1--; + x2++; + } + { + FLOAT s, t, u, v; + t = x1[-16] * wp[-10]; + s = x1[-32] * wp[-2]; + t += (x1[-48] - x1[16]) * wp[-9]; + s += x1[-96] * wp[-1]; + t += (x1[-80] + x1[48]) * wp[-8]; + s += x1[-160] * wp[0]; + t += (x1[-112] - x1[80]) * wp[-7]; + s += x1[-224] * wp[1]; + t += (x1[-144] + x1[112]) * wp[-6]; + s -= x1[32] * wp[2]; + t += (x1[-176] - x1[144]) * wp[-5]; + s -= x1[96] * wp[3]; + t += (x1[-208] + x1[176]) * wp[-4]; + s -= x1[160] * wp[4]; + t += (x1[-240] - x1[208]) * wp[-3]; + s -= x1[224]; + + u = s - t; + v = s + t; + + t = a[14]; + s = a[15] - t; + + a[31] = v + t; /* A0 */ + a[30] = u + s; /* A1 */ + a[15] = u - s; /* A2 */ + a[14] = v - t; /* A3 */ + } + { + FLOAT xr; + xr = a[28] - a[0]; + a[0] += a[28]; + a[28] = xr * wp[-2 * 18 + 7]; + xr = a[29] - a[1]; + a[1] += a[29]; + a[29] = xr * wp[-2 * 18 + 7]; + + xr = a[26] - a[2]; + a[2] += a[26]; + a[26] = xr * wp[-4 * 18 + 7]; + xr = a[27] - a[3]; + a[3] += a[27]; + a[27] = xr * wp[-4 * 18 + 7]; + + xr = a[24] - a[4]; + a[4] += a[24]; + a[24] = xr * wp[-6 * 18 + 7]; + xr = a[25] - a[5]; + a[5] += a[25]; + a[25] = xr * wp[-6 * 18 + 7]; + + xr = a[22] - a[6]; + a[6] += a[22]; + a[22] = xr * SQRT2; + xr = a[23] - a[7]; + a[7] += a[23]; + a[23] = xr * SQRT2 - a[7]; + a[7] -= a[6]; + a[22] -= a[7]; + a[23] -= a[22]; + + xr = a[6]; + a[6] = a[31] - xr; + a[31] = a[31] + xr; + xr = a[7]; + a[7] = a[30] - xr; + a[30] = a[30] + xr; + xr = a[22]; + a[22] = a[15] - xr; + a[15] = a[15] + xr; + xr = a[23]; + a[23] = a[14] - xr; + a[14] = a[14] + xr; + + xr = a[20] - a[8]; + a[8] += a[20]; + a[20] = xr * wp[-10 * 18 + 7]; + xr = a[21] - a[9]; + a[9] += a[21]; + a[21] = xr * wp[-10 * 18 + 7]; + + xr = a[18] - a[10]; + a[10] += a[18]; + a[18] = xr * wp[-12 * 18 + 7]; + xr = a[19] - a[11]; + a[11] += a[19]; + a[19] = xr * wp[-12 * 18 + 7]; + + xr = a[16] - a[12]; + a[12] += a[16]; + a[16] = xr * wp[-14 * 18 + 7]; + xr = a[17] - a[13]; + a[13] += a[17]; + a[17] = xr * wp[-14 * 18 + 7]; + + xr = -a[20] + a[24]; + a[20] += a[24]; + a[24] = xr * wp[-12 * 18 + 7]; + xr = -a[21] + a[25]; + a[21] += a[25]; + a[25] = xr * wp[-12 * 18 + 7]; + + xr = a[4] - a[8]; + a[4] += a[8]; + a[8] = xr * wp[-12 * 18 + 7]; + xr = a[5] - a[9]; + a[5] += a[9]; + a[9] = xr * wp[-12 * 18 + 7]; + + xr = a[0] - a[12]; + a[0] += a[12]; + a[12] = xr * wp[-4 * 18 + 7]; + xr = a[1] - a[13]; + a[1] += a[13]; + a[13] = xr * wp[-4 * 18 + 7]; + xr = a[16] - a[28]; + a[16] += a[28]; + a[28] = xr * wp[-4 * 18 + 7]; + xr = -a[17] + a[29]; + a[17] += a[29]; + a[29] = xr * wp[-4 * 18 + 7]; + + xr = SQRT2 * (a[2] - a[10]); + a[2] += a[10]; + a[10] = xr; + xr = SQRT2 * (a[3] - a[11]); + a[3] += a[11]; + a[11] = xr; + xr = SQRT2 * (-a[18] + a[26]); + a[18] += a[26]; + a[26] = xr - a[18]; + xr = SQRT2 * (-a[19] + a[27]); + a[19] += a[27]; + a[27] = xr - a[19]; + + xr = a[2]; + a[19] -= a[3]; + a[3] -= xr; + a[2] = a[31] - xr; + a[31] += xr; + xr = a[3]; + a[11] -= a[19]; + a[18] -= xr; + a[3] = a[30] - xr; + a[30] += xr; + xr = a[18]; + a[27] -= a[11]; + a[19] -= xr; + a[18] = a[15] - xr; + a[15] += xr; + + xr = a[19]; + a[10] -= xr; + a[19] = a[14] - xr; + a[14] += xr; + xr = a[10]; + a[11] -= xr; + a[10] = a[23] - xr; + a[23] += xr; + xr = a[11]; + a[26] -= xr; + a[11] = a[22] - xr; + a[22] += xr; + xr = a[26]; + a[27] -= xr; + a[26] = a[7] - xr; + a[7] += xr; + + xr = a[27]; + a[27] = a[6] - xr; + a[6] += xr; + + xr = SQRT2 * (a[0] - a[4]); + a[0] += a[4]; + a[4] = xr; + xr = SQRT2 * (a[1] - a[5]); + a[1] += a[5]; + a[5] = xr; + xr = SQRT2 * (a[16] - a[20]); + a[16] += a[20]; + a[20] = xr; + xr = SQRT2 * (a[17] - a[21]); + a[17] += a[21]; + a[21] = xr; + + xr = -SQRT2 * (a[8] - a[12]); + a[8] += a[12]; + a[12] = xr - a[8]; + xr = -SQRT2 * (a[9] - a[13]); + a[9] += a[13]; + a[13] = xr - a[9]; + xr = -SQRT2 * (a[25] - a[29]); + a[25] += a[29]; + a[29] = xr - a[25]; + xr = -SQRT2 * (a[24] + a[28]); + a[24] -= a[28]; + a[28] = xr - a[24]; + + xr = a[24] - a[16]; + a[24] = xr; + xr = a[20] - xr; + a[20] = xr; + xr = a[28] - xr; + a[28] = xr; + + xr = a[25] - a[17]; + a[25] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[17] - a[1]; + a[17] = xr; + xr = a[9] - xr; + a[9] = xr; + xr = a[25] - xr; + a[25] = xr; + xr = a[5] - xr; + a[5] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[13] - xr; + a[13] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[1] - a[0]; + a[1] = xr; + xr = a[16] - xr; + a[16] = xr; + xr = a[17] - xr; + a[17] = xr; + xr = a[8] - xr; + a[8] = xr; + xr = a[9] - xr; + a[9] = xr; + xr = a[24] - xr; + a[24] = xr; + xr = a[25] - xr; + a[25] = xr; + xr = a[4] - xr; + a[4] = xr; + xr = a[5] - xr; + a[5] = xr; + xr = a[20] - xr; + a[20] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[12] - xr; + a[12] = xr; + xr = a[13] - xr; + a[13] = xr; + xr = a[28] - xr; + a[28] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[0]; + a[0] += a[31]; + a[31] -= xr; + xr = a[1]; + a[1] += a[30]; + a[30] -= xr; + xr = a[16]; + a[16] += a[15]; + a[15] -= xr; + xr = a[17]; + a[17] += a[14]; + a[14] -= xr; + xr = a[8]; + a[8] += a[23]; + a[23] -= xr; + xr = a[9]; + a[9] += a[22]; + a[22] -= xr; + xr = a[24]; + a[24] += a[7]; + a[7] -= xr; + xr = a[25]; + a[25] += a[6]; + a[6] -= xr; + xr = a[4]; + a[4] += a[27]; + a[27] -= xr; + xr = a[5]; + a[5] += a[26]; + a[26] -= xr; + xr = a[20]; + a[20] += a[11]; + a[11] -= xr; + xr = a[21]; + a[21] += a[10]; + a[10] -= xr; + xr = a[12]; + a[12] += a[19]; + a[19] -= xr; + xr = a[13]; + a[13] += a[18]; + a[18] -= xr; + xr = a[28]; + a[28] += a[3]; + a[3] -= xr; + xr = a[29]; + a[29] += a[2]; + a[2] -= xr; + } + +} + + +/*-------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the MDCT */ +/* In the case of long blocks (type 0,1,3) there are */ +/* 36 coefficents in the time domain and 18 in the frequency */ +/* domain. */ +/* In the case of short blocks (type 2) there are 3 */ +/* transformations with short length. This leads to 12 coefficents */ +/* in the time and 6 in the frequency domain. In this case the */ +/* results are stored side by side in the vector out[]. */ +/* */ +/* New layer3 */ +/* */ +/*-------------------------------------------------------------------*/ + +inline static void +mdct_short(FLOAT * inout) +{ + int l; + for (l = 0; l < 3; l++) { + FLOAT tc0, tc1, tc2, ts0, ts1, ts2; + + ts0 = inout[2 * 3] * win[SHORT_TYPE][0] - inout[5 * 3]; + tc0 = inout[0 * 3] * win[SHORT_TYPE][2] - inout[3 * 3]; + tc1 = ts0 + tc0; + tc2 = ts0 - tc0; + + ts0 = inout[5 * 3] * win[SHORT_TYPE][0] + inout[2 * 3]; + tc0 = inout[3 * 3] * win[SHORT_TYPE][2] + inout[0 * 3]; + ts1 = ts0 + tc0; + ts2 = -ts0 + tc0; + + tc0 = (inout[1 * 3] * win[SHORT_TYPE][1] - inout[4 * 3]) * 2.069978111953089e-11; /* tritab_s[1] */ + ts0 = (inout[4 * 3] * win[SHORT_TYPE][1] + inout[1 * 3]) * 2.069978111953089e-11; /* tritab_s[1] */ + + inout[3 * 0] = tc1 * 1.907525191737280e-11 /* tritab_s[2] */ + tc0; + inout[3 * 5] = -ts1 * 1.907525191737280e-11 /* tritab_s[0] */ + ts0; + + tc2 = tc2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[2] */ ; + ts1 = ts1 * 0.5 * 1.907525191737281e-11 + ts0; + inout[3 * 1] = tc2 - ts1; + inout[3 * 2] = tc2 + ts1; + + tc1 = tc1 * 0.5 * 1.907525191737281e-11 - tc0; + ts2 = ts2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[0] */ ; + inout[3 * 3] = tc1 + ts2; + inout[3 * 4] = tc1 - ts2; + + inout++; + } +} + +inline static void +mdct_long(FLOAT * out, FLOAT const *in) +{ + FLOAT ct, st; + { + FLOAT tc1, tc2, tc3, tc4, ts5, ts6, ts7, ts8; + /* 1,2, 5,6, 9,10, 13,14, 17 */ + tc1 = in[17] - in[9]; + tc3 = in[15] - in[11]; + tc4 = in[14] - in[12]; + ts5 = in[0] + in[8]; + ts6 = in[1] + in[7]; + ts7 = in[2] + in[6]; + ts8 = in[3] + in[5]; + + out[17] = (ts5 + ts7 - ts8) - (ts6 - in[4]); + st = (ts5 + ts7 - ts8) * cx[7] + (ts6 - in[4]); + ct = (tc1 - tc3 - tc4) * cx[6]; + out[5] = ct + st; + out[6] = ct - st; + + tc2 = (in[16] - in[10]) * cx[6]; + ts6 = ts6 * cx[7] + in[4]; + ct = tc1 * cx[0] + tc2 + tc3 * cx[1] + tc4 * cx[2]; + st = -ts5 * cx[4] + ts6 - ts7 * cx[5] + ts8 * cx[3]; + out[1] = ct + st; + out[2] = ct - st; + + ct = tc1 * cx[1] - tc2 - tc3 * cx[2] + tc4 * cx[0]; + st = -ts5 * cx[5] + ts6 - ts7 * cx[3] + ts8 * cx[4]; + out[9] = ct + st; + out[10] = ct - st; + + ct = tc1 * cx[2] - tc2 + tc3 * cx[0] - tc4 * cx[1]; + st = ts5 * cx[3] - ts6 + ts7 * cx[4] - ts8 * cx[5]; + out[13] = ct + st; + out[14] = ct - st; + } + { + FLOAT ts1, ts2, ts3, ts4, tc5, tc6, tc7, tc8; + + ts1 = in[8] - in[0]; + ts3 = in[6] - in[2]; + ts4 = in[5] - in[3]; + tc5 = in[17] + in[9]; + tc6 = in[16] + in[10]; + tc7 = in[15] + in[11]; + tc8 = in[14] + in[12]; + + out[0] = (tc5 + tc7 + tc8) + (tc6 + in[13]); + ct = (tc5 + tc7 + tc8) * cx[7] - (tc6 + in[13]); + st = (ts1 - ts3 + ts4) * cx[6]; + out[11] = ct + st; + out[12] = ct - st; + + ts2 = (in[7] - in[1]) * cx[6]; + tc6 = in[13] - tc6 * cx[7]; + ct = tc5 * cx[3] - tc6 + tc7 * cx[4] + tc8 * cx[5]; + st = ts1 * cx[2] + ts2 + ts3 * cx[0] + ts4 * cx[1]; + out[3] = ct + st; + out[4] = ct - st; + + ct = -tc5 * cx[5] + tc6 - tc7 * cx[3] - tc8 * cx[4]; + st = ts1 * cx[1] + ts2 - ts3 * cx[2] - ts4 * cx[0]; + out[7] = ct + st; + out[8] = ct - st; + + ct = -tc5 * cx[4] + tc6 - tc7 * cx[5] - tc8 * cx[3]; + st = ts1 * cx[0] - ts2 + ts3 * cx[1] - ts4 * cx[2]; + out[15] = ct + st; + out[16] = ct - st; + } +} + + +void +mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int gr, k, ch; + const sample_t *wk; + + wk = w0 + 286; + /* thinking cache performance, ch->gr loop is better than gr->ch loop */ + for (ch = 0; ch < cfg->channels_out; ch++) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + int band; + gr_info *const gi = &(gfc->l3_side.tt[gr][ch]); + FLOAT *mdct_enc = gi->xr; + FLOAT *samp = esv->sb_sample[ch][1 - gr][0]; + + for (k = 0; k < 18 / 2; k++) { + window_subband(wk, samp); + window_subband(wk + 32, samp + 32); + samp += 64; + wk += 64; + /* + * Compensate for inversion in the analysis filter + */ + for (band = 1; band < 32; band += 2) { + samp[band - 32] *= -1; + } + } + + /* + * Perform imdct of 18 previous subband samples + * + 18 current subband samples + */ + for (band = 0; band < 32; band++, mdct_enc += 18) { + int type = gi->block_type; + FLOAT const *const band0 = esv->sb_sample[ch][gr][0] + order[band]; + FLOAT *const band1 = esv->sb_sample[ch][1 - gr][0] + order[band]; + if (gi->mixed_block_flag && band < 2) + type = 0; + if (esv->amp_filter[band] < 1e-12) { + memset(mdct_enc, 0, 18 * sizeof(FLOAT)); + } + else { + if (esv->amp_filter[band] < 1.0) { + for (k = 0; k < 18; k++) + band1[k * 32] *= esv->amp_filter[band]; + } + if (type == SHORT_TYPE) { + for (k = -NS / 4; k < 0; k++) { + FLOAT const w = win[SHORT_TYPE][k + 3]; + mdct_enc[k * 3 + 9] = band0[(9 + k) * 32] * w - band0[(8 - k) * 32]; + mdct_enc[k * 3 + 18] = band0[(14 - k) * 32] * w + band0[(15 + k) * 32]; + mdct_enc[k * 3 + 10] = band0[(15 + k) * 32] * w - band0[(14 - k) * 32]; + mdct_enc[k * 3 + 19] = band1[(2 - k) * 32] * w + band1[(3 + k) * 32]; + mdct_enc[k * 3 + 11] = band1[(3 + k) * 32] * w - band1[(2 - k) * 32]; + mdct_enc[k * 3 + 20] = band1[(8 - k) * 32] * w + band1[(9 + k) * 32]; + } + mdct_short(mdct_enc); + } + else { + FLOAT work[18]; + for (k = -NL / 4; k < 0; k++) { + FLOAT a, b; + a = win[type][k + 27] * band1[(k + 9) * 32] + + win[type][k + 36] * band1[(8 - k) * 32]; + b = win[type][k + 9] * band0[(k + 9) * 32] + - win[type][k + 18] * band0[(8 - k) * 32]; + work[k + 9] = a - b * tantab_l[k + 9]; + work[k + 18] = a * tantab_l[k + 9] + b; + } + + mdct_long(mdct_enc, work); + } + } + /* + * Perform aliasing reduction butterfly + */ + if (type != SHORT_TYPE && band != 0) { + for (k = 7; k >= 0; --k) { + FLOAT bu, bd; + bu = mdct_enc[k] * ca[k] + mdct_enc[-1 - k] * cs[k]; + bd = mdct_enc[k] * cs[k] - mdct_enc[-1 - k] * ca[k]; + + mdct_enc[-1 - k] = bu; + mdct_enc[k] = bd; + } + } + } + } + wk = w1 + 286; + if (cfg->mode_gr == 1) { + memcpy(esv->sb_sample[ch][0], esv->sb_sample[ch][1], 576 * sizeof(FLOAT)); + } + } +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.h new file mode 100644 index 00000000..0b58a954 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/newmdct.h @@ -0,0 +1,27 @@ +/* + * New Modified DCT include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_NEWMDCT_H +#define LAME_NEWMDCT_H + +void mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1); + +#endif /* LAME_NEWMDCT_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/presets.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/presets.c new file mode 100644 index 00000000..93594f5b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/presets.c @@ -0,0 +1,404 @@ +/* + * presets.c -- Apply presets + * + * Copyright (c) 2002-2008 Gabriel Bouvigne + * Copyright (c) 2007-2012 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "set_get.h" +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" + +#define SET_OPTION(opt, val, def) if (enforce) \ + (void) lame_set_##opt(gfp, val); \ + else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \ + (void) lame_set_##opt(gfp, val); + +#define SET__OPTION(opt, val, def) if (enforce) \ + lame_set_##opt(gfp, val); \ + else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \ + lame_set_##opt(gfp, val); + +#undef Min +#undef Max + +static inline int +min_int(int a, int b) +{ + if (a < b) { + return a; + } + return b; +} + +static inline int +max_int(int a, int b) +{ + if (a > b) { + return a; + } + return b; +} + + + +typedef struct { + int vbr_q; + int quant_comp; + int quant_comp_s; + int expY; + FLOAT st_lrm; /*short threshold */ + FLOAT st_s; + FLOAT masking_adj; + FLOAT masking_adj_short; + FLOAT ath_lower; + FLOAT ath_curve; + FLOAT ath_sensitivity; + FLOAT interch; + int safejoint; + int sfb21mod; + FLOAT msfix; + FLOAT minval; + FLOAT ath_fixpoint; +} vbr_presets_t; + + /* *INDENT-OFF* */ + + /* Switch mappings for VBR mode VBR_RH */ + static const vbr_presets_t vbr_old_switch_map[] = { + /*vbr_q qcomp_l qcomp_s expY st_lrm st_s mask adj_l adj_s ath_lower ath_curve ath_sens interChR safejoint sfb21mod msfix */ + {0, 9, 9, 0, 5.20, 125.0, -4.2, -6.3, 4.8, 1, 0, 0, 2, 21, 0.97, 5, 100}, + {1, 9, 9, 0, 5.30, 125.0, -3.6, -5.6, 4.5, 1.5, 0, 0, 2, 21, 1.35, 5, 100}, + {2, 9, 9, 0, 5.60, 125.0, -2.2, -3.5, 2.8, 2, 0, 0, 2, 21, 1.49, 5, 100}, + {3, 9, 9, 1, 5.80, 130.0, -1.8, -2.8, 2.6, 3, -4, 0, 2, 20, 1.64, 5, 100}, + {4, 9, 9, 1, 6.00, 135.0, -0.7, -1.1, 1.1, 3.5, -8, 0, 2, 0, 1.79, 5, 100}, + {5, 9, 9, 1, 6.40, 140.0, 0.5, 0.4, -7.5, 4, -12, 0.0002, 0, 0, 1.95, 5, 100}, + {6, 9, 9, 1, 6.60, 145.0, 0.67, 0.65, -14.7, 6.5, -19, 0.0004, 0, 0, 2.30, 5, 100}, + {7, 9, 9, 1, 6.60, 145.0, 0.8, 0.75, -19.7, 8, -22, 0.0006, 0, 0, 2.70, 5, 100}, + {8, 9, 9, 1, 6.60, 145.0, 1.2, 1.15, -27.5, 10, -23, 0.0007, 0, 0, 0, 5, 100}, + {9, 9, 9, 1, 6.60, 145.0, 1.6, 1.6, -36, 11, -25, 0.0008, 0, 0, 0, 5, 100}, + {10, 9, 9, 1, 6.60, 145.0, 2.0, 2.0, -36, 12, -25, 0.0008, 0, 0, 0, 5, 100} + }; + + static const vbr_presets_t vbr_mt_psy_switch_map[] = { + /*vbr_q qcomp_l qcomp_s expY st_lrm st_s mask adj_l adj_s ath_lower ath_curve ath_sens --- safejoint sfb21mod msfix */ + {0, 9, 9, 0, 4.20, 25.0, -6.8, -6.8, 7.1, 1, 0, 0, 2, 31, 1.000, 5, 100}, + {1, 9, 9, 0, 4.20, 25.0, -4.8, -4.8, 5.4, 1.4, -1, 0, 2, 27, 1.122, 5, 98}, + {2, 9, 9, 0, 4.20, 25.0, -2.6, -2.6, 3.7, 2.0, -3, 0, 2, 23, 1.288, 5, 97}, + {3, 9, 9, 1, 4.20, 25.0, -1.6, -1.6, 2.0, 2.0, -5, 0, 2, 18, 1.479, 5, 96}, + {4, 9, 9, 1, 4.20, 25.0, -0.0, -0.0, 0.0, 2.0, -8, 0, 2, 12, 1.698, 5, 95}, + {5, 9, 9, 1, 4.20, 25.0, 1.3, 1.3, -6, 3.5, -11, 0, 2, 8, 1.950, 5, 94.2}, +#if 0 + {6, 9, 9, 1, 4.50, 100.0, 1.5, 1.5, -24.0, 6.0, -14, 0, 2, 4, 2.239, 3, 93.9}, + {7, 9, 9, 1, 4.80, 200.0, 1.7, 1.7, -28.0, 9.0, -20, 0, 2, 0, 2.570, 1, 93.6}, +#else + {6, 9, 9, 1, 4.50, 100.0, 2.2, 2.3, -12.0, 6.0, -14, 0, 2, 4, 2.239, 3, 93.9}, + {7, 9, 9, 1, 4.80, 200.0, 2.7, 2.7, -18.0, 9.0, -17, 0, 2, 0, 2.570, 1, 93.6}, +#endif + {8, 9, 9, 1, 5.30, 300.0, 2.8, 2.8, -21.0, 10.0, -23, 0.0002, 0, 0, 2.951, 0, 93.3}, + {9, 9, 9, 1, 6.60, 300.0, 2.8, 2.8, -23.0, 11.0, -25, 0.0006, 0, 0, 3.388, 0, 93.3}, + {10, 9, 9, 1, 25.00, 300.0, 2.8, 2.8, -25.0, 12.0, -27, 0.0025, 0, 0, 3.500, 0, 93.3} + }; + + /* *INDENT-ON* */ + +static vbr_presets_t const* +get_vbr_preset(int v) +{ + switch (v) { + case vbr_mtrh: + case vbr_mt: + return &vbr_mt_psy_switch_map[0]; + default: + return &vbr_old_switch_map[0]; + } +} + +#define NOOP(m) (void)p.m +#define LERP(m) (p.m = p.m + x * (q.m - p.m)) + +static void +apply_vbr_preset(lame_global_flags * gfp, int a, int enforce) +{ + vbr_presets_t const *vbr_preset = get_vbr_preset(lame_get_VBR(gfp)); + float x = gfp->VBR_q_frac; + vbr_presets_t p = vbr_preset[a]; + vbr_presets_t q = vbr_preset[a + 1]; + vbr_presets_t const *set = &p; + + NOOP(vbr_q); + NOOP(quant_comp); + NOOP(quant_comp_s); + NOOP(expY); + LERP(st_lrm); + LERP(st_s); + LERP(masking_adj); + LERP(masking_adj_short); + LERP(ath_lower); + LERP(ath_curve); + LERP(ath_sensitivity); + LERP(interch); + NOOP(safejoint); + LERP(sfb21mod); + LERP(msfix); + LERP(minval); + LERP(ath_fixpoint); + + (void) lame_set_VBR_q(gfp, set->vbr_q); + SET_OPTION(quant_comp, set->quant_comp, -1); + SET_OPTION(quant_comp_short, set->quant_comp_s, -1); + if (set->expY) { + (void) lame_set_experimentalY(gfp, set->expY); + } + SET_OPTION(short_threshold_lrm, set->st_lrm, -1); + SET_OPTION(short_threshold_s, set->st_s, -1); + SET_OPTION(maskingadjust, set->masking_adj, 0); + SET_OPTION(maskingadjust_short, set->masking_adj_short, 0); + if (lame_get_VBR(gfp) == vbr_mt || lame_get_VBR(gfp) == vbr_mtrh) { + lame_set_ATHtype(gfp, 5); + } + SET_OPTION(ATHlower, set->ath_lower, 0); + SET_OPTION(ATHcurve, set->ath_curve, -1); + SET_OPTION(athaa_sensitivity, set->ath_sensitivity, 0); + if (set->interch > 0) { + SET_OPTION(interChRatio, set->interch, -1); + } + + /* parameters for which there is no proper set/get interface */ + if (set->safejoint > 0) { + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); + } + if (set->sfb21mod > 0) { + int const nsp = lame_get_exp_nspsytune(gfp); + int const val = (nsp >> 20) & 63; + if (val == 0) { + int const sf21mod = (set->sfb21mod << 20) | nsp; + (void) lame_set_exp_nspsytune(gfp, sf21mod); + } + } + SET__OPTION(msfix, set->msfix, -1); + + if (enforce == 0) { + gfp->VBR_q = a; + gfp->VBR_q_frac = x; + } + gfp->internal_flags->cfg.minval = set->minval; + { /* take care of gain adjustments */ + double const x = fabs(gfp->scale); + double const y = (x > 0.f) ? (10.f * log10(x)) : 0.f; + gfp->internal_flags->cfg.ATHfixpoint = set->ath_fixpoint - y; + } +} + +static int +apply_abr_preset(lame_global_flags * gfp, int preset, int enforce) +{ + typedef struct { + int abr_kbps; + int quant_comp; + int quant_comp_s; + int safejoint; + FLOAT nsmsfix; + FLOAT st_lrm; /*short threshold */ + FLOAT st_s; + FLOAT scale; + FLOAT masking_adj; + FLOAT ath_lower; + FLOAT ath_curve; + FLOAT interch; + int sfscale; + } abr_presets_t; + + + /* *INDENT-OFF* */ + + /* + * Switch mappings for ABR mode + */ + const abr_presets_t abr_switch_map[] = { + /* kbps quant q_s safejoint nsmsfix st_lrm st_s scale msk ath_lwr ath_curve interch , sfscale */ + { 8, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -30.0, 11, 0.0012, 1}, /* 8, impossible to use in stereo */ + { 16, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -25.0, 11, 0.0010, 1}, /* 16 */ + { 24, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -20.0, 11, 0.0010, 1}, /* 24 */ + { 32, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -15.0, 11, 0.0010, 1}, /* 32 */ + { 40, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -10.0, 11, 0.0009, 1}, /* 40 */ + { 48, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -10.0, 11, 0.0009, 1}, /* 48 */ + { 56, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -6.0, 11, 0.0008, 1}, /* 56 */ + { 64, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -2.0, 11, 0.0008, 1}, /* 64 */ + { 80, 9, 9, 0, 0, 6.60, 145, 0.95, 0, .0, 8, 0.0007, 1}, /* 80 */ + { 96, 9, 9, 0, 2.50, 6.60, 145, 0.95, 0, 1.0, 5.5, 0.0006, 1}, /* 96 */ + {112, 9, 9, 0, 2.25, 6.60, 145, 0.95, 0, 2.0, 4.5, 0.0005, 1}, /* 112 */ + {128, 9, 9, 0, 1.95, 6.40, 140, 0.95, 0, 3.0, 4, 0.0002, 1}, /* 128 */ + {160, 9, 9, 1, 1.79, 6.00, 135, 0.95, -2, 5.0, 3.5, 0, 1}, /* 160 */ + {192, 9, 9, 1, 1.49, 5.60, 125, 0.97, -4, 7.0, 3, 0, 0}, /* 192 */ + {224, 9, 9, 1, 1.25, 5.20, 125, 0.98, -6, 9.0, 2, 0, 0}, /* 224 */ + {256, 9, 9, 1, 0.97, 5.20, 125, 1.00, -8, 10.0, 1, 0, 0}, /* 256 */ + {320, 9, 9, 1, 0.90, 5.20, 125, 1.00, -10, 12.0, 0, 0, 0} /* 320 */ + }; + + /* *INDENT-ON* */ + + /* Variables for the ABR stuff */ + int r; + int actual_bitrate = preset; + + r = nearestBitrateFullIndex(preset); + + (void) lame_set_VBR(gfp, vbr_abr); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, (actual_bitrate)); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, min_int(lame_get_VBR_mean_bitrate_kbps(gfp), 320)); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, max_int(lame_get_VBR_mean_bitrate_kbps(gfp), 8)); + (void) lame_set_brate(gfp, lame_get_VBR_mean_bitrate_kbps(gfp)); + + + /* parameters for which there is no proper set/get interface */ + if (abr_switch_map[r].safejoint > 0) + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); /* safejoint */ + + if (abr_switch_map[r].sfscale > 0) + (void) lame_set_sfscale(gfp, 1); + + + SET_OPTION(quant_comp, abr_switch_map[r].quant_comp, -1); + SET_OPTION(quant_comp_short, abr_switch_map[r].quant_comp_s, -1); + + SET__OPTION(msfix, abr_switch_map[r].nsmsfix, -1); + + SET_OPTION(short_threshold_lrm, abr_switch_map[r].st_lrm, -1); + SET_OPTION(short_threshold_s, abr_switch_map[r].st_s, -1); + + /* ABR seems to have big problems with clipping, especially at low bitrates */ + /* so we compensate for that here by using a scale value depending on bitrate */ + lame_set_scale(gfp, lame_get_scale(gfp) * abr_switch_map[r].scale); + + SET_OPTION(maskingadjust, abr_switch_map[r].masking_adj, 0); + if (abr_switch_map[r].masking_adj > 0) { + SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * .9, 0); + } + else { + SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * 1.1, 0); + } + + + SET_OPTION(ATHlower, abr_switch_map[r].ath_lower, 0); + SET_OPTION(ATHcurve, abr_switch_map[r].ath_curve, -1); + + SET_OPTION(interChRatio, abr_switch_map[r].interch, -1); + + (void) abr_switch_map[r].abr_kbps; + + gfp->internal_flags->cfg.minval = 5. * (abr_switch_map[r].abr_kbps / 320.); + + return preset; +} + + + +int +apply_preset(lame_global_flags * gfp, int preset, int enforce) +{ + /*translate legacy presets */ + switch (preset) { + case R3MIX: + { + preset = V3; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case MEDIUM: + case MEDIUM_FAST: + { + preset = V4; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case STANDARD: + case STANDARD_FAST: + { + preset = V2; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case EXTREME: + case EXTREME_FAST: + { + preset = V0; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case INSANE: + { + preset = 320; + gfp->preset = preset; + (void) apply_abr_preset(gfp, preset, enforce); + lame_set_VBR(gfp, vbr_off); + return preset; + } + } + + gfp->preset = preset; + { + switch (preset) { + case V9: + apply_vbr_preset(gfp, 9, enforce); + return preset; + case V8: + apply_vbr_preset(gfp, 8, enforce); + return preset; + case V7: + apply_vbr_preset(gfp, 7, enforce); + return preset; + case V6: + apply_vbr_preset(gfp, 6, enforce); + return preset; + case V5: + apply_vbr_preset(gfp, 5, enforce); + return preset; + case V4: + apply_vbr_preset(gfp, 4, enforce); + return preset; + case V3: + apply_vbr_preset(gfp, 3, enforce); + return preset; + case V2: + apply_vbr_preset(gfp, 2, enforce); + return preset; + case V1: + apply_vbr_preset(gfp, 1, enforce); + return preset; + case V0: + apply_vbr_preset(gfp, 0, enforce); + return preset; + default: + break; + } + } + if (8 <= preset && preset <= 320) { + return apply_abr_preset(gfp, preset, enforce); + } + + gfp->preset = 0; /*no corresponding preset found */ + return preset; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.c new file mode 100644 index 00000000..60076ee7 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.c @@ -0,0 +1,2167 @@ +/* + * psymodel.c + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2001-2002 Naoki Shibata + * Copyright (c) 2000-2003 Takehiro Tominaga + * Copyright (c) 2000-2012 Robert Hegemann + * Copyright (c) 2000-2005 Gabriel Bouvigne + * Copyright (c) 2000-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: psymodel.c,v 1.216 2017/09/06 19:38:23 aleidinger Exp $ */ + + +/* +PSYCHO ACOUSTICS + + +This routine computes the psycho acoustics, delayed by one granule. + +Input: buffer of PCM data (1024 samples). + +This window should be centered over the 576 sample granule window. +The routine will compute the psycho acoustics for +this granule, but return the psycho acoustics computed +for the *previous* granule. This is because the block +type of the previous granule can only be determined +after we have computed the psycho acoustics for the following +granule. + +Output: maskings and energies for each scalefactor band. +block type, PE, and some correlation measures. +The PE is used by CBR modes to determine if extra bits +from the bit reservoir should be used. The correlation +measures are used to determine mid/side or regular stereo. +*/ +/* +Notation: + +barks: a non-linear frequency scale. Mapping from frequency to + barks is given by freq2bark() + +scalefactor bands: The spectrum (frequencies) are broken into + SBMAX "scalefactor bands". Thes bands + are determined by the MPEG ISO spec. In + the noise shaping/quantization code, we allocate + bits among the partition bands to achieve the + best possible quality + +partition bands: The spectrum is also broken into about + 64 "partition bands". Each partition + band is about .34 barks wide. There are about 2-5 + partition bands for each scalefactor band. + +LAME computes all psycho acoustic information for each partition +band. Then at the end of the computations, this information +is mapped to scalefactor bands. The energy in each scalefactor +band is taken as the sum of the energy in all partition bands +which overlap the scalefactor band. The maskings can be computed +in the same way (and thus represent the average masking in that band) +or by taking the minmum value multiplied by the number of +partition bands used (which represents a minimum masking in that band). +*/ +/* +The general outline is as follows: + +1. compute the energy in each partition band +2. compute the tonality in each partition band +3. compute the strength of each partion band "masker" +4. compute the masking (via the spreading function applied to each masker) +5. Modifications for mid/side masking. + +Each partition band is considiered a "masker". The strength +of the i'th masker in band j is given by: + + s3(bark(i)-bark(j))*strength(i) + +The strength of the masker is a function of the energy and tonality. +The more tonal, the less masking. LAME uses a simple linear formula +(controlled by NMT and TMN) which says the strength is given by the +energy divided by a linear function of the tonality. +*/ +/* +s3() is the "spreading function". It is given by a formula +determined via listening tests. + +The total masking in the j'th partition band is the sum over +all maskings i. It is thus given by the convolution of +the strength with s3(), the "spreading function." + +masking(j) = sum_over_i s3(i-j)*strength(i) = s3 o strength + +where "o" = convolution operator. s3 is given by a formula determined +via listening tests. It is normalized so that s3 o 1 = 1. + +Note: instead of a simple convolution, LAME also has the +option of using "additive masking" + +The most critical part is step 2, computing the tonality of each +partition band. LAME has two tonality estimators. The first +is based on the ISO spec, and measures how predictiable the +signal is over time. The more predictable, the more tonal. +The second measure is based on looking at the spectrum of +a single granule. The more peaky the spectrum, the more +tonal. By most indications, the latter approach is better. + +Finally, in step 5, the maskings for the mid and side +channel are possibly increased. Under certain circumstances, +noise in the mid & side channels is assumed to also +be masked by strong maskers in the L or R channels. + + +Other data computed by the psy-model: + +ms_ratio side-channel / mid-channel masking ratio (for previous granule) +ms_ratio_next side-channel / mid-channel masking ratio for this granule + +percep_entropy[2] L and R values (prev granule) of PE - A measure of how + much pre-echo is in the previous granule +percep_entropy_MS[2] mid and side channel values (prev granule) of percep_entropy +energy[4] L,R,M,S energy in each channel, prev granule +blocktype_d[2] block type to use for previous granule +*/ + + + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <float.h> + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "psymodel.h" +#include "lame_global_flags.h" +#include "fft.h" +#include "lame-analysis.h" + + +#define NSFIRLEN 21 + +#ifdef M_LN10 +#define LN_TO_LOG10 (M_LN10/10) +#else +#define LN_TO_LOG10 0.2302585093 +#endif + + +/* + L3psycho_anal. Compute psycho acoustics. + + Data returned to the calling program must be delayed by one + granule. + + This is done in two places. + If we do not need to know the blocktype, the copying + can be done here at the top of the program: we copy the data for + the last granule (computed during the last call) before it is + overwritten with the new data. It looks like this: + + 0. static psymodel_data + 1. calling_program_data = psymodel_data + 2. compute psymodel_data + + For data which needs to know the blocktype, the copying must be + done at the end of this loop, and the old values must be saved: + + 0. static psymodel_data_old + 1. compute psymodel_data + 2. compute possible block type of this granule + 3. compute final block type of previous granule based on #2. + 4. calling_program_data = psymodel_data_old + 5. psymodel_data_old = psymodel_data +*/ + + + + + +/* psycho_loudness_approx + jd - 2001 mar 12 +in: energy - BLKSIZE/2 elements of frequency magnitudes ^ 2 + gfp - uses out_samplerate, ATHtype (also needed for ATHformula) +returns: loudness^2 approximation, a positive value roughly tuned for a value + of 1.0 for signals near clipping. +notes: When calibrated, feeding this function binary white noise at sample + values +32767 or -32768 should return values that approach 3. + ATHformula is used to approximate an equal loudness curve. +future: Data indicates that the shape of the equal loudness curve varies + with intensity. This function might be improved by using an equal + loudness curve shaped for typical playback levels (instead of the + ATH, that is shaped for the threshold). A flexible realization might + simply bend the existing ATH curve to achieve the desired shape. + However, the potential gain may not be enough to justify an effort. +*/ +static FLOAT +psycho_loudness_approx(FLOAT const *energy, FLOAT const *eql_w) +{ + int i; + FLOAT loudness_power; + + loudness_power = 0.0; + /* apply weights to power in freq. bands */ + for (i = 0; i < BLKSIZE / 2; ++i) + loudness_power += energy[i] * eql_w[i]; + loudness_power *= VO_SCALE; + + return loudness_power; +} + +/* mask_add optimization */ +/* init the limit values used to avoid computing log in mask_add when it is not necessary */ + +/* For example, with i = 10*log10(m2/m1)/10*16 (= log10(m2/m1)*16) + * + * abs(i)>8 is equivalent (as i is an integer) to + * abs(i)>=9 + * i>=9 || i<=-9 + * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16 + * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16) + * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16 + * exp10 is strictly increasing thus this is equivalent to + * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants + */ + + +#define I1LIMIT 8 /* as in if(i>8) */ +#define I2LIMIT 23 /* as in if(i>24) -> changed 23 */ +#define MLIMIT 15 /* as in if(m<15) */ + +/* pow(10, (I1LIMIT + 1) / 16.0); */ +static const FLOAT ma_max_i1 = 3.6517412725483771; +/* pow(10, (I2LIMIT + 1) / 16.0); */ +static const FLOAT ma_max_i2 = 31.622776601683793; +/* pow(10, (MLIMIT) / 10.0); */ +static const FLOAT ma_max_m = 31.622776601683793; + + /*This is the masking table: + According to tonality, values are going from 0dB (TMN) + to 9.3dB (NMT). + After additive masking computation, 8dB are added, so + final values are going from 8dB to 17.3dB + */ +static const FLOAT tab[] = { + 1.0 /*pow(10, -0) */ , + 0.79433 /*pow(10, -0.1) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.25119 /*pow(10, -0.6) */ , + 0.11749 /*pow(10, -0.93) */ +}; + +static const int tab_mask_add_delta[] = { 2, 2, 2, 1, 1, 1, 0, 0, -1 }; +#define STATIC_ASSERT_EQUAL_DIMENSION(A,B) enum{static_assert_##A=1/((dimension_of(A) == dimension_of(B))?1:0)} + +inline static int +mask_add_delta(int i) +{ + STATIC_ASSERT_EQUAL_DIMENSION(tab_mask_add_delta,tab); + assert(i < (int)dimension_of(tab)); + return tab_mask_add_delta[i]; +} + + +static void +init_mask_add_max_values(void) +{ +#ifndef NDEBUG + FLOAT const _ma_max_i1 = pow(10, (I1LIMIT + 1) / 16.0); + FLOAT const _ma_max_i2 = pow(10, (I2LIMIT + 1) / 16.0); + FLOAT const _ma_max_m = pow(10, (MLIMIT) / 10.0); + assert(fabs(ma_max_i1 - _ma_max_i1) <= FLT_EPSILON); + assert(fabs(ma_max_i2 - _ma_max_i2) <= FLT_EPSILON); + assert(fabs(ma_max_m - _ma_max_m ) <= FLT_EPSILON); +#endif +} + + + + +/* addition of simultaneous masking Naoki Shibata 2000/7 */ +inline static FLOAT +vbrpsy_mask_add(FLOAT m1, FLOAT m2, int b, int delta) +{ + static const FLOAT table2[] = { + 1.33352 * 1.33352, 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497, + 1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382, 1.22321 * 1.22321, + 1.14758 * 1.14758, + 1 + }; + + FLOAT ratio; + + if (m1 < 0) { + m1 = 0; + } + if (m2 < 0) { + m2 = 0; + } + if (m1 <= 0) { + return m2; + } + if (m2 <= 0) { + return m1; + } + if (m2 > m1) { + ratio = m2 / m1; + } + else { + ratio = m1 / m2; + } + if (abs(b) <= delta) { /* approximately, 1 bark = 3 partitions */ + /* originally 'if(i > 8)' */ + if (ratio >= ma_max_i1) { + return m1 + m2; + } + else { + int i = (int) (FAST_LOG10_X(ratio, 16.0f)); + return (m1 + m2) * table2[i]; + } + } + if (ratio < ma_max_i2) { + return m1 + m2; + } + if (m1 < m2) { + m1 = m2; + } + return m1; +} + + +/* short block threshold calculation (part 2) + + partition band bo_s[sfb] is at the transition from scalefactor + band sfb to the next one sfb+1; enn and thmm have to be split + between them +*/ +static void +convert_partition2scalefac(PsyConst_CB2SB_t const *const gd, FLOAT const *eb, FLOAT const *thr, + FLOAT enn_out[], FLOAT thm_out[]) +{ + FLOAT enn, thmm; + int sb, b, n = gd->n_sb; + enn = thmm = 0.0f; + for (sb = b = 0; sb < n; ++b, ++sb) { + int const bo_sb = gd->bo[sb]; + int const npart = gd->npart; + int const b_lim = bo_sb < npart ? bo_sb : npart; + while (b < b_lim) { + assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */ + assert(thr[b] >= 0); + enn += eb[b]; + thmm += thr[b]; + b++; + } + if (b >= npart) { + enn_out[sb] = enn; + thm_out[sb] = thmm; + ++sb; + break; + } + assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */ + assert(thr[b] >= 0); + { + /* at transition sfb -> sfb+1 */ + FLOAT const w_curr = gd->bo_weight[sb]; + FLOAT const w_next = 1.0f - w_curr; + enn += w_curr * eb[b]; + thmm += w_curr * thr[b]; + enn_out[sb] = enn; + thm_out[sb] = thmm; + enn = w_next * eb[b]; + thmm = w_next * thr[b]; + } + } + /* zero initialize the rest */ + for (; sb < n; ++sb) { + enn_out[sb] = 0; + thm_out[sb] = 0; + } +} + +static void +convert_partition2scalefac_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn, + int sblock) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + FLOAT enn[SBMAX_s], thm[SBMAX_s]; + int sb; + convert_partition2scalefac(gds, eb, thr, enn, thm); + for (sb = 0; sb < SBMAX_s; ++sb) { + psv->en[chn].s[sb][sblock] = enn[sb]; + psv->thm[chn].s[sb][sblock] = thm[sb]; + } +} + +/* longblock threshold calculation (part 2) */ +static void +convert_partition2scalefac_l(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + FLOAT *enn = &psv->en[chn].l[0]; + FLOAT *thm = &psv->thm[chn].l[0]; + convert_partition2scalefac(gdl, eb, thr, enn, thm); +} + +static void +convert_partition2scalefac_l_to_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, + int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->l_to_s; + FLOAT enn[SBMAX_s], thm[SBMAX_s]; + int sb, sblock; + convert_partition2scalefac(gds, eb, thr, enn, thm); + for (sb = 0; sb < SBMAX_s; ++sb) { + FLOAT const scale = 1. / 64.f; + FLOAT const tmp_enn = enn[sb]; + FLOAT const tmp_thm = thm[sb] * scale; + for (sblock = 0; sblock < 3; ++sblock) { + psv->en[chn].s[sb][sblock] = tmp_enn; + psv->thm[chn].s[sb][sblock] = tmp_thm; + } + } +} + + + +static inline FLOAT +NS_INTERP(FLOAT x, FLOAT y, FLOAT r) +{ + /* was pow((x),(r))*pow((y),1-(r)) */ + if (r >= 1.0f) + return x; /* 99.7% of the time */ + if (r <= 0.0f) + return y; + if (y > 0.0f) + return powf(x / y, r) * y; /* rest of the time */ + return 0.0f; /* never happens */ +} + + + +static FLOAT +pecalc_s(III_psy_ratio const *mr, FLOAT masking_lower) +{ + FLOAT pe_s; + static const FLOAT regcoef_s[] = { + 11.8, /* these values are tuned only for 44.1kHz... */ + 13.6, + 17.2, + 32, + 46.5, + 51.3, + 57.5, + 67.1, + 71.5, + 84.6, + 97.6, + 130, +/* 255.8 */ + }; + unsigned int sb, sblock; + + pe_s = 1236.28f / 4; + for (sb = 0; sb < SBMAX_s - 1; sb++) { + for (sblock = 0; sblock < 3; sblock++) { + FLOAT const thm = mr->thm.s[sb][sblock]; + assert(sb < dimension_of(regcoef_s)); + if (thm > 0.0f) { + FLOAT const x = thm * masking_lower; + FLOAT const en = mr->en.s[sb][sblock]; + if (en > x) { + if (en > x * 1e10f) { + pe_s += regcoef_s[sb] * (10.0f * LOG10); + } + else { + assert(x > 0); + pe_s += regcoef_s[sb] * FAST_LOG10(en / x); + } + } + } + } + } + + return pe_s; +} + +static FLOAT +pecalc_l(III_psy_ratio const *mr, FLOAT masking_lower) +{ + FLOAT pe_l; + static const FLOAT regcoef_l[] = { + 6.8, /* these values are tuned only for 44.1kHz... */ + 5.8, + 5.8, + 6.4, + 6.5, + 9.9, + 12.1, + 14.4, + 15, + 18.9, + 21.6, + 26.9, + 34.2, + 40.2, + 46.8, + 56.5, + 60.7, + 73.9, + 85.7, + 93.4, + 126.1, +/* 241.3 */ + }; + unsigned int sb; + + pe_l = 1124.23f / 4; + for (sb = 0; sb < SBMAX_l - 1; sb++) { + FLOAT const thm = mr->thm.l[sb]; + assert(sb < dimension_of(regcoef_l)); + if (thm > 0.0f) { + FLOAT const x = thm * masking_lower; + FLOAT const en = mr->en.l[sb]; + if (en > x) { + if (en > x * 1e10f) { + pe_l += regcoef_l[sb] * (10.0f * LOG10); + } + else { + assert(x > 0); + pe_l += regcoef_l[sb] * FAST_LOG10(en / x); + } + } + } + } + + return pe_l; +} + + +static void +calc_energy(PsyConst_CB2SB_t const *l, FLOAT const *fftenergy, FLOAT * eb, FLOAT * max, FLOAT * avg) +{ + int b, j; + + for (b = j = 0; b < l->npart; ++b) { + FLOAT ebb = 0, m = 0; + int i; + for (i = 0; i < l->numlines[b]; ++i, ++j) { + FLOAT const el = fftenergy[j]; + assert(el >= 0); + ebb += el; + if (m < el) + m = el; + } + eb[b] = ebb; + max[b] = m; + avg[b] = ebb * l->rnumlines[b]; + assert(l->rnumlines[b] >= 0); + assert(ebb >= 0); + assert(eb[b] >= 0); + assert(max[b] >= 0); + assert(avg[b] >= 0); + } +} + + +static void +calc_mask_index_l(lame_internal_flags const *gfc, FLOAT const *max, + FLOAT const *avg, unsigned char *mask_idx) +{ + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + FLOAT m, a; + int b, k; + int const last_tab_entry = sizeof(tab) / sizeof(tab[0]) - 1; + b = 0; + a = avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gdl->numlines[b] + gdl->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + + for (b = 1; b < gdl->npart - 1; b++) { + a = avg[b - 1] + avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 3.0f - a) + / (a * (gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + } + assert(b > 0); + assert(b == gdl->npart - 1); + + a = avg[b - 1] + avg[b]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + assert((gdl->numlines[b - 1] + gdl->numlines[b] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gdl->numlines[b - 1] + gdl->numlines[b] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + assert(b == (gdl->npart - 1)); +} + + +static void +vbrpsy_compute_fft_l(lame_internal_flags * gfc, const sample_t * const buffer[2], int chn, + int gr_out, FLOAT fftenergy[HBLKSIZE], FLOAT(*wsamp_l)[BLKSIZE]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *psv = &gfc->sv_psy; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + int j; + + if (chn < 2) { + fft_long(gfc, *wsamp_l, chn, buffer); + } + else if (chn == 2) { + FLOAT const sqrt2_half = SQRT2 * 0.5f; + /* FFT data for mid and side channel is derived from L & R */ + for (j = BLKSIZE - 1; j >= 0; --j) { + FLOAT const l = wsamp_l[0][j]; + FLOAT const r = wsamp_l[1][j]; + wsamp_l[0][j] = (l + r) * sqrt2_half; + wsamp_l[1][j] = (l - r) * sqrt2_half; + } + } + + /********************************************************************* + * compute energies + *********************************************************************/ + fftenergy[0] = wsamp_l[0][0]; + fftenergy[0] *= fftenergy[0]; + + for (j = BLKSIZE / 2 - 1; j >= 0; --j) { + FLOAT const re = (*wsamp_l)[BLKSIZE / 2 - j]; + FLOAT const im = (*wsamp_l)[BLKSIZE / 2 + j]; + fftenergy[BLKSIZE / 2 - j] = (re * re + im * im) * 0.5f; + } + /* total energy */ + { + FLOAT totalenergy = 0.0f; + for (j = 11; j < HBLKSIZE; j++) + totalenergy += fftenergy[j]; + + psv->tot_ener[chn] = totalenergy; + } + + if (plt) { + for (j = 0; j < HBLKSIZE; j++) { + plt->energy[gr_out][chn][j] = plt->energy_save[chn][j]; + plt->energy_save[chn][j] = fftenergy[j]; + } + } +} + + +static void +vbrpsy_compute_fft_s(lame_internal_flags const *gfc, const sample_t * const buffer[2], int chn, + int sblock, FLOAT(*fftenergy_s)[HBLKSIZE_s], FLOAT(*wsamp_s)[3][BLKSIZE_s]) +{ + int j; + + if (sblock == 0 && chn < 2) { + fft_short(gfc, *wsamp_s, chn, buffer); + } + if (chn == 2) { + FLOAT const sqrt2_half = SQRT2 * 0.5f; + /* FFT data for mid and side channel is derived from L & R */ + for (j = BLKSIZE_s - 1; j >= 0; --j) { + FLOAT const l = wsamp_s[0][sblock][j]; + FLOAT const r = wsamp_s[1][sblock][j]; + wsamp_s[0][sblock][j] = (l + r) * sqrt2_half; + wsamp_s[1][sblock][j] = (l - r) * sqrt2_half; + } + } + + /********************************************************************* + * compute energies + *********************************************************************/ + fftenergy_s[sblock][0] = (*wsamp_s)[sblock][0]; + fftenergy_s[sblock][0] *= fftenergy_s[sblock][0]; + for (j = BLKSIZE_s / 2 - 1; j >= 0; --j) { + FLOAT const re = (*wsamp_s)[sblock][BLKSIZE_s / 2 - j]; + FLOAT const im = (*wsamp_s)[sblock][BLKSIZE_s / 2 + j]; + fftenergy_s[sblock][BLKSIZE_s / 2 - j] = (re * re + im * im) * 0.5f; + } +} + + + /********************************************************************* + * compute loudness approximation (used for ATH auto-level adjustment) + *********************************************************************/ +static void +vbrpsy_compute_loudness_approximation_l(lame_internal_flags * gfc, int gr_out, int chn, + const FLOAT fftenergy[HBLKSIZE]) +{ + PsyStateVar_t *psv = &gfc->sv_psy; + if (chn < 2) { /*no loudness for mid/side ch */ + gfc->ov_psy.loudness_sq[gr_out][chn] = psv->loudness_sq_save[chn]; + psv->loudness_sq_save[chn] = psycho_loudness_approx(fftenergy, gfc->ATH->eql_w); + } +} + + + /********************************************************************** + * Apply HPF of fs/4 to the input signal. + * This is used for attack detection / handling. + **********************************************************************/ +static void +vbrpsy_attack_detection(lame_internal_flags * gfc, const sample_t * const buffer[2], int gr_out, + III_psy_ratio masking_ratio[2][2], III_psy_ratio masking_MS_ratio[2][2], + FLOAT energy[4], FLOAT sub_short_factor[4][3], int ns_attacks[4][4], + int uselongblock[2]) +{ + FLOAT ns_hpfsmpl[2][576]; + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + int const n_chn_out = cfg->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : n_chn_out; + int chn, i, j; + + memset(&ns_hpfsmpl[0][0], 0, sizeof(ns_hpfsmpl)); + /* Don't copy the input buffer into a temporary buffer */ + /* unroll the loop 2 times */ + for (chn = 0; chn < n_chn_out; chn++) { + static const FLOAT fircoef[] = { + -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2, + -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2, + -5.52212e-17 * 2, -0.313819 * 2 + }; + /* apply high pass filter of fs/4 */ + const sample_t *const firbuf = &buffer[chn][576 - 350 - NSFIRLEN + 192]; + assert(dimension_of(fircoef) == ((NSFIRLEN - 1) / 2)); + for (i = 0; i < 576; i++) { + FLOAT sum1, sum2; + sum1 = firbuf[i + 10]; + sum2 = 0.0; + for (j = 0; j < ((NSFIRLEN - 1) / 2) - 1; j += 2) { + sum1 += fircoef[j] * (firbuf[i + j] + firbuf[i + NSFIRLEN - j]); + sum2 += fircoef[j + 1] * (firbuf[i + j + 1] + firbuf[i + NSFIRLEN - j - 1]); + } + ns_hpfsmpl[chn][i] = sum1 + sum2; + } + masking_ratio[gr_out][chn].en = psv->en[chn]; + masking_ratio[gr_out][chn].thm = psv->thm[chn]; + if (n_chn_psy > 2) { + /* MS maskings */ + /*percep_MS_entropy [chn-2] = gfc -> pe [chn]; */ + masking_MS_ratio[gr_out][chn].en = psv->en[chn + 2]; + masking_MS_ratio[gr_out][chn].thm = psv->thm[chn + 2]; + } + } + for (chn = 0; chn < n_chn_psy; chn++) { + FLOAT attack_intensity[12]; + FLOAT en_subshort[12]; + FLOAT en_short[4] = { 0, 0, 0, 0 }; + FLOAT const *pf = ns_hpfsmpl[chn & 1]; + int ns_uselongblock = 1; + + if (chn == 2) { + for (i = 0, j = 576; j > 0; ++i, --j) { + FLOAT const l = ns_hpfsmpl[0][i]; + FLOAT const r = ns_hpfsmpl[1][i]; + ns_hpfsmpl[0][i] = l + r; + ns_hpfsmpl[1][i] = l - r; + } + } + /*************************************************************** + * determine the block type (window type) + ***************************************************************/ + /* calculate energies of each sub-shortblocks */ + for (i = 0; i < 3; i++) { + en_subshort[i] = psv->last_en_subshort[chn][i + 6]; + assert(psv->last_en_subshort[chn][i + 4] > 0); + attack_intensity[i] = en_subshort[i] / psv->last_en_subshort[chn][i + 4]; + en_short[0] += en_subshort[i]; + } + + for (i = 0; i < 9; i++) { + FLOAT const *const pfe = pf + 576 / 9; + FLOAT p = 1.; + for (; pf < pfe; pf++) + if (p < fabs(*pf)) + p = fabs(*pf); + psv->last_en_subshort[chn][i] = en_subshort[i + 3] = p; + en_short[1 + i / 3] += p; + if (p > en_subshort[i + 3 - 2]) { + assert(en_subshort[i + 3 - 2] > 0); + p = p / en_subshort[i + 3 - 2]; + } + else if (en_subshort[i + 3 - 2] > p * 10.0f) { + assert(p > 0); + p = en_subshort[i + 3 - 2] / (p * 10.0f); + } + else { + p = 0.0; + } + attack_intensity[i + 3] = p; + } + + /* pulse like signal detection for fatboy.wav and so on */ + for (i = 0; i < 3; ++i) { + FLOAT const enn = + en_subshort[i * 3 + 3] + en_subshort[i * 3 + 4] + en_subshort[i * 3 + 5]; + FLOAT factor = 1.f; + if (en_subshort[i * 3 + 5] * 6 < enn) { + factor *= 0.5f; + if (en_subshort[i * 3 + 4] * 6 < enn) { + factor *= 0.5f; + } + } + sub_short_factor[chn][i] = factor; + } + + if (plt) { + FLOAT x = attack_intensity[0]; + for (i = 1; i < 12; i++) { + if (x < attack_intensity[i]) { + x = attack_intensity[i]; + } + } + plt->ers[gr_out][chn] = plt->ers_save[chn]; + plt->ers_save[chn] = x; + } + + /* compare energies between sub-shortblocks */ + { + FLOAT x = gfc->cd_psy->attack_threshold[chn]; + for (i = 0; i < 12; i++) { + if (ns_attacks[chn][i / 3] == 0) { + if (attack_intensity[i] > x) { + ns_attacks[chn][i / 3] = (i % 3) + 1; + } + } + } + } + /* should have energy change between short blocks, in order to avoid periodic signals */ + /* Good samples to show the effect are Trumpet test songs */ + /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */ + /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */ + for (i = 1; i < 4; i++) { + FLOAT const u = en_short[i - 1]; + FLOAT const v = en_short[i]; + FLOAT const m = Max(u, v); + if (m < 40000) { /* (2) */ + if (u < 1.7f * v && v < 1.7f * u) { /* (1) */ + if (i == 1 && ns_attacks[chn][0] <= ns_attacks[chn][i]) { + ns_attacks[chn][0] = 0; + } + ns_attacks[chn][i] = 0; + } + } + } + + if (ns_attacks[chn][0] <= psv->last_attacks[chn]) { + ns_attacks[chn][0] = 0; + } + + if (psv->last_attacks[chn] == 3 || + ns_attacks[chn][0] + ns_attacks[chn][1] + ns_attacks[chn][2] + ns_attacks[chn][3]) { + ns_uselongblock = 0; + + if (ns_attacks[chn][1] && ns_attacks[chn][0]) { + ns_attacks[chn][1] = 0; + } + if (ns_attacks[chn][2] && ns_attacks[chn][1]) { + ns_attacks[chn][2] = 0; + } + if (ns_attacks[chn][3] && ns_attacks[chn][2]) { + ns_attacks[chn][3] = 0; + } + } + + if (chn < 2) { + uselongblock[chn] = ns_uselongblock; + } + else { + if (ns_uselongblock == 0) { + uselongblock[0] = uselongblock[1] = 0; + } + } + + /* there is a one granule delay. Copy maskings computed last call + * into masking_ratio to return to calling program. + */ + energy[chn] = psv->tot_ener[chn]; + } +} + + +static void +vbrpsy_skip_masking_s(lame_internal_flags * gfc, int chn, int sblock) +{ + if (sblock == 0) { + FLOAT *nbs2 = &gfc->sv_psy.nb_s2[chn][0]; + FLOAT *nbs1 = &gfc->sv_psy.nb_s1[chn][0]; + int const n = gfc->cd_psy->s.npart; + int b; + for (b = 0; b < n; b++) { + nbs2[b] = nbs1[b]; + } + } +} + + +static void +vbrpsy_calc_mask_index_s(lame_internal_flags const *gfc, FLOAT const *max, + FLOAT const *avg, unsigned char *mask_idx) +{ + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + FLOAT m, a; + int b, k; + int const last_tab_entry = dimension_of(tab) - 1; + b = 0; + a = avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gds->numlines[b] + gds->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gds->numlines[b] + gds->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + + for (b = 1; b < gds->npart - 1; b++) { + a = avg[b - 1] + avg[b] + avg[b + 1]; + assert(b + 1 < gds->npart); + assert(a >= 0); + if (a > 0.0) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 3.0f - a) + / (a * (gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + } + assert(b > 0); + assert(b == gds->npart - 1); + + a = avg[b - 1] + avg[b]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + assert((gds->numlines[b - 1] + gds->numlines[b] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gds->numlines[b - 1] + gds->numlines[b] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + assert(b == (gds->npart - 1)); +} + + +static void +vbrpsy_compute_masking_s(lame_internal_flags * gfc, const FLOAT(*fftenergy_s)[HBLKSIZE_s], + FLOAT * eb, FLOAT * thr, int chn, int sblock) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + FLOAT max[CBANDS], avg[CBANDS]; + int i, j, b; + unsigned char mask_idx_s[CBANDS]; + + memset(max, 0, sizeof(max)); + memset(avg, 0, sizeof(avg)); + + for (b = j = 0; b < gds->npart; ++b) { + FLOAT ebb = 0, m = 0; + int const n = gds->numlines[b]; + for (i = 0; i < n; ++i, ++j) { + FLOAT const el = fftenergy_s[sblock][j]; + ebb += el; + if (m < el) + m = el; + } + eb[b] = ebb; + assert(ebb >= 0); + max[b] = m; + assert(n > 0); + avg[b] = ebb * gds->rnumlines[b]; + assert(avg[b] >= 0); + } + assert(b == gds->npart); + assert(j == 129); + vbrpsy_calc_mask_index_s(gfc, max, avg, mask_idx_s); + for (j = b = 0; b < gds->npart; b++) { + int kk = gds->s3ind[b][0]; + int const last = gds->s3ind[b][1]; + int const delta = mask_add_delta(mask_idx_s[b]); + int dd, dd_n; + FLOAT x, ecb, avg_mask; + FLOAT const masking_lower = gds->masking_lower[b] * gfc->sv_qnt.masking_lower; + + dd = mask_idx_s[kk]; + dd_n = 1; + ecb = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]]; + ++j, ++kk; + while (kk <= last) { + dd += mask_idx_s[kk]; + dd_n += 1; + x = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]]; + ecb = vbrpsy_mask_add(ecb, x, kk - b, delta); + ++j, ++kk; + } + dd = (1 + 2 * dd) / (2 * dd_n); + avg_mask = tab[dd] * 0.5f; + ecb *= avg_mask; +#if 0 /* we can do PRE ECHO control now here, or do it later */ + if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) { + /* limit calculated threshold by even older granule */ + FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b]; + FLOAT const t2 = rpelev2_s * psv->nb_s2[chn][b]; + FLOAT const tm = (t2 > 0) ? Min(ecb, t2) : ecb; + thr[b] = (t1 > 0) ? NS_INTERP(Min(tm, t1), ecb, 0.6) : ecb; + } + else { + /* limit calculated threshold by older granule */ + FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b]; + thr[b] = (t1 > 0) ? NS_INTERP(Min(ecb, t1), ecb, 0.6) : ecb; + } +#else /* we do it later */ + thr[b] = ecb; +#endif + psv->nb_s2[chn][b] = psv->nb_s1[chn][b]; + psv->nb_s1[chn][b] = ecb; + { + /* if THR exceeds EB, the quantization routines will take the difference + * from other bands. in case of strong tonal samples (tonaltest.wav) + * this leads to heavy distortions. that's why we limit THR here. + */ + x = max[b]; + x *= gds->minval[b]; + x *= avg_mask; + if (thr[b] > x) { + thr[b] = x; + } + } + if (masking_lower > 1) { + thr[b] *= masking_lower; + } + if (thr[b] > eb[b]) { + thr[b] = eb[b]; + } + if (masking_lower < 1) { + thr[b] *= masking_lower; + } + + assert(thr[b] >= 0); + } + for (; b < CBANDS; ++b) { + eb[b] = 0; + thr[b] = 0; + } +} + + +static void +vbrpsy_compute_masking_l(lame_internal_flags * gfc, const FLOAT fftenergy[HBLKSIZE], + FLOAT eb_l[CBANDS], FLOAT thr[CBANDS], int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + FLOAT max[CBANDS], avg[CBANDS]; + unsigned char mask_idx_l[CBANDS + 2]; + int k, b; + + /********************************************************************* + * Calculate the energy and the tonality of each partition. + *********************************************************************/ + calc_energy(gdl, fftenergy, eb_l, max, avg); + calc_mask_index_l(gfc, max, avg, mask_idx_l); + + /********************************************************************* + * convolve the partitioned energy and unpredictability + * with the spreading function, s3_l[b][k] + ********************************************************************/ + k = 0; + for (b = 0; b < gdl->npart; b++) { + FLOAT x, ecb, avg_mask, t; + FLOAT const masking_lower = gdl->masking_lower[b] * gfc->sv_qnt.masking_lower; + /* convolve the partitioned energy with the spreading function */ + int kk = gdl->s3ind[b][0]; + int const last = gdl->s3ind[b][1]; + int const delta = mask_add_delta(mask_idx_l[b]); + int dd = 0, dd_n = 0; + + dd = mask_idx_l[kk]; + dd_n += 1; + ecb = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]]; + ++k, ++kk; + while (kk <= last) { + dd += mask_idx_l[kk]; + dd_n += 1; + x = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]]; + t = vbrpsy_mask_add(ecb, x, kk - b, delta); +#if 0 + ecb += eb_l[kk]; + if (ecb > t) { + ecb = t; + } +#else + ecb = t; +#endif + ++k, ++kk; + } + dd = (1 + 2 * dd) / (2 * dd_n); + avg_mask = tab[dd] * 0.5f; + ecb *= avg_mask; + + /**** long block pre-echo control ****/ + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) { + FLOAT const ecb_limit = rpelev * psv->nb_l1[chn][b]; + if (ecb_limit > 0) { + thr[b] = Min(ecb, ecb_limit); + } + else { + /* Robert 071209: + Because we don't calculate long block psy when we know a granule + should be of short blocks, we don't have any clue how the granule + before would have looked like as a long block. So we have to guess + a little bit for this END_TYPE block. + Most of the time we get away with this sloppyness. (fingers crossed :) + The speed increase is worth it. + */ + thr[b] = Min(ecb, eb_l[b] * NS_PREECHO_ATT2); + } + } + else { + FLOAT ecb_limit_2 = rpelev2 * psv->nb_l2[chn][b]; + FLOAT ecb_limit_1 = rpelev * psv->nb_l1[chn][b]; + FLOAT ecb_limit; + if (ecb_limit_2 <= 0) { + ecb_limit_2 = ecb; + } + if (ecb_limit_1 <= 0) { + ecb_limit_1 = ecb; + } + if (psv->blocktype_old[chn & 0x01] == NORM_TYPE) { + ecb_limit = Min(ecb_limit_1, ecb_limit_2); + } + else { + ecb_limit = ecb_limit_1; + } + thr[b] = Min(ecb, ecb_limit); + } + psv->nb_l2[chn][b] = psv->nb_l1[chn][b]; + psv->nb_l1[chn][b] = ecb; + { + /* if THR exceeds EB, the quantization routines will take the difference + * from other bands. in case of strong tonal samples (tonaltest.wav) + * this leads to heavy distortions. that's why we limit THR here. + */ + x = max[b]; + x *= gdl->minval[b]; + x *= avg_mask; + if (thr[b] > x) { + thr[b] = x; + } + } + if (masking_lower > 1) { + thr[b] *= masking_lower; + } + if (thr[b] > eb_l[b]) { + thr[b] = eb_l[b]; + } + if (masking_lower < 1) { + thr[b] *= masking_lower; + } + assert(thr[b] >= 0); + } + for (; b < CBANDS; ++b) { + eb_l[b] = 0; + thr[b] = 0; + } +} + + +static void +vbrpsy_compute_block_type(SessionConfig_t const *cfg, int *uselongblock) +{ + int chn; + + if (cfg->short_blocks == short_block_coupled + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + && !(uselongblock[0] && uselongblock[1])) + uselongblock[0] = uselongblock[1] = 0; + + for (chn = 0; chn < cfg->channels_out; chn++) { + /* disable short blocks */ + if (cfg->short_blocks == short_block_dispensed) { + uselongblock[chn] = 1; + } + if (cfg->short_blocks == short_block_forced) { + uselongblock[chn] = 0; + } + } +} + + +static void +vbrpsy_apply_block_type(PsyStateVar_t * psv, int nch, int const *uselongblock, int *blocktype_d) +{ + int chn; + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn = 0; chn < nch; chn++) { + int blocktype = NORM_TYPE; + /* disable short blocks */ + + if (uselongblock[chn]) { + /* no attack : use long blocks */ + assert(psv->blocktype_old[chn] != START_TYPE); + if (psv->blocktype_old[chn] == SHORT_TYPE) + blocktype = STOP_TYPE; + } + else { + /* attack : use short blocks */ + blocktype = SHORT_TYPE; + if (psv->blocktype_old[chn] == NORM_TYPE) { + psv->blocktype_old[chn] = START_TYPE; + } + if (psv->blocktype_old[chn] == STOP_TYPE) + psv->blocktype_old[chn] = SHORT_TYPE; + } + + blocktype_d[chn] = psv->blocktype_old[chn]; /* value returned to calling program */ + psv->blocktype_old[chn] = blocktype; /* save for next call to l3psy_anal */ + } +} + + +/*************************************************************** + * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper + ***************************************************************/ + +static void +vbrpsy_compute_MS_thresholds(const FLOAT eb[4][CBANDS], FLOAT thr[4][CBANDS], + const FLOAT cb_mld[CBANDS], const FLOAT ath_cb[CBANDS], FLOAT athlower, + FLOAT msfix, int n) +{ + FLOAT const msfix2 = msfix * 2.f; + FLOAT rside, rmid; + int b; + for (b = 0; b < n; ++b) { + FLOAT const ebM = eb[2][b]; + FLOAT const ebS = eb[3][b]; + FLOAT const thmL = thr[0][b]; + FLOAT const thmR = thr[1][b]; + FLOAT thmM = thr[2][b]; + FLOAT thmS = thr[3][b]; + + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (thmL <= 1.58f * thmR && thmR <= 1.58f * thmL) { + FLOAT const mld_m = cb_mld[b] * ebS; + FLOAT const mld_s = cb_mld[b] * ebM; + FLOAT const tmp_m = Min(thmS, mld_m); + FLOAT const tmp_s = Min(thmM, mld_s); + rmid = Max(thmM, tmp_m); + rside = Max(thmS, tmp_s); + } + else { + rmid = thmM; + rside = thmS; + } + if (msfix > 0.f) { + /***************************************************************/ + /* Adjust M/S maskings if user set "msfix" */ + /***************************************************************/ + /* Naoki Shibata 2000 */ + FLOAT thmLR, thmMS; + FLOAT const ath = ath_cb[b] * athlower; + FLOAT const tmp_l = Max(thmL, ath); + FLOAT const tmp_r = Max(thmR, ath); + thmLR = Min(tmp_l, tmp_r); + thmM = Max(rmid, ath); + thmS = Max(rside, ath); + thmMS = thmM + thmS; + if (thmMS > 0.f && (thmLR * msfix2) < thmMS) { + FLOAT const f = thmLR * msfix2 / thmMS; + thmM *= f; + thmS *= f; + assert(thmMS > 0.f); + } + rmid = Min(thmM, rmid); + rside = Min(thmS, rside); + } + if (rmid > ebM) { + rmid = ebM; + } + if (rside > ebS) { + rside = ebS; + } + thr[2][b] = rmid; + thr[3][b] = rside; + } +} + + +/* + * NOTE: the bitrate reduction from the inter-channel masking effect is low + * compared to the chance of getting annyoing artefacts. L3psycho_anal_vbr does + * not use this feature. (Robert 071216) +*/ + +int +L3psycho_anal_vbr(lame_internal_flags * gfc, + const sample_t * const buffer[2], int gr_out, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT percep_entropy[2], FLOAT percep_MS_entropy[2], + FLOAT energy[4], int blocktype_d[2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + + III_psy_xmin last_thm[4]; + + /* fft and energy calculation */ + FLOAT(*wsamp_l)[BLKSIZE]; + FLOAT(*wsamp_s)[3][BLKSIZE_s]; + FLOAT fftenergy[HBLKSIZE]; + FLOAT fftenergy_s[3][HBLKSIZE_s]; + FLOAT wsamp_L[2][BLKSIZE]; + FLOAT wsamp_S[2][3][BLKSIZE_s]; + FLOAT eb[4][CBANDS], thr[4][CBANDS]; + + FLOAT sub_short_factor[4][3]; + FLOAT thmm; + FLOAT const pcfact = 0.6f; + FLOAT const ath_factor = + (cfg->msfix > 0.f) ? (cfg->ATH_offset_factor * gfc->ATH->adjust_factor) : 1.f; + + const FLOAT(*const_eb)[CBANDS] = (const FLOAT(*)[CBANDS]) eb; + const FLOAT(*const_fftenergy_s)[HBLKSIZE_s] = (const FLOAT(*)[HBLKSIZE_s]) fftenergy_s; + + /* block type */ + int ns_attacks[4][4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} }; + int uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int chn, sb, sblock; + + /* chn=2 and 3 = Mid and Side channels */ + int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : cfg->channels_out; + + memcpy(&last_thm[0], &psv->thm[0], sizeof(last_thm)); + + vbrpsy_attack_detection(gfc, buffer, gr_out, masking_ratio, masking_MS_ratio, energy, + sub_short_factor, ns_attacks, uselongblock); + + vbrpsy_compute_block_type(cfg, uselongblock); + + /* LONG BLOCK CASE */ + { + for (chn = 0; chn < n_chn_psy; chn++) { + int const ch01 = chn & 0x01; + + wsamp_l = wsamp_L + ch01; + vbrpsy_compute_fft_l(gfc, buffer, chn, gr_out, fftenergy, wsamp_l); + vbrpsy_compute_loudness_approximation_l(gfc, gr_out, chn, fftenergy); + vbrpsy_compute_masking_l(gfc, fftenergy, eb[chn], thr[chn], chn); + } + if (cfg->mode == JOINT_STEREO) { + if ((uselongblock[0] + uselongblock[1]) == 2) { + vbrpsy_compute_MS_thresholds(const_eb, thr, gdl->mld_cb, gfc->ATH->cb_l, + ath_factor, cfg->msfix, gdl->npart); + } + } + /* TODO: apply adaptive ATH masking here ?? */ + for (chn = 0; chn < n_chn_psy; chn++) { + convert_partition2scalefac_l(gfc, eb[chn], thr[chn], chn); + convert_partition2scalefac_l_to_s(gfc, eb[chn], thr[chn], chn); + } + } + /* SHORT BLOCKS CASE */ + { + int const force_short_block_calc = gfc->cd_psy->force_short_block_calc; + for (sblock = 0; sblock < 3; sblock++) { + for (chn = 0; chn < n_chn_psy; ++chn) { + int const ch01 = chn & 0x01; + if (uselongblock[ch01] && !force_short_block_calc) { + vbrpsy_skip_masking_s(gfc, chn, sblock); + } + else { + /* compute masking thresholds for short blocks */ + wsamp_s = wsamp_S + ch01; + vbrpsy_compute_fft_s(gfc, buffer, chn, sblock, fftenergy_s, wsamp_s); + vbrpsy_compute_masking_s(gfc, const_fftenergy_s, eb[chn], thr[chn], chn, + sblock); + } + } + if (cfg->mode == JOINT_STEREO) { + if ((uselongblock[0] + uselongblock[1]) == 0) { + vbrpsy_compute_MS_thresholds(const_eb, thr, gds->mld_cb, gfc->ATH->cb_s, + ath_factor, cfg->msfix, gds->npart); + } + } + /* TODO: apply adaptive ATH masking here ?? */ + for (chn = 0; chn < n_chn_psy; ++chn) { + int const ch01 = chn & 0x01; + if (!uselongblock[ch01] || force_short_block_calc) { + convert_partition2scalefac_s(gfc, eb[chn], thr[chn], chn, sblock); + } + } + } + + /**** short block pre-echo control ****/ + for (chn = 0; chn < n_chn_psy; chn++) { + for (sb = 0; sb < SBMAX_s; sb++) { + FLOAT new_thmm[3], prev_thm, t1, t2; + for (sblock = 0; sblock < 3; sblock++) { + thmm = psv->thm[chn].s[sb][sblock]; + thmm *= NS_PREECHO_ATT0; + + t1 = t2 = thmm; + + if (sblock > 0) { + prev_thm = new_thmm[sblock - 1]; + } + else { + prev_thm = last_thm[chn].s[sb][2]; + } + if (ns_attacks[chn][sblock] >= 2 || ns_attacks[chn][sblock + 1] == 1) { + t1 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT1 * pcfact); + } + thmm = Min(t1, thmm); + if (ns_attacks[chn][sblock] == 1) { + t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact); + } + else if ((sblock == 0 && psv->last_attacks[chn] == 3) + || (sblock > 0 && ns_attacks[chn][sblock - 1] == 3)) { /* 2nd preceeding block */ + switch (sblock) { + case 0: + prev_thm = last_thm[chn].s[sb][1]; + break; + case 1: + prev_thm = last_thm[chn].s[sb][2]; + break; + case 2: + prev_thm = new_thmm[0]; + break; + } + t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact); + } + + thmm = Min(t1, thmm); + thmm = Min(t2, thmm); + + /* pulse like signal detection for fatboy.wav and so on */ + thmm *= sub_short_factor[chn][sblock]; + + new_thmm[sblock] = thmm; + } + for (sblock = 0; sblock < 3; sblock++) { + psv->thm[chn].s[sb][sblock] = new_thmm[sblock]; + } + } + } + } + for (chn = 0; chn < n_chn_psy; chn++) { + psv->last_attacks[chn] = ns_attacks[chn][2]; + } + + + /*************************************************************** + * determine final block type + ***************************************************************/ + vbrpsy_apply_block_type(psv, cfg->channels_out, uselongblock, blocktype_d); + + /********************************************************************* + * compute the value of PE to return ... no delay and advance + *********************************************************************/ + for (chn = 0; chn < n_chn_psy; chn++) { + FLOAT *ppe; + int type; + III_psy_ratio const *mr; + + if (chn > 1) { + ppe = percep_MS_entropy - 2; + type = NORM_TYPE; + if (blocktype_d[0] == SHORT_TYPE || blocktype_d[1] == SHORT_TYPE) + type = SHORT_TYPE; + mr = &masking_MS_ratio[gr_out][chn - 2]; + } + else { + ppe = percep_entropy; + type = blocktype_d[chn]; + mr = &masking_ratio[gr_out][chn]; + } + if (type == SHORT_TYPE) { + ppe[chn] = pecalc_s(mr, gfc->sv_qnt.masking_lower); + } + else { + ppe[chn] = pecalc_l(mr, gfc->sv_qnt.masking_lower); + } + + if (plt) { + plt->pe[gr_out][chn] = ppe[chn]; + } + } + return 0; +} + + + + +/* + * The spreading function. Values returned in units of energy + */ +static FLOAT +s3_func(FLOAT bark) +{ + FLOAT tempx, x, tempy, temp; + tempx = bark; + if (tempx >= 0) + tempx *= 3; + else + tempx *= 1.5; + + 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); + + /* Normalization. The spreading function should be normalized so that: + +inf + / + | s3 [ bark ] d(bark) = 1 + / + -inf + */ + tempx /= .6609193; + return tempx; +} + +#if 0 +static FLOAT +norm_s3_func(void) +{ + double lim_a = 0, lim_b = 0; + double x = 0, l, h; + for (x = 0; s3_func(x) > 1e-20; x -= 1); + l = x; + h = 0; + while (fabs(h - l) > 1e-12) { + x = (h + l) / 2; + if (s3_func(x) > 0) { + h = x; + } + else { + l = x; + } + } + lim_a = l; + for (x = 0; s3_func(x) > 1e-20; x += 1); + l = 0; + h = x; + while (fabs(h - l) > 1e-12) { + x = (h + l) / 2; + if (s3_func(x) > 0) { + l = x; + } + else { + h = x; + } + } + lim_b = h; + { + double sum = 0; + int const m = 1000; + int i; + for (i = 0; i <= m; ++i) { + double x = lim_a + i * (lim_b - lim_a) / m; + double y = s3_func(x); + sum += y; + } + { + double norm = (m + 1) / (sum * (lim_b - lim_a)); + /*printf( "norm = %lf\n",norm); */ + return norm; + } + } +} +#endif + +static FLOAT +stereo_demask(double f) +{ + /* setup stereo demasking thresholds */ + /* formula reverse enginerred from plot in paper */ + double arg = freq2bark(f); + arg = (Min(arg, 15.5) / 15.5); + + return pow(10.0, 1.25 * (1 - cos(PI * arg)) - 2.5); +} + +static void +init_numline(PsyConst_CB2SB_t * gd, FLOAT sfreq, int fft_size, + int mdct_size, int sbmax, int const *scalepos) +{ + FLOAT b_frq[CBANDS + 1]; + FLOAT const mdct_freq_frac = sfreq / (2.0f * mdct_size); + FLOAT const deltafreq = fft_size / (2.0f * mdct_size); + int partition[HBLKSIZE] = { 0 }; + int i, j, ni; + int sfb; + sfreq /= fft_size; + j = 0; + ni = 0; + /* compute numlines, the number of spectral lines in each partition band */ + /* each partition band should be about DELBARK wide. */ + for (i = 0; i < CBANDS; i++) { + FLOAT bark1; + int j2, nl; + bark1 = freq2bark(sfreq * j); + + b_frq[i] = sfreq * j; + + for (j2 = j; freq2bark(sfreq * j2) - bark1 < DELBARK && j2 <= fft_size / 2; j2++); + + nl = j2 - j; + gd->numlines[i] = nl; + gd->rnumlines[i] = (nl > 0) ? (1.0f / nl) : 0; + + ni = i + 1; + + while (j < j2) { + assert(j < HBLKSIZE); + partition[j++] = i; + } + if (j > fft_size / 2) { + j = fft_size / 2; + ++i; + break; + } + } + assert(i < CBANDS); + b_frq[i] = sfreq * j; + + gd->n_sb = sbmax; + gd->npart = ni; + + { + j = 0; + for (i = 0; i < gd->npart; i++) { + int const nl = gd->numlines[i]; + FLOAT const freq = sfreq * (j + nl / 2); + gd->mld_cb[i] = stereo_demask(freq); + j += nl; + } + for (; i < CBANDS; ++i) { + gd->mld_cb[i] = 1; + } + } + for (sfb = 0; sfb < sbmax; sfb++) { + int i1, i2, bo; + int start = scalepos[sfb]; + int end = scalepos[sfb + 1]; + + i1 = floor(.5 + deltafreq * (start - .5)); + if (i1 < 0) + i1 = 0; + i2 = floor(.5 + deltafreq * (end - .5)); + + if (i2 > fft_size / 2) + i2 = fft_size / 2; + + bo = partition[i2]; + gd->bm[sfb] = (partition[i1] + partition[i2]) / 2; + gd->bo[sfb] = bo; + + /* calculate how much of this band belongs to current scalefactor band */ + { + FLOAT const f_tmp = mdct_freq_frac * end; + FLOAT bo_w = (f_tmp - b_frq[bo]) / (b_frq[bo + 1] - b_frq[bo]); + if (bo_w < 0) { + bo_w = 0; + } + else { + if (bo_w > 1) { + bo_w = 1; + } + } + gd->bo_weight[sfb] = bo_w; + } + gd->mld[sfb] = stereo_demask(mdct_freq_frac * start); + } +} + +static void +compute_bark_values(PsyConst_CB2SB_t const *gd, FLOAT sfreq, int fft_size, + FLOAT * bval, FLOAT * bval_width) +{ + /* compute bark values of each critical band */ + int k, j = 0, ni = gd->npart; + sfreq /= fft_size; + for (k = 0; k < ni; k++) { + int const w = gd->numlines[k]; + FLOAT bark1, bark2; + + bark1 = freq2bark(sfreq * (j)); + bark2 = freq2bark(sfreq * (j + w - 1)); + bval[k] = .5 * (bark1 + bark2); + + bark1 = freq2bark(sfreq * (j - .5)); + bark2 = freq2bark(sfreq * (j + w - .5)); + bval_width[k] = bark2 - bark1; + j += w; + } +} + +static int +init_s3_values(FLOAT ** p, int (*s3ind)[2], int npart, + FLOAT const *bval, FLOAT const *bval_width, FLOAT const *norm) +{ + FLOAT s3[CBANDS][CBANDS]; + /* The s3 array is not linear in the bark scale. + * bval[x] should be used to get the bark value. + */ + int i, j, k; + int numberOfNoneZero = 0; + + memset(&s3[0][0], 0, sizeof(s3)); + + /* s[i][j], the value of the spreading function, + * centered at band j (masker), for band i (maskee) + * + * i.e.: sum over j to spread into signal barkval=i + * NOTE: i and j are used opposite as in the ISO docs + */ + for (i = 0; i < npart; i++) { + for (j = 0; j < npart; j++) { + FLOAT v = s3_func(bval[i] - bval[j]) * bval_width[j]; + s3[i][j] = v * norm[i]; + } + } + for (i = 0; i < npart; i++) { + for (j = 0; j < npart; j++) { + if (s3[i][j] > 0.0f) + break; + } + s3ind[i][0] = j; + + for (j = npart - 1; j > 0; j--) { + if (s3[i][j] > 0.0f) + break; + } + s3ind[i][1] = j; + numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1); + } + *p = lame_calloc(FLOAT, numberOfNoneZero); + if (!*p) + return -1; + + k = 0; + for (i = 0; i < npart; i++) + for (j = s3ind[i][0]; j <= s3ind[i][1]; j++) + (*p)[k++] = s3[i][j]; + + return 0; +} + +int +psymodel_init(lame_global_flags const *gfp) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + SessionConfig_t *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_t *gd; + int i, j, b, sb, k; + FLOAT bvl_a = 13, bvl_b = 24; + FLOAT snr_l_a = 0, snr_l_b = 0; + FLOAT snr_s_a = -8.25, snr_s_b = -4.5; + + FLOAT bval[CBANDS]; + FLOAT bval_width[CBANDS]; + FLOAT norm[CBANDS]; + FLOAT const sfreq = cfg->samplerate_out; + + FLOAT xav = 10, xbv = 12; + FLOAT const minval_low = (0.f - cfg->minval); + + if (gfc->cd_psy != 0) { + return 0; + } + memset(norm, 0, sizeof(norm)); + + gd = lame_calloc(PsyConst_t, 1); + gfc->cd_psy = gd; + + gd->force_short_block_calc = gfp->experimentalZ; + + psv->blocktype_old[0] = psv->blocktype_old[1] = NORM_TYPE; /* the vbr header is long blocks */ + + for (i = 0; i < 4; ++i) { + for (j = 0; j < CBANDS; ++j) { + psv->nb_l1[i][j] = 1e20; + psv->nb_l2[i][j] = 1e20; + psv->nb_s1[i][j] = psv->nb_s2[i][j] = 1.0; + } + for (sb = 0; sb < SBMAX_l; sb++) { + psv->en[i].l[sb] = 1e20; + psv->thm[i].l[sb] = 1e20; + } + for (j = 0; j < 3; ++j) { + for (sb = 0; sb < SBMAX_s; sb++) { + psv->en[i].s[sb][j] = 1e20; + psv->thm[i].s[sb][j] = 1e20; + } + psv->last_attacks[i] = 0; + } + for (j = 0; j < 9; j++) + psv->last_en_subshort[i][j] = 10.; + } + + + /* init. for loudness approx. -jd 2001 mar 27 */ + psv->loudness_sq_save[0] = psv->loudness_sq_save[1] = 0.0; + + + + /************************************************************************* + * now compute the psychoacoustic model specific constants + ************************************************************************/ + /* compute numlines, bo, bm, bval, bval_width, mld */ + init_numline(&gd->l, sfreq, BLKSIZE, 576, SBMAX_l, gfc->scalefac_band.l); + assert(gd->l.npart < CBANDS); + compute_bark_values(&gd->l, sfreq, BLKSIZE, bval, bval_width); + + /* compute the spreading function */ + for (i = 0; i < gd->l.npart; i++) { + double snr = snr_l_a; + if (bval[i] >= bvl_a) { + snr = snr_l_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + + snr_l_a * (bvl_b - bval[i]) / (bvl_b - bvl_a); + } + norm[i] = pow(10.0, snr / 10.0); + } + i = init_s3_values(&gd->l.s3, gd->l.s3ind, gd->l.npart, bval, bval_width, norm); + if (i) + return i; + + /* compute long block specific values, ATH and MINVAL */ + j = 0; + for (i = 0; i < gd->l.npart; i++) { + double x; + + /* ATH */ + x = FLOAT_MAX; + for (k = 0; k < gd->l.numlines[i]; k++, j++) { + FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE); + FLOAT level; + /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */ + level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */ + level = pow(10., 0.1 * level); /* convert from dB -> energy */ + level *= gd->l.numlines[i]; + if (x > level) + x = level; + } + gfc->ATH->cb_l[i] = x; + + /* MINVAL. + For low freq, the strength of the masking is limited by minval + this is an ISO MPEG1 thing, dont know if it is really needed */ + /* FIXME: it does work to reduce low-freq problems in S53-Wind-Sax + and lead-voice samples, but introduces some 3 kbps bit bloat too. + TODO: Further refinement of the shape of this hack. + */ + x = 20.0 * (bval[i] / xav - 1.0); + if (x > 6) { + x = 30; + } + if (x < minval_low) { + x = minval_low; + } + if (cfg->samplerate_out < 44000) { + x = 30; + } + x -= 8.; + gd->l.minval[i] = pow(10.0, x / 10.) * gd->l.numlines[i]; + } + + /************************************************************************ + * do the same things for short blocks + ************************************************************************/ + init_numline(&gd->s, sfreq, BLKSIZE_s, 192, SBMAX_s, gfc->scalefac_band.s); + assert(gd->s.npart < CBANDS); + compute_bark_values(&gd->s, sfreq, BLKSIZE_s, bval, bval_width); + + /* SNR formula. short block is normalized by SNR. is it still right ? */ + j = 0; + for (i = 0; i < gd->s.npart; i++) { + double x; + double snr = snr_s_a; + if (bval[i] >= bvl_a) { + snr = snr_s_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + + snr_s_a * (bvl_b - bval[i]) / (bvl_b - bvl_a); + } + norm[i] = pow(10.0, snr / 10.0); + + /* ATH */ + x = FLOAT_MAX; + for (k = 0; k < gd->s.numlines[i]; k++, j++) { + FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE_s); + FLOAT level; + /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */ + level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */ + level = pow(10., 0.1 * level); /* convert from dB -> energy */ + level *= gd->s.numlines[i]; + if (x > level) + x = level; + } + gfc->ATH->cb_s[i] = x; + + /* MINVAL. + For low freq, the strength of the masking is limited by minval + this is an ISO MPEG1 thing, dont know if it is really needed */ + x = 7.0 * (bval[i] / xbv - 1.0); + if (bval[i] > xbv) { + x *= 1 + log(1 + x) * 3.1; + } + if (bval[i] < xbv) { + x *= 1 + log(1 - x) * 2.3; + } + if (x > 6) { + x = 30; + } + if (x < minval_low) { + x = minval_low; + } + if (cfg->samplerate_out < 44000) { + x = 30; + } + x -= 8; + gd->s.minval[i] = pow(10.0, x / 10) * gd->s.numlines[i]; + } + + i = init_s3_values(&gd->s.s3, gd->s.s3ind, gd->s.npart, bval, bval_width, norm); + if (i) + return i; + + + init_mask_add_max_values(); + init_fft(gfc); + + /* setup temporal masking */ + gd->decay = exp(-1.0 * LOG10 / (temporalmask_sustain_sec * sfreq / 192.0)); + + { + FLOAT msfix; + msfix = NS_MSFIX; + if (cfg->use_safe_joint_stereo) + msfix = 1.0; + if (fabs(cfg->msfix) > 0.0) + msfix = cfg->msfix; + cfg->msfix = msfix; + + /* spread only from npart_l bands. Normally, we use the spreading + * function to convolve from npart_l down to npart_l bands + */ + for (b = 0; b < gd->l.npart; b++) + if (gd->l.s3ind[b][1] > gd->l.npart - 1) + gd->l.s3ind[b][1] = gd->l.npart - 1; + } + + /* prepare for ATH auto adjustment: + * we want to decrease the ATH by 12 dB per second + */ +#define frame_duration (576. * cfg->mode_gr / sfreq) + gfc->ATH->decay = pow(10., -12. / 10. * frame_duration); + gfc->ATH->adjust_factor = 0.01; /* minimum, for leading low loudness */ + gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */ +#undef frame_duration + + assert(gd->l.bo[SBMAX_l - 1] <= gd->l.npart); + assert(gd->s.bo[SBMAX_s - 1] <= gd->s.npart); + + if (cfg->ATHtype != -1) { + /* compute equal loudness weights (eql_w) */ + FLOAT freq; + FLOAT const freq_inc = (FLOAT) cfg->samplerate_out / (FLOAT) (BLKSIZE); + FLOAT eql_balance = 0.0; + freq = 0.0; + for (i = 0; i < BLKSIZE / 2; ++i) { + /* convert ATH dB to relative power (not dB) */ + /* to determine eql_w */ + freq += freq_inc; + gfc->ATH->eql_w[i] = 1. / pow(10, ATHformula(cfg, freq) / 10); + eql_balance += gfc->ATH->eql_w[i]; + } + eql_balance = 1.0 / eql_balance; + for (i = BLKSIZE / 2; --i >= 0;) { /* scale weights */ + gfc->ATH->eql_w[i] *= eql_balance; + } + } + { + for (b = j = 0; b < gd->s.npart; ++b) { + for (i = 0; i < gd->s.numlines[b]; ++i) { + ++j; + } + } + assert(j == 129); + for (b = j = 0; b < gd->l.npart; ++b) { + for (i = 0; i < gd->l.numlines[b]; ++i) { + ++j; + } + } + assert(j == 513); + } + /* short block attack threshold */ + { + float x = gfp->attackthre; + float y = gfp->attackthre_s; + if (x < 0) { + x = NSATTACKTHRE; + } + if (y < 0) { + y = NSATTACKTHRE_S; + } + gd->attack_threshold[0] = gd->attack_threshold[1] = gd->attack_threshold[2] = x; + gd->attack_threshold[3] = y; + } + { + float sk_s = -10.f, sk_l = -4.7f; + static float const sk[] = + { -7.4, -7.4, -7.4, -9.5, -7.4, -6.1, -5.5, -4.7, -4.7, -4.7, -4.7 }; + if (gfp->VBR_q < 4) { + sk_l = sk_s = sk[0]; + } + else { + sk_l = sk_s = sk[gfp->VBR_q] + gfp->VBR_q_frac * (sk[gfp->VBR_q] - sk[gfp->VBR_q + 1]); + } + b = 0; + for (; b < gd->s.npart; b++) { + float m = (float) (gd->s.npart - b) / gd->s.npart; + gd->s.masking_lower[b] = powf(10.f, sk_s * m * 0.1f); + } + for (; b < CBANDS; ++b) { + gd->s.masking_lower[b] = 1.f; + } + b = 0; + for (; b < gd->l.npart; b++) { + float m = (float) (gd->l.npart - b) / gd->l.npart; + gd->l.masking_lower[b] = powf(10.f, sk_l * m * 0.1f); + } + for (; b < CBANDS; ++b) { + gd->l.masking_lower[b] = 1.f; + } + } + memcpy(&gd->l_to_s, &gd->l, sizeof(gd->l_to_s)); + init_numline(&gd->l_to_s, sfreq, BLKSIZE, 192, SBMAX_s, gfc->scalefac_band.s); + return 0; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.h new file mode 100644 index 00000000..f46083cd --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/psymodel.h @@ -0,0 +1,64 @@ +/* + * psymodel.h + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_PSYMODEL_H +#define LAME_PSYMODEL_H + + +int L3psycho_anal_ns(lame_internal_flags * gfc, + const sample_t *const buffer[2], int gr, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]); + +int L3psycho_anal_vbr(lame_internal_flags * gfc, + const sample_t *const buffer[2], int gr, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]); + + +int psymodel_init(lame_global_flags const* gfp); + + +#define rpelev 2 +#define rpelev2 16 +#define rpelev_s 2 +#define rpelev2_s 16 + +/* size of each partition band, in barks: */ +#define DELBARK .34 + + +/* tuned for output level (sensitive to energy scale) */ +#define VO_SCALE (1./( 14752*14752 )/(BLKSIZE/2)) + +#define temporalmask_sustain_sec 0.01 + +#define NS_PREECHO_ATT0 0.8 +#define NS_PREECHO_ATT1 0.6 +#define NS_PREECHO_ATT2 0.3 + +#define NS_MSFIX 3.5 +#define NSATTACKTHRE 4.4 +#define NSATTACKTHRE_S 25 + +#endif /* LAME_PSYMODEL_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.c new file mode 100644 index 00000000..9ba9c16d --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.c @@ -0,0 +1,2050 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 1999-2003 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2001-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: quantize.c,v 1.219 2017/08/02 19:48:05 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "reservoir.h" +#include "bitstream.h" +#include "vbrquantize.h" +#include "quantize.h" +#ifdef HAVE_XMMINTRIN_H +#include "vector/lame_intrin.h" +#endif + + + + +/* convert from L/R <-> Mid/Side */ +static void +ms_convert(III_side_info_t * l3_side, int gr) +{ + int i; + for (i = 0; i < 576; ++i) { + FLOAT l, r; + l = l3_side->tt[gr][0].xr[i]; + r = l3_side->tt[gr][1].xr[i]; + l3_side->tt[gr][0].xr[i] = (l + r) * (FLOAT) (SQRT2 * 0.5); + l3_side->tt[gr][1].xr[i] = (l - r) * (FLOAT) (SQRT2 * 0.5); + } +} + +/************************************************************************ + * + * init_outer_loop() + * mt 6/99 + * + * initializes cod_info, scalefac and xrpow + * + * returns 0 if all energies in xr are zero, else 1 + * + ************************************************************************/ + +static void +init_xrpow_core_c(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum) +{ + int i; + FLOAT tmp; + *sum = 0; + for (i = 0; i <= upper; ++i) { + tmp = fabs(cod_info->xr[i]); + *sum += tmp; + xrpow[i] = sqrt(tmp * sqrt(tmp)); + + if (xrpow[i] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[i]; + } +} + + + + + +void +init_xrpow_core_init(lame_internal_flags * const gfc) +{ + gfc->init_xrpow_core = init_xrpow_core_c; + +#if defined(HAVE_XMMINTRIN_H) + if (gfc->CPU_features.SSE) + gfc->init_xrpow_core = init_xrpow_core_sse; +#endif +#ifndef HAVE_NASM +#ifdef MIN_ARCH_SSE + gfc->init_xrpow_core = init_xrpow_core_sse; +#endif +#endif +} + + + +static int +init_xrpow(lame_internal_flags * gfc, gr_info * const cod_info, FLOAT xrpow[576]) +{ + FLOAT sum = 0; + int i; + int const upper = cod_info->max_nonzero_coeff; + + assert(xrpow != NULL); + cod_info->xrpow_max = 0; + + /* check if there is some energy we have to quantize + * and calculate xrpow matching our fresh scalefactors + */ + assert(0 <= upper && upper <= 575); + memset(&(xrpow[upper]), 0, (576 - upper) * sizeof(xrpow[0])); + + + gfc->init_xrpow_core(cod_info, xrpow, upper, &sum); + + /* return 1 if we have something to quantize, else 0 + */ + if (sum > (FLOAT) 1E-20) { + int j = 0; + if (gfc->sv_qnt.substep_shaping & 2) + j = 1; + + for (i = 0; i < cod_info->psymax; i++) + gfc->sv_qnt.pseudohalf[i] = j; + + return 1; + } + + memset(&cod_info->l3_enc[0], 0, sizeof(int) * 576); + return 0; +} + + + + + +/* +Gabriel Bouvigne feb/apr 2003 +Analog silence detection in partitionned sfb21 +or sfb12 for short blocks + +From top to bottom of sfb, changes to 0 +coeffs which are below ath. It stops on the first +coeff higher than ath. +*/ +static void +psfb21_analogsilence(lame_internal_flags const *gfc, gr_info * const cod_info) +{ + ATH_t const *const ATH = gfc->ATH; + FLOAT *const xr = cod_info->xr; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT blocks */ + int gsfb; + int stop = 0; + for (gsfb = PSFB21 - 1; gsfb >= 0 && !stop; gsfb--) { + int const start = gfc->scalefac_band.psfb21[gsfb]; + int const end = gfc->scalefac_band.psfb21[gsfb + 1]; + int j; + FLOAT ath21; + ath21 = athAdjust(ATH->adjust_factor, ATH->psfb21[gsfb], ATH->floor, 0); + + if (gfc->sv_qnt.longfact[21] > 1e-12f) + ath21 *= gfc->sv_qnt.longfact[21]; + + for (j = end - 1; j >= start; j--) { + if (fabs(xr[j]) < ath21) + xr[j] = 0; + else { + stop = 1; + break; + } + } + } + } + else { + /*note: short blocks coeffs are reordered */ + int block; + for (block = 0; block < 3; block++) { + + int gsfb; + int stop = 0; + for (gsfb = PSFB12 - 1; gsfb >= 0 && !stop; gsfb--) { + int const start = gfc->scalefac_band.s[12] * 3 + + (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]) * block + + (gfc->scalefac_band.psfb12[gsfb] - gfc->scalefac_band.psfb12[0]); + int const end = + start + (gfc->scalefac_band.psfb12[gsfb + 1] - gfc->scalefac_band.psfb12[gsfb]); + int j; + FLOAT ath12; + ath12 = athAdjust(ATH->adjust_factor, ATH->psfb12[gsfb], ATH->floor, 0); + + if (gfc->sv_qnt.shortfact[12] > 1e-12f) + ath12 *= gfc->sv_qnt.shortfact[12]; + + for (j = end - 1; j >= start; j--) { + if (fabs(xr[j]) < ath12) + xr[j] = 0; + else { + stop = 1; + break; + } + } + } + } + } + +} + + + + + +static void +init_outer_loop(lame_internal_flags const *gfc, gr_info * const cod_info) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, j; + /* initialize fresh cod_info + */ + cod_info->part2_3_length = 0; + cod_info->big_values = 0; + cod_info->count1 = 0; + cod_info->global_gain = 210; + cod_info->scalefac_compress = 0; + /* mixed_block_flag, block_type was set in psymodel.c */ + cod_info->table_select[0] = 0; + cod_info->table_select[1] = 0; + cod_info->table_select[2] = 0; + cod_info->subblock_gain[0] = 0; + cod_info->subblock_gain[1] = 0; + cod_info->subblock_gain[2] = 0; + cod_info->subblock_gain[3] = 0; /* this one is always 0 */ + cod_info->region0_count = 0; + cod_info->region1_count = 0; + cod_info->preflag = 0; + cod_info->scalefac_scale = 0; + cod_info->count1table_select = 0; + cod_info->part2_length = 0; + if (cfg->samplerate_out <= 8000) { + cod_info->sfb_lmax = 17; + cod_info->sfb_smin = 9; + cod_info->psy_lmax = 17; + } + else { + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; + cod_info->psy_lmax = gfc->sv_qnt.sfb21_extra ? SBMAX_l : SBPSY_l; + } + cod_info->psymax = cod_info->psy_lmax; + cod_info->sfbmax = cod_info->sfb_lmax; + cod_info->sfbdivide = 11; + for (sfb = 0; sfb < SBMAX_l; sfb++) { + cod_info->width[sfb] + = gfc->scalefac_band.l[sfb + 1] - gfc->scalefac_band.l[sfb]; + cod_info->window[sfb] = 3; /* which is always 0. */ + } + if (cod_info->block_type == SHORT_TYPE) { + FLOAT ixwork[576]; + FLOAT *ix; + + cod_info->sfb_smin = 0; + cod_info->sfb_lmax = 0; + if (cod_info->mixed_block_flag) { + /* + * MPEG-1: sfbs 0-7 long block, 3-12 short blocks + * MPEG-2(.5): sfbs 0-5 long block, 3-12 short blocks + */ + cod_info->sfb_smin = 3; + cod_info->sfb_lmax = cfg->mode_gr * 2 + 4; + } + if (cfg->samplerate_out <= 8000) { + cod_info->psymax + = cod_info->sfb_lmax + + 3 * (9 - cod_info->sfb_smin); + cod_info->sfbmax = cod_info->sfb_lmax + 3 * (9 - cod_info->sfb_smin); + } + else { + cod_info->psymax + = cod_info->sfb_lmax + + 3 * ((gfc->sv_qnt.sfb21_extra ? SBMAX_s : SBPSY_s) - cod_info->sfb_smin); + cod_info->sfbmax = cod_info->sfb_lmax + 3 * (SBPSY_s - cod_info->sfb_smin); + } + cod_info->sfbdivide = cod_info->sfbmax - 18; + cod_info->psy_lmax = cod_info->sfb_lmax; + /* re-order the short blocks, for more efficient encoding below */ + /* By Takehiro TOMINAGA */ + /* + Within each scalefactor band, data is given for successive + time windows, beginning with window 0 and ending with window 2. + Within each window, the quantized values are then arranged in + order of increasing frequency... + */ + ix = &cod_info->xr[gfc->scalefac_band.l[cod_info->sfb_lmax]]; + memcpy(ixwork, cod_info->xr, 576 * sizeof(FLOAT)); + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + int const start = gfc->scalefac_band.s[sfb]; + int const end = gfc->scalefac_band.s[sfb + 1]; + int window, l; + for (window = 0; window < 3; window++) { + for (l = start; l < end; l++) { + *ix++ = ixwork[3 * l + window]; + } + } + } + + j = cod_info->sfb_lmax; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + cod_info->width[j] = cod_info->width[j + 1] = cod_info->width[j + 2] + = gfc->scalefac_band.s[sfb + 1] - gfc->scalefac_band.s[sfb]; + cod_info->window[j] = 0; + cod_info->window[j + 1] = 1; + cod_info->window[j + 2] = 2; + j += 3; + } + } + + cod_info->count1bits = 0; + cod_info->sfb_partition_table = nr_of_sfb_block[0][0]; + cod_info->slen[0] = 0; + cod_info->slen[1] = 0; + cod_info->slen[2] = 0; + cod_info->slen[3] = 0; + + cod_info->max_nonzero_coeff = 575; + + /* fresh scalefactors are all zero + */ + memset(cod_info->scalefac, 0, sizeof(cod_info->scalefac)); + + if (cfg->vbr != vbr_mt && cfg->vbr != vbr_mtrh && cfg->vbr != vbr_abr && cfg->vbr != vbr_off) { + psfb21_analogsilence(gfc, cod_info); + } +} + + + +/************************************************************************ + * + * bin_search_StepSize() + * + * author/date?? + * + * binary step size search + * used by outer_loop to get a quantizer step size to start with + * + ************************************************************************/ + +typedef enum { + BINSEARCH_NONE, + BINSEARCH_UP, + BINSEARCH_DOWN +} binsearchDirection_t; + +static int +bin_search_StepSize(lame_internal_flags * const gfc, gr_info * const cod_info, + int desired_rate, const int ch, const FLOAT xrpow[576]) +{ + int nBits; + int CurrentStep = gfc->sv_qnt.CurrentStep[ch]; + int flag_GoneOver = 0; + int const start = gfc->sv_qnt.OldValue[ch]; + binsearchDirection_t Direction = BINSEARCH_NONE; + cod_info->global_gain = start; + desired_rate -= cod_info->part2_length; + + assert(CurrentStep); + for (;;) { + int step; + nBits = count_bits(gfc, xrpow, cod_info, 0); + + if (CurrentStep == 1 || nBits == desired_rate) + break; /* nothing to adjust anymore */ + + if (nBits > desired_rate) { + /* increase Quantize_StepSize */ + if (Direction == BINSEARCH_DOWN) + flag_GoneOver = 1; + + if (flag_GoneOver) + CurrentStep /= 2; + Direction = BINSEARCH_UP; + step = CurrentStep; + } + else { + /* decrease Quantize_StepSize */ + if (Direction == BINSEARCH_UP) + flag_GoneOver = 1; + + if (flag_GoneOver) + CurrentStep /= 2; + Direction = BINSEARCH_DOWN; + step = -CurrentStep; + } + cod_info->global_gain += step; + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + flag_GoneOver = 1; + } + if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + flag_GoneOver = 1; + } + } + + assert(cod_info->global_gain >= 0); + assert(cod_info->global_gain < 256); + + while (nBits > desired_rate && cod_info->global_gain < 255) { + cod_info->global_gain++; + nBits = count_bits(gfc, xrpow, cod_info, 0); + } + gfc->sv_qnt.CurrentStep[ch] = (start - cod_info->global_gain >= 4) ? 4 : 2; + gfc->sv_qnt.OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = nBits; + return nBits; +} + + + + +/************************************************************************ + * + * trancate_smallspectrums() + * + * Takehiro TOMINAGA 2002-07-21 + * + * trancate smaller nubmers into 0 as long as the noise threshold is allowed. + * + ************************************************************************/ +static int +floatcompare(const void *v1, const void *v2) +{ + const FLOAT *const a = v1, *const b = v2; + if (*a > *b) + return 1; + if (*a < *b) + return -1; + return 0; +} + +static void +trancate_smallspectrums(lame_internal_flags const *gfc, + gr_info * const gi, const FLOAT * const l3_xmin, FLOAT * const work) +{ + int sfb, j, width; + FLOAT distort[SFBMAX]; + calc_noise_result dummy; + + if ((!(gfc->sv_qnt.substep_shaping & 4) && gi->block_type == SHORT_TYPE) + || gfc->sv_qnt.substep_shaping & 0x80) + return; + (void) calc_noise(gi, l3_xmin, distort, &dummy, 0); + for (j = 0; j < 576; j++) { + FLOAT xr = 0.0; + if (gi->l3_enc[j] != 0) + xr = fabs(gi->xr[j]); + work[j] = xr; + } + + j = 0; + sfb = 8; + if (gi->block_type == SHORT_TYPE) + sfb = 6; + do { + FLOAT allowedNoise, trancateThreshold; + int nsame, start; + + width = gi->width[sfb]; + j += width; + if (distort[sfb] >= 1.0) + continue; + + qsort(&work[j - width], width, sizeof(FLOAT), floatcompare); + if (EQ(work[j - 1], 0.0)) + continue; /* all zero sfb */ + + allowedNoise = (1.0 - distort[sfb]) * l3_xmin[sfb]; + trancateThreshold = 0.0; + start = 0; + do { + FLOAT noise; + for (nsame = 1; start + nsame < width; nsame++) + if (NEQ(work[start + j - width], work[start + j + nsame - width])) + break; + + noise = work[start + j - width] * work[start + j - width] * nsame; + if (allowedNoise < noise) { + if (start != 0) + trancateThreshold = work[start + j - width - 1]; + break; + } + allowedNoise -= noise; + start += nsame; + } while (start < width); + if (EQ(trancateThreshold, 0.0)) + continue; + +/* printf("%e %e %e\n", */ +/* trancateThreshold/l3_xmin[sfb], */ +/* trancateThreshold/(l3_xmin[sfb]*start), */ +/* trancateThreshold/(l3_xmin[sfb]*(start+width)) */ +/* ); */ +/* if (trancateThreshold > 1000*l3_xmin[sfb]*start) */ +/* trancateThreshold = 1000*l3_xmin[sfb]*start; */ + + do { + if (fabs(gi->xr[j - width]) <= trancateThreshold) + gi->l3_enc[j - width] = 0; + } while (--width > 0); + } while (++sfb < gi->psymax); + + gi->part2_3_length = noquant_count_bits(gfc, gi, 0); +} + + +/************************************************************************* + * + * loop_break() + * + * author/date?? + * + * Function: Returns zero if there is a scalefac which has not been + * amplified. Otherwise it returns one. + * + *************************************************************************/ + +inline static int +loop_break(const gr_info * const cod_info) +{ + int sfb; + + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) + if (cod_info->scalefac[sfb] + + cod_info->subblock_gain[cod_info->window[sfb]] == 0) + return 0; + + return 1; +} + + + + +/* mt 5/99: Function: Improved calc_noise for a single channel */ + +/************************************************************************* + * + * quant_compare() + * + * author/date?? + * + * several different codes to decide which quantization is better + * + *************************************************************************/ + +static double +penalties(double noise) +{ + return FAST_LOG10(0.368 + 0.632 * noise * noise * noise); +} + +static double +get_klemm_noise(const FLOAT * distort, const gr_info * const gi) +{ + int sfb; + double klemm_noise = 1E-37; + for (sfb = 0; sfb < gi->psymax; sfb++) + klemm_noise += penalties(distort[sfb]); + + return Max(1e-20, klemm_noise); +} + +inline static int +quant_compare(const int quant_comp, + const calc_noise_result * const best, + calc_noise_result * const calc, const gr_info * const gi, const FLOAT * distort) +{ + /* + noise is given in decibels (dB) relative to masking thesholds. + + over_noise: ??? (the previous comment is fully wrong) + tot_noise: ??? (the previous comment is fully wrong) + max_noise: max quantization noise + + */ + int better; + + switch (quant_comp) { + default: + case 9:{ + if (best->over_count > 0) { + /* there are distorted sfb */ + better = calc->over_SSD <= best->over_SSD; + if (calc->over_SSD == best->over_SSD) + better = calc->bits < best->bits; + } + else { + /* no distorted sfb */ + better = ((calc->max_noise < 0) && + ((calc->max_noise * 10 + calc->bits) <= + (best->max_noise * 10 + best->bits))); + } + break; + } + + case 0: + better = calc->over_count < best->over_count + || (calc->over_count == best->over_count && calc->over_noise < best->over_noise) + || (calc->over_count == best->over_count && + EQ(calc->over_noise, best->over_noise) && calc->tot_noise < best->tot_noise); + break; + + case 8: + calc->max_noise = get_klemm_noise(distort, gi); + /*lint --fallthrough */ + case 1: + better = calc->max_noise < best->max_noise; + break; + case 2: + better = calc->tot_noise < best->tot_noise; + break; + case 3: + better = (calc->tot_noise < best->tot_noise) + && (calc->max_noise < best->max_noise); + break; + case 4: + better = (calc->max_noise <= 0.0 && best->max_noise > 0.2) + || (calc->max_noise <= 0.0 && + best->max_noise < 0.0 && + best->max_noise > calc->max_noise - 0.2 && calc->tot_noise < best->tot_noise) + || (calc->max_noise <= 0.0 && + best->max_noise > 0.0 && + best->max_noise > calc->max_noise - 0.2 && + calc->tot_noise < best->tot_noise + best->over_noise) + || (calc->max_noise > 0.0 && + best->max_noise > -0.05 && + best->max_noise > calc->max_noise - 0.1 && + calc->tot_noise + calc->over_noise < best->tot_noise + best->over_noise) + || (calc->max_noise > 0.0 && + best->max_noise > -0.1 && + best->max_noise > calc->max_noise - 0.15 && + calc->tot_noise + calc->over_noise + calc->over_noise < + best->tot_noise + best->over_noise + best->over_noise); + break; + case 5: + better = calc->over_noise < best->over_noise + || (EQ(calc->over_noise, best->over_noise) && calc->tot_noise < best->tot_noise); + break; + case 6: + better = calc->over_noise < best->over_noise + || (EQ(calc->over_noise, best->over_noise) && + (calc->max_noise < best->max_noise + || (EQ(calc->max_noise, best->max_noise) && calc->tot_noise <= best->tot_noise) + )); + break; + case 7: + better = calc->over_count < best->over_count || calc->over_noise < best->over_noise; + break; + } + + + if (best->over_count == 0) { + /* + If no distorted bands, only use this quantization + if it is better, and if it uses less bits. + Unfortunately, part2_3_length is sometimes a poor + estimator of the final size at low bitrates. + */ + better = better && calc->bits < best->bits; + } + + + return better; +} + + + +/************************************************************************* + * + * amp_scalefac_bands() + * + * author/date?? + * + * Amplify the scalefactor bands that violate the masking threshold. + * See ISO 11172-3 Section C.1.5.4.3.5 + * + * distort[] = noise/masking + * distort[] > 1 ==> noise is not masked + * distort[] < 1 ==> noise is masked + * max_dist = maximum value of distort[] + * + * Three algorithms: + * noise_shaping_amp + * 0 Amplify all bands with distort[]>1. + * + * 1 Amplify all bands with distort[] >= max_dist^(.5); + * ( 50% in the db scale) + * + * 2 Amplify first band with distort[] >= max_dist; + * + * + * For algorithms 0 and 1, if max_dist < 1, then amplify all bands + * with distort[] >= .95*max_dist. This is to make sure we always + * amplify at least one band. + * + * + *************************************************************************/ +static void +amp_scalefac_bands(lame_internal_flags * gfc, + gr_info * const cod_info, FLOAT const *distort, FLOAT xrpow[576], int bRefine) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int j, sfb; + FLOAT ifqstep34, trigger; + int noise_shaping_amp; + + if (cod_info->scalefac_scale == 0) { + ifqstep34 = 1.29683955465100964055; /* 2**(.75*.5) */ + } + else { + ifqstep34 = 1.68179283050742922612; /* 2**(.75*1) */ + } + + /* compute maximum value of distort[] */ + trigger = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + if (trigger < distort[sfb]) + trigger = distort[sfb]; + } + + noise_shaping_amp = cfg->noise_shaping_amp; + if (noise_shaping_amp == 3) { + if (bRefine == 1) + noise_shaping_amp = 2; + else + noise_shaping_amp = 1; + } + switch (noise_shaping_amp) { + case 2: + /* amplify exactly 1 band */ + break; + + case 1: + /* amplify bands within 50% of max (on db scale) */ + if (trigger > 1.0) + trigger = pow(trigger, .5); + else + trigger *= .95; + break; + + case 0: + default: + /* ISO algorithm. amplify all bands with distort>1 */ + if (trigger > 1.0) + trigger = 1.0; + else + trigger *= .95; + break; + } + + j = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + int const width = cod_info->width[sfb]; + int l; + j += width; + if (distort[sfb] < trigger) + continue; + + if (gfc->sv_qnt.substep_shaping & 2) { + gfc->sv_qnt.pseudohalf[sfb] = !gfc->sv_qnt.pseudohalf[sfb]; + if (!gfc->sv_qnt.pseudohalf[sfb] && cfg->noise_shaping_amp == 2) + return; + } + cod_info->scalefac[sfb]++; + for (l = -width; l < 0; l++) { + xrpow[j + l] *= ifqstep34; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + + if (cfg->noise_shaping_amp == 2) + return; + } +} + +/************************************************************************* + * + * inc_scalefac_scale() + * + * Takehiro Tominaga 2000-xx-xx + * + * turns on scalefac scale and adjusts scalefactors + * + *************************************************************************/ + +static void +inc_scalefac_scale(gr_info * const cod_info, FLOAT xrpow[576]) +{ + int l, j, sfb; + const FLOAT ifqstep34 = 1.29683955465100964055; + + j = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + int const width = cod_info->width[sfb]; + int s = cod_info->scalefac[sfb]; + if (cod_info->preflag) + s += pretab[sfb]; + j += width; + if (s & 1) { + s++; + for (l = -width; l < 0; l++) { + xrpow[j + l] *= ifqstep34; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + } + cod_info->scalefac[sfb] = s >> 1; + } + cod_info->preflag = 0; + cod_info->scalefac_scale = 1; +} + + + +/************************************************************************* + * + * inc_subblock_gain() + * + * Takehiro Tominaga 2000-xx-xx + * + * increases the subblock gain and adjusts scalefactors + * + *************************************************************************/ + +static int +inc_subblock_gain(const lame_internal_flags * const gfc, gr_info * const cod_info, FLOAT xrpow[576]) +{ + int sfb, window; + int *const scalefac = cod_info->scalefac; + + /* subbloc_gain can't do anything in the long block region */ + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (scalefac[sfb] >= 16) + return 1; + } + + for (window = 0; window < 3; window++) { + int s1, s2, l, j; + s1 = s2 = 0; + + for (sfb = cod_info->sfb_lmax + window; sfb < cod_info->sfbdivide; sfb += 3) { + if (s1 < scalefac[sfb]) + s1 = scalefac[sfb]; + } + for (; sfb < cod_info->sfbmax; sfb += 3) { + if (s2 < scalefac[sfb]) + s2 = scalefac[sfb]; + } + + if (s1 < 16 && s2 < 8) + continue; + + if (cod_info->subblock_gain[window] >= 7) + return 1; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + cod_info->subblock_gain[window]++; + j = gfc->scalefac_band.l[cod_info->sfb_lmax]; + for (sfb = cod_info->sfb_lmax + window; sfb < cod_info->sfbmax; sfb += 3) { + FLOAT amp; + int const width = cod_info->width[sfb]; + int s = scalefac[sfb]; + assert(s >= 0); + s = s - (4 >> cod_info->scalefac_scale); + if (s >= 0) { + scalefac[sfb] = s; + j += width * 3; + continue; + } + + scalefac[sfb] = 0; + { + int const gain = 210 + (s << (cod_info->scalefac_scale + 1)); + amp = IPOW20(gain); + } + j += width * (window + 1); + for (l = -width; l < 0; l++) { + xrpow[j + l] *= amp; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + j += width * (3 - window - 1); + } + + { + FLOAT const amp = IPOW20(202); + j += cod_info->width[sfb] * (window + 1); + for (l = -cod_info->width[sfb]; l < 0; l++) { + xrpow[j + l] *= amp; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + } + } + return 0; +} + + + +/******************************************************************** + * + * balance_noise() + * + * Takehiro Tominaga /date?? + * Robert Hegemann 2000-09-06: made a function of it + * + * amplifies scalefactor bands, + * - if all are already amplified returns 0 + * - if some bands are amplified too much: + * * try to increase scalefac_scale + * * if already scalefac_scale was set + * try on short blocks to increase subblock gain + * + ********************************************************************/ +inline static int +balance_noise(lame_internal_flags * gfc, + gr_info * const cod_info, FLOAT const *distort, FLOAT xrpow[576], int bRefine) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int status; + + amp_scalefac_bands(gfc, cod_info, distort, xrpow, bRefine); + + /* check to make sure we have not amplified too much + * loop_break returns 0 if there is an unamplified scalefac + * scale_bitcount returns 0 if no scalefactors are too large + */ + + status = loop_break(cod_info); + + if (status) + return 0; /* all bands amplified */ + + /* not all scalefactors have been amplified. so these + * scalefacs are possibly valid. encode them: + */ + status = scale_bitcount(gfc, cod_info); + + if (!status) + return 1; /* amplified some bands not exceeding limits */ + + /* some scalefactors are too large. + * lets try setting scalefac_scale=1 + */ + if (cfg->noise_shaping > 1) { + memset(&gfc->sv_qnt.pseudohalf[0], 0, sizeof(gfc->sv_qnt.pseudohalf)); + if (!cod_info->scalefac_scale) { + inc_scalefac_scale(cod_info, xrpow); + status = 0; + } + else { + if (cod_info->block_type == SHORT_TYPE && cfg->subblock_gain > 0) { + status = inc_subblock_gain(gfc, cod_info, xrpow) + || loop_break(cod_info); + } + } + } + + if (!status) { + status = scale_bitcount(gfc, cod_info); + } + return !status; +} + + + +/************************************************************************ + * + * outer_loop () + * + * Function: The outer iteration loop controls the masking conditions + * of all scalefactorbands. It computes the best scalefac and + * global gain. This module calls the inner iteration loop + * + * mt 5/99 completely rewritten to allow for bit reservoir control, + * mid/side channels with L/R or mid/side masking thresholds, + * and chooses best quantization instead of last quantization when + * no distortion free quantization can be found. + * + * added VBR support mt 5/99 + * + * some code shuffle rh 9/00 + ************************************************************************/ + +static int +outer_loop(lame_internal_flags * gfc, gr_info * const cod_info, const FLOAT * const l3_xmin, /* allowed distortion */ + FLOAT xrpow[576], /* coloured magnitudes of spectral */ + const int ch, const int targ_bits) +{ /* maximum allowed bits */ + SessionConfig_t const *const cfg = &gfc->cfg; + gr_info cod_info_w; + FLOAT save_xrpow[576]; + FLOAT distort[SFBMAX]; + calc_noise_result best_noise_info; + int huff_bits; + int better; + int age; + calc_noise_data prev_noise; + int best_part2_3_length = 9999999; + int bEndOfSearch = 0; + int bRefine = 0; + int best_ggain_pass1 = 0; + + (void) bin_search_StepSize(gfc, cod_info, targ_bits, ch, xrpow); + + if (!cfg->noise_shaping) + /* fast mode, no noise shaping, we are ready */ + return 100; /* default noise_info.over_count */ + + memset(&prev_noise, 0, sizeof(calc_noise_data)); + + + /* compute the distortion in this quantization */ + /* coefficients and thresholds both l/r (or both mid/side) */ + (void) calc_noise(cod_info, l3_xmin, distort, &best_noise_info, &prev_noise); + best_noise_info.bits = cod_info->part2_3_length; + + cod_info_w = *cod_info; + age = 0; + /* if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh) */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT) * 576); + + while (!bEndOfSearch) { + /* BEGIN MAIN LOOP */ + do { + calc_noise_result noise_info; + int search_limit; + int maxggain = 255; + + /* When quantization with no distorted bands is found, + * allow up to X new unsuccesful tries in serial. This + * gives us more possibilities for different quant_compare modes. + * Much more than 3 makes not a big difference, it is only slower. + */ + + if (gfc->sv_qnt.substep_shaping & 2) { + search_limit = 20; + } + else { + search_limit = 3; + } + + + + /* Check if the last scalefactor band is distorted. + * in VBR mode we can't get rid of the distortion, so quit now + * and VBR mode will try again with more bits. + * (makes a 10% speed increase, the files I tested were + * binary identical, 2000/05/20 Robert Hegemann) + * distort[] > 1 means noise > allowed noise + */ + if (gfc->sv_qnt.sfb21_extra) { + if (distort[cod_info_w.sfbmax] > 1.0) + break; + if (cod_info_w.block_type == SHORT_TYPE + && (distort[cod_info_w.sfbmax + 1] > 1.0 + || distort[cod_info_w.sfbmax + 2] > 1.0)) + break; + } + + /* try a new scalefactor conbination on cod_info_w */ + if (balance_noise(gfc, &cod_info_w, distort, xrpow, bRefine) == 0) + break; + if (cod_info_w.scalefac_scale) + maxggain = 254; + + /* inner_loop starts with the initial quantization step computed above + * and slowly increases until the bits < huff_bits. + * Thus it is important not to start with too large of an inital + * quantization step. Too small is ok, but inner_loop will take longer + */ + huff_bits = targ_bits - cod_info_w.part2_length; + if (huff_bits <= 0) + break; + + /* increase quantizer stepsize until needed bits are below maximum + */ + while ((cod_info_w.part2_3_length + = count_bits(gfc, xrpow, &cod_info_w, &prev_noise)) > huff_bits + && cod_info_w.global_gain <= maxggain) + cod_info_w.global_gain++; + + if (cod_info_w.global_gain > maxggain) + break; + + if (best_noise_info.over_count == 0) { + + while ((cod_info_w.part2_3_length + = count_bits(gfc, xrpow, &cod_info_w, &prev_noise)) > best_part2_3_length + && cod_info_w.global_gain <= maxggain) + cod_info_w.global_gain++; + + if (cod_info_w.global_gain > maxggain) + break; + } + + /* compute the distortion in this quantization */ + (void) calc_noise(&cod_info_w, l3_xmin, distort, &noise_info, &prev_noise); + noise_info.bits = cod_info_w.part2_3_length; + + /* check if this quantization is better + * than our saved quantization */ + if (cod_info->block_type != SHORT_TYPE) /* NORM, START or STOP type */ + better = cfg->quant_comp; + else + better = cfg->quant_comp_short; + + + better = quant_compare(better, &best_noise_info, &noise_info, &cod_info_w, distort); + + + /* save data so we can restore this quantization later */ + if (better) { + best_part2_3_length = cod_info->part2_3_length; + best_noise_info = noise_info; + *cod_info = cod_info_w; + age = 0; + /* save data so we can restore this quantization later */ + /*if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh) */ { + /* store for later reuse */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT) * 576); + } + } + else { + /* early stop? */ + if (cfg->full_outer_loop == 0) { + if (++age > search_limit && best_noise_info.over_count == 0) + break; + if ((cfg->noise_shaping_amp == 3) && bRefine && age > 30) + break; + if ((cfg->noise_shaping_amp == 3) && bRefine && + (cod_info_w.global_gain - best_ggain_pass1) > 15) + break; + } + } + } + while ((cod_info_w.global_gain + cod_info_w.scalefac_scale) < 255); + + if (cfg->noise_shaping_amp == 3) { + if (!bRefine) { + /* refine search */ + cod_info_w = *cod_info; + memcpy(xrpow, save_xrpow, sizeof(FLOAT) * 576); + age = 0; + best_ggain_pass1 = cod_info_w.global_gain; + + bRefine = 1; + } + else { + /* search already refined, stop */ + bEndOfSearch = 1; + } + + } + else { + bEndOfSearch = 1; + } + } + + assert((cod_info->global_gain + cod_info->scalefac_scale) <= 255); + /* finish up + */ + if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh || cfg->vbr == vbr_mt) + /* restore for reuse on next try */ + memcpy(xrpow, save_xrpow, sizeof(FLOAT) * 576); + /* do the 'substep shaping' + */ + else if (gfc->sv_qnt.substep_shaping & 1) + trancate_smallspectrums(gfc, cod_info, l3_xmin, xrpow); + + return best_noise_info.over_count; +} + + + + + +/************************************************************************ + * + * iteration_finish_one() + * + * Robert Hegemann 2000-09-06 + * + * update reservoir status after FINAL quantization/bitrate + * + ************************************************************************/ + +static void +iteration_finish_one(lame_internal_flags * gfc, int gr, int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t *const l3_side = &gfc->l3_side; + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* try some better scalefac storage + */ + best_scalefac_store(gfc, gr, ch, l3_side); + + /* best huffman_divide may save some bits too + */ + if (cfg->use_best_huffman == 1) + best_huffman_divide(gfc, cod_info); + + /* update reservoir status after FINAL quantization/bitrate + */ + ResvAdjust(gfc, cod_info); +} + + + +/********************************************************************* + * + * VBR_encode_granule() + * + * 2000-09-04 Robert Hegemann + * + *********************************************************************/ + +static void +VBR_encode_granule(lame_internal_flags * gfc, gr_info * const cod_info, const FLOAT * const l3_xmin, /* allowed distortion of the scalefactor */ + FLOAT xrpow[576], /* coloured magnitudes of spectral values */ + const int ch, int min_bits, int max_bits) +{ + gr_info bst_cod_info; + FLOAT bst_xrpow[576]; + int const Max_bits = max_bits; + int real_bits = max_bits + 1; + int this_bits = (max_bits + min_bits) / 2; + int dbits, over, found = 0; + int const sfb21_extra = gfc->sv_qnt.sfb21_extra; + + assert(Max_bits <= MAX_BITS_PER_CHANNEL); + memset(bst_cod_info.l3_enc, 0, sizeof(bst_cod_info.l3_enc)); + + /* search within round about 40 bits of optimal + */ + do { + assert(this_bits >= min_bits); + assert(this_bits <= max_bits); + assert(min_bits <= max_bits); + + if (this_bits > Max_bits - 42) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = sfb21_extra; + + over = outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, this_bits); + + /* is quantization as good as we are looking for ? + * in this case: is no scalefactor band distorted? + */ + if (over <= 0) { + found = 1; + /* now we know it can be done with "real_bits" + * and maybe we can skip some iterations + */ + real_bits = cod_info->part2_3_length; + + /* store best quantization so far + */ + bst_cod_info = *cod_info; + memcpy(bst_xrpow, xrpow, sizeof(FLOAT) * 576); + + /* try with fewer bits + */ + max_bits = real_bits - 32; + dbits = max_bits - min_bits; + this_bits = (max_bits + min_bits) / 2; + } + else { + /* try with more bits + */ + min_bits = this_bits + 32; + dbits = max_bits - min_bits; + this_bits = (max_bits + min_bits) / 2; + + if (found) { + found = 2; + /* start again with best quantization so far + */ + *cod_info = bst_cod_info; + memcpy(xrpow, bst_xrpow, sizeof(FLOAT) * 576); + } + } + } while (dbits > 12); + + gfc->sv_qnt.sfb21_extra = sfb21_extra; + + /* found=0 => nothing found, use last one + * found=1 => we just found the best and left the loop + * found=2 => we restored a good one and have now l3_enc to restore too + */ + if (found == 2) { + memcpy(cod_info->l3_enc, bst_cod_info.l3_enc, sizeof(int) * 576); + } + assert(cod_info->part2_3_length <= Max_bits); + +} + + + +/************************************************************************ + * + * get_framebits() + * + * Robert Hegemann 2000-09-05 + * + * calculates + * * how many bits are available for analog silent granules + * * how many bits to use for the lowest allowed bitrate + * * how many bits each bitrate would provide + * + ************************************************************************/ + +static void +get_framebits(lame_internal_flags * gfc, int frameBits[15]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + int bitsPerFrame, i; + + /* always use at least this many bits per granule per channel + * unless we detect analog silence, see below + */ + eov->bitrate_index = cfg->vbr_min_bitrate_index; + bitsPerFrame = getframebits(gfc); + + /* bits for analog silence + */ + eov->bitrate_index = 1; + bitsPerFrame = getframebits(gfc); + + for (i = 1; i <= cfg->vbr_max_bitrate_index; i++) { + eov->bitrate_index = i; + frameBits[i] = ResvFrameBegin(gfc, &bitsPerFrame); + } +} + + + +/********************************************************************* + * + * VBR_prepare() + * + * 2000-09-04 Robert Hegemann + * + * * converts LR to MS coding when necessary + * * calculates allowed/adjusted quantization noise amounts + * * detects analog silent frames + * + * some remarks: + * - lower masking depending on Quality setting + * - quality control together with adjusted ATH MDCT scaling + * on lower quality setting allocate more noise from + * ATH masking, and on higher quality setting allocate + * less noise from ATH masking. + * - experiments show that going more than 2dB over GPSYCHO's + * limits ends up in very annoying artefacts + * + *********************************************************************/ + +/* RH: this one needs to be overhauled sometime */ + +static int +VBR_old_prepare(lame_internal_flags * gfc, + const FLOAT pe[2][2], FLOAT const ms_ener_ratio[2], + const III_psy_ratio ratio[2][2], + FLOAT l3_xmin[2][2][SFBMAX], + int frameBits[16], int min_bits[2][2], int max_bits[2][2], int bands[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + + FLOAT masking_lower_db, adjust = 0.0; + int gr, ch; + int analog_silence = 1; + int avg, mxb, bits = 0; + + eov->bitrate_index = cfg->vbr_max_bitrate_index; + avg = ResvFrameBegin(gfc, &avg) / cfg->mode_gr; + + get_framebits(gfc, frameBits); + + for (gr = 0; gr < cfg->mode_gr; gr++) { + mxb = on_pe(gfc, pe, max_bits[gr], avg, gr, 0); + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + reduce_side(max_bits[gr], ms_ener_ratio[gr], avg, mxb); + } + for (ch = 0; ch < cfg->channels_out; ++ch) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + adjust = 1.28 / (1 + exp(3.5 - pe[gr][ch] / 300.)) - 0.05; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + adjust = 2.56 / (1 + exp(3.5 - pe[gr][ch] / 300.)) - 0.14; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + init_outer_loop(gfc, cod_info); + bands[gr][ch] = calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin[gr][ch]); + if (bands[gr][ch]) + analog_silence = 0; + + min_bits[gr][ch] = 126; + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (bits > frameBits[cfg->vbr_max_bitrate_index] && bits > 0) { + max_bits[gr][ch] *= frameBits[cfg->vbr_max_bitrate_index]; + max_bits[gr][ch] /= bits; + } + if (min_bits[gr][ch] > max_bits[gr][ch]) + min_bits[gr][ch] = max_bits[gr][ch]; + + } /* for ch */ + } /* for gr */ + + return analog_silence; +} + +static void +bitpressure_strategy(lame_internal_flags const *gfc, + FLOAT l3_xmin[2][2][SFBMAX], const int min_bits[2][2], int max_bits[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int gr, ch, sfb; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &gfc->l3_side.tt[gr][ch]; + FLOAT *pxmin = l3_xmin[gr][ch]; + for (sfb = 0; sfb < gi->psy_lmax; sfb++) + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_l / SBMAX_l; + + if (gi->block_type == SHORT_TYPE) { + for (sfb = gi->sfb_smin; sfb < SBMAX_s; sfb++) { + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + } + } + max_bits[gr][ch] = Max(min_bits[gr][ch], 0.9 * max_bits[gr][ch]); + } + } +} + +/************************************************************************ + * + * VBR_iteration_loop() + * + * tries to find out how many bits are needed for each granule and channel + * to get an acceptable quantization. An appropriate bitrate will then be + * choosed for quantization. rh 8/99 + * + * Robert Hegemann 2000-09-06 rewrite + * + ************************************************************************/ + +void +VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[2][2][SFBMAX]; + + FLOAT xrpow[576]; + int bands[2][2]; + int frameBits[15]; + int used_bits; + int bits; + int min_bits[2][2], max_bits[2][2]; + int mean_bits; + int ch, gr, analog_silence; + III_side_info_t *const l3_side = &gfc->l3_side; + + analog_silence = VBR_old_prepare(gfc, pe, ms_ener_ratio, ratio, + l3_xmin, frameBits, min_bits, max_bits, bands); + + /*---------------------------------*/ + for (;;) { + + /* quantize granules with lowest possible number of bits + */ + + used_bits = 0; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + int ret; + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + ret = init_xrpow(gfc, cod_info, xrpow); + if (ret == 0 || max_bits[gr][ch] == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + continue; /* with next channel */ + } + + VBR_encode_granule(gfc, cod_info, l3_xmin[gr][ch], xrpow, + ch, min_bits[gr][ch], max_bits[gr][ch]); + + /* do the 'substep shaping' + */ + if (gfc->sv_qnt.substep_shaping & 1) { + trancate_smallspectrums(gfc, &l3_side->tt[gr][ch], l3_xmin[gr][ch], xrpow); + } + + ret = cod_info->part2_3_length + cod_info->part2_length; + used_bits += ret; + } /* for ch */ + } /* for gr */ + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !cfg->enforce_min_bitrate) + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + eov->bitrate_index = 1; + else + eov->bitrate_index = cfg->vbr_min_bitrate_index; + + for (; eov->bitrate_index < cfg->vbr_max_bitrate_index; eov->bitrate_index++) { + if (used_bits <= frameBits[eov->bitrate_index]) + break; + } + bits = ResvFrameBegin(gfc, &mean_bits); + + if (used_bits <= bits) + break; + + bitpressure_strategy(gfc, l3_xmin, (const int (*)[2])min_bits, max_bits); + + } /* breaks adjusted */ + /*--------------------------------------*/ + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + iteration_finish_one(gfc, gr, ch); + } /* for ch */ + } /* for gr */ + ResvFrameEnd(gfc, mean_bits); +} + + + +static int +VBR_new_prepare(lame_internal_flags * gfc, + const FLOAT pe[2][2], const III_psy_ratio ratio[2][2], + FLOAT l3_xmin[2][2][SFBMAX], int frameBits[16], int max_bits[2][2], + int* max_resv) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + + int gr, ch; + int analog_silence = 1; + int avg, bits = 0; + int maximum_framebits; + + if (!cfg->free_format) { + eov->bitrate_index = cfg->vbr_max_bitrate_index; + (void) ResvFrameBegin(gfc, &avg); + *max_resv = gfc->sv_enc.ResvMax; + + get_framebits(gfc, frameBits); + maximum_framebits = frameBits[cfg->vbr_max_bitrate_index]; + } + else { + eov->bitrate_index = 0; + maximum_framebits = ResvFrameBegin(gfc, &avg); + frameBits[0] = maximum_framebits; + *max_resv = gfc->sv_enc.ResvMax; + } + + for (gr = 0; gr < cfg->mode_gr; gr++) { + (void) on_pe(gfc, pe, max_bits[gr], avg, gr, 0); + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + } + for (ch = 0; ch < cfg->channels_out; ++ch) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + + gfc->sv_qnt.masking_lower = pow(10.0, gfc->sv_qnt.mask_adjust * 0.1); + + init_outer_loop(gfc, cod_info); + if (0 != calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin[gr][ch])) + analog_silence = 0; + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (bits > maximum_framebits && bits > 0) { + max_bits[gr][ch] *= maximum_framebits; + max_bits[gr][ch] /= bits; + } + + } /* for ch */ + } /* for gr */ + if (analog_silence) { + *max_resv = 0; + } + return analog_silence; +} + + + +void +VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[2][2][SFBMAX]; + + FLOAT xrpow[2][2][576]; + int frameBits[15]; + int used_bits; + int max_bits[2][2]; + int ch, gr, analog_silence, pad; + III_side_info_t *const l3_side = &gfc->l3_side; + + const FLOAT (*const_l3_xmin)[2][SFBMAX] = (const FLOAT (*)[2][SFBMAX])l3_xmin; + const FLOAT (*const_xrpow)[2][576] = (const FLOAT (*)[2][576])xrpow; + const int (*const_max_bits)[2] = (const int (*)[2])max_bits; + + (void) ms_ener_ratio; /* not used */ + + memset(xrpow, 0, sizeof(xrpow)); + + analog_silence = VBR_new_prepare(gfc, pe, ratio, l3_xmin, frameBits, max_bits, &pad); + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + if (0 == init_xrpow(gfc, cod_info, xrpow[gr][ch])) { + max_bits[gr][ch] = 0; /* silent granule needs no bits */ + } + } /* for ch */ + } /* for gr */ + + /* quantize granules with lowest possible number of bits + */ + + used_bits = VBR_encode_frame(gfc, const_xrpow, const_l3_xmin, const_max_bits); + + if (!cfg->free_format) { + int i, j; + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !cfg->enforce_min_bitrate) { + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + i = 1; + } + else { + i = cfg->vbr_min_bitrate_index; + } + + for (; i < cfg->vbr_max_bitrate_index; i++) { + if (used_bits <= frameBits[i]) + break; + } + if (i > cfg->vbr_max_bitrate_index) { + i = cfg->vbr_max_bitrate_index; + } + if (pad > 0) { + for (j = cfg->vbr_max_bitrate_index; j > i; --j) { + int const unused = frameBits[j] - used_bits; + if (unused <= pad) + break; + } + eov->bitrate_index = j; + } + else { + eov->bitrate_index = i; + } + } + else { +#if 0 + static int mmm = 0; + int fff = getFramesize_kbps(gfc, used_bits); + int hhh = getFramesize_kbps(gfc, MAX_BITS_PER_GRANULE * cfg->mode_gr); + if (mmm < fff) + mmm = fff; + printf("demand=%3d kbps max=%3d kbps limit=%3d kbps\n", fff, mmm, hhh); +#endif + eov->bitrate_index = 0; + } + if (used_bits <= frameBits[eov->bitrate_index]) { + /* update Reservoire status */ + int mean_bits, fullframebits; + fullframebits = ResvFrameBegin(gfc, &mean_bits); + assert(used_bits <= fullframebits); + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const cod_info = &l3_side->tt[gr][ch]; + ResvAdjust(gfc, cod_info); + } + } + ResvFrameEnd(gfc, mean_bits); + } + else { + /* SHOULD NOT HAPPEN INTERNAL ERROR + */ + ERRORF(gfc, "INTERNAL ERROR IN VBR NEW CODE, please send bug report\n"); + exit(-1); + } +} + + + + + +/******************************************************************** + * + * calc_target_bits() + * + * calculates target bits for ABR encoding + * + * mt 2000/05/31 + * + ********************************************************************/ + +static void +calc_target_bits(lame_internal_flags * gfc, + const FLOAT pe[2][2], + FLOAT const ms_ener_ratio[2], + int targ_bits[2][2], int *analog_silence_bits, int *max_frame_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + III_side_info_t const *const l3_side = &gfc->l3_side; + FLOAT res_factor; + int gr, ch, totbits, mean_bits; + int framesize = 576 * cfg->mode_gr; + + eov->bitrate_index = cfg->vbr_max_bitrate_index; + *max_frame_bits = ResvFrameBegin(gfc, &mean_bits); + + eov->bitrate_index = 1; + mean_bits = getframebits(gfc) - cfg->sideinfo_len * 8; + *analog_silence_bits = mean_bits / (cfg->mode_gr * cfg->channels_out); + + mean_bits = cfg->vbr_avg_bitrate_kbps * framesize * 1000; + if (gfc->sv_qnt.substep_shaping & 1) + mean_bits *= 1.09; + mean_bits /= cfg->samplerate_out; + mean_bits -= cfg->sideinfo_len * 8; + mean_bits /= (cfg->mode_gr * cfg->channels_out); + + /* + res_factor is the percentage of the target bitrate that should + be used on average. the remaining bits are added to the + bitreservoir and used for difficult to encode frames. + + Since we are tracking the average bitrate, we should adjust + res_factor "on the fly", increasing it if the average bitrate + is greater than the requested bitrate, and decreasing it + otherwise. Reasonable ranges are from .9 to 1.0 + + Until we get the above suggestion working, we use the following + tuning: + compression ratio res_factor + 5.5 (256kbps) 1.0 no need for bitreservoir + 11 (128kbps) .93 7% held for reservoir + + with linear interpolation for other values. + + */ + res_factor = .93 + .07 * (11.0 - cfg->compression_ratio) / (11.0 - 5.5); + if (res_factor < .90) + res_factor = .90; + if (res_factor > 1.00) + res_factor = 1.00; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + int sum = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + targ_bits[gr][ch] = res_factor * mean_bits; + + if (pe[gr][ch] > 700) { + int add_bits = (pe[gr][ch] - 700) / 1.4; + + gr_info const *const cod_info = &l3_side->tt[gr][ch]; + targ_bits[gr][ch] = res_factor * mean_bits; + + /* short blocks use a little extra, no matter what the pe */ + if (cod_info->block_type == SHORT_TYPE) { + if (add_bits < mean_bits / 2) + add_bits = mean_bits / 2; + } + /* at most increase bits by 1.5*average */ + if (add_bits > mean_bits * 3 / 2) + add_bits = mean_bits * 3 / 2; + else if (add_bits < 0) + add_bits = 0; + + targ_bits[gr][ch] += add_bits; + } + if (targ_bits[gr][ch] > MAX_BITS_PER_CHANNEL) { + targ_bits[gr][ch] = MAX_BITS_PER_CHANNEL; + } + sum += targ_bits[gr][ch]; + } /* for ch */ + if (sum > MAX_BITS_PER_GRANULE) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[gr][ch] *= MAX_BITS_PER_GRANULE; + targ_bits[gr][ch] /= sum; + } + } + } /* for gr */ + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) + for (gr = 0; gr < cfg->mode_gr; gr++) { + reduce_side(targ_bits[gr], ms_ener_ratio[gr], mean_bits * cfg->channels_out, + MAX_BITS_PER_GRANULE); + } + + /* sum target bits + */ + totbits = 0; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (targ_bits[gr][ch] > MAX_BITS_PER_CHANNEL) + targ_bits[gr][ch] = MAX_BITS_PER_CHANNEL; + totbits += targ_bits[gr][ch]; + } + } + + /* repartion target bits if needed + */ + if (totbits > *max_frame_bits && totbits > 0) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + targ_bits[gr][ch] *= *max_frame_bits; + targ_bits[gr][ch] /= totbits; + } + } + } +} + + + + + + +/******************************************************************** + * + * ABR_iteration_loop() + * + * encode a frame with a disired average bitrate + * + * mt 2000/05/31 + * + ********************************************************************/ + +void +ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[SFBMAX]; + FLOAT xrpow[576]; + int targ_bits[2][2]; + int mean_bits, max_frame_bits; + int ch, gr, ath_over; + int analog_silence_bits; + gr_info *cod_info; + III_side_info_t *const l3_side = &gfc->l3_side; + + mean_bits = 0; + + calc_target_bits(gfc, pe, ms_ener_ratio, targ_bits, &analog_silence_bits, &max_frame_bits); + + /* encode granules + */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + } + for (ch = 0; ch < cfg->channels_out; ch++) { + FLOAT adjust, masking_lower_db; + cod_info = &l3_side->tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + /* adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + /* adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + + /* cod_info, scalefac and xrpow get initialized in init_outer_loop + */ + init_outer_loop(gfc, cod_info); + if (init_xrpow(gfc, cod_info, xrpow)) { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + ath_over = calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin); + if (0 == ath_over) /* analog silence */ + targ_bits[gr][ch] = analog_silence_bits; + + (void) outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, targ_bits[gr][ch]); + } + iteration_finish_one(gfc, gr, ch); + } /* ch */ + } /* gr */ + + /* find a bitrate which can refill the resevoir to positive size. + */ + for (eov->bitrate_index = cfg->vbr_min_bitrate_index; + eov->bitrate_index <= cfg->vbr_max_bitrate_index; eov->bitrate_index++) { + if (ResvFrameBegin(gfc, &mean_bits) >= 0) + break; + } + assert(eov->bitrate_index <= cfg->vbr_max_bitrate_index); + + ResvFrameEnd(gfc, mean_bits); +} + + + + + + +/************************************************************************ + * + * CBR_iteration_loop() + * + * author/date?? + * + * encodes one frame of MP3 data with constant bitrate + * + ************************************************************************/ + +void +CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT l3_xmin[SFBMAX]; + FLOAT xrpow[576]; + int targ_bits[2]; + int mean_bits, max_bits; + int gr, ch; + III_side_info_t *const l3_side = &gfc->l3_side; + gr_info *cod_info; + + (void) ResvFrameBegin(gfc, &mean_bits); + + /* quantize! */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + + /* calculate needed bits + */ + max_bits = on_pe(gfc, pe, targ_bits, mean_bits, gr, gr); + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + reduce_side(targ_bits, ms_ener_ratio[gr], mean_bits, max_bits); + } + + for (ch = 0; ch < cfg->channels_out; ch++) { + FLOAT adjust, masking_lower_db; + cod_info = &l3_side->tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + /* adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + /* adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + init_outer_loop(gfc, cod_info); + if (init_xrpow(gfc, cod_info, xrpow)) { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + (void) calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin); + (void) outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, targ_bits[ch]); + } + + iteration_finish_one(gfc, gr, ch); + assert(cod_info->part2_3_length <= MAX_BITS_PER_CHANNEL); + assert(cod_info->part2_3_length <= targ_bits[ch]); + } /* for ch */ + } /* for gr */ + + ResvFrameEnd(gfc, mean_bits); +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.h new file mode 100644 index 00000000..56edcc70 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize.h @@ -0,0 +1,38 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_QUANTIZE_H +#define LAME_QUANTIZE_H + +void CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + + +#endif /* LAME_QUANTIZE_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.c new file mode 100644 index 00000000..d8d6447e --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.c @@ -0,0 +1,1074 @@ +/* + * quantize_pvt source file + * + * Copyright (c) 1999-2002 Takehiro Tominaga + * Copyright (c) 2000-2012 Robert Hegemann + * Copyright (c) 2001 Naoki Shibata + * Copyright (c) 2002-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: quantize_pvt.c,v 1.175 2017/09/06 15:07:30 robert Exp $ */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "reservoir.h" +#include "lame-analysis.h" +#include <float.h> + + +#define NSATHSCALE 100 /* Assuming dynamic range=96dB, this value should be 92 */ + +/* + The following table is used to implement the scalefactor + partitioning for MPEG2 as described in section + 2.4.3.2 of the IS. The indexing corresponds to the + way the tables are presented in the IS: + + [table_number][row_in_table][column of nr_of_sfb] +*/ +const int nr_of_sfb_block[6][3][4] = { + { + {6, 5, 5, 5}, + {9, 9, 9, 9}, + {6, 9, 9, 9} + }, + { + {6, 5, 7, 3}, + {9, 9, 12, 6}, + {6, 9, 12, 6} + }, + { + {11, 10, 0, 0}, + {18, 18, 0, 0}, + {15, 18, 0, 0} + }, + { + {7, 7, 7, 0}, + {12, 12, 12, 0}, + {6, 15, 12, 0} + }, + { + {6, 6, 6, 3}, + {12, 9, 9, 6}, + {6, 12, 9, 6} + }, + { + {8, 8, 5, 0}, + {15, 12, 9, 0}, + {6, 18, 9, 0} + } +}; + + +/* Table B.6: layer3 preemphasis */ +const int pretab[SBMAX_l] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + Here are MPEG1 Table B.8 and MPEG2 Table B.1 + -- Layer III scalefactor bands. + Index into this using a method such as: + idx = fr_ps->header->sampling_frequency + + (fr_ps->header->version * 3) +*/ + + +const scalefac_struct sfBandIndex[9] = { + { /* Table B.2.b: 22.05 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.2.c: 24 kHz */ /* docs: 332. mpg123(broken): 330 */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, + 540, 576}, + {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.2.a: 16 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.b: 44.1 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, + 576}, + {0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.c: 48 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, + 576}, + {0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.a: 32 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, + 576}, + {0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 11.025 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0 / 3, 12 / 3, 24 / 3, 36 / 3, 54 / 3, 78 / 3, 108 / 3, 144 / 3, 186 / 3, 240 / 3, 312 / 3, + 402 / 3, 522 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 12 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0 / 3, 12 / 3, 24 / 3, 36 / 3, 54 / 3, 78 / 3, 108 / 3, 144 / 3, 186 / 3, 240 / 3, 312 / 3, + 402 / 3, 522 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 8 kHz */ + {0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, + 572, 574, 576}, + {0 / 3, 24 / 3, 48 / 3, 72 / 3, 108 / 3, 156 / 3, 216 / 3, 288 / 3, 372 / 3, 480 / 3, 486 / 3, + 492 / 3, 498 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + } +}; + + +/* FIXME: move global variables in some struct */ + +FLOAT pow20[Q_MAX + Q_MAX2 + 1]; +FLOAT ipow20[Q_MAX]; +FLOAT pow43[PRECALC_SIZE]; +/* initialized in first call to iteration_init */ +#ifdef TAKEHIRO_IEEE754_HACK +FLOAT adj43asm[PRECALC_SIZE]; +#else +FLOAT adj43[PRECALC_SIZE]; +#endif + +/* +compute the ATH for each scalefactor band +cd range: 0..96db + +Input: 3.3kHz signal 32767 amplitude (3.3kHz is where ATH is smallest = -5db) +longblocks: sfb=12 en0/bw=-11db max_en0 = 1.3db +shortblocks: sfb=5 -9db 0db + +Input: 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 (repeated) +longblocks: amp=1 sfb=12 en0/bw=-103 db max_en0 = -92db + amp=32767 sfb=12 -12 db -1.4db + +Input: 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 (repeated) +shortblocks: amp=1 sfb=5 en0/bw= -99 -86 + amp=32767 sfb=5 -9 db 4db + + +MAX energy of largest wave at 3.3kHz = 1db +AVE energy of largest wave at 3.3kHz = -11db +Let's take AVE: -11db = maximum signal in sfb=12. +Dynamic range of CD: 96db. Therefor energy of smallest audible wave +in sfb=12 = -11 - 96 = -107db = ATH at 3.3kHz. + +ATH formula for this wave: -5db. To adjust to LAME scaling, we need +ATH = ATH_formula - 103 (db) +ATH = ATH * 2.5e-10 (ener) + +*/ + +static FLOAT +ATHmdct(SessionConfig_t const *cfg, FLOAT f) +{ + FLOAT ath; + + ath = ATHformula(cfg, f); + + if (cfg->ATHfixpoint > 0) { + ath -= cfg->ATHfixpoint; + } + else { + ath -= NSATHSCALE; + } + ath += cfg->ATH_offset_db; + + /* modify the MDCT scaling for the ATH and convert to energy */ + ath = powf(10.0f, ath * 0.1f); + return ath; +} + +static void +compute_ath(lame_internal_flags const* gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT *const ATH_l = gfc->ATH->l; + FLOAT *const ATH_psfb21 = gfc->ATH->psfb21; + FLOAT *const ATH_s = gfc->ATH->s; + FLOAT *const ATH_psfb12 = gfc->ATH->psfb12; + int sfb, i, start, end; + FLOAT ATH_f; + FLOAT const samp_freq = cfg->samplerate_out; + + for (sfb = 0; sfb < SBMAX_l; sfb++) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb + 1]; + ATH_l[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 576); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_l[sfb] = Min(ATH_l[sfb], ATH_f); + } + } + + for (sfb = 0; sfb < PSFB21; sfb++) { + start = gfc->scalefac_band.psfb21[sfb]; + end = gfc->scalefac_band.psfb21[sfb + 1]; + ATH_psfb21[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 576); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_psfb21[sfb] = Min(ATH_psfb21[sfb], ATH_f); + } + } + + for (sfb = 0; sfb < SBMAX_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb + 1]; + ATH_s[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 192); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_s[sfb] = Min(ATH_s[sfb], ATH_f); + } + ATH_s[sfb] *= (gfc->scalefac_band.s[sfb + 1] - gfc->scalefac_band.s[sfb]); + } + + for (sfb = 0; sfb < PSFB12; sfb++) { + start = gfc->scalefac_band.psfb12[sfb]; + end = gfc->scalefac_band.psfb12[sfb + 1]; + ATH_psfb12[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 192); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_psfb12[sfb] = Min(ATH_psfb12[sfb], ATH_f); + } + /*not sure about the following */ + ATH_psfb12[sfb] *= (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]); + } + + + /* no-ATH mode: + * reduce ATH to -200 dB + */ + + if (cfg->noATH) { + for (sfb = 0; sfb < SBMAX_l; sfb++) { + ATH_l[sfb] = 1E-20; + } + for (sfb = 0; sfb < PSFB21; sfb++) { + ATH_psfb21[sfb] = 1E-20; + } + for (sfb = 0; sfb < SBMAX_s; sfb++) { + ATH_s[sfb] = 1E-20; + } + for (sfb = 0; sfb < PSFB12; sfb++) { + ATH_psfb12[sfb] = 1E-20; + } + } + + /* work in progress, don't rely on it too much + */ + gfc->ATH->floor = 10. * log10(ATHmdct(cfg, -1.)); + + /* + { FLOAT g=10000, t=1e30, x; + for ( f = 100; f < 10000; f++ ) { + x = ATHmdct( cfg, f ); + if ( t > x ) t = x, g = f; + } + printf("min=%g\n", g); + } */ +} + + +static float const payload_long[2][4] = +{ {-0.000f, -0.000f, -0.000f, +0.000f} +, {-0.500f, -0.250f, -0.025f, +0.500f} +}; +static float const payload_short[2][4] = +{ {-0.000f, -0.000f, -0.000f, +0.000f} +, {-2.000f, -1.000f, -0.050f, +0.500f} +}; + +/************************************************************************/ +/* initialization for iteration_loop */ +/************************************************************************/ +void +iteration_init(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t *const l3_side = &gfc->l3_side; + FLOAT adjust, db; + int i, sel; + + if (gfc->iteration_init_init == 0) { + gfc->iteration_init_init = 1; + + l3_side->main_data_begin = 0; + compute_ath(gfc); + + pow43[0] = 0.0; + for (i = 1; i < PRECALC_SIZE; i++) + pow43[i] = pow((FLOAT) i, 4.0 / 3.0); + +#ifdef TAKEHIRO_IEEE754_HACK + adj43asm[0] = 0.0; + for (i = 1; i < PRECALC_SIZE; i++) + adj43asm[i] = i - 0.5 - pow(0.5 * (pow43[i - 1] + pow43[i]), 0.75); +#else + for (i = 0; i < PRECALC_SIZE - 1; i++) + adj43[i] = (i + 1) - pow(0.5 * (pow43[i] + pow43[i + 1]), 0.75); + adj43[i] = 0.5; +#endif + for (i = 0; i < Q_MAX; i++) + ipow20[i] = pow(2.0, (double) (i - 210) * -0.1875); + for (i = 0; i <= Q_MAX + Q_MAX2; i++) + pow20[i] = pow(2.0, (double) (i - 210 - Q_MAX2) * 0.25); + + huffman_init(gfc); + init_xrpow_core_init(gfc); + + sel = 1;/* RH: all modes like vbr-new (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) ? 1 : 0;*/ + + /* long */ + db = cfg->adjust_bass_db + payload_long[sel][0]; + adjust = powf(10.f, db * 0.1f); + for (i = 0; i <= 6; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_alto_db + payload_long[sel][1]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 13; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_treble_db + payload_long[sel][2]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 20; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_sfb21_db + payload_long[sel][3]; + adjust = powf(10.f, db * 0.1f); + for (; i < SBMAX_l; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + + /* short */ + db = cfg->adjust_bass_db + payload_short[sel][0]; + adjust = powf(10.f, db * 0.1f); + for (i = 0; i <= 2; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_alto_db + payload_short[sel][1]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 6; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_treble_db + payload_short[sel][2]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 11; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_sfb21_db + payload_short[sel][3]; + adjust = powf(10.f, db * 0.1f); + for (; i < SBMAX_s; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + } +} + + + + + +/************************************************************************ + * allocate bits among 2 channels based on PE + * mt 6/99 + * bugfixes rh 8/01: often allocated more than the allowed 4095 bits + ************************************************************************/ +int +on_pe(lame_internal_flags * gfc, const FLOAT pe[][2], int targ_bits[2], int mean_bits, int gr, int cbr) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int extra_bits = 0, tbits, bits; + int add_bits[2] = {0, 0}; + int max_bits; /* maximum allowed bits for this granule */ + int ch; + + /* allocate targ_bits for granule */ + ResvMaxBits(gfc, mean_bits, &tbits, &extra_bits, cbr); + max_bits = tbits + extra_bits; + if (max_bits > MAX_BITS_PER_GRANULE) /* hard limit per granule */ + max_bits = MAX_BITS_PER_GRANULE; + + for (bits = 0, ch = 0; ch < cfg->channels_out; ++ch) { + /****************************************************************** + * allocate bits for each channel + ******************************************************************/ + targ_bits[ch] = Min(MAX_BITS_PER_CHANNEL, tbits / cfg->channels_out); + + add_bits[ch] = targ_bits[ch] * pe[gr][ch] / 700.0 - targ_bits[ch]; + + /* at most increase bits by 1.5*average */ + if (add_bits[ch] > mean_bits * 3 / 4) + add_bits[ch] = mean_bits * 3 / 4; + if (add_bits[ch] < 0) + add_bits[ch] = 0; + + if (add_bits[ch] + targ_bits[ch] > MAX_BITS_PER_CHANNEL) + add_bits[ch] = Max(0, MAX_BITS_PER_CHANNEL - targ_bits[ch]); + + bits += add_bits[ch]; + } + if (bits > extra_bits && bits > 0) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + add_bits[ch] = extra_bits * add_bits[ch] / bits; + } + } + + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[ch] += add_bits[ch]; + extra_bits -= add_bits[ch]; + } + + for (bits = 0, ch = 0; ch < cfg->channels_out; ++ch) { + bits += targ_bits[ch]; + } + if (bits > MAX_BITS_PER_GRANULE) { + int sum = 0; + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[ch] *= MAX_BITS_PER_GRANULE; + targ_bits[ch] /= bits; + sum += targ_bits[ch]; + } + assert(sum <= MAX_BITS_PER_GRANULE); + } + + return max_bits; +} + + + + +void +reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits) +{ + int move_bits; + FLOAT fac; + + assert(max_bits <= MAX_BITS_PER_GRANULE); + assert(targ_bits[0] + targ_bits[1] <= MAX_BITS_PER_GRANULE); + + /* ms_ener_ratio = 0: allocate 66/33 mid/side fac=.33 + * ms_ener_ratio =.5: allocate 50/50 mid/side fac= 0 */ + /* 75/25 split is fac=.5 */ + /* float fac = .50*(.5-ms_ener_ratio[gr])/.5; */ + fac = .33 * (.5 - ms_ener_ratio) / .5; + if (fac < 0) + fac = 0; + if (fac > .5) + fac = .5; + + /* number of bits to move from side channel to mid channel */ + /* move_bits = fac*targ_bits[1]; */ + move_bits = fac * .5 * (targ_bits[0] + targ_bits[1]); + + if (move_bits > MAX_BITS_PER_CHANNEL - targ_bits[0]) { + move_bits = MAX_BITS_PER_CHANNEL - targ_bits[0]; + } + if (move_bits < 0) + move_bits = 0; + + if (targ_bits[1] >= 125) { + /* dont reduce side channel below 125 bits */ + if (targ_bits[1] - move_bits > 125) { + + /* if mid channel already has 2x more than average, dont bother */ + /* mean_bits = bits per granule (for both channels) */ + if (targ_bits[0] < mean_bits) + targ_bits[0] += move_bits; + targ_bits[1] -= move_bits; + } + else { + targ_bits[0] += targ_bits[1] - 125; + targ_bits[1] = 125; + } + } + + move_bits = targ_bits[0] + targ_bits[1]; + if (move_bits > max_bits) { + targ_bits[0] = (max_bits * targ_bits[0]) / move_bits; + targ_bits[1] = (max_bits * targ_bits[1]) / move_bits; + } + assert(targ_bits[0] <= MAX_BITS_PER_CHANNEL); + assert(targ_bits[1] <= MAX_BITS_PER_CHANNEL); + assert(targ_bits[0] + targ_bits[1] <= MAX_BITS_PER_GRANULE); +} + + +/** + * Robert Hegemann 2001-04-27: + * this adjusts the ATH, keeping the original noise floor + * affects the higher frequencies more than the lower ones + */ + +FLOAT +athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint) +{ + /* work in progress + */ + FLOAT const o = 90.30873362f; + FLOAT const p = (ATHfixpoint < 1.f) ? 94.82444863f : ATHfixpoint; + FLOAT u = FAST_LOG10_X(x, 10.0f); + FLOAT const v = a * a; + FLOAT w = 0.0f; + u -= athFloor; /* undo scaling */ + if (v > 1E-20f) + w = 1.f + FAST_LOG10_X(v, 10.0f / o); + if (w < 0) + w = 0.f; + u *= w; + u += athFloor + o - p; /* redo scaling */ + + return powf(10.f, 0.1f * u); +} + + + +/*************************************************************************/ +/* calc_xmin */ +/*************************************************************************/ + +/* + Calculate the allowed distortion for each scalefactor band, + as determined by the psychoacoustic model. + xmin(sb) = ratio(sb) * en(sb) / bw(sb) + + returns number of sfb's with energy > ATH +*/ + +int +calc_xmin(lame_internal_flags const *gfc, + III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * pxmin) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, gsfb, j = 0, ath_over = 0, k; + ATH_t const *const ATH = gfc->ATH; + const FLOAT *const xr = cod_info->xr; + int max_nonzero; + + for (gsfb = 0; gsfb < cod_info->psy_lmax; gsfb++) { + FLOAT en0, xmin; + FLOAT rh1, rh2, rh3; + int width, l; + + xmin = athAdjust(ATH->adjust_factor, ATH->l[gsfb], ATH->floor, cfg->ATHfixpoint); + xmin *= gfc->sv_qnt.longfact[gsfb]; + + width = cod_info->width[gsfb]; + rh1 = xmin / width; +#ifdef DBL_EPSILON + rh2 = DBL_EPSILON; +#else + rh2 = 2.2204460492503131e-016; +#endif + en0 = 0.0; + for (l = 0; l < width; ++l) { + FLOAT const xa = xr[j++]; + FLOAT const x2 = xa * xa; + en0 += x2; + rh2 += (x2 < rh1) ? x2 : rh1; + } + if (en0 > xmin) + ath_over++; + + if (en0 < xmin) { + rh3 = en0; + } + else if (rh2 < xmin) { + rh3 = xmin; + } + else { + rh3 = rh2; + } + xmin = rh3; + { + FLOAT const e = ratio->en.l[gsfb]; + if (e > 1e-12f) { + FLOAT x; + x = en0 * ratio->thm.l[gsfb] / e; + x *= gfc->sv_qnt.longfact[gsfb]; + if (xmin < x) + xmin = x; + } + } + xmin = Max(xmin, DBL_EPSILON); + cod_info->energy_above_cutoff[gsfb] = (en0 > xmin+1e-14f) ? 1 : 0; + *pxmin++ = xmin; + } /* end of long block loop */ + + + + + /*use this function to determine the highest non-zero coeff */ + max_nonzero = 0; + for (k = 575; k > 0; --k) { + if (fabs(xr[k]) > 1e-12f) { + max_nonzero = k; + break; + } + } + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ + max_nonzero |= 1; /* only odd numbers */ + } + else { + max_nonzero /= 6; /* 3 short blocks */ + max_nonzero *= 6; + max_nonzero += 5; + } + + if (gfc->sv_qnt.sfb21_extra == 0 && cfg->samplerate_out < 44000) { + int const sfb_l = (cfg->samplerate_out <= 8000) ? 17 : 21; + int const sfb_s = (cfg->samplerate_out <= 8000) ? 9 : 12; + int limit = 575; + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ + limit = gfc->scalefac_band.l[sfb_l]-1; + } + else { + limit = 3*gfc->scalefac_band.s[sfb_s]-1; + } + if (max_nonzero > limit) { + max_nonzero = limit; + } + } + cod_info->max_nonzero_coeff = max_nonzero; + + + + for (sfb = cod_info->sfb_smin; gsfb < cod_info->psymax; sfb++, gsfb += 3) { + int width, b, l; + FLOAT tmpATH; + + tmpATH = athAdjust(ATH->adjust_factor, ATH->s[sfb], ATH->floor, cfg->ATHfixpoint); + tmpATH *= gfc->sv_qnt.shortfact[sfb]; + + width = cod_info->width[gsfb]; + for (b = 0; b < 3; b++) { + FLOAT en0 = 0.0, xmin = tmpATH; + FLOAT rh1, rh2, rh3; + + rh1 = tmpATH / width; +#ifdef DBL_EPSILON + rh2 = DBL_EPSILON; +#else + rh2 = 2.2204460492503131e-016; +#endif + for (l = 0; l < width; ++l) { + FLOAT const xa = xr[j++]; + FLOAT const x2 = xa * xa; + en0 += x2; + rh2 += (x2 < rh1) ? x2 : rh1; + } + if (en0 > tmpATH) + ath_over++; + + if (en0 < tmpATH) { + rh3 = en0; + } + else if (rh2 < tmpATH) { + rh3 = tmpATH; + } + else { + rh3 = rh2; + } + xmin = rh3; + { + FLOAT const e = ratio->en.s[sfb][b]; + if (e > 1e-12f) { + FLOAT x; + x = en0 * ratio->thm.s[sfb][b] / e; + x *= gfc->sv_qnt.shortfact[sfb]; + if (xmin < x) + xmin = x; + } + } + xmin = Max(xmin, DBL_EPSILON); + cod_info->energy_above_cutoff[gsfb+b] = (en0 > xmin+1e-14f) ? 1 : 0; + *pxmin++ = xmin; + } /* b */ + if (cfg->use_temporal_masking_effect) { + if (pxmin[-3] > pxmin[-3 + 1]) + pxmin[-3 + 1] += (pxmin[-3] - pxmin[-3 + 1]) * gfc->cd_psy->decay; + if (pxmin[-3 + 1] > pxmin[-3 + 2]) + pxmin[-3 + 2] += (pxmin[-3 + 1] - pxmin[-3 + 2]) * gfc->cd_psy->decay; + } + } /* end of short block sfb loop */ + + return ath_over; +} + + +static FLOAT +calc_noise_core_c(const gr_info * const cod_info, int *startline, int l, FLOAT step) +{ + FLOAT noise = 0; + int j = *startline; + const int *const ix = cod_info->l3_enc; + + if (j > cod_info->count1) { + while (l--) { + FLOAT temp; + temp = cod_info->xr[j]; + j++; + noise += temp * temp; + temp = cod_info->xr[j]; + j++; + noise += temp * temp; + } + } + else if (j > cod_info->big_values) { + FLOAT ix01[2]; + ix01[0] = 0; + ix01[1] = step; + while (l--) { + FLOAT temp; + temp = fabs(cod_info->xr[j]) - ix01[ix[j]]; + j++; + noise += temp * temp; + temp = fabs(cod_info->xr[j]) - ix01[ix[j]]; + j++; + noise += temp * temp; + } + } + else { + while (l--) { + FLOAT temp; + temp = fabs(cod_info->xr[j]) - pow43[ix[j]] * step; + j++; + noise += temp * temp; + temp = fabs(cod_info->xr[j]) - pow43[ix[j]] * step; + j++; + noise += temp * temp; + } + } + + *startline = j; + return noise; +} + + +/*************************************************************************/ +/* calc_noise */ +/*************************************************************************/ + +/* -oo dB => -1.00 */ +/* - 6 dB => -0.97 */ +/* - 3 dB => -0.80 */ +/* - 2 dB => -0.64 */ +/* - 1 dB => -0.38 */ +/* 0 dB => 0.00 */ +/* + 1 dB => +0.49 */ +/* + 2 dB => +1.06 */ +/* + 3 dB => +1.68 */ +/* + 6 dB => +3.69 */ +/* +10 dB => +6.45 */ + +int +calc_noise(gr_info const *const cod_info, + FLOAT const *l3_xmin, + FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise) +{ + int sfb, l, over = 0; + FLOAT over_noise_db = 0; + FLOAT tot_noise_db = 0; /* 0 dB relative to masking */ + FLOAT max_noise = -20.0; /* -200 dB relative to masking */ + int j = 0; + const int *scalefac = cod_info->scalefac; + + res->over_SSD = 0; + + + for (sfb = 0; sfb < cod_info->psymax; sfb++) { + int const s = + cod_info->global_gain - (((*scalefac++) + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + - cod_info->subblock_gain[cod_info->window[sfb]] * 8; + FLOAT const r_l3_xmin = 1.f / *l3_xmin++; + FLOAT distort_ = 0.0f; + FLOAT noise = 0.0f; + + if (prev_noise && (prev_noise->step[sfb] == s)) { + + /* use previously computed values */ + j += cod_info->width[sfb]; + distort_ = r_l3_xmin * prev_noise->noise[sfb]; + + noise = prev_noise->noise_log[sfb]; + + } + else { + FLOAT const step = POW20(s); + l = cod_info->width[sfb] >> 1; + + if ((j + cod_info->width[sfb]) > cod_info->max_nonzero_coeff) { + int usefullsize; + usefullsize = cod_info->max_nonzero_coeff - j + 1; + + if (usefullsize > 0) + l = usefullsize >> 1; + else + l = 0; + } + + noise = calc_noise_core_c(cod_info, &j, l, step); + + + if (prev_noise) { + /* save noise values */ + prev_noise->step[sfb] = s; + prev_noise->noise[sfb] = noise; + } + + distort_ = r_l3_xmin * noise; + + /* multiplying here is adding in dB, but can overflow */ + noise = FAST_LOG10(Max(distort_, 1E-20f)); + + if (prev_noise) { + /* save noise values */ + prev_noise->noise_log[sfb] = noise; + } + } + *distort++ = distort_; + + if (prev_noise) { + /* save noise values */ + prev_noise->global_gain = cod_info->global_gain;; + } + + + /*tot_noise *= Max(noise, 1E-20); */ + tot_noise_db += noise; + + if (noise > 0.0) { + int tmp; + + tmp = Max((int) (noise * 10 + .5), 1); + res->over_SSD += tmp * tmp; + + over++; + /* multiplying here is adding in dB -but can overflow */ + /*over_noise *= noise; */ + over_noise_db += noise; + } + max_noise = Max(max_noise, noise); + + } + + res->over_count = over; + res->tot_noise = tot_noise_db; + res->over_noise = over_noise_db; + res->max_noise = max_noise; + + return over; +} + + + + + + + + +/************************************************************************ + * + * set_pinfo() + * + * updates plotting data + * + * Mark Taylor 2000-??-?? + * + * Robert Hegemann: moved noise/distortion calc into it + * + ************************************************************************/ + +static void +set_pinfo(lame_internal_flags const *gfc, + gr_info * const cod_info, const III_psy_ratio * const ratio, const int gr, const int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, sfb2; + int j, i, l, start, end, bw; + FLOAT en0, en1; + FLOAT const ifqstep = (cod_info->scalefac_scale == 0) ? .5 : 1.0; + int const *const scalefac = cod_info->scalefac; + + FLOAT l3_xmin[SFBMAX], xfsf[SFBMAX]; + calc_noise_result noise; + + (void) calc_xmin(gfc, ratio, cod_info, l3_xmin); + (void) calc_noise(cod_info, l3_xmin, xfsf, &noise, 0); + + j = 0; + sfb2 = cod_info->sfb_lmax; + if (cod_info->block_type != SHORT_TYPE && !cod_info->mixed_block_flag) + sfb2 = 22; + for (sfb = 0; sfb < sfb2; sfb++) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb + 1]; + bw = end - start; + for (en0 = 0.0; j < end; j++) + en0 += cod_info->xr[j] * cod_info->xr[j]; + en0 /= bw; + /* convert to MDCT units */ + en1 = 1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->en[gr][ch][sfb] = en1 * en0; + gfc->pinfo->xfsf[gr][ch][sfb] = en1 * l3_xmin[sfb] * xfsf[sfb] / bw; + + if (ratio->en.l[sfb] > 0 && !cfg->ATHonly) + en0 = en0 / ratio->en.l[sfb]; + else + en0 = 0.0; + + gfc->pinfo->thr[gr][ch][sfb] = en1 * Max(en0 * ratio->thm.l[sfb], gfc->ATH->l[sfb]); + + /* there is no scalefactor bands >= SBPSY_l */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = 0; + if (cod_info->preflag && sfb >= 11) + gfc->pinfo->LAMEsfb[gr][ch][sfb] = -ifqstep * pretab[sfb]; + + if (sfb < SBPSY_l) { + assert(scalefac[sfb] >= 0); /* scfsi should be decoded by caller side */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] -= ifqstep * scalefac[sfb]; + } + } /* for sfb */ + + if (cod_info->block_type == SHORT_TYPE) { + sfb2 = sfb; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb + 1]; + bw = end - start; + for (i = 0; i < 3; i++) { + for (en0 = 0.0, l = start; l < end; l++) { + en0 += cod_info->xr[j] * cod_info->xr[j]; + j++; + } + en0 = Max(en0 / bw, 1e-20); + /* convert to MDCT units */ + en1 = 1e15; /* scaling so it shows up on FFT plot */ + + gfc->pinfo->en_s[gr][ch][3 * sfb + i] = en1 * en0; + gfc->pinfo->xfsf_s[gr][ch][3 * sfb + i] = en1 * l3_xmin[sfb2] * xfsf[sfb2] / bw; + if (ratio->en.s[sfb][i] > 0) + en0 = en0 / ratio->en.s[sfb][i]; + else + en0 = 0.0; + if (cfg->ATHonly || cfg->ATHshort) + en0 = 0; + + gfc->pinfo->thr_s[gr][ch][3 * sfb + i] = + en1 * Max(en0 * ratio->thm.s[sfb][i], gfc->ATH->s[sfb]); + + /* there is no scalefactor bands >= SBPSY_s */ + gfc->pinfo->LAMEsfb_s[gr][ch][3 * sfb + i] + = -2.0 * cod_info->subblock_gain[i]; + if (sfb < SBPSY_s) { + gfc->pinfo->LAMEsfb_s[gr][ch][3 * sfb + i] -= ifqstep * scalefac[sfb2]; + } + sfb2++; + } + } + } /* block type short */ + gfc->pinfo->LAMEqss[gr][ch] = cod_info->global_gain; + gfc->pinfo->LAMEmainbits[gr][ch] = cod_info->part2_3_length + cod_info->part2_length; + gfc->pinfo->LAMEsfbits[gr][ch] = cod_info->part2_length; + + gfc->pinfo->over[gr][ch] = noise.over_count; + gfc->pinfo->max_noise[gr][ch] = noise.max_noise * 10.0; + gfc->pinfo->over_noise[gr][ch] = noise.over_noise * 10.0; + gfc->pinfo->tot_noise[gr][ch] = noise.tot_noise * 10.0; + gfc->pinfo->over_SSD[gr][ch] = noise.over_SSD; +} + + +/************************************************************************ + * + * set_frame_pinfo() + * + * updates plotting data for a whole frame + * + * Robert Hegemann 2000-10-21 + * + ************************************************************************/ + +void +set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int ch; + int gr; + + /* for every granule and channel patch l3_enc and set info + */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + int scalefac_sav[SFBMAX]; + memcpy(scalefac_sav, cod_info->scalefac, sizeof(scalefac_sav)); + + /* reconstruct the scalefactors in case SCFSI was used + */ + if (gr == 1) { + int sfb; + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (cod_info->scalefac[sfb] < 0) /* scfsi */ + cod_info->scalefac[sfb] = gfc->l3_side.tt[0][ch].scalefac[sfb]; + } + } + + set_pinfo(gfc, cod_info, &ratio[gr][ch], gr, ch); + memcpy(cod_info->scalefac, scalefac_sav, sizeof(scalefac_sav)); + } /* for ch */ + } /* for gr */ +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.h new file mode 100644 index 00000000..b8333e7e --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/quantize_pvt.h @@ -0,0 +1,128 @@ +/* + * quantize_pvt include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_QUANTIZE_PVT_H +#define LAME_QUANTIZE_PVT_H + +#define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */ + +/* buggy Winamp decoder cannot handle values > 8191 */ +/* #define IXMAX_VAL 8191 */ + +#define PRECALC_SIZE (IXMAX_VAL+2) + + +extern const int nr_of_sfb_block[6][3][4]; +extern const int pretab[SBMAX_l]; +extern const int slen1_tab[16]; +extern const int slen2_tab[16]; + +extern const scalefac_struct sfBandIndex[9]; + +extern FLOAT pow43[PRECALC_SIZE]; +#ifdef TAKEHIRO_IEEE754_HACK +extern FLOAT adj43asm[PRECALC_SIZE]; +#else +extern FLOAT adj43[PRECALC_SIZE]; +#endif + +#define Q_MAX (256+1) +#define Q_MAX2 116 /* minimum possible number of + -cod_info->global_gain + + ((scalefac[] + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + + for long block, 0+((15+3)<<2) = 18*4 = 72 + for short block, 0+(15<<2)+7*8 = 15*4+56 = 116 + */ + +extern FLOAT pow20[Q_MAX + Q_MAX2 + 1]; +extern FLOAT ipow20[Q_MAX]; + +typedef struct calc_noise_result_t { + FLOAT over_noise; /* sum of quantization noise > masking */ + FLOAT tot_noise; /* sum of all quantization noise */ + FLOAT max_noise; /* max quantization noise */ + int over_count; /* number of quantization noise > masking */ + int over_SSD; /* SSD-like cost of distorted bands */ + int bits; +} calc_noise_result; + + +/** +* allows re-use of previously +* computed noise values +*/ +typedef struct calc_noise_data_t { + int global_gain; + int sfb_count1; + int step[39]; + FLOAT noise[39]; + FLOAT noise_log[39]; +} calc_noise_data; + + +int on_pe(lame_internal_flags * gfc, const FLOAT pe[2][2], + int targ_bits[2], int mean_bits, int gr, int cbr); + +void reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits); + + +void iteration_init(lame_internal_flags * gfc); + + +int calc_xmin(lame_internal_flags const *gfc, + III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * l3_xmin); + +int calc_noise(const gr_info * const cod_info, + const FLOAT * l3_xmin, + FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise); + +void set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]); + + + + +/* takehiro.c */ + +int count_bits(lame_internal_flags const *const gfc, const FLOAT * const xr, + gr_info * const cod_info, calc_noise_data * prev_noise); +int noquant_count_bits(lame_internal_flags const *const gfc, + gr_info * const cod_info, calc_noise_data * prev_noise); + + +void best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const cod_info); + +void best_scalefac_store(const lame_internal_flags * gfc, const int gr, const int ch, + III_side_info_t * const l3_side); + +int scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info); + +void huffman_init(lame_internal_flags * const gfc); + +void init_xrpow_core_init(lame_internal_flags * const gfc); + +FLOAT athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint); + +#define LARGE_BITS 100000 + +#endif /* LAME_QUANTIZE_PVT_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.c new file mode 100644 index 00000000..4fdaa8d3 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.c @@ -0,0 +1,293 @@ +/* + * bit reservoir source file + * + * Copyright (c) 1999-2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: reservoir.c,v 1.45 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "reservoir.h" + +#include "bitstream.h" +#include "lame-analysis.h" +#include "lame_global_flags.h" + + +/* + ResvFrameBegin: + Called (repeatedly) at the beginning of a frame. Updates the maximum + size of the reservoir, and checks to make sure main_data_begin + was set properly by the formatter +*/ + +/* + * Background information: + * + * This is the original text from the ISO standard. Because of + * sooo many bugs and irritations correcting comments are added + * in brackets []. A '^W' means you should remove the last word. + * + * 1) The following rule can be used to calculate the maximum + * number of bits used for one granule [^W frame]: + * At the highest possible bitrate of Layer III (320 kbps + * per stereo signal [^W^W^W], 48 kHz) the frames must be of + * [^W^W^W are designed to have] constant length, i.e. + * one buffer [^W^W the frame] length is: + * + * 320 kbps * 1152/48 kHz = 7680 bit = 960 byte + * + * This value is used as the maximum buffer per channel [^W^W] at + * lower bitrates [than 320 kbps]. At 64 kbps mono or 128 kbps + * stereo the main granule length is 64 kbps * 576/48 kHz = 768 bit + * [per granule and channel] at 48 kHz sampling frequency. + * This means that there is a maximum deviation (short time buffer + * [= reservoir]) of 7680 - 2*2*768 = 4608 bits is allowed at 64 kbps. + * The actual deviation is equal to the number of bytes [with the + * meaning of octets] denoted by the main_data_end offset pointer. + * The actual maximum deviation is (2^9-1)*8 bit = 4088 bits + * [for MPEG-1 and (2^8-1)*8 bit for MPEG-2, both are hard limits]. + * ... The xchange of buffer bits between the left and right channel + * is allowed without restrictions [exception: dual channel]. + * Because of the [constructed] constraint on the buffer size + * main_data_end is always set to 0 in the case of bit_rate_index==14, + * i.e. data rate 320 kbps per stereo signal [^W^W^W]. In this case + * all data are allocated between adjacent header [^W sync] words + * [, i.e. there is no buffering at all]. + */ + +int +ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int fullFrameBits; + int resvLimit; + int maxmp3buf; + III_side_info_t *const l3_side = &gfc->l3_side; + int frameLength; + int meanBits; + + frameLength = getframebits(gfc); + meanBits = (frameLength - cfg->sideinfo_len * 8) / cfg->mode_gr; + +/* + * Meaning of the variables: + * resvLimit: (0, 8, ..., 8*255 (MPEG-2), 8*511 (MPEG-1)) + * Number of bits can be stored in previous frame(s) due to + * counter size constaints + * maxmp3buf: ( ??? ... 8*1951 (MPEG-1 and 2), 8*2047 (MPEG-2.5)) + * Number of bits allowed to encode one frame (you can take 8*511 bit + * from the bit reservoir and at most 8*1440 bit from the current + * frame (320 kbps, 32 kHz), so 8*1951 bit is the largest possible + * value for MPEG-1 and -2) + * + * maximum allowed granule/channel size times 4 = 8*2047 bits., + * so this is the absolute maximum supported by the format. + * + * + * fullFrameBits: maximum number of bits available for encoding + * the current frame. + * + * mean_bits: target number of bits per granule. + * + * frameLength: + * + * gfc->ResvMax: maximum allowed reservoir + * + * gfc->ResvSize: current reservoir size + * + * l3_side->resvDrain_pre: + * ancillary data to be added to previous frame: + * (only usefull in VBR modes if it is possible to have + * maxmp3buf < fullFrameBits)). Currently disabled, + * see #define NEW_DRAIN + * 2010-02-13: RH now enabled, it seems to be needed for CBR too, + * as there exists one example, where the FhG decoder + * can't decode a -b320 CBR file anymore. + * + * l3_side->resvDrain_post: + * ancillary data to be added to this frame: + * + */ + + /* main_data_begin has 9 bits in MPEG-1, 8 bits MPEG-2 */ + resvLimit = (8 * 256) * cfg->mode_gr - 8; + + /* maximum allowed frame size. dont use more than this number of + bits, even if the frame has the space for them: */ + maxmp3buf = cfg->buffer_constraint; + esv->ResvMax = maxmp3buf - frameLength; + if (esv->ResvMax > resvLimit) + esv->ResvMax = resvLimit; + if (esv->ResvMax < 0 || cfg->disable_reservoir) + esv->ResvMax = 0; + + fullFrameBits = meanBits * cfg->mode_gr + Min(esv->ResvSize, esv->ResvMax); + + if (fullFrameBits > maxmp3buf) + fullFrameBits = maxmp3buf; + + assert(0 == esv->ResvMax % 8); + assert(esv->ResvMax >= 0); + + l3_side->resvDrain_pre = 0; + + if (gfc->pinfo != NULL) { + gfc->pinfo->mean_bits = meanBits / 2; /* expected bits per channel per granule [is this also right for mono/stereo, MPEG-1/2 ?] */ + gfc->pinfo->resvsize = esv->ResvSize; + } + *mean_bits = meanBits; + return fullFrameBits; +} + + +/* + ResvMaxBits + returns targ_bits: target number of bits to use for 1 granule + extra_bits: amount extra available from reservoir + Mark Taylor 4/99 +*/ +void +ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *extra_bits, int cbr) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int add_bits, targBits, extraBits; + int ResvSize = esv->ResvSize, ResvMax = esv->ResvMax; + + /* conpensate the saved bits used in the 1st granule */ + if (cbr) + ResvSize += mean_bits; + + if (gfc->sv_qnt.substep_shaping & 1) + ResvMax *= 0.9; + + targBits = mean_bits; + + /* extra bits if the reservoir is almost full */ + if (ResvSize * 10 > ResvMax * 9) { + add_bits = ResvSize - (ResvMax * 9) / 10; + targBits += add_bits; + gfc->sv_qnt.substep_shaping |= 0x80; + } + else { + add_bits = 0; + gfc->sv_qnt.substep_shaping &= 0x7f; + /* build up reservoir. this builds the reservoir a little slower + * than FhG. It could simple be mean_bits/15, but this was rigged + * to always produce 100 (the old value) at 128kbs */ + /* *targ_bits -= (int) (mean_bits/15.2); */ + if (!cfg->disable_reservoir && !(gfc->sv_qnt.substep_shaping & 1)) + targBits -= .1 * mean_bits; + } + + + /* amount from the reservoir we are allowed to use. ISO says 6/10 */ + extraBits = (ResvSize < (esv->ResvMax * 6) / 10 ? ResvSize : (esv->ResvMax * 6) / 10); + extraBits -= add_bits; + + if (extraBits < 0) + extraBits = 0; + + *targ_bits = targBits; + *extra_bits = extraBits; +} + +/* + ResvAdjust: + Called after a granule's bit allocation. Readjusts the size of + the reservoir to reflect the granule's usage. +*/ +void +ResvAdjust(lame_internal_flags * gfc, gr_info const *gi) +{ + gfc->sv_enc.ResvSize -= gi->part2_3_length + gi->part2_length; +} + + +/* + ResvFrameEnd: + Called after all granules in a frame have been allocated. Makes sure + that the reservoir size is within limits, possibly by adding stuffing + bits. +*/ +void +ResvFrameEnd(lame_internal_flags * gfc, int mean_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *const l3_side = &gfc->l3_side; + int stuffingBits; + int over_bits; + + esv->ResvSize += mean_bits * cfg->mode_gr; + stuffingBits = 0; + l3_side->resvDrain_post = 0; + l3_side->resvDrain_pre = 0; + + /* we must be byte aligned */ + if ((over_bits = esv->ResvSize % 8) != 0) + stuffingBits += over_bits; + + + over_bits = (esv->ResvSize - stuffingBits) - esv->ResvMax; + if (over_bits > 0) { + assert(0 == over_bits % 8); + assert(over_bits >= 0); + stuffingBits += over_bits; + } + + + /* NOTE: enabling the NEW_DRAIN code fixes some problems with FhG decoder + shipped with MS Windows operating systems. Using this, it is even + possible to use Gabriel's lax buffer consideration again, which + assumes, any decoder should have a buffer large enough + for a 320 kbps frame at 32 kHz sample rate. + + old drain code: + lame -b320 BlackBird.wav ---> does not play with GraphEdit.exe using FhG decoder V1.5 Build 50 + + new drain code: + lame -b320 BlackBird.wav ---> plays fine with GraphEdit.exe using FhG decoder V1.5 Build 50 + + Robert Hegemann, 2010-02-13. + */ + /* drain as many bits as possible into previous frame ancillary data + * In particular, in VBR mode ResvMax may have changed, and we have + * to make sure main_data_begin does not create a reservoir bigger + * than ResvMax mt 4/00*/ + { + int mdb_bytes = Min(l3_side->main_data_begin * 8, stuffingBits) / 8; + l3_side->resvDrain_pre += 8 * mdb_bytes; + stuffingBits -= 8 * mdb_bytes; + esv->ResvSize -= 8 * mdb_bytes; + l3_side->main_data_begin -= mdb_bytes; + } + /* drain the rest into this frames ancillary data */ + l3_side->resvDrain_post += stuffingBits; + esv->ResvSize -= stuffingBits; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.h new file mode 100644 index 00000000..7c585936 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/reservoir.h @@ -0,0 +1,31 @@ +/* + * bit reservoir include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_RESERVOIR_H +#define LAME_RESERVOIR_H + +int ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits); +void ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *max_bits, + int cbr); +void ResvAdjust(lame_internal_flags * gfc, gr_info const *gi); +void ResvFrameEnd(lame_internal_flags * gfc, int mean_bits); + +#endif /* LAME_RESERVOIR_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.c new file mode 100644 index 00000000..f7639005 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.c @@ -0,0 +1,2346 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * set/get functions for lame_global_flags + * + * Copyright (c) 2001-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: set_get.c,v 1.104 2017/09/06 15:07:30 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "bitstream.h" /* because of compute_flushbits */ + +#include "set_get.h" +#include "lame_global_flags.h" + +/* + * input stream description + */ + + +/* number of samples */ +/* it's unlikely for this function to return an error */ +int +lame_set_num_samples(lame_global_flags * gfp, unsigned long num_samples) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 2^32-1 */ + gfp->num_samples = num_samples; + return 0; + } + return -1; +} + +unsigned long +lame_get_num_samples(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->num_samples; + } + return 0; +} + + +/* input samplerate */ +int +lame_set_in_samplerate(lame_global_flags * gfp, int in_samplerate) +{ + if (is_lame_global_flags_valid(gfp)) { + if (in_samplerate < 1) + return -1; + /* input sample rate in Hz, default = 44100 Hz */ + gfp->samplerate_in = in_samplerate; + return 0; + } + return -1; +} + +int +lame_get_in_samplerate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->samplerate_in; + } + return 0; +} + + +/* number of channels in input stream */ +int +lame_set_num_channels(lame_global_flags * gfp, int num_channels) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 2 */ + if (2 < num_channels || 0 >= num_channels) { + return -1; /* we don't support more than 2 channels */ + } + gfp->num_channels = num_channels; + return 0; + } + return -1; +} + +int +lame_get_num_channels(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->num_channels; + } + return 0; +} + + +/* scale the input by this amount before encoding (not used for decoding) */ +int +lame_set_scale(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale = scale; + return 0; + } + return -1; +} + +float +lame_get_scale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale; + } + return 0; +} + + +/* scale the channel 0 (left) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_left(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale_left = scale; + return 0; + } + return -1; +} + +float +lame_get_scale_left(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale_left; + } + return 0; +} + + +/* scale the channel 1 (right) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_right(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale_right = scale; + return 0; + } + return -1; +} + +float +lame_get_scale_right(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale_right; + } + return 0; +} + + +/* output sample rate in Hz */ +int +lame_set_out_samplerate(lame_global_flags * gfp, int out_samplerate) +{ + if (is_lame_global_flags_valid(gfp)) { + /* + * default = 0: LAME picks best value based on the amount + * of compression + * MPEG only allows: + * MPEG1 32, 44.1, 48khz + * MPEG2 16, 22.05, 24 + * MPEG2.5 8, 11.025, 12 + * + * (not used by decoding routines) + */ + if (out_samplerate != 0) { + int v=0; + if (SmpFrqIndex(out_samplerate, &v) < 0) + return -1; + } + gfp->samplerate_out = out_samplerate; + return 0; + } + return -1; +} + +int +lame_get_out_samplerate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->samplerate_out; + } + return 0; +} + + + + +/* + * general control parameters + */ + +/* collect data for an MP3 frame analzyer */ +int +lame_set_analysis(lame_global_flags * gfp, int analysis) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > analysis || 1 < analysis) + return -1; + gfp->analysis = analysis; + return 0; + } + return -1; +} + +int +lame_get_analysis(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->analysis && 1 >= gfp->analysis); + return gfp->analysis; + } + return 0; +} + + +/* write a Xing VBR header frame */ +int +lame_set_bWriteVbrTag(lame_global_flags * gfp, int bWriteVbrTag) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (on) for VBR/ABR modes, 0 (off) for CBR mode */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > bWriteVbrTag || 1 < bWriteVbrTag) + return -1; + gfp->write_lame_tag = bWriteVbrTag; + return 0; + } + return -1; +} + +int +lame_get_bWriteVbrTag(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->write_lame_tag && 1 >= gfp->write_lame_tag); + return gfp->write_lame_tag; + } + return 0; +} + + + +/* decode only, use lame/mpglib to convert mp3 to wav */ +int +lame_set_decode_only(lame_global_flags * gfp, int decode_only) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > decode_only || 1 < decode_only) + return -1; + gfp->decode_only = decode_only; + return 0; + } + return -1; +} + +int +lame_get_decode_only(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->decode_only && 1 >= gfp->decode_only); + return gfp->decode_only; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* 1=encode a Vorbis .ogg file. default=0 */ +/* DEPRECATED */ +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); +#else +#endif + +/* encode a Vorbis .ogg file */ +/* DEPRECATED */ +int +lame_set_ogg(lame_global_flags * gfp, int ogg) +{ + (void) gfp; + (void) ogg; + return -1; +} + +int +lame_get_ogg(const lame_global_flags * gfp) +{ + (void) gfp; + return 0; +} + + +/* + * Internal algorithm selection. + * True quality is determined by the bitrate but this variable will effect + * quality by selecting expensive or cheap algorithms. + * quality=0..9. 0=best (very slow). 9=worst. + * recommended: 3 near-best quality, not too slow + * 5 good quality, fast + * 7 ok quality, really fast + */ +int +lame_set_quality(lame_global_flags * gfp, int quality) +{ + if (is_lame_global_flags_valid(gfp)) { + if (quality < 0) { + gfp->quality = 0; + } + else if (quality > 9) { + gfp->quality = 9; + } + else { + gfp->quality = quality; + } + return 0; + } + return -1; +} + +int +lame_get_quality(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quality; + } + return 0; +} + + +/* mode = STEREO, JOINT_STEREO, DUAL_CHANNEL (not supported), MONO */ +int +lame_set_mode(lame_global_flags * gfp, MPEG_mode mode) +{ + if (is_lame_global_flags_valid(gfp)) { + int mpg_mode = mode; + /* default: lame chooses based on compression ratio and input channels */ + if (mpg_mode < 0 || MAX_INDICATOR <= mpg_mode) + return -1; /* Unknown MPEG mode! */ + gfp->mode = mode; + return 0; + } + return -1; +} + +MPEG_mode +lame_get_mode(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(gfp->mode < MAX_INDICATOR); + return gfp->mode; + } + return NOT_SET; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* + mode_automs. Use a M/S mode with a switching threshold based on + compression ratio + DEPRECATED +*/ +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); +#else +#endif + +/* Us a M/S mode with a switching threshold based on compression ratio */ +/* DEPRECATED */ +int +lame_set_mode_automs(lame_global_flags * gfp, int mode_automs) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > mode_automs || 1 < mode_automs) + return -1; + lame_set_mode(gfp, JOINT_STEREO); + return 0; + } + return -1; +} + +int +lame_get_mode_automs(const lame_global_flags * gfp) +{ + (void) gfp; + return 1; +} + + +/* + * Force M/S for all frames. For testing only. + * Requires mode = 1. + */ +int +lame_set_force_ms(lame_global_flags * gfp, int force_ms) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > force_ms || 1 < force_ms) + return -1; + gfp->force_ms = force_ms; + return 0; + } + return -1; +} + +int +lame_get_force_ms(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->force_ms && 1 >= gfp->force_ms); + return gfp->force_ms; + } + return 0; +} + + +/* Use free_format. */ +int +lame_set_free_format(lame_global_flags * gfp, int free_format) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > free_format || 1 < free_format) + return -1; + gfp->free_format = free_format; + return 0; + } + return -1; +} + +int +lame_get_free_format(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->free_format && 1 >= gfp->free_format); + return gfp->free_format; + } + return 0; +} + + + +/* Perform ReplayGain analysis */ +int +lame_set_findReplayGain(lame_global_flags * gfp, int findReplayGain) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > findReplayGain || 1 < findReplayGain) + return -1; + gfp->findReplayGain = findReplayGain; + return 0; + } + return -1; +} + +int +lame_get_findReplayGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->findReplayGain && 1 >= gfp->findReplayGain); + return gfp->findReplayGain; + } + return 0; +} + + +/* Decode on the fly. Find the peak sample. If ReplayGain analysis is + enabled then perform it on the decoded data. */ +int +lame_set_decode_on_the_fly(lame_global_flags * gfp, int decode_on_the_fly) +{ + if (is_lame_global_flags_valid(gfp)) { +#ifndef DECODE_ON_THE_FLY + return -1; +#else + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > decode_on_the_fly || 1 < decode_on_the_fly) + return -1; + + gfp->decode_on_the_fly = decode_on_the_fly; + + return 0; +#endif + } + return -1; +} + +int +lame_get_decode_on_the_fly(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->decode_on_the_fly && 1 >= gfp->decode_on_the_fly); + return gfp->decode_on_the_fly; + } + return 0; +} + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* DEPRECATED: now does the same as lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_input(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_input(const lame_global_flags *); + +/* DEPRECATED: now does the same as + lame_set_decode_on_the_fly() && lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_decode(const lame_global_flags *); + +/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() + default = 0 (disabled) */ +int CDECL lame_set_findPeakSample(lame_global_flags *, int); +int CDECL lame_get_findPeakSample(const lame_global_flags *); +#else +#endif + +/* DEPRECATED. same as lame_set_decode_on_the_fly() */ +int +lame_set_findPeakSample(lame_global_flags * gfp, int arg) +{ + return lame_set_decode_on_the_fly(gfp, arg); +} + +int +lame_get_findPeakSample(const lame_global_flags * gfp) +{ + return lame_get_decode_on_the_fly(gfp); +} + +/* DEPRECATED. same as lame_set_findReplayGain() */ +int +lame_set_ReplayGain_input(lame_global_flags * gfp, int arg) +{ + return lame_set_findReplayGain(gfp, arg); +} + +int +lame_get_ReplayGain_input(const lame_global_flags * gfp) +{ + return lame_get_findReplayGain(gfp); +} + +/* DEPRECATED. same as lame_set_decode_on_the_fly() && + lame_set_findReplayGain() */ +int +lame_set_ReplayGain_decode(lame_global_flags * gfp, int arg) +{ + if (lame_set_decode_on_the_fly(gfp, arg) < 0 || lame_set_findReplayGain(gfp, arg) < 0) + return -1; + else + return 0; +} + +int +lame_get_ReplayGain_decode(const lame_global_flags * gfp) +{ + if (lame_get_decode_on_the_fly(gfp) > 0 && lame_get_findReplayGain(gfp) > 0) + return 1; + else + return 0; +} + + +/* set and get some gapless encoding flags */ + +int +lame_set_nogap_total(lame_global_flags * gfp, int the_nogap_total) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->nogap_total = the_nogap_total; + return 0; + } + return -1; +} + +int +lame_get_nogap_total(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->nogap_total; + } + return 0; +} + +int +lame_set_nogap_currentindex(lame_global_flags * gfp, int the_nogap_index) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->nogap_current = the_nogap_index; + return 0; + } + return -1; +} + +int +lame_get_nogap_currentindex(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->nogap_current; + } + return 0; +} + + +/* message handlers */ +int +lame_set_errorf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.errorf = func; + return 0; + } + return -1; +} + +int +lame_set_debugf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.debugf = func; + return 0; + } + return -1; +} + +int +lame_set_msgf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.msgf = func; + return 0; + } + return -1; +} + + +/* + * Set one of + * - brate + * - compression ratio. + * + * Default is compression ratio of 11. + */ +int +lame_set_brate(lame_global_flags * gfp, int brate) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->brate = brate; + if (brate > 320) { + gfp->disable_reservoir = 1; + } + return 0; + } + return -1; +} + +int +lame_get_brate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->brate; + } + return 0; +} + +int +lame_set_compression_ratio(lame_global_flags * gfp, float compression_ratio) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->compression_ratio = compression_ratio; + return 0; + } + return -1; +} + +float +lame_get_compression_ratio(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->compression_ratio; + } + return 0; +} + + + + +/* + * frame parameters + */ + +/* Mark as copyright protected. */ +int +lame_set_copyright(lame_global_flags * gfp, int copyright) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > copyright || 1 < copyright) + return -1; + gfp->copyright = copyright; + return 0; + } + return -1; +} + +int +lame_get_copyright(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->copyright && 1 >= gfp->copyright); + return gfp->copyright; + } + return 0; +} + + +/* Mark as original. */ +int +lame_set_original(lame_global_flags * gfp, int original) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > original || 1 < original) + return -1; + gfp->original = original; + return 0; + } + return -1; +} + +int +lame_get_original(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->original && 1 >= gfp->original); + return gfp->original; + } + return 0; +} + + +/* + * error_protection. + * Use 2 bytes from each frame for CRC checksum. + */ +int +lame_set_error_protection(lame_global_flags * gfp, int error_protection) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > error_protection || 1 < error_protection) + return -1; + gfp->error_protection = error_protection; + return 0; + } + return -1; +} + +int +lame_get_error_protection(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->error_protection && 1 >= gfp->error_protection); + return gfp->error_protection; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) */ +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); +#else +#endif + +/* + * padding_type. + * PAD_NO = pad no frames + * PAD_ALL = pad all frames + * PAD_ADJUST = adjust padding + */ +int +lame_set_padding_type(lame_global_flags * gfp, Padding_type padding_type) +{ + (void) gfp; + (void) padding_type; + return 0; +} + +Padding_type +lame_get_padding_type(const lame_global_flags * gfp) +{ + (void) gfp; + return PAD_ADJUST; +} + + +/* MP3 'private extension' bit. Meaningless. */ +int +lame_set_extension(lame_global_flags * gfp, int extension) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > extension || 1 < extension) + return -1; + gfp->extension = extension; + return 0; + } + return -1; +} + +int +lame_get_extension(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->extension && 1 >= gfp->extension); + return gfp->extension; + } + return 0; +} + + +/* Enforce strict ISO compliance. */ +int +lame_set_strict_ISO(lame_global_flags * gfp, int val) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (val < MDB_DEFAULT || MDB_MAXIMUM < val) + return -1; + gfp->strict_ISO = val; + return 0; + } + return -1; +} + +int +lame_get_strict_ISO(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->strict_ISO; + } + return 0; +} + + + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* Disable the bit reservoir. For testing only. */ +int +lame_set_disable_reservoir(lame_global_flags * gfp, int disable_reservoir) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > disable_reservoir || 1 < disable_reservoir) + return -1; + gfp->disable_reservoir = disable_reservoir; + return 0; + } + return -1; +} + +int +lame_get_disable_reservoir(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->disable_reservoir && 1 >= gfp->disable_reservoir); + return gfp->disable_reservoir; + } + return 0; +} + + + + +int +lame_set_experimentalX(lame_global_flags * gfp, int experimentalX) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_set_quant_comp(gfp, experimentalX); + lame_set_quant_comp_short(gfp, experimentalX); + return 0; + } + return -1; +} + +int +lame_get_experimentalX(const lame_global_flags * gfp) +{ + return lame_get_quant_comp(gfp); +} + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_quant_comp(lame_global_flags * gfp, int quant_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->quant_comp = quant_type; + return 0; + } + return -1; +} + +int +lame_get_quant_comp(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quant_comp; + } + return 0; +} + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_quant_comp_short(lame_global_flags * gfp, int quant_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->quant_comp_short = quant_type; + return 0; + } + return -1; +} + +int +lame_get_quant_comp_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quant_comp_short; + } + return 0; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalY(lame_global_flags * gfp, int experimentalY) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->experimentalY = experimentalY; + return 0; + } + return -1; +} + +int +lame_get_experimentalY(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->experimentalY; + } + return 0; +} + + +int +lame_set_experimentalZ(lame_global_flags * gfp, int experimentalZ) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->experimentalZ = experimentalZ; + return 0; + } + return -1; +} + +int +lame_get_experimentalZ(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->experimentalZ; + } + return 0; +} + + +/* Naoki's psycho acoustic model. */ +int +lame_set_exp_nspsytune(lame_global_flags * gfp, int exp_nspsytune) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + gfp->exp_nspsytune = exp_nspsytune; + return 0; + } + return -1; +} + +int +lame_get_exp_nspsytune(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->exp_nspsytune; + } + return 0; +} + + + + +/******************************************************************** + * VBR control + ***********************************************************************/ + +/* Types of VBR. default = vbr_off = CBR */ +int +lame_set_VBR(lame_global_flags * gfp, vbr_mode VBR) +{ + if (is_lame_global_flags_valid(gfp)) { + int vbr_q = VBR; + if (0 > vbr_q || vbr_max_indicator <= vbr_q) + return -1; /* Unknown VBR mode! */ + gfp->VBR = VBR; + return 0; + } + return -1; +} + +vbr_mode +lame_get_VBR(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(gfp->VBR < vbr_max_indicator); + return gfp->VBR; + } + return vbr_off; +} + + +/* + * VBR quality level. + * 0 = highest + * 9 = lowest + */ +int +lame_set_VBR_q(lame_global_flags * gfp, int VBR_q) +{ + if (is_lame_global_flags_valid(gfp)) { + int ret = 0; + + if (0 > VBR_q) { + ret = -1; /* Unknown VBR quality level! */ + VBR_q = 0; + } + if (9 < VBR_q) { + ret = -1; + VBR_q = 9; + } + gfp->VBR_q = VBR_q; + gfp->VBR_q_frac = 0; + return ret; + } + return -1; +} + +int +lame_get_VBR_q(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->VBR_q && 10 > gfp->VBR_q); + return gfp->VBR_q; + } + return 0; +} + +int +lame_set_VBR_quality(lame_global_flags * gfp, float VBR_q) +{ + if (is_lame_global_flags_valid(gfp)) { + int ret = 0; + + if (0 > VBR_q) { + ret = -1; /* Unknown VBR quality level! */ + VBR_q = 0; + } + if (9.999 < VBR_q) { + ret = -1; + VBR_q = 9.999; + } + + gfp->VBR_q = (int) VBR_q; + gfp->VBR_q_frac = VBR_q - gfp->VBR_q; + + return ret; + } + return -1; +} + +float +lame_get_VBR_quality(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_q + gfp->VBR_q_frac; + } + return 0; +} + + +/* Ignored except for VBR = vbr_abr (ABR mode) */ +int +lame_set_VBR_mean_bitrate_kbps(lame_global_flags * gfp, int VBR_mean_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_mean_bitrate_kbps = VBR_mean_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_mean_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_mean_bitrate_kbps; + } + return 0; +} + +int +lame_set_VBR_min_bitrate_kbps(lame_global_flags * gfp, int VBR_min_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_min_bitrate_kbps = VBR_min_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_min_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_min_bitrate_kbps; + } + return 0; +} + +int +lame_set_VBR_max_bitrate_kbps(lame_global_flags * gfp, int VBR_max_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_max_bitrate_kbps = VBR_max_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_max_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_max_bitrate_kbps; + } + return 0; +} + + +/* + * Strictly enforce VBR_min_bitrate. + * Normally it will be violated for analog silence. + */ +int +lame_set_VBR_hard_min(lame_global_flags * gfp, int VBR_hard_min) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > VBR_hard_min || 1 < VBR_hard_min) + return -1; + + gfp->VBR_hard_min = VBR_hard_min; + + return 0; + } + return -1; +} + +int +lame_get_VBR_hard_min(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->VBR_hard_min && 1 >= gfp->VBR_hard_min); + return gfp->VBR_hard_min; + } + return 0; +} + + +/******************************************************************** + * Filtering control + ***********************************************************************/ + +/* + * Freqency in Hz to apply lowpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_lowpassfreq(lame_global_flags * gfp, int lowpassfreq) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->lowpassfreq = lowpassfreq; + return 0; + } + return -1; +} + +int +lame_get_lowpassfreq(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->lowpassfreq; + } + return 0; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_lowpasswidth(lame_global_flags * gfp, int lowpasswidth) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->lowpasswidth = lowpasswidth; + return 0; + } + return -1; +} + +int +lame_get_lowpasswidth(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->lowpasswidth; + } + return 0; +} + + +/* + * Frequency in Hz to apply highpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_highpassfreq(lame_global_flags * gfp, int highpassfreq) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->highpassfreq = highpassfreq; + return 0; + } + return -1; +} + +int +lame_get_highpassfreq(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->highpassfreq; + } + return 0; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_highpasswidth(lame_global_flags * gfp, int highpasswidth) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->highpasswidth = highpasswidth; + return 0; + } + return -1; +} + +int +lame_get_highpasswidth(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->highpasswidth; + } + return 0; +} + + + + +/* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + + +/* Adjust masking values. */ +int +lame_set_maskingadjust(lame_global_flags * gfp, float adjust) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->maskingadjust = adjust; + return 0; + } + return -1; +} + +float +lame_get_maskingadjust(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->maskingadjust; + } + return 0; +} + +int +lame_set_maskingadjust_short(lame_global_flags * gfp, float adjust) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->maskingadjust_short = adjust; + return 0; + } + return -1; +} + +float +lame_get_maskingadjust_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->maskingadjust_short; + } + return 0; +} + +/* Only use ATH for masking. */ +int +lame_set_ATHonly(lame_global_flags * gfp, int ATHonly) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHonly = ATHonly; + return 0; + } + return -1; +} + +int +lame_get_ATHonly(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHonly; + } + return 0; +} + + +/* Only use ATH for short blocks. */ +int +lame_set_ATHshort(lame_global_flags * gfp, int ATHshort) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHshort = ATHshort; + return 0; + } + return -1; +} + +int +lame_get_ATHshort(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHshort; + } + return 0; +} + + +/* Disable ATH. */ +int +lame_set_noATH(lame_global_flags * gfp, int noATH) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->noATH = noATH; + return 0; + } + return -1; +} + +int +lame_get_noATH(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->noATH; + } + return 0; +} + + +/* Select ATH formula. */ +int +lame_set_ATHtype(lame_global_flags * gfp, int ATHtype) +{ + if (is_lame_global_flags_valid(gfp)) { + /* XXX: ATHtype should be converted to an enum. */ + gfp->ATHtype = ATHtype; + return 0; + } + return -1; +} + +int +lame_get_ATHtype(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHtype; + } + return 0; +} + + +/* Select ATH formula 4 shape. */ +int +lame_set_ATHcurve(lame_global_flags * gfp, float ATHcurve) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHcurve = ATHcurve; + return 0; + } + return -1; +} + +float +lame_get_ATHcurve(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHcurve; + } + return 0; +} + + +/* Lower ATH by this many db. */ +int +lame_set_ATHlower(lame_global_flags * gfp, float ATHlower) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATH_lower_db = ATHlower; + return 0; + } + return -1; +} + +float +lame_get_ATHlower(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATH_lower_db; + } + return 0; +} + + +/* Select ATH adaptive adjustment scheme. */ +int +lame_set_athaa_type(lame_global_flags * gfp, int athaa_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->athaa_type = athaa_type; + return 0; + } + return -1; +} + +int +lame_get_athaa_type(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->athaa_type; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL lame_set_athaa_loudapprox(lame_global_flags * gfp, int athaa_loudapprox); +int CDECL lame_get_athaa_loudapprox(const lame_global_flags * gfp); +#else +#endif + +/* Select the loudness approximation used by the ATH adaptive auto-leveling. */ +int +lame_set_athaa_loudapprox(lame_global_flags * gfp, int athaa_loudapprox) +{ + (void) gfp; + (void) athaa_loudapprox; + return 0; +} + +int +lame_get_athaa_loudapprox(const lame_global_flags * gfp) +{ + (void) gfp; + /* obsolete, the type known under number 2 is the only survival */ + return 2; +} + + +/* Adjust (in dB) the point below which adaptive ATH level adjustment occurs. */ +int +lame_set_athaa_sensitivity(lame_global_flags * gfp, float athaa_sensitivity) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->athaa_sensitivity = athaa_sensitivity; + return 0; + } + return -1; +} + +float +lame_get_athaa_sensitivity(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->athaa_sensitivity; + } + return 0; +} + + +/* Predictability limit (ISO tonality formula) */ +int lame_set_cwlimit(lame_global_flags * gfp, int cwlimit); +int lame_get_cwlimit(const lame_global_flags * gfp); + +int +lame_set_cwlimit(lame_global_flags * gfp, int cwlimit) +{ + (void) gfp; + (void) cwlimit; + return 0; +} + +int +lame_get_cwlimit(const lame_global_flags * gfp) +{ + (void) gfp; + return 0; +} + + + +/* + * Allow blocktypes to differ between channels. + * default: + * 0 for jstereo => block types coupled + * 1 for stereo => block types may differ + */ +int +lame_set_allow_diff_short(lame_global_flags * gfp, int allow_diff_short) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->short_blocks = allow_diff_short ? short_block_allowed : short_block_coupled; + return 0; + } + return -1; +} + +int +lame_get_allow_diff_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + if (gfp->short_blocks == short_block_allowed) + return 1; /* short blocks allowed to differ */ + else + return 0; /* not set, dispensed, forced or coupled */ + } + return 0; +} + + +/* Use temporal masking effect */ +int +lame_set_useTemporal(lame_global_flags * gfp, int useTemporal) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 <= useTemporal && useTemporal <= 1) { + gfp->useTemporal = useTemporal; + return 0; + } + } + return -1; +} + +int +lame_get_useTemporal(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->useTemporal && 1 >= gfp->useTemporal); + return gfp->useTemporal; + } + return 0; +} + + +/* Use inter-channel masking effect */ +int +lame_set_interChRatio(lame_global_flags * gfp, float ratio) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0.0 (no inter-channel maskin) */ + if (0 <= ratio && ratio <= 1.0) { + gfp->interChRatio = ratio; + return 0; + } + } + return -1; +} + +float +lame_get_interChRatio(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert((0 <= gfp->interChRatio && gfp->interChRatio <= 1.0) || EQ(gfp->interChRatio, -1)); + return gfp->interChRatio; + } + return 0; +} + + +/* Use pseudo substep shaping method */ +int +lame_set_substep(lame_global_flags * gfp, int method) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0.0 (no substep noise shaping) */ + if (0 <= method && method <= 7) { + gfp->substep_shaping = method; + return 0; + } + } + return -1; +} + +int +lame_get_substep(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->substep_shaping && gfp->substep_shaping <= 7); + return gfp->substep_shaping; + } + return 0; +} + +/* scalefactors scale */ +int +lame_set_sfscale(lame_global_flags * gfp, int val) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->noise_shaping = (val != 0) ? 2 : 1; + return 0; + } + return -1; +} + +int +lame_get_sfscale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return (gfp->noise_shaping == 2) ? 1 : 0; + } + return 0; +} + +/* subblock gain */ +int +lame_set_subblock_gain(lame_global_flags * gfp, int sbgain) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->subblock_gain = sbgain; + return 0; + } + return -1; +} + +int +lame_get_subblock_gain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->subblock_gain; + } + return 0; +} + + +/* Disable short blocks. */ +int +lame_set_no_short_blocks(lame_global_flags * gfp, int no_short_blocks) +{ + if (is_lame_global_flags_valid(gfp)) { + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 <= no_short_blocks && no_short_blocks <= 1) { + gfp->short_blocks = no_short_blocks ? short_block_dispensed : short_block_allowed; + return 0; + } + } + return -1; +} + +int +lame_get_no_short_blocks(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + switch (gfp->short_blocks) { + default: + case short_block_not_set: + return -1; + case short_block_dispensed: + return 1; + case short_block_allowed: + case short_block_coupled: + case short_block_forced: + return 0; + } + } + return -1; +} + + +/* Force short blocks. */ +int +lame_set_force_short_blocks(lame_global_flags * gfp, int short_blocks) +{ + if (is_lame_global_flags_valid(gfp)) { + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > short_blocks || 1 < short_blocks) + return -1; + + if (short_blocks == 1) + gfp->short_blocks = short_block_forced; + else if (gfp->short_blocks == short_block_forced) + gfp->short_blocks = short_block_allowed; + + return 0; + } + return -1; +} + +int +lame_get_force_short_blocks(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + switch (gfp->short_blocks) { + default: + case short_block_not_set: + return -1; + case short_block_dispensed: + case short_block_allowed: + case short_block_coupled: + return 0; + case short_block_forced: + return 1; + } + } + return -1; +} + +int +lame_set_short_threshold_lrm(lame_global_flags * gfp, float lrm) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->attackthre = lrm; + return 0; + } + return -1; +} + +float +lame_get_short_threshold_lrm(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->attackthre; + } + return 0; +} + +int +lame_set_short_threshold_s(lame_global_flags * gfp, float s) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->attackthre_s = s; + return 0; + } + return -1; +} + +float +lame_get_short_threshold_s(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->attackthre_s; + } + return 0; +} + +int +lame_set_short_threshold(lame_global_flags * gfp, float lrm, float s) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_set_short_threshold_lrm(gfp, lrm); + lame_set_short_threshold_s(gfp, s); + return 0; + } + return -1; +} + + +/* + * Input PCM is emphased PCM + * (for instance from one of the rarely emphased CDs). + * + * It is STRONGLY not recommended to use this, because psycho does not + * take it into account, and last but not least many decoders + * ignore these bits + */ +int +lame_set_emphasis(lame_global_flags * gfp, int emphasis) +{ + if (is_lame_global_flags_valid(gfp)) { + /* XXX: emphasis should be converted to an enum */ + if (0 <= emphasis && emphasis < 4) { + gfp->emphasis = emphasis; + return 0; + } + } + return -1; +} + +int +lame_get_emphasis(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->emphasis && gfp->emphasis < 4); + return gfp->emphasis; + } + return 0; +} + + + + +/***************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/***************************************************************/ + +/* MPEG version. + * 0 = MPEG-2 + * 1 = MPEG-1 + * (2 = MPEG-2.5) + */ +int +lame_get_version(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->cfg.version; + } + } + return 0; +} + + +/* Encoder delay. */ +int +lame_get_encoder_delay(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.encoder_delay; + } + } + return 0; +} + +/* padding added to the end of the input */ +int +lame_get_encoder_padding(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.encoder_padding; + } + } + return 0; +} + + +/* Size of MPEG frame. */ +int +lame_get_framesize(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + return 576 * cfg->mode_gr; + } + } + return 0; +} + + +/* Number of frames encoded so far. */ +int +lame_get_frameNum(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.frame_number; + } + } + return 0; +} + +int +lame_get_mf_samples_to_encode(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->sv_enc.mf_samples_to_encode; + } + } + return 0; +} + +int CDECL +lame_get_size_mp3buffer(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + int size; + compute_flushbits(gfc, &size); + return size; + } + } + return 0; +} + +int +lame_get_RadioGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.RadioGain; + } + } + return 0; +} + +int +lame_get_AudiophileGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return 0; + } + } + return 0; +} + +float +lame_get_PeakSample(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return (float) gfc->ov_rpg.PeakSample; + } + } + return 0; +} + +int +lame_get_noclipGainChange(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.noclipGainChange; + } + } + return 0; +} + +float +lame_get_noclipScale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.noclipScale; + } + } + return 0; +} + + +/* + * LAME's estimate of the total number of frames to be encoded. + * Only valid if calling program set num_samples. + */ +int +lame_get_totalframes(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + unsigned long const pcm_samples_per_frame = 576 * cfg->mode_gr; + unsigned long pcm_samples_to_encode = gfp->num_samples; + unsigned long end_padding = 0; + int frames = 0; + + if (pcm_samples_to_encode == (0ul-1ul)) + return 0; /* unknown */ + + /* estimate based on user set num_samples: */ + if (cfg->samplerate_in != cfg->samplerate_out) { + /* resampling, estimate new samples_to_encode */ + double resampled_samples_to_encode = 0.0, frames_f = 0.0; + if (cfg->samplerate_in > 0) { + resampled_samples_to_encode = pcm_samples_to_encode; + resampled_samples_to_encode *= cfg->samplerate_out; + resampled_samples_to_encode /= cfg->samplerate_in; + } + if (resampled_samples_to_encode <= 0.0) + return 0; /* unlikely to happen, so what, no estimate! */ + frames_f = floor(resampled_samples_to_encode / pcm_samples_per_frame); + if (frames_f >= (INT_MAX-2)) + return 0; /* overflow, happens eventually, no estimate! */ + frames = frames_f; + resampled_samples_to_encode -= frames * pcm_samples_per_frame; + pcm_samples_to_encode = ceil(resampled_samples_to_encode); + } + else { + frames = pcm_samples_to_encode / pcm_samples_per_frame; + pcm_samples_to_encode -= frames * pcm_samples_per_frame; + } + pcm_samples_to_encode += 576ul; + end_padding = pcm_samples_per_frame - (pcm_samples_to_encode % pcm_samples_per_frame); + if (end_padding < 576ul) { + end_padding += pcm_samples_per_frame; + } + pcm_samples_to_encode += end_padding; + frames += (pcm_samples_to_encode / pcm_samples_per_frame); + /* check to see if we underestimated totalframes */ + /* if (totalframes < gfp->frameNum) */ + /* totalframes = gfp->frameNum; */ + return frames; + } + } + return 0; +} + + + + + +int +lame_set_preset(lame_global_flags * gfp, int preset) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->preset = preset; + return apply_preset(gfp, preset, 1); + } + return -1; +} + + + +int +lame_set_asm_optimizations(lame_global_flags * gfp, int optim, int mode) +{ + if (is_lame_global_flags_valid(gfp)) { + mode = (mode == 1 ? 1 : 0); + switch (optim) { + case MMX:{ + gfp->asm_optimizations.mmx = mode; + return optim; + } + case AMD_3DNOW:{ + gfp->asm_optimizations.amd3dnow = mode; + return optim; + } + case SSE:{ + gfp->asm_optimizations.sse = mode; + return optim; + } + default: + return optim; + } + } + return -1; +} + + +void +lame_set_write_id3tag_automatic(lame_global_flags * gfp, int v) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->write_id3tag_automatic = v; + } +} + + +int +lame_get_write_id3tag_automatic(lame_global_flags const *gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->write_id3tag_automatic; + } + return 1; +} + + +/* + +UNDOCUMENTED, experimental settings. These routines are not prototyped +in lame.h. You should not use them, they are experimental and may +change. + +*/ + + +/* + * just another daily changing developer switch + */ +void CDECL lame_set_tune(lame_global_flags *, float); + +void +lame_set_tune(lame_global_flags * gfp, float val) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->tune_value_a = val; + gfp->tune = 1; + } +} + +/* Custom msfix hack */ +void +lame_set_msfix(lame_global_flags * gfp, double msfix) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 */ + gfp->msfix = msfix; + } +} + +float +lame_get_msfix(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->msfix; + } + return 0; +} + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL lame_set_preset_expopts(lame_global_flags *, int); +#else +#endif + +int +lame_set_preset_expopts(lame_global_flags * gfp, int preset_expopts) +{ + (void) gfp; + (void) preset_expopts; + return 0; +} + + +int +lame_set_preset_notune(lame_global_flags * gfp, int preset_notune) +{ + (void) gfp; + (void) preset_notune; + return 0; +} + +static int +calc_maximum_input_samples_for_buffer_size(lame_internal_flags const* gfc, size_t buffer_size) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int const pcm_samples_per_frame = 576 * cfg->mode_gr; + int frames_per_buffer = 0, input_samples_per_buffer = 0; + int kbps = 320; + + if (cfg->samplerate_out < 16000) + kbps = 64; + else if (cfg->samplerate_out < 32000) + kbps = 160; + else + kbps = 320; + if (cfg->free_format) + kbps = cfg->avg_bitrate; + else if (cfg->vbr == vbr_off) { + kbps = cfg->avg_bitrate; + } + { + int const pad = 1; + int const bpf = ((cfg->version + 1) * 72000 * kbps / cfg->samplerate_out + pad); + frames_per_buffer = buffer_size / bpf; + } + { + double ratio = (double) cfg->samplerate_in / cfg->samplerate_out; + input_samples_per_buffer = pcm_samples_per_frame * frames_per_buffer * ratio; + } + return input_samples_per_buffer; +} + +int +lame_get_maximum_number_of_samples(lame_t gfp, size_t buffer_size) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return calc_maximum_input_samples_for_buffer_size(gfc, buffer_size); + } + } + return LAME_GENERICERROR; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.h new file mode 100644 index 00000000..37e4bcdb --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/set_get.h @@ -0,0 +1,76 @@ +/* + * set_get.h -- Internal set/get definitions + * + * Copyright (C) 2003 Gabriel Bouvigne / Lame project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef __SET_GET_H__ +#define __SET_GET_H__ + +#include <lame.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* select psychoacoustic model */ + +/* manage short blocks */ + int CDECL lame_set_short_threshold(lame_global_flags *, float, float); + int CDECL lame_set_short_threshold_lrm(lame_global_flags *, float); + float CDECL lame_get_short_threshold_lrm(const lame_global_flags *); + int CDECL lame_set_short_threshold_s(lame_global_flags *, float); + float CDECL lame_get_short_threshold_s(const lame_global_flags *); + + + int CDECL lame_set_maskingadjust(lame_global_flags *, float); + float CDECL lame_get_maskingadjust(const lame_global_flags *); + + int CDECL lame_set_maskingadjust_short(lame_global_flags *, float); + float CDECL lame_get_maskingadjust_short(const lame_global_flags *); + +/* select ATH formula 4 shape */ + int CDECL lame_set_ATHcurve(lame_global_flags *, float); + float CDECL lame_get_ATHcurve(const lame_global_flags *); + + int CDECL lame_set_preset_notune(lame_global_flags *, int); + +/* substep shaping method */ + int CDECL lame_set_substep(lame_global_flags *, int); + int CDECL lame_get_substep(const lame_global_flags *); + +/* scalefactors scale */ + int CDECL lame_set_sfscale(lame_global_flags *, int); + int CDECL lame_get_sfscale(const lame_global_flags *); + +/* subblock gain */ + int CDECL lame_set_subblock_gain(lame_global_flags *, int); + int CDECL lame_get_subblock_gain(const lame_global_flags *); + + + +/*presets*/ + int apply_preset(lame_global_flags *, int preset, int enforce); + + void CDECL lame_set_tune(lame_t, float); /* FOR INTERNAL USE ONLY */ + void CDECL lame_set_msfix(lame_t gfp, double msfix); + + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.c new file mode 100644 index 00000000..a0230999 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.c @@ -0,0 +1,564 @@ +/* + * MPEG layer 3 tables source file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: tables.c,v 1.29 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "machine.h" + +#include "lame.h" +#include "tables.h" + + +static const uint16_t t1HB[] = { + 1, 1, + 1, 0 +}; + +static const uint16_t t2HB[] = { + 1, 2, 1, + 3, 1, 1, + 3, 2, 0 +}; + +static const uint16_t t3HB[] = { + 3, 2, 1, + 1, 1, 1, + 3, 2, 0 +}; + +static const uint16_t t5HB[] = { + 1, 2, 6, 5, + 3, 1, 4, 4, + 7, 5, 7, 1, + 6, 1, 1, 0 +}; + +static const uint16_t t6HB[] = { + 7, 3, 5, 1, + 6, 2, 3, 2, + 5, 4, 4, 1, + 3, 3, 2, 0 +}; + +static const uint16_t t7HB[] = { + 1, 2, 10, 19, 16, 10, + 3, 3, 7, 10, 5, 3, + 11, 4, 13, 17, 8, 4, + 12, 11, 18, 15, 11, 2, + 7, 6, 9, 14, 3, 1, + 6, 4, 5, 3, 2, 0 +}; + +static const uint16_t t8HB[] = { + 3, 4, 6, 18, 12, 5, + 5, 1, 2, 16, 9, 3, + 7, 3, 5, 14, 7, 3, + 19, 17, 15, 13, 10, 4, + 13, 5, 8, 11, 5, 1, + 12, 4, 4, 1, 1, 0 +}; + +static const uint16_t t9HB[] = { + 7, 5, 9, 14, 15, 7, + 6, 4, 5, 5, 6, 7, + 7, 6, 8, 8, 8, 5, + 15, 6, 9, 10, 5, 1, + 11, 7, 9, 6, 4, 1, + 14, 4, 6, 2, 6, 0 +}; + +static const uint16_t t10HB[] = { + 1, 2, 10, 23, 35, 30, 12, 17, + 3, 3, 8, 12, 18, 21, 12, 7, + 11, 9, 15, 21, 32, 40, 19, 6, + 14, 13, 22, 34, 46, 23, 18, 7, + 20, 19, 33, 47, 27, 22, 9, 3, + 31, 22, 41, 26, 21, 20, 5, 3, + 14, 13, 10, 11, 16, 6, 5, 1, + 9, 8, 7, 8, 4, 4, 2, 0 +}; + +static const uint16_t t11HB[] = { + 3, 4, 10, 24, 34, 33, 21, 15, + 5, 3, 4, 10, 32, 17, 11, 10, + 11, 7, 13, 18, 30, 31, 20, 5, + 25, 11, 19, 59, 27, 18, 12, 5, + 35, 33, 31, 58, 30, 16, 7, 5, + 28, 26, 32, 19, 17, 15, 8, 14, + 14, 12, 9, 13, 14, 9, 4, 1, + 11, 4, 6, 6, 6, 3, 2, 0 +}; + +static const uint16_t t12HB[] = { + 9, 6, 16, 33, 41, 39, 38, 26, + 7, 5, 6, 9, 23, 16, 26, 11, + 17, 7, 11, 14, 21, 30, 10, 7, + 17, 10, 15, 12, 18, 28, 14, 5, + 32, 13, 22, 19, 18, 16, 9, 5, + 40, 17, 31, 29, 17, 13, 4, 2, + 27, 12, 11, 15, 10, 7, 4, 1, + 27, 12, 8, 12, 6, 3, 1, 0 +}; + +static const uint16_t t13HB[] = { + 1, 5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19, + 3, 4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14, + 15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16, + 22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14, + 35, 16, 60, 57, 97, 75, 114, 91, 54, 73, 55, 41, 48, 53, 23, 24, + 58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17, + 47, 45, 78, 74, 115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15, + 72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42, + 43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16, + 53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11, + 35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22, + 53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14, 9, 7, + 34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17, 9, 5, + 45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10, 7, 6, 3, + 48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10, 6, 1, 4, 2, + 16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16, 8, 1, 1, 0, 1 +}; + +static const uint16_t t15HB[] = { + 7, 12, 18, 53, 47, 76, 124, 108, 89, 123, 108, 119, 107, 81, 122, 63, + 13, 5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36, + 19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33, + 29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29, + 52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27, + 77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38, + 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30, + 109, 53, 49, 94, 88, 75, 66, 122, 91, 73, 56, 42, 64, 44, 21, 25, + 90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20, + 71, 34, 67, 60, 58, 49, 88, 76, 67, 106, 71, 54, 38, 39, 23, 15, + 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62, 9, + 86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11, + 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14, 7, + 91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14, 8, 9, 3, + 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10, 2, 1, + 71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10, 6, 8, 6, 2, 0 +}; + +static const uint16_t t16HB[] = { + 1, 5, 14, 44, 74, 63, 110, 93, 172, 149, 138, 242, 225, 195, 376, 17, + 3, 4, 12, 20, 35, 62, 53, 47, 83, 75, 68, 119, 201, 107, 207, 9, + 15, 13, 23, 38, 67, 58, 103, 90, 161, 72, 127, 117, 110, 209, 206, 16, + 45, 21, 39, 69, 64, 114, 99, 87, 158, 140, 252, 212, 199, 387, 365, 26, + 75, 36, 68, 65, 115, 101, 179, 164, 155, 264, 246, 226, 395, 382, 362, 9, + 66, 30, 59, 56, 102, 185, 173, 265, 142, 253, 232, 400, 388, 378, 445, 16, + 111, 54, 52, 100, 184, 178, 160, 133, 257, 244, 228, 217, 385, 366, 715, 10, + 98, 48, 91, 88, 165, 157, 148, 261, 248, 407, 397, 372, 380, 889, 884, 8, + 85, 84, 81, 159, 156, 143, 260, 249, 427, 401, 392, 383, 727, 713, 708, 7, + 154, 76, 73, 141, 131, 256, 245, 426, 406, 394, 384, 735, 359, 710, 352, 11, + 139, 129, 67, 125, 247, 233, 229, 219, 393, 743, 737, 720, 885, 882, 439, 4, + 243, 120, 118, 115, 227, 223, 396, 746, 742, 736, 721, 712, 706, 223, 436, 6, + 202, 224, 222, 218, 216, 389, 386, 381, 364, 888, 443, 707, 440, 437, 1728, 4, + 747, 211, 210, 208, 370, 379, 734, 723, 714, 1735, 883, 877, 876, 3459, 865, 2, + 377, 369, 102, 187, 726, 722, 358, 711, 709, 866, 1734, 871, 3458, 870, 434, 0, + 12, 10, 7, 11, 10, 17, 11, 9, 13, 12, 10, 7, 5, 3, 1, 3 +}; + +static const uint16_t t24HB[] = { + 15, 13, 46, 80, 146, 262, 248, 434, 426, 669, 653, 649, 621, 517, 1032, 88, + 14, 12, 21, 38, 71, 130, 122, 216, 209, 198, 327, 345, 319, 297, 279, 42, + 47, 22, 41, 74, 68, 128, 120, 221, 207, 194, 182, 340, 315, 295, 541, 18, + 81, 39, 75, 70, 134, 125, 116, 220, 204, 190, 178, 325, 311, 293, 271, 16, + 147, 72, 69, 135, 127, 118, 112, 210, 200, 188, 352, 323, 306, 285, 540, 14, + 263, 66, 129, 126, 119, 114, 214, 202, 192, 180, 341, 317, 301, 281, 262, 12, + 249, 123, 121, 117, 113, 215, 206, 195, 185, 347, 330, 308, 291, 272, 520, 10, + 435, 115, 111, 109, 211, 203, 196, 187, 353, 332, 313, 298, 283, 531, 381, 17, + 427, 212, 208, 205, 201, 193, 186, 177, 169, 320, 303, 286, 268, 514, 377, 16, + 335, 199, 197, 191, 189, 181, 174, 333, 321, 305, 289, 275, 521, 379, 371, 11, + 668, 184, 183, 179, 175, 344, 331, 314, 304, 290, 277, 530, 383, 373, 366, 10, + 652, 346, 171, 168, 164, 318, 309, 299, 287, 276, 263, 513, 375, 368, 362, 6, + 648, 322, 316, 312, 307, 302, 292, 284, 269, 261, 512, 376, 370, 364, 359, 4, + 620, 300, 296, 294, 288, 282, 273, 266, 515, 380, 374, 369, 365, 361, 357, 2, + 1033, 280, 278, 274, 267, 264, 259, 382, 378, 372, 367, 363, 360, 358, 356, 0, + 43, 20, 19, 17, 15, 13, 11, 9, 7, 6, 4, 7, 5, 3, 1, 3 +}; + +static const uint16_t t32HB[] = { + 1 << 0, 5 << 1, 4 << 1, 5 << 2, 6 << 1, 5 << 2, 4 << 2, 4 << 3, + 7 << 1, 3 << 2, 6 << 2, 0 << 3, 7 << 2, 2 << 3, 3 << 3, 1 << 4 +}; + +static const uint16_t t33HB[] = { + 15 << 0, 14 << 1, 13 << 1, 12 << 2, 11 << 1, 10 << 2, 9 << 2, 8 << 3, + 7 << 1, 6 << 2, 5 << 2, 4 << 3, 3 << 2, 2 << 3, 1 << 3, 0 << 4 +}; + + +const uint8_t t1l[] = { + 1, 4, + 3, 5 +}; + +static const uint8_t t2l[] = { + 1, 4, 7, + 4, 5, 7, + 6, 7, 8 +}; + +static const uint8_t t3l[] = { + 2, 3, 7, + 4, 4, 7, + 6, 7, 8 +}; + +static const uint8_t t5l[] = { + 1, 4, 7, 8, + 4, 5, 8, 9, + 7, 8, 9, 10, + 8, 8, 9, 10 +}; + +static const uint8_t t6l[] = { + 3, 4, 6, 8, + 4, 4, 6, 7, + 5, 6, 7, 8, + 7, 7, 8, 9 +}; + +static const uint8_t t7l[] = { + 1, 4, 7, 9, 9, 10, + 4, 6, 8, 9, 9, 10, + 7, 7, 9, 10, 10, 11, + 8, 9, 10, 11, 11, 11, + 8, 9, 10, 11, 11, 12, + 9, 10, 11, 12, 12, 12 +}; + +static const uint8_t t8l[] = { + 2, 4, 7, 9, 9, 10, + 4, 4, 6, 10, 10, 10, + 7, 6, 8, 10, 10, 11, + 9, 10, 10, 11, 11, 12, + 9, 9, 10, 11, 12, 12, + 10, 10, 11, 11, 13, 13 +}; + +static const uint8_t t9l[] = { + 3, 4, 6, 7, 9, 10, + 4, 5, 6, 7, 8, 10, + 5, 6, 7, 8, 9, 10, + 7, 7, 8, 9, 9, 10, + 8, 8, 9, 9, 10, 11, + 9, 9, 10, 10, 11, 11 +}; + +static const uint8_t t10l[] = { + 1, 4, 7, 9, 10, 10, 10, 11, + 4, 6, 8, 9, 10, 11, 10, 10, + 7, 8, 9, 10, 11, 12, 11, 11, + 8, 9, 10, 11, 12, 12, 11, 12, + 9, 10, 11, 12, 12, 12, 12, 12, + 10, 11, 12, 12, 13, 13, 12, 13, + 9, 10, 11, 12, 12, 12, 13, 13, + 10, 10, 11, 12, 12, 13, 13, 13 +}; + +static const uint8_t t11l[] = { + 2, 4, 6, 8, 9, 10, 9, 10, + 4, 5, 6, 8, 10, 10, 9, 10, + 6, 7, 8, 9, 10, 11, 10, 10, + 8, 8, 9, 11, 10, 12, 10, 11, + 9, 10, 10, 11, 11, 12, 11, 12, + 9, 10, 11, 12, 12, 13, 12, 13, + 9, 9, 9, 10, 11, 12, 12, 12, + 9, 9, 10, 11, 12, 12, 12, 12 +}; + +static const uint8_t t12l[] = { + 4, 4, 6, 8, 9, 10, 10, 10, + 4, 5, 6, 7, 9, 9, 10, 10, + 6, 6, 7, 8, 9, 10, 9, 10, + 7, 7, 8, 8, 9, 10, 10, 10, + 8, 8, 9, 9, 10, 10, 10, 11, + 9, 9, 10, 10, 10, 11, 10, 11, + 9, 9, 9, 10, 10, 11, 11, 12, + 10, 10, 10, 11, 11, 11, 11, 12 +}; + +static const uint8_t t13l[] = { + 1, 5, 7, 8, 9, 10, 10, 11, 10, 11, 12, 12, 13, 13, 14, 14, + 4, 6, 8, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 14, 14, 14, + 7, 8, 9, 10, 11, 11, 12, 12, 11, 12, 12, 13, 13, 14, 15, 15, + 8, 9, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 15, + 9, 9, 11, 11, 12, 12, 13, 13, 12, 13, 13, 14, 14, 15, 15, 16, + 10, 10, 11, 12, 12, 12, 13, 13, 13, 13, 14, 13, 15, 15, 16, 16, + 10, 11, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, + 11, 11, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 18, 18, + 10, 10, 11, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 17, 17, + 11, 11, 12, 12, 13, 13, 13, 15, 14, 15, 15, 16, 16, 16, 18, 17, + 11, 12, 12, 13, 13, 14, 14, 15, 14, 15, 16, 15, 16, 17, 18, 19, + 12, 12, 12, 13, 14, 14, 14, 14, 15, 15, 15, 16, 17, 17, 17, 18, + 12, 13, 13, 14, 14, 15, 14, 15, 16, 16, 17, 17, 17, 18, 18, 18, + 13, 13, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 18, 17, 18, 18, + 14, 14, 14, 15, 15, 15, 17, 16, 16, 19, 17, 17, 17, 19, 18, 18, + 13, 14, 15, 16, 16, 16, 17, 16, 17, 17, 18, 18, 21, 20, 21, 18 +}; + +static const uint8_t t15l[] = { + 3, 5, 6, 8, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 14, + 5, 5, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, + 6, 7, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, + 10, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 14, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, + 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 14, + 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, + 12, 12, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 15, 15, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 15, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15 +}; + +static const uint8_t t16_5l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 11, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 11, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 12, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 13, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 12, + 10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 13, + 11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 13, + 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 13, + 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 13, + 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 14, + 12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 13, + 13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 14, + 13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 14, + 15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 14, + 14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 14, + 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 12 +}; + +static const uint8_t t16l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 10, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 10, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 11, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 12, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 11, + 10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 12, + 11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 12, + 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 12, + 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 12, + 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 13, + 12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 12, + 13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 13, + 13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 13, + 15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 13, + 14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 13, + 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10 +}; + +static const uint8_t t24l[] = { + 4, 5, 7, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 13, 10, + 5, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 10, + 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 9, + 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 9, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 9, + 10, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 9, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 9, + 11, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 10, + 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 10, + 12, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, + 12, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10, + 13, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 6 +}; + +const uint8_t t32l[] = { + 1 + 0, 4 + 1, 4 + 1, 5 + 2, 4 + 1, 6 + 2, 5 + 2, 6 + 3, + 4 + 1, 5 + 2, 5 + 2, 6 + 3, 5 + 2, 6 + 3, 6 + 3, 6 + 4 +}; + +const uint8_t t33l[] = { + 4 + 0, 4 + 1, 4 + 1, 4 + 2, 4 + 1, 4 + 2, 4 + 2, 4 + 3, + 4 + 1, 4 + 2, 4 + 2, 4 + 3, 4 + 2, 4 + 3, 4 + 3, 4 + 4 +}; + + +const struct huffcodetab ht[HTN] = { + /* xlen, linmax, table, hlen */ + {0, 0, NULL, NULL}, + {2, 0, t1HB, t1l}, + {3, 0, t2HB, t2l}, + {3, 0, t3HB, t3l}, + {0, 0, NULL, NULL}, /* Apparently not used */ + {4, 0, t5HB, t5l}, + {4, 0, t6HB, t6l}, + {6, 0, t7HB, t7l}, + {6, 0, t8HB, t8l}, + {6, 0, t9HB, t9l}, + {8, 0, t10HB, t10l}, + {8, 0, t11HB, t11l}, + {8, 0, t12HB, t12l}, + {16, 0, t13HB, t13l}, + {0, 0, NULL, t16_5l}, /* Apparently not used */ + {16, 0, t15HB, t15l}, + + {1, 1, t16HB, t16l}, + {2, 3, t16HB, t16l}, + {3, 7, t16HB, t16l}, + {4, 15, t16HB, t16l}, + {6, 63, t16HB, t16l}, + {8, 255, t16HB, t16l}, + {10, 1023, t16HB, t16l}, + {13, 8191, t16HB, t16l}, + + {4, 15, t24HB, t24l}, + {5, 31, t24HB, t24l}, + {6, 63, t24HB, t24l}, + {7, 127, t24HB, t24l}, + {8, 255, t24HB, t24l}, + {9, 511, t24HB, t24l}, + {11, 2047, t24HB, t24l}, + {13, 8191, t24HB, t24l}, + + {0, 0, t32HB, t32l}, + {0, 0, t33HB, t33l}, +}; + + + + + +/* for (i = 0; i < 16*16; i++) { + * largetbl[i] = ((ht[16].hlen[i]) << 16) + ht[24].hlen[i]; + * } + */ +const uint32_t largetbl[16 * 16] = { + 0x010004, 0x050005, 0x070007, 0x090008, 0x0a0009, 0x0a000a, 0x0b000a, 0x0b000b, + 0x0c000b, 0x0c000c, 0x0c000c, 0x0d000c, 0x0d000c, 0x0d000c, 0x0e000d, 0x0a000a, + 0x040005, 0x060006, 0x080007, 0x090008, 0x0a0009, 0x0b000a, 0x0b000a, 0x0b000b, + 0x0c000b, 0x0c000b, 0x0c000c, 0x0d000c, 0x0e000c, 0x0d000c, 0x0e000c, 0x0a000a, + 0x070007, 0x080007, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000b, + 0x0d000b, 0x0c000b, 0x0d000b, 0x0d000c, 0x0d000c, 0x0e000c, 0x0e000d, 0x0b0009, + 0x090008, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0c000b, + 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0c0009, + 0x0a0009, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000a, 0x0d000b, + 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000d, 0x0b0009, + 0x0a000a, 0x0a0009, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0e000b, + 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0c0009, + 0x0b000a, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0d000b, 0x0d000b, + 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000d, 0x0c0009, + 0x0b000b, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, + 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x11000d, 0x11000d, 0x0c000a, + 0x0b000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, + 0x0f000b, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000d, 0x10000d, 0x0c000a, + 0x0c000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, 0x0f000c, + 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0f000d, 0x10000d, 0x0f000d, 0x0d000a, + 0x0c000c, 0x0d000b, 0x0c000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, + 0x0f000c, 0x10000c, 0x10000c, 0x10000d, 0x11000d, 0x11000d, 0x10000d, 0x0c000a, + 0x0d000c, 0x0d000c, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x10000c, + 0x10000c, 0x10000c, 0x10000c, 0x10000d, 0x10000d, 0x0f000d, 0x10000d, 0x0d000a, + 0x0d000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, + 0x0f000c, 0x11000c, 0x10000d, 0x10000d, 0x10000d, 0x10000d, 0x12000d, 0x0d000a, + 0x0f000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000c, + 0x10000d, 0x12000d, 0x11000d, 0x11000d, 0x11000d, 0x13000d, 0x11000d, 0x0d000a, + 0x0e000d, 0x0f000c, 0x0d000c, 0x0e000c, 0x10000c, 0x10000c, 0x0f000c, 0x10000d, + 0x10000d, 0x11000d, 0x12000d, 0x11000d, 0x13000d, 0x11000d, 0x10000d, 0x0d000a, + 0x0a0009, 0x0a0009, 0x0a0009, 0x0b0009, 0x0b0009, 0x0c0009, 0x0c0009, 0x0c0009, + 0x0d0009, 0x0d0009, 0x0d0009, 0x0d000a, 0x0d000a, 0x0d000a, 0x0d000a, 0x0a0006 +}; + +/* for (i = 0; i < 3*3; i++) { + * table23[i] = ((ht[2].hlen[i]) << 16) + ht[3].hlen[i]; + * } + */ +const uint32_t table23[3 * 3] = { + 0x010002, 0x040003, 0x070007, + 0x040004, 0x050004, 0x070007, + 0x060006, 0x070007, 0x080008 +}; + +/* for (i = 0; i < 4*4; i++) { + * table56[i] = ((ht[5].hlen[i]) << 16) + ht[6].hlen[i]; + * } + */ +const uint32_t table56[4 * 4] = { + 0x010003, 0x040004, 0x070006, 0x080008, 0x040004, 0x050004, 0x080006, 0x090007, + 0x070005, 0x080006, 0x090007, 0x0a0008, 0x080007, 0x080007, 0x090008, 0x0a0009 +}; + + + +/* + * 0: MPEG-2 LSF + * 1: MPEG-1 + * 2: MPEG-2.5 LSF FhG extention (1995-07-11 shn) + */ + +typedef enum { + MPEG_2 = 0, + MPEG_1 = 1, + MPEG_25 = 2 +} MPEG_t; + +const int bitrate_table[3][16] = { + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1}, /* MPEG 2 */ + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1}, /* MPEG 1 */ + {0, 8, 16, 24, 32, 40, 48, 56, 64, -1, -1, -1, -1, -1, -1, -1}, /* MPEG 2.5 */ +}; + +const int samplerate_table[3][4] = { + {22050, 24000, 16000, -1}, /* MPEG 2 */ + {44100, 48000, 32000, -1}, /* MPEG 1 */ + {11025, 12000, 8000, -1}, /* MPEG 2.5 */ +}; + +int +lame_get_bitrate(int mpeg_version, int table_index) +{ + if (0 <= mpeg_version && mpeg_version <= 2) { + if (0 <= table_index && table_index <= 15) { + return bitrate_table[mpeg_version][table_index]; + } + } + return -1; +} + +int +lame_get_samplerate(int mpeg_version, int table_index) +{ + if (0 <= mpeg_version && mpeg_version <= 2) { + if (0 <= table_index && table_index <= 3) { + return samplerate_table[mpeg_version][table_index]; + } + } + return -1; +} + + +/* This is the scfsi_band table from 2.4.2.7 of the IS */ +const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; + +/* end of tables.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.h new file mode 100644 index 00000000..0dd7deb2 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/tables.h @@ -0,0 +1,95 @@ +/* + * MPEG layer 3 tables include file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_TABLES_H +#define LAME_TABLES_H + +#if 0 +typedef struct { + unsigned char no; + unsigned char width; + unsigned char minval_2; + float quiet_thr; + float norm; + float bark; +} type1_t; + +typedef struct { + unsigned char no; + unsigned char width; + float quiet_thr; + float norm; + float SNR; + float bark; +} type2_t; + +typedef struct { + unsigned int no:5; + unsigned int cbw:3; + unsigned int bu:6; + unsigned int bo:6; + unsigned int w1_576:10; + unsigned int w2_576:10; +} type34_t; + +typedef struct { + size_t len1; + const type1_t *const tab1; + size_t len2; + const type2_t *const tab2; + size_t len3; + const type34_t *const tab3; + size_t len4; + const type34_t *const tab4; +} type5_t; + +extern const type5_t table5[6]; + +#endif + +#define HTN 34 + +struct huffcodetab { + const unsigned int xlen; /* max. x-index+ */ + const unsigned int linmax; /* max number to be stored in linbits */ + const uint16_t *table; /* pointer to array[xlen][ylen] */ + const uint8_t *hlen; /* pointer to array[xlen][ylen] */ +}; + +extern const struct huffcodetab ht[HTN]; + /* global memory block */ + /* array of all huffcodtable headers */ + /* 0..31 Huffman code table 0..31 */ + /* 32,33 count1-tables */ + +extern const uint8_t t32l[]; +extern const uint8_t t33l[]; + +extern const uint32_t largetbl[16 * 16]; +extern const uint32_t table23[3 * 3]; +extern const uint32_t table56[4 * 4]; + +extern const int scfsi_band[5]; + +extern const int bitrate_table [3][16]; +extern const int samplerate_table [3][ 4]; + +#endif /* LAME_TABLES_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/takehiro.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/takehiro.c new file mode 100644 index 00000000..67aba1be --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/takehiro.c @@ -0,0 +1,1375 @@ +/* + * MP3 huffman table selecting and bit counting + * + * Copyright (c) 1999-2005 Takehiro TOMINAGA + * Copyright (c) 2002-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: takehiro.c,v 1.80 2017/09/06 15:07:30 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "tables.h" + + +static const struct { + const int region0_count; + const int region1_count; +} subdv_table[23] = { + { + 0, 0}, /* 0 bands */ + { + 0, 0}, /* 1 bands */ + { + 0, 0}, /* 2 bands */ + { + 0, 0}, /* 3 bands */ + { + 0, 0}, /* 4 bands */ + { + 0, 1}, /* 5 bands */ + { + 1, 1}, /* 6 bands */ + { + 1, 1}, /* 7 bands */ + { + 1, 2}, /* 8 bands */ + { + 2, 2}, /* 9 bands */ + { + 2, 3}, /* 10 bands */ + { + 2, 3}, /* 11 bands */ + { + 3, 4}, /* 12 bands */ + { + 3, 4}, /* 13 bands */ + { + 3, 4}, /* 14 bands */ + { + 4, 5}, /* 15 bands */ + { + 4, 5}, /* 16 bands */ + { + 4, 6}, /* 17 bands */ + { + 5, 6}, /* 18 bands */ + { + 5, 6}, /* 19 bands */ + { + 5, 7}, /* 20 bands */ + { + 6, 7}, /* 21 bands */ + { + 6, 7}, /* 22 bands */ +}; + + + + + +/********************************************************************* + * nonlinear quantization of xr + * More accurate formula than the ISO formula. Takes into account + * the fact that we are quantizing xr -> ix, but we want ix^4/3 to be + * as close as possible to x^4/3. (taking the nearest int would mean + * ix is as close as possible to xr, which is different.) + * + * From Segher Boessenkool <segher@eastsite.nl> 11/1999 + * + * 09/2000: ASM code removed in favor of IEEE754 hack by Takehiro + * Tominaga. If you need the ASM code, check CVS circa Aug 2000. + * + * 01/2004: Optimizations by Gabriel Bouvigne + *********************************************************************/ + + + + + +static void +quantize_lines_xrpow_01(unsigned int l, FLOAT istep, const FLOAT * xr, int *ix) +{ + const FLOAT compareval0 = (1.0f - 0.4054f) / istep; + unsigned int i; + + assert(l > 0); + assert(l % 2 == 0); + for (i = 0; i < l; i += 2) { + FLOAT const xr_0 = xr[i+0]; + FLOAT const xr_1 = xr[i+1]; + int const ix_0 = (compareval0 > xr_0) ? 0 : 1; + int const ix_1 = (compareval0 > xr_1) ? 0 : 1; + ix[i+0] = ix_0; + ix[i+1] = ix_1; + } +} + + + +#ifdef TAKEHIRO_IEEE754_HACK + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + + +static void +quantize_lines_xrpow(unsigned int l, FLOAT istep, const FLOAT * xp, int *pi) +{ + fi_union *fi; + unsigned int remaining; + + assert(l > 0); + + fi = (fi_union *) pi; + + l = l >> 1; + remaining = l % 2; + l = l >> 1; + while (l--) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + double x2 = istep * xp[2]; + double x3 = istep * xp[3]; + + x0 += MAGIC_FLOAT; + fi[0].f = x0; + x1 += MAGIC_FLOAT; + fi[1].f = x1; + x2 += MAGIC_FLOAT; + fi[2].f = x2; + x3 += MAGIC_FLOAT; + fi[3].f = x3; + + fi[0].f = x0 + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x1 + adj43asm[fi[1].i - MAGIC_INT]; + fi[2].f = x2 + adj43asm[fi[2].i - MAGIC_INT]; + fi[3].f = x3 + adj43asm[fi[3].i - MAGIC_INT]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi += 4; + xp += 4; + }; + if (remaining) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + + x0 += MAGIC_FLOAT; + fi[0].f = x0; + x1 += MAGIC_FLOAT; + fi[1].f = x1; + + fi[0].f = x0 + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x1 + adj43asm[fi[1].i - MAGIC_INT]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + } + +} + + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + * + * Note: using floor() or (int) is extremely slow. On machines where + * the TAKEHIRO_IEEE754_HACK code above does not work, it is worthwile + * to write some ASM for XRPOW_FTOI(). + *********************************************************************/ +#define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#define QUANTFAC(rx) adj43[rx] +#define ROUNDFAC 0.4054 + + +static void +quantize_lines_xrpow(unsigned int l, FLOAT istep, const FLOAT * xr, int *ix) +{ + unsigned int remaining; + + assert(l > 0); + + l = l >> 1; + remaining = l % 2; + l = l >> 1; + while (l--) { + FLOAT x0, x1, x2, x3; + int rx0, rx1, rx2, rx3; + + x0 = *xr++ * istep; + x1 = *xr++ * istep; + XRPOW_FTOI(x0, rx0); + x2 = *xr++ * istep; + XRPOW_FTOI(x1, rx1); + x3 = *xr++ * istep; + XRPOW_FTOI(x2, rx2); + x0 += QUANTFAC(rx0); + XRPOW_FTOI(x3, rx3); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x0, *ix++); + x2 += QUANTFAC(rx2); + XRPOW_FTOI(x1, *ix++); + x3 += QUANTFAC(rx3); + XRPOW_FTOI(x2, *ix++); + XRPOW_FTOI(x3, *ix++); + }; + if (remaining) { + FLOAT x0, x1; + int rx0, rx1; + + x0 = *xr++ * istep; + x1 = *xr++ * istep; + XRPOW_FTOI(x0, rx0); + XRPOW_FTOI(x1, rx1); + x0 += QUANTFAC(rx0); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x0, *ix++); + XRPOW_FTOI(x1, *ix++); + } + +} + + + +#endif + + + +/********************************************************************* + * Quantization function + * This function will select which lines to quantize and call the + * proper quantization function + *********************************************************************/ + +static void +quantize_xrpow(const FLOAT * xp, int *pi, FLOAT istep, gr_info const *const cod_info, + calc_noise_data const *prev_noise) +{ + /* quantize on xr^(3/4) instead of xr */ + int sfb; + int sfbmax; + int j = 0; + int prev_data_use; + int *iData; + int accumulate = 0; + int accumulate01 = 0; + int *acc_iData; + const FLOAT *acc_xp; + + iData = pi; + acc_xp = xp; + acc_iData = iData; + + + /* Reusing previously computed data does not seems to work if global gain + is changed. Finding why it behaves this way would allow to use a cache of + previously computed values (let's 10 cached values per sfb) that would + probably provide a noticeable speedup */ + prev_data_use = (prev_noise && (cod_info->global_gain == prev_noise->global_gain)); + + if (cod_info->block_type == SHORT_TYPE) + sfbmax = 38; + else + sfbmax = 21; + + for (sfb = 0; sfb <= sfbmax; sfb++) { + int step = -1; + + if (prev_data_use || cod_info->block_type == NORM_TYPE) { + step = + cod_info->global_gain + - ((cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + - cod_info->subblock_gain[cod_info->window[sfb]] * 8; + } + assert(cod_info->width[sfb] >= 0); + if (prev_data_use && (prev_noise->step[sfb] == step)) { + /* do not recompute this part, + but compute accumulated lines */ + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + } + else { /*should compute this part */ + int l; + l = cod_info->width[sfb]; + + if ((j + cod_info->width[sfb]) > cod_info->max_nonzero_coeff) { + /*do not compute upper zero part */ + int usefullsize; + usefullsize = cod_info->max_nonzero_coeff - j + 1; + memset(&pi[cod_info->max_nonzero_coeff], 0, + sizeof(int) * (576 - cod_info->max_nonzero_coeff)); + l = usefullsize; + + if (l < 0) { + l = 0; + } + + /* no need to compute higher sfb values */ + sfb = sfbmax + 1; + } + + /*accumulate lines to quantize */ + if (!accumulate && !accumulate01) { + acc_iData = iData; + acc_xp = xp; + } + if (prev_noise && + prev_noise->sfb_count1 > 0 && + sfb >= prev_noise->sfb_count1 && + prev_noise->step[sfb] > 0 && step >= prev_noise->step[sfb]) { + + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + acc_iData = iData; + acc_xp = xp; + } + accumulate01 += l; + } + else { + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + acc_iData = iData; + acc_xp = xp; + } + accumulate += l; + } + + if (l <= 0) { + /* rh: 20040215 + * may happen due to "prev_data_use" optimization + */ + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + + break; /* ends for-loop */ + } + } + if (sfb <= sfbmax) { + iData += cod_info->width[sfb]; + xp += cod_info->width[sfb]; + j += cod_info->width[sfb]; + } + } + if (accumulate) { /*last data part */ + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + if (accumulate01) { /*last data part */ + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + +} + + + + +/*************************************************************************/ +/* ix_max */ +/*************************************************************************/ + +static int +ix_max(const int *ix, const int *end) +{ + int max1 = 0, max2 = 0; + + do { + int const x1 = *ix++; + int const x2 = *ix++; + if (max1 < x1) + max1 = x1; + + if (max2 < x2) + max2 = x2; + } while (ix < end); + if (max1 < max2) + max1 = max2; + return max1; +} + + + + + + + + +static int +count_bit_ESC(const int *ix, const int *const end, int t1, const int t2, unsigned int *const s) +{ + /* ESC-table is used */ + unsigned int const linbits = ht[t1].xlen * 65536u + ht[t2].xlen; + unsigned int sum = 0, sum2; + + do { + unsigned int x = *ix++; + unsigned int y = *ix++; + + if (x >= 15u) { + x = 15u; + sum += linbits; + } + if (y >= 15u) { + y = 15u; + sum += linbits; + } + x <<= 4u; + x += y; + sum += largetbl[x]; + } while (ix < end); + + sum2 = sum & 0xffffu; + sum >>= 16u; + + if (sum > sum2) { + sum = sum2; + t1 = t2; + } + + *s += sum; + return t1; +} + + +static int +count_bit_noESC(const int *ix, const int *end, int mx, unsigned int *s) +{ + /* No ESC-words */ + unsigned int sum1 = 0; + const uint8_t *const hlen1 = ht[1].hlen; + (void) mx; + + do { + unsigned int const x0 = *ix++; + unsigned int const x1 = *ix++; + sum1 += hlen1[ x0+x0 + x1 ]; + } while (ix < end); + + *s += sum1; + return 1; +} + + +static const int huf_tbl_noESC[] = { + 1, 2, 5, 7, 7, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13 +}; + + +static int +count_bit_noESC_from2(const int *ix, const int *end, int max, unsigned int *s) +{ + int t1 = huf_tbl_noESC[max - 1]; + /* No ESC-words */ + const unsigned int xlen = ht[t1].xlen; + uint32_t const* table = (t1 == 2) ? &table23[0] : &table56[0]; + unsigned int sum = 0, sum2; + + do { + unsigned int const x0 = *ix++; + unsigned int const x1 = *ix++; + sum += table[ x0 * xlen + x1 ]; + } while (ix < end); + + sum2 = sum & 0xffffu; + sum >>= 16u; + + if (sum > sum2) { + sum = sum2; + t1++; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC_from3(const int *ix, const int *end, int max, unsigned int * s) +{ + int t1 = huf_tbl_noESC[max - 1]; + /* No ESC-words */ + unsigned int sum1 = 0; + unsigned int sum2 = 0; + unsigned int sum3 = 0; + const unsigned int xlen = ht[t1].xlen; + const uint8_t *const hlen1 = ht[t1].hlen; + const uint8_t *const hlen2 = ht[t1 + 1].hlen; + const uint8_t *const hlen3 = ht[t1 + 2].hlen; + int t; + + do { + unsigned int x0 = *ix++; + unsigned int x1 = *ix++; + unsigned int x = x0 * xlen + x1; + sum1 += hlen1[x]; + sum2 += hlen2[x]; + sum3 += hlen3[x]; + } while (ix < end); + + t = t1; + if (sum1 > sum2) { + sum1 = sum2; + t++; + } + if (sum1 > sum3) { + sum1 = sum3; + t = t1 + 2; + } + *s += sum1; + + return t; +} + + +/*************************************************************************/ +/* choose table */ +/*************************************************************************/ + +/* + Choose the Huffman table that will encode ix[begin..end] with + the fewest bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ +static int count_bit_null(const int* ix, const int* end, int max, unsigned int* s) +{ + (void) ix; + (void) end; + (void) max; + (void) s; + return 0; +} + +typedef int (*count_fnc)(const int* ix, const int* end, int max, unsigned int* s); + +static const count_fnc count_fncs[] = +{ &count_bit_null +, &count_bit_noESC +, &count_bit_noESC_from2 +, &count_bit_noESC_from2 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +}; + +static int +choose_table_nonMMX(const int *ix, const int *const end, int *const _s) +{ + unsigned int* s = (unsigned int*)_s; + unsigned int max; + int choice, choice2; + max = ix_max(ix, end); + + if (max <= 15) { + return count_fncs[max](ix, end, max, s); + } + /* try tables with linbits */ + if (max > IXMAX_VAL) { + *s = LARGE_BITS; + return -1; + } + max -= 15u; + for (choice2 = 24; choice2 < 32; choice2++) { + if (ht[choice2].linmax >= max) { + break; + } + } + + for (choice = choice2 - 8; choice < 24; choice++) { + if (ht[choice].linmax >= max) { + break; + } + } + return count_bit_ESC(ix, end, choice, choice2, s); +} + + + +/*************************************************************************/ +/* count_bit */ +/*************************************************************************/ +int +noquant_count_bits(lame_internal_flags const *const gfc, + gr_info * const gi, calc_noise_data * prev_noise) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int bits = 0; + int i, a1, a2; + int const *const ix = gi->l3_enc; + + i = Min(576, ((gi->max_nonzero_coeff + 2) >> 1) << 1); + + if (prev_noise) + prev_noise->sfb_count1 = 0; + + /* Determine count1 region */ + for (; i > 1; i -= 2) + if (ix[i - 1] | ix[i - 2]) + break; + gi->count1 = i; + + /* Determines the number of bits to encode the quadruples. */ + a1 = a2 = 0; + for (; i > 3; i -= 4) { + int x4 = ix[i-4]; + int x3 = ix[i-3]; + int x2 = ix[i-2]; + int x1 = ix[i-1]; + int p; + /* hack to check if all values <= 1 */ + if ((unsigned int) (x4 | x3 | x2 | x1) > 1) + break; + + p = ((x4 * 2 + x3) * 2 + x2) * 2 + x1; + a1 += t32l[p]; + a2 += t33l[p]; + } + + bits = a1; + gi->count1table_select = 0; + if (a1 > a2) { + bits = a2; + gi->count1table_select = 1; + } + + gi->count1bits = bits; + gi->big_values = i; + if (i == 0) + return bits; + + if (gi->block_type == SHORT_TYPE) { + a1 = 3 * gfc->scalefac_band.s[3]; + if (a1 > gi->big_values) + a1 = gi->big_values; + a2 = gi->big_values; + + } + else if (gi->block_type == NORM_TYPE) { + assert(i <= 576); /* bv_scf has 576 entries (0..575) */ + a1 = gi->region0_count = gfc->sv_qnt.bv_scf[i - 2]; + a2 = gi->region1_count = gfc->sv_qnt.bv_scf[i - 1]; + + assert(a1 + a2 + 2 < SBPSY_l); + a2 = gfc->scalefac_band.l[a1 + a2 + 2]; + a1 = gfc->scalefac_band.l[a1 + 1]; + if (a2 < i) + gi->table_select[2] = gfc->choose_table(ix + a2, ix + i, &bits); + + } + else { + gi->region0_count = 7; + /*gi->region1_count = SBPSY_l - 7 - 1; */ + gi->region1_count = SBMAX_l - 1 - 7 - 1; + a1 = gfc->scalefac_band.l[7 + 1]; + a2 = i; + if (a1 > a2) { + a1 = a2; + } + } + + + /* have to allow for the case when bigvalues < region0 < region1 */ + /* (and region0, region1 are ignored) */ + a1 = Min(a1, i); + a2 = Min(a2, i); + + assert(a1 >= 0); + assert(a2 >= 0); + + /* Count the number of bits necessary to code the bigvalues region. */ + if (0 < a1) + gi->table_select[0] = gfc->choose_table(ix, ix + a1, &bits); + if (a1 < a2) + gi->table_select[1] = gfc->choose_table(ix + a1, ix + a2, &bits); + if (cfg->use_best_huffman == 2) { + gi->part2_3_length = bits; + best_huffman_divide(gfc, gi); + bits = gi->part2_3_length; + } + + + if (prev_noise) { + if (gi->block_type == NORM_TYPE) { + int sfb = 0; + while (gfc->scalefac_band.l[sfb] < gi->big_values) { + sfb++; + } + prev_noise->sfb_count1 = sfb; + } + } + + return bits; +} + +int +count_bits(lame_internal_flags const *const gfc, + const FLOAT * const xr, gr_info * const gi, calc_noise_data * prev_noise) +{ + int *const ix = gi->l3_enc; + + /* since quantize_xrpow uses table lookup, we need to check this first: */ + FLOAT const w = (IXMAX_VAL) / IPOW20(gi->global_gain); + + if (gi->xrpow_max > w) + return LARGE_BITS; + + quantize_xrpow(xr, ix, IPOW20(gi->global_gain), gi, prev_noise); + + if (gfc->sv_qnt.substep_shaping & 2) { + int sfb, j = 0; + /* 0.634521682242439 = 0.5946*2**(.5*0.1875) */ + int const gain = gi->global_gain + gi->scalefac_scale; + const FLOAT roundfac = 0.634521682242439 / IPOW20(gain); + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + int const width = gi->width[sfb]; + assert(width >= 0); + if (!gfc->sv_qnt.pseudohalf[sfb]) { + j += width; + } + else { + int k; + for (k = j, j += width; k < j; ++k) { + ix[k] = (xr[k] >= roundfac) ? ix[k] : 0; + } + } + } + } + return noquant_count_bits(gfc, gi, prev_noise); +} + +/*********************************************************************** + re-calculate the best scalefac_compress using scfsi + the saved bits are kept in the bit reservoir. + **********************************************************************/ + + +inline static void +recalc_divide_init(const lame_internal_flags * const gfc, + gr_info const *cod_info, + int const *const ix, int r01_bits[], int r01_div[], int r0_tbl[], int r1_tbl[]) +{ + int r0, r1, bigv, r0t, r1t, bits; + + bigv = cod_info->big_values; + + for (r0 = 0; r0 <= 7 + 15; r0++) { + r01_bits[r0] = LARGE_BITS; + } + + for (r0 = 0; r0 < 16; r0++) { + int const a1 = gfc->scalefac_band.l[r0 + 1]; + int r0bits; + if (a1 >= bigv) + break; + r0bits = 0; + r0t = gfc->choose_table(ix, ix + a1, &r0bits); + + for (r1 = 0; r1 < 8; r1++) { + int const a2 = gfc->scalefac_band.l[r0 + r1 + 2]; + if (a2 >= bigv) + break; + + bits = r0bits; + r1t = gfc->choose_table(ix + a1, ix + a2, &bits); + if (r01_bits[r0 + r1] > bits) { + r01_bits[r0 + r1] = bits; + r01_div[r0 + r1] = r0; + r0_tbl[r0 + r1] = r0t; + r1_tbl[r0 + r1] = r1t; + } + } + } +} + +inline static void +recalc_divide_sub(const lame_internal_flags * const gfc, + const gr_info * cod_info2, + gr_info * const gi, + const int *const ix, + const int r01_bits[], const int r01_div[], const int r0_tbl[], const int r1_tbl[]) +{ + int bits, r2, a2, bigv, r2t; + + bigv = cod_info2->big_values; + + for (r2 = 2; r2 < SBMAX_l + 1; r2++) { + a2 = gfc->scalefac_band.l[r2]; + if (a2 >= bigv) + break; + + bits = r01_bits[r2 - 2] + cod_info2->count1bits; + if (gi->part2_3_length <= bits) + break; + + r2t = gfc->choose_table(ix + a2, ix + bigv, &bits); + if (gi->part2_3_length <= bits) + continue; + + memcpy(gi, cod_info2, sizeof(gr_info)); + gi->part2_3_length = bits; + gi->region0_count = r01_div[r2 - 2]; + gi->region1_count = r2 - 2 - r01_div[r2 - 2]; + gi->table_select[0] = r0_tbl[r2 - 2]; + gi->table_select[1] = r1_tbl[r2 - 2]; + gi->table_select[2] = r2t; + } +} + + + + +void +best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const gi) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int i, a1, a2; + gr_info cod_info2; + int const *const ix = gi->l3_enc; + + int r01_bits[7 + 15 + 1]; + int r01_div[7 + 15 + 1]; + int r0_tbl[7 + 15 + 1]; + int r1_tbl[7 + 15 + 1]; + + + /* SHORT BLOCK stuff fails for MPEG2 */ + if (gi->block_type == SHORT_TYPE && cfg->mode_gr == 1) + return; + + + memcpy(&cod_info2, gi, sizeof(gr_info)); + if (gi->block_type == NORM_TYPE) { + recalc_divide_init(gfc, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + recalc_divide_sub(gfc, &cod_info2, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + } + + i = cod_info2.big_values; + if (i == 0 || (unsigned int) (ix[i - 2] | ix[i - 1]) > 1) + return; + + i = gi->count1 + 2; + if (i > 576) + return; + + /* Determines the number of bits to encode the quadruples. */ + memcpy(&cod_info2, gi, sizeof(gr_info)); + cod_info2.count1 = i; + a1 = a2 = 0; + + assert(i <= 576); + + for (; i > cod_info2.big_values; i -= 4) { + int const p = ((ix[i - 4] * 2 + ix[i - 3]) * 2 + ix[i - 2]) * 2 + ix[i - 1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + cod_info2.big_values = i; + + cod_info2.count1table_select = 0; + if (a1 > a2) { + a1 = a2; + cod_info2.count1table_select = 1; + } + + cod_info2.count1bits = a1; + + if (cod_info2.block_type == NORM_TYPE) + recalc_divide_sub(gfc, &cod_info2, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + else { + /* Count the number of bits necessary to code the bigvalues region. */ + cod_info2.part2_3_length = a1; + a1 = gfc->scalefac_band.l[7 + 1]; + if (a1 > i) { + a1 = i; + } + if (a1 > 0) + cod_info2.table_select[0] = + gfc->choose_table(ix, ix + a1, (int *) &cod_info2.part2_3_length); + if (i > a1) + cod_info2.table_select[1] = + gfc->choose_table(ix + a1, ix + i, (int *) &cod_info2.part2_3_length); + if (gi->part2_3_length > cod_info2.part2_3_length) + memcpy(gi, &cod_info2, sizeof(gr_info)); + } +} + +static const int slen1_n[16] = { 1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16 }; +static const int slen2_n[16] = { 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; +const int slen1_tab[16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; +const int slen2_tab[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; + +static void +scfsi_calc(int ch, III_side_info_t * l3_side) +{ + unsigned int i; + int s1, s2, c1, c2; + int sfb; + gr_info *const gi = &l3_side->tt[1][ch]; + gr_info const *const g0 = &l3_side->tt[0][ch]; + + for (i = 0; i < (sizeof(scfsi_band) / sizeof(int)) - 1; i++) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + if (g0->scalefac[sfb] != gi->scalefac[sfb] + && gi->scalefac[sfb] >= 0) + break; + } + if (sfb == scfsi_band[i + 1]) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + gi->scalefac[sfb] = -1; + } + l3_side->scfsi[ch][i] = 1; + } + } + + s1 = c1 = 0; + for (sfb = 0; sfb < 11; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; + c1++; + if (s1 < gi->scalefac[sfb]) + s1 = gi->scalefac[sfb]; + } + + s2 = c2 = 0; + for (; sfb < SBPSY_l; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; + c2++; + if (s2 < gi->scalefac[sfb]) + s2 = gi->scalefac[sfb]; + } + + for (i = 0; i < 16; i++) { + if (s1 < slen1_n[i] && s2 < slen2_n[i]) { + int const c = slen1_tab[i] * c1 + slen2_tab[i] * c2; + if (gi->part2_length > c) { + gi->part2_length = c; + gi->scalefac_compress = (int)i; + } + } + } +} + +/* +Find the optimal way to store the scalefactors. +Only call this routine after final scalefactors have been +chosen and the channel/granule will not be re-encoded. + */ +void +best_scalefac_store(const lame_internal_flags * gfc, + const int gr, const int ch, III_side_info_t * const l3_side) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + /* use scalefac_scale if we can */ + gr_info *const gi = &l3_side->tt[gr][ch]; + int sfb, i, j, l; + int recalc = 0; + + /* remove scalefacs from bands with ix=0. This idea comes + * from the AAC ISO docs. added mt 3/00 */ + /* check if l3_enc=0 */ + j = 0; + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + int const width = gi->width[sfb]; + assert(width >= 0); + for (l = j, j += width; l < j; ++l) { + if (gi->l3_enc[l] != 0) + break; + } + if (l == j) + gi->scalefac[sfb] = recalc = -2; /* anything goes. */ + /* only best_scalefac_store and calc_scfsi + * know--and only they should know--about the magic number -2. + */ + } + + if (!gi->scalefac_scale && !gi->preflag) { + int s = 0; + for (sfb = 0; sfb < gi->sfbmax; sfb++) + if (gi->scalefac[sfb] > 0) + s |= gi->scalefac[sfb]; + + if (!(s & 1) && s != 0) { + for (sfb = 0; sfb < gi->sfbmax; sfb++) + if (gi->scalefac[sfb] > 0) + gi->scalefac[sfb] >>= 1; + + gi->scalefac_scale = recalc = 1; + } + } + + if (!gi->preflag && gi->block_type != SHORT_TYPE && cfg->mode_gr == 2) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (gi->scalefac[sfb] < pretab[sfb] && gi->scalefac[sfb] != -2) + break; + if (sfb == SBPSY_l) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (gi->scalefac[sfb] > 0) + gi->scalefac[sfb] -= pretab[sfb]; + + gi->preflag = recalc = 1; + } + } + + for (i = 0; i < 4; i++) + l3_side->scfsi[ch][i] = 0; + + if (cfg->mode_gr == 2 && gr == 1 + && l3_side->tt[0][ch].block_type != SHORT_TYPE + && l3_side->tt[1][ch].block_type != SHORT_TYPE) { + scfsi_calc(ch, l3_side); + recalc = 0; + } + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + if (gi->scalefac[sfb] == -2) { + gi->scalefac[sfb] = 0; /* if anything goes, then 0 is a good choice */ + } + } + if (recalc) { + (void) scale_bitcount(gfc, gi); + } +} + + +#ifndef NDEBUG +static int +all_scalefactors_not_negative(int const *scalefac, int n) +{ + int i; + for (i = 0; i < n; ++i) { + if (scalefac[i] < 0) + return 0; + } + return 1; +} +#endif + + +/* number of bits used to encode scalefacs */ + +/* 18*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_short[16] = { + 0, 18, 36, 54, 54, 36, 54, 72, 54, 72, 90, 72, 90, 108, 108, 126 +}; + +/* 17*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_mixed[16] = { + 0, 18, 36, 54, 51, 35, 53, 71, 52, 70, 88, 69, 87, 105, 104, 122 +}; + +/* 11*slen1_tab[i] + 10*slen2_tab[i] */ +static const int scale_long[16] = { + 0, 10, 20, 30, 33, 21, 31, 41, 32, 42, 52, 43, 53, 63, 64, 74 +}; + + +/*************************************************************************/ +/* scale_bitcount */ +/*************************************************************************/ + +/* Also calculates the number of bits necessary to code the scalefactors. */ + +static int +mpeg1_scale_bitcount(const lame_internal_flags * gfc, gr_info * const cod_info) +{ + int k, sfb, max_slen1 = 0, max_slen2 = 0; + + /* maximum values */ + const int *tab; + int *const scalefac = cod_info->scalefac; + + (void) gfc; + assert(all_scalefactors_not_negative(scalefac, cod_info->sfbmax)); + + if (cod_info->block_type == SHORT_TYPE) { + tab = scale_short; + if (cod_info->mixed_block_flag) + tab = scale_mixed; + } + else { /* block_type == 1,2,or 3 */ + tab = scale_long; + if (!cod_info->preflag) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (scalefac[sfb] < pretab[sfb]) + break; + + if (sfb == SBPSY_l) { + cod_info->preflag = 1; + for (sfb = 11; sfb < SBPSY_l; sfb++) + scalefac[sfb] -= pretab[sfb]; + } + } + } + + for (sfb = 0; sfb < cod_info->sfbdivide; sfb++) + if (max_slen1 < scalefac[sfb]) + max_slen1 = scalefac[sfb]; + + for (; sfb < cod_info->sfbmax; sfb++) + if (max_slen2 < scalefac[sfb]) + max_slen2 = scalefac[sfb]; + + /* from Takehiro TOMINAGA <tominaga@isoternet.org> 10/99 + * loop over *all* posible values of scalefac_compress to find the + * one which uses the smallest number of bits. ISO would stop + * at first valid index */ + cod_info->part2_length = LARGE_BITS; + for (k = 0; k < 16; k++) { + if (max_slen1 < slen1_n[k] && max_slen2 < slen2_n[k] + && cod_info->part2_length > tab[k]) { + cod_info->part2_length = tab[k]; + cod_info->scalefac_compress = k; + } + } + return cod_info->part2_length == LARGE_BITS; +} + + + +/* + table of largest scalefactor values for MPEG2 +*/ +static const int max_range_sfac_tab[6][4] = { + {15, 15, 7, 7}, + {15, 15, 7, 0}, + {7, 3, 0, 0}, + {15, 31, 31, 0}, + {7, 7, 7, 0}, + {3, 3, 0, 0} +}; + + + + +/*************************************************************************/ +/* scale_bitcount_lsf */ +/*************************************************************************/ + +/* Also counts the number of bits to encode the scalefacs but for MPEG 2 */ +/* Lower sampling frequencies (24, 22.05 and 16 kHz.) */ + +/* This is reverse-engineered from section 2.4.3.2 of the MPEG2 IS, */ +/* "Audio Decoding Layer III" */ + +static int +mpeg2_scale_bitcount(const lame_internal_flags * gfc, gr_info * const cod_info) +{ + int table_number, row_in_table, partition, nr_sfb, window, over; + int i, sfb, max_sfac[4]; + const int *partition_table; + int const *const scalefac = cod_info->scalefac; + + /* + Set partition table. Note that should try to use table one, + but do not yet... + */ + if (cod_info->preflag) + table_number = 2; + else + table_number = 0; + + for (i = 0; i < 4; i++) + max_sfac[i] = 0; + + if (cod_info->block_type == SHORT_TYPE) { + row_in_table = 1; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for (sfb = 0, partition = 0; partition < 4; partition++) { + nr_sfb = partition_table[partition] / 3; + for (i = 0; i < nr_sfb; i++, sfb++) + for (window = 0; window < 3; window++) + if (scalefac[sfb * 3 + window] > max_sfac[partition]) + max_sfac[partition] = scalefac[sfb * 3 + window]; + } + } + else { + row_in_table = 0; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for (sfb = 0, partition = 0; partition < 4; partition++) { + nr_sfb = partition_table[partition]; + for (i = 0; i < nr_sfb; i++, sfb++) + if (scalefac[sfb] > max_sfac[partition]) + max_sfac[partition] = scalefac[sfb]; + } + } + + for (over = 0, partition = 0; partition < 4; partition++) { + if (max_sfac[partition] > max_range_sfac_tab[table_number][partition]) + over++; + } + if (!over) { + /* + Since no bands have been over-amplified, we can set scalefac_compress + and slen[] for the formatter + */ + static const int log2tab[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + int slen1, slen2, slen3, slen4; + + cod_info->sfb_partition_table = nr_of_sfb_block[table_number][row_in_table]; + for (partition = 0; partition < 4; partition++) + cod_info->slen[partition] = log2tab[max_sfac[partition]]; + + /* set scalefac_compress */ + slen1 = cod_info->slen[0]; + slen2 = cod_info->slen[1]; + slen3 = cod_info->slen[2]; + slen4 = cod_info->slen[3]; + + switch (table_number) { + case 0: + cod_info->scalefac_compress = (((slen1 * 5) + slen2) << 4) + + (slen3 << 2) + + slen4; + break; + + case 1: + cod_info->scalefac_compress = 400 + (((slen1 * 5) + slen2) << 2) + + slen3; + break; + + case 2: + cod_info->scalefac_compress = 500 + (slen1 * 3) + slen2; + break; + + default: + ERRORF(gfc, "intensity stereo not implemented yet\n"); + break; + } + } +#ifdef DEBUG + if (over) + ERRORF(gfc, "---WARNING !! Amplification of some bands over limits\n"); +#endif + if (!over) { + assert(cod_info->sfb_partition_table); + cod_info->part2_length = 0; + for (partition = 0; partition < 4; partition++) + cod_info->part2_length += + cod_info->slen[partition] * cod_info->sfb_partition_table[partition]; + } + return over; +} + + +int +scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info) +{ + if (gfc->cfg.mode_gr == 2) { + return mpeg1_scale_bitcount(gfc, cod_info); + } + else { + return mpeg2_scale_bitcount(gfc, cod_info); + } +} + + +#ifdef MMX_choose_table +extern int choose_table_MMX(const int *ix, const int *const end, int *const s); +#endif + +void +huffman_init(lame_internal_flags * const gfc) +{ + int i; + + gfc->choose_table = choose_table_nonMMX; + +#ifdef MMX_choose_table + if (gfc->CPU_features.MMX) { + gfc->choose_table = choose_table_MMX; + } +#endif + + for (i = 2; i <= 576; i += 2) { + int scfb_anz = 0, bv_index; + while (gfc->scalefac_band.l[++scfb_anz] < i); + + bv_index = subdv_table[scfb_anz].region0_count; + while (gfc->scalefac_band.l[bv_index + 1] > i) + bv_index--; + + if (bv_index < 0) { + /* this is an indication that everything is going to + be encoded as region0: bigvalues < region0 < region1 + so lets set region0, region1 to some value larger + than bigvalues */ + bv_index = subdv_table[scfb_anz].region0_count; + } + + gfc->sv_qnt.bv_scf[i - 2] = bv_index; + + bv_index = subdv_table[scfb_anz].region1_count; + while (gfc->scalefac_band.l[bv_index + gfc->sv_qnt.bv_scf[i - 2] + 2] > i) + bv_index--; + + if (bv_index < 0) { + bv_index = subdv_table[scfb_anz].region1_count; + } + + gfc->sv_qnt.bv_scf[i - 1] = bv_index; + } +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.c new file mode 100644 index 00000000..43b457cd --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.c @@ -0,0 +1,1018 @@ +/* + * lame utility library source file + * + * Copyright (c) 1999 Albert L Faber + * Copyright (c) 2000-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: util.c,v 1.159 2017/09/06 15:07:30 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <float.h> +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "tables.h" + +#define PRECOMPUTE +#if defined(__FreeBSD__) && !defined(__alpha__) +# include <machine/floatingpoint.h> +#endif + + +/*********************************************************************** +* +* Global Function Definitions +* +***********************************************************************/ +/*empty and close mallocs in gfc */ + +void +free_id3tag(lame_internal_flags * const gfc) +{ + gfc->tag_spec.language[0] = 0; + if (gfc->tag_spec.title != 0) { + free(gfc->tag_spec.title); + gfc->tag_spec.title = 0; + } + if (gfc->tag_spec.artist != 0) { + free(gfc->tag_spec.artist); + gfc->tag_spec.artist = 0; + } + if (gfc->tag_spec.album != 0) { + free(gfc->tag_spec.album); + gfc->tag_spec.album = 0; + } + if (gfc->tag_spec.comment != 0) { + free(gfc->tag_spec.comment); + gfc->tag_spec.comment = 0; + } + + if (gfc->tag_spec.albumart != 0) { + free(gfc->tag_spec.albumart); + gfc->tag_spec.albumart = 0; + gfc->tag_spec.albumart_size = 0; + gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE; + } + if (gfc->tag_spec.v2_head != 0) { + FrameDataNode *node = gfc->tag_spec.v2_head; + do { + void *p = node->dsc.ptr.b; + void *q = node->txt.ptr.b; + void *r = node; + node = node->nxt; + free(p); + free(q); + free(r); + } while (node != 0); + gfc->tag_spec.v2_head = 0; + gfc->tag_spec.v2_tail = 0; + } +} + + +static void +free_global_data(lame_internal_flags * gfc) +{ + if (gfc && gfc->cd_psy) { + if (gfc->cd_psy->l.s3) { + /* XXX allocated in psymodel_init() */ + free(gfc->cd_psy->l.s3); + } + if (gfc->cd_psy->s.s3) { + /* XXX allocated in psymodel_init() */ + free(gfc->cd_psy->s.s3); + } + free(gfc->cd_psy); + gfc->cd_psy = 0; + } +} + + +void +freegfc(lame_internal_flags * const gfc) +{ /* bit stream structure */ + int i; + + if (gfc == 0) return; + + for (i = 0; i <= 2 * BPC; i++) + if (gfc->sv_enc.blackfilt[i] != NULL) { + free(gfc->sv_enc.blackfilt[i]); + gfc->sv_enc.blackfilt[i] = NULL; + } + if (gfc->sv_enc.inbuf_old[0]) { + free(gfc->sv_enc.inbuf_old[0]); + gfc->sv_enc.inbuf_old[0] = NULL; + } + if (gfc->sv_enc.inbuf_old[1]) { + free(gfc->sv_enc.inbuf_old[1]); + gfc->sv_enc.inbuf_old[1] = NULL; + } + + if (gfc->bs.buf != NULL) { + free(gfc->bs.buf); + gfc->bs.buf = NULL; + } + + if (gfc->VBR_seek_table.bag) { + free(gfc->VBR_seek_table.bag); + gfc->VBR_seek_table.bag = NULL; + gfc->VBR_seek_table.size = 0; + } + if (gfc->ATH) { + free(gfc->ATH); + } + if (gfc->sv_rpg.rgdata) { + free(gfc->sv_rpg.rgdata); + } + if (gfc->sv_enc.in_buffer_0) { + free(gfc->sv_enc.in_buffer_0); + } + if (gfc->sv_enc.in_buffer_1) { + free(gfc->sv_enc.in_buffer_1); + } + free_id3tag(gfc); + +#ifdef DECODE_ON_THE_FLY + if (gfc->hip) { + hip_decode_exit(gfc->hip); + gfc->hip = 0; + } +#endif + + free_global_data(gfc); + + free(gfc); +} + +void +calloc_aligned(aligned_pointer_t * ptr, unsigned int size, unsigned int bytes) +{ + if (ptr) { + if (!ptr->pointer) { + ptr->pointer = malloc(size + bytes); + if (ptr->pointer != 0) { + memset(ptr->pointer, 0, size + bytes); + if (bytes > 0) { + ptr->aligned = (void *) ((((size_t) ptr->pointer + bytes - 1) / bytes) * bytes); + } + else { + ptr->aligned = ptr->pointer; + } + } + else { + ptr->aligned = 0; + } + } + } +} + +void +free_aligned(aligned_pointer_t * ptr) +{ + if (ptr) { + if (ptr->pointer) { + free(ptr->pointer); + ptr->pointer = 0; + ptr->aligned = 0; + } + } +} + +/*those ATH formulas are returning +their minimum value for input = -1*/ + +static FLOAT +ATHformula_GB(FLOAT f, FLOAT value, FLOAT f_min, FLOAT f_max) +{ + /* 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.*/ + + FLOAT ath; + + /* the following Hack allows to ask for the lowest value */ + if (f < -.3) + f = 3410; + + f /= 1000; /* convert to khz */ + f = Max(f_min, f); + f = Min(f_max, 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 * value) * 0.001 * pow(f, 4.0); + return ath; +} + + + +FLOAT +ATHformula(SessionConfig_t const *cfg, FLOAT f) +{ + FLOAT ath; + switch (cfg->ATHtype) { + case 0: + ath = ATHformula_GB(f, 9, 0.1f, 24.0f); + break; + case 1: + ath = ATHformula_GB(f, -1, 0.1f, 24.0f); /*over sensitive, should probably be removed */ + break; + case 2: + ath = ATHformula_GB(f, 0, 0.1f, 24.0f); + break; + case 3: + ath = ATHformula_GB(f, 1, 0.1f, 24.0f) + 6; /*modification of GB formula by Roel */ + break; + case 4: + ath = ATHformula_GB(f, cfg->ATHcurve, 0.1f, 24.0f); + break; + case 5: + ath = ATHformula_GB(f, cfg->ATHcurve, 3.41f, 16.1f); + break; + default: + ath = ATHformula_GB(f, 0, 0.1f, 24.0f); + break; + } + return ath; +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT +freq2bark(FLOAT freq) +{ + /* input: freq in hz output: barks */ + if (freq < 0) + freq = 0; + freq = freq * 0.001; + return 13.0 * atan(.76 * freq) + 3.5 * atan(freq * freq / (7.5 * 7.5)); +} + +#if 0 +extern FLOAT freq2cbw(FLOAT freq); + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT +freq2cbw(FLOAT freq) +{ + /* input: freq in hz output: critical band width */ + freq = freq * 0.001; + return 25 + 75 * pow(1 + 1.4 * (freq * freq), 0.69); +} + +#endif + + + + +#define ABS(A) (((A)>0) ? (A) : -(A)) + +int +FindNearestBitrate(int bRate, /* legal rates from 8 to 320 */ + int version, int samplerate) +{ /* MPEG-1 or MPEG-2 LSF */ + int bitrate; + int i; + + if (samplerate < 16000) + version = 2; + + bitrate = bitrate_table[version][1]; + + for (i = 2; i <= 14; i++) { + if (bitrate_table[version][i] > 0) { + if (ABS(bitrate_table[version][i] - bRate) < ABS(bitrate - bRate)) + bitrate = bitrate_table[version][i]; + } + } + return bitrate; +} + + + + + +#ifndef Min +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#endif +#ifndef Max +#define Max(A, B) ((A) > (B) ? (A) : (B)) +#endif + + +/* Used to find table index when + * we need bitrate-based values + * determined using tables + * + * bitrate in kbps + * + * Gabriel Bouvigne 2002-11-03 + */ +int +nearestBitrateFullIndex(uint16_t bitrate) +{ + /* borrowed from DM abr presets */ + + const int full_bitrate_table[] = + { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }; + + + int lower_range = 0, lower_range_kbps = 0, upper_range = 0, upper_range_kbps = 0; + + + int b; + + + /* We assume specified bitrate will be 320kbps */ + upper_range_kbps = full_bitrate_table[16]; + upper_range = 16; + lower_range_kbps = full_bitrate_table[16]; + lower_range = 16; + + /* Determine which significant bitrates the value specified falls between, + * if loop ends without breaking then we were correct above that the value was 320 + */ + for (b = 0; b < 16; b++) { + if ((Max(bitrate, full_bitrate_table[b + 1])) != bitrate) { + upper_range_kbps = full_bitrate_table[b + 1]; + upper_range = b + 1; + lower_range_kbps = full_bitrate_table[b]; + lower_range = (b); + break; /* We found upper range */ + } + } + + /* Determine which range the value specified is closer to */ + if ((upper_range_kbps - bitrate) > (bitrate - lower_range_kbps)) { + return lower_range; + } + return upper_range; +} + + + + + +/* map frequency to a valid MP3 sample frequency + * + * Robert Hegemann 2000-07-01 + */ +int +map2MP3Frequency(int freq) +{ + if (freq <= 8000) + return 8000; + if (freq <= 11025) + return 11025; + if (freq <= 12000) + return 12000; + if (freq <= 16000) + return 16000; + if (freq <= 22050) + return 22050; + if (freq <= 24000) + return 24000; + if (freq <= 32000) + return 32000; + if (freq <= 44100) + return 44100; + + return 48000; +} + +int +BitrateIndex(int bRate, /* legal rates from 32 to 448 kbps */ + int version, /* MPEG-1 or MPEG-2/2.5 LSF */ + int samplerate) +{ /* convert bitrate in kbps to index */ + int i; + if (samplerate < 16000) + version = 2; + for (i = 0; i <= 14; i++) { + if (bitrate_table[version][i] > 0) { + if (bitrate_table[version][i] == bRate) { + return i; + } + } + } + return -1; +} + +/* convert samp freq in Hz to index */ + +int +SmpFrqIndex(int sample_freq, int *const version) +{ + switch (sample_freq) { + case 44100: + *version = 1; + return 0; + case 48000: + *version = 1; + return 1; + case 32000: + *version = 1; + return 2; + case 22050: + *version = 0; + return 0; + case 24000: + *version = 0; + return 1; + case 16000: + *version = 0; + return 2; + case 11025: + *version = 0; + return 0; + case 12000: + *version = 0; + return 1; + case 8000: + *version = 0; + return 2; + default: + *version = 0; + return -1; + } +} + + +/***************************************************************************** +* +* End of bit_stream.c package +* +*****************************************************************************/ + + + + + + + + + + +/* resampling via FIR filter, blackman window */ +inline static FLOAT +blackman(FLOAT x, FLOAT fcn, int l) +{ + /* This algorithm from: + SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C + S.D. Stearns and R.A. David, Prentice-Hall, 1992 + */ + FLOAT bkwn, x2; + FLOAT const wcn = (PI * fcn); + + x /= l; + if (x < 0) + x = 0; + if (x > 1) + x = 1; + x2 = x - .5; + + bkwn = 0.42 - 0.5 * cos(2 * x * PI) + 0.08 * cos(4 * x * PI); + if (fabs(x2) < 1e-9) + return wcn / PI; + else + return (bkwn * sin(l * wcn * x2) / (PI * l * x2)); + + +} + + + + +/* gcd - greatest common divisor */ +/* Joint work of Euclid and M. Hendry */ + +static int +gcd(int i, int j) +{ + /* assert ( i > 0 && j > 0 ); */ + return j ? gcd(j, i % j) : i; +} + + + +static int +fill_buffer_resample(lame_internal_flags * gfc, + sample_t * outbuf, + int desired_len, sample_t const *inbuf, int len, int *num_used, int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *esv = &gfc->sv_enc; + double resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out; + int BLACKSIZE; + FLOAT offset, xvalue; + int i, j = 0, k; + int filter_l; + FLOAT fcn, intratio; + FLOAT *inbuf_old; + int bpc; /* number of convolution functions to pre-compute */ + bpc = cfg->samplerate_out / gcd(cfg->samplerate_out, cfg->samplerate_in); + if (bpc > BPC) + bpc = BPC; + + intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < FLT_EPSILON); + fcn = 1.00 / resample_ratio; + if (fcn > 1.00) + fcn = 1.00; + filter_l = 31; /* must be odd */ + filter_l += intratio; /* unless resample_ratio=int, it must be even */ + + + BLACKSIZE = filter_l + 1; /* size of data needed for FIR */ + + if (gfc->fill_buffer_resample_init == 0) { + esv->inbuf_old[0] = lame_calloc(sample_t, BLACKSIZE); + esv->inbuf_old[1] = lame_calloc(sample_t, BLACKSIZE); + for (i = 0; i <= 2 * bpc; ++i) + esv->blackfilt[i] = lame_calloc(sample_t, BLACKSIZE); + + esv->itime[0] = 0; + esv->itime[1] = 0; + + /* precompute blackman filter coefficients */ + for (j = 0; j <= 2 * bpc; j++) { + FLOAT sum = 0.; + offset = (j - bpc) / (2. * bpc); + for (i = 0; i <= filter_l; i++) + sum += esv->blackfilt[j][i] = blackman(i - offset, fcn, filter_l); + for (i = 0; i <= filter_l; i++) + esv->blackfilt[j][i] /= sum; + } + gfc->fill_buffer_resample_init = 1; + } + + inbuf_old = esv->inbuf_old[ch]; + + /* time of j'th element in inbuf = itime + j/ifreq; */ + /* time of k'th element in outbuf = j/ofreq */ + for (k = 0; k < desired_len; k++) { + double time0 = k * resample_ratio; /* time of k'th output sample */ + int joff; + + j = floor(time0 - esv->itime[ch]); + + /* check if we need more input data */ + if ((filter_l + j - filter_l / 2) >= len) + break; + + /* blackman filter. by default, window centered at j+.5(filter_l%2) */ + /* but we want a window centered at time0. */ + offset = (time0 - esv->itime[ch] - (j + .5 * (filter_l % 2))); + assert(fabs(offset) <= .501); + + /* find the closest precomputed window for this offset: */ + joff = floor((offset * 2 * bpc) + bpc + .5); + + xvalue = 0.; + for (i = 0; i <= filter_l; ++i) { + int const j2 = i + j - filter_l / 2; + sample_t y; + assert(j2 < len); + assert(j2 + BLACKSIZE >= 0); + y = (j2 < 0) ? inbuf_old[BLACKSIZE + j2] : inbuf[j2]; +#ifdef PRECOMPUTE + xvalue += y * esv->blackfilt[joff][i]; +#else + xvalue += y * blackman(i - offset, fcn, filter_l); /* very slow! */ +#endif + } + outbuf[k] = xvalue; + } + + + /* k = number of samples added to outbuf */ + /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2] */ + + /* how many samples of input data were used: */ + *num_used = Min(len, filter_l + j - filter_l / 2); + + /* adjust our input time counter. Incriment by the number of samples used, + * then normalize so that next output sample is at time 0, next + * input buffer is at time itime[ch] */ + esv->itime[ch] += *num_used - k * resample_ratio; + + /* save the last BLACKSIZE samples into the inbuf_old buffer */ + if (*num_used >= BLACKSIZE) { + for (i = 0; i < BLACKSIZE; i++) + inbuf_old[i] = inbuf[*num_used + i - BLACKSIZE]; + } + else { + /* shift in *num_used samples into inbuf_old */ + int const n_shift = BLACKSIZE - *num_used; /* number of samples to shift */ + + /* shift n_shift samples by *num_used, to make room for the + * num_used new samples */ + for (i = 0; i < n_shift; ++i) + inbuf_old[i] = inbuf_old[i + *num_used]; + + /* shift in the *num_used samples */ + for (j = 0; i < BLACKSIZE; ++i, ++j) + inbuf_old[i] = inbuf[j]; + + assert(j == *num_used); + } + return k; /* return the number samples created at the new samplerate */ +} + +int +isResamplingNecessary(SessionConfig_t const* cfg) +{ + int const l = cfg->samplerate_out * 0.9995f; + int const h = cfg->samplerate_out * 1.0005f; + return (cfg->samplerate_in < l) || (h < cfg->samplerate_in) ? 1 : 0; +} + +/* copy in new samples from in_buffer into mfbuf, with resampling + if necessary. n_in = number of samples from the input buffer that + were used. n_out = number of samples copied into mfbuf */ + +void +fill_buffer(lame_internal_flags * gfc, + sample_t * const mfbuf[2], sample_t const * const in_buffer[2], int nsamples, int *n_in, int *n_out) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int mf_size = gfc->sv_enc.mf_size; + int framesize = 576 * cfg->mode_gr; + int nout, ch = 0; + int nch = cfg->channels_out; + + /* copy in new samples into mfbuf, with resampling if necessary */ + if (isResamplingNecessary(cfg)) { + do { + nout = + fill_buffer_resample(gfc, &mfbuf[ch][mf_size], + framesize, in_buffer[ch], nsamples, n_in, ch); + } while (++ch < nch); + *n_out = nout; + } + else { + nout = Min(framesize, nsamples); + do { + memcpy(&mfbuf[ch][mf_size], &in_buffer[ch][0], nout * sizeof(mfbuf[0][0])); + } while (++ch < nch); + *n_out = nout; + *n_in = nout; + } +} + + + + + + + +/*********************************************************************** +* +* Message Output +* +***********************************************************************/ + +void +lame_report_def(const char *format, va_list args) +{ + (void) vfprintf(stderr, format, args); + fflush(stderr); /* an debug function should flush immediately */ +} + +void +lame_report_fnc(lame_report_function print_f, const char *format, ...) +{ + if (print_f) { + va_list args; + va_start(args, format); + print_f(format, args); + va_end(args); + } +} + + +void +lame_debugf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_dbg) { + va_list args; + va_start(args, format); + gfc->report_dbg(format, args); + va_end(args); + } +} + + +void +lame_msgf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_msg) { + va_list args; + va_start(args, format); + gfc->report_msg(format, args); + va_end(args); + } +} + + +void +lame_errorf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_err) { + va_list args; + va_start(args, format); + gfc->report_err(format, args); + va_end(args); + } +} + + + +/*********************************************************************** + * + * routines to detect CPU specific features like 3DNow, MMX, SSE + * + * donated by Frank Klemm + * added Robert Hegemann 2000-10-10 + * + ***********************************************************************/ + +#ifdef HAVE_NASM +extern int has_MMX_nasm(void); +extern int has_3DNow_nasm(void); +extern int has_SSE_nasm(void); +extern int has_SSE2_nasm(void); +#endif + +int +has_MMX(void) +{ +#ifdef HAVE_NASM + return has_MMX_nasm(); +#else + return 0; /* don't know, assume not */ +#endif +} + +int +has_3DNow(void) +{ +#ifdef HAVE_NASM + return has_3DNow_nasm(); +#else + return 0; /* don't know, assume not */ +#endif +} + +int +has_SSE(void) +{ +#ifdef HAVE_NASM + return has_SSE_nasm(); +#else +#if defined( _M_X64 ) || defined( MIN_ARCH_SSE ) + return 1; +#else + return 0; /* don't know, assume not */ +#endif +#endif +} + +int +has_SSE2(void) +{ +#ifdef HAVE_NASM + return has_SSE2_nasm(); +#else +#if defined( _M_X64 ) || defined( MIN_ARCH_SSE ) + return 1; +#else + return 0; /* don't know, assume not */ +#endif +#endif +} + +void +disable_FPE(void) +{ +/* extremly system dependent stuff, move to a lib to make the code readable */ +/*==========================================================================*/ + + + + /* + * Disable floating point exceptions + */ + + + + +#if defined(__FreeBSD__) && !defined(__alpha__) + { + /* seet floating point mask to the Linux default */ + fp_except_t mask; + mask = fpgetmask(); + /* if bit is set, we get SIGFPE on that error! */ + fpsetmask(mask & ~(FP_X_INV | FP_X_DZ)); + /* DEBUGF("FreeBSD mask is 0x%x\n",mask); */ + } +#endif + +#if defined(__riscos__) && !defined(ABORTFP) + /* Disable FPE's under RISC OS */ + /* if bit is set, we disable trapping that error! */ + /* _FPE_IVO : invalid operation */ + /* _FPE_DVZ : divide by zero */ + /* _FPE_OFL : overflow */ + /* _FPE_UFL : underflow */ + /* _FPE_INX : inexact */ + DisableFPETraps(_FPE_IVO | _FPE_DVZ | _FPE_OFL); +#endif + + /* + * Debugging stuff + * The default is to ignore FPE's, unless compiled with -DABORTFP + * so add code below to ENABLE FPE's. + */ + +#if defined(ABORTFP) +#if defined(_MSC_VER) + { +#if 0 + /* rh 061207 + the following fix seems to be a workaround for a problem in the + parent process calling LAME. It would be better to fix the broken + application => code disabled. + */ + + /* set affinity to a single CPU. Fix for EAC/lame on SMP systems from + "Todd Richmond" <todd.richmond@openwave.com> */ + SYSTEM_INFO si; + GetSystemInfo(&si); + SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask); +#endif +#include <float.h> + unsigned int mask; + mask = _controlfp(0, 0); + mask &= ~(_EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + mask = _controlfp(mask, _MCW_EM); + } +#elif defined(__CYGWIN__) +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +# define _EM_INEXACT 0x00000020 /* inexact (precision) */ +# define _EM_UNDERFLOW 0x00000010 /* underflow */ +# define _EM_OVERFLOW 0x00000008 /* overflow */ +# define _EM_ZERODIVIDE 0x00000004 /* zero divide */ +# define _EM_INVALID 0x00000001 /* invalid */ + { + unsigned int mask; + _FPU_GETCW(mask); + /* Set the FPU control word to abort on most FPEs */ + mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + _FPU_SETCW(mask); + } +# elif defined(__linux__) + { + +# include <fpu_control.h> +# ifndef _FPU_GETCW +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# endif +# ifndef _FPU_SETCW +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# endif + + /* + * Set the Linux mask to abort on most FPE's + * if bit is set, we _mask_ SIGFPE on that error! + * mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM ); + */ + + unsigned int mask; + _FPU_GETCW(mask); + mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM); + _FPU_SETCW(mask); + } +#endif +#endif /* ABORTFP */ +} + + + + + +#ifdef USE_FAST_LOG +/*********************************************************************** + * + * Fast Log Approximation for log2, used to approximate every other log + * (log10 and log) + * maximum absolute error for log10 is around 10-6 + * maximum *relative* error can be high when x is almost 1 because error/log10(x) tends toward x/e + * + * use it if typical RESULT values are > 1e-5 (for example if x>1.00001 or x<0.99999) + * or if the relative precision in the domain around 1 is not important (result in 1 is exact and 0) + * + ***********************************************************************/ + + +#define LOG2_SIZE (512) +#define LOG2_SIZE_L2 (9) + +static ieee754_float32_t log_table[LOG2_SIZE + 1]; + + + +void +init_log_table(void) +{ + int j; + static int init = 0; + + /* Range for log2(x) over [1,2[ is [0,1[ */ + assert((1 << LOG2_SIZE_L2) == LOG2_SIZE); + + if (!init) { + for (j = 0; j < LOG2_SIZE + 1; j++) + log_table[j] = log(1.0f + j / (ieee754_float32_t) LOG2_SIZE) / log(2.0f); + } + init = 1; +} + + + +ieee754_float32_t +fast_log2(ieee754_float32_t x) +{ + ieee754_float32_t log2val, partial; + union { + ieee754_float32_t f; + int i; + } fi; + int mantisse; + fi.f = x; + mantisse = fi.i & 0x7fffff; + log2val = ((fi.i >> 23) & 0xFF) - 0x7f; + partial = (mantisse & ((1 << (23 - LOG2_SIZE_L2)) - 1)); + partial *= 1.0f / ((1 << (23 - LOG2_SIZE_L2))); + + + mantisse >>= (23 - LOG2_SIZE_L2); + + /* log2val += log_table[mantisse]; without interpolation the results are not good */ + log2val += log_table[mantisse] * (1.0f - partial) + log_table[mantisse + 1] * partial; + + return log2val; +} + +#else /* Don't use FAST_LOG */ + + +void +init_log_table(void) +{ +} + + +#endif + +/* end of util.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.h new file mode 100644 index 00000000..13f0cd42 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/util.h @@ -0,0 +1,616 @@ +/* + * lame utility library include file + * + * Copyright (c) 1999 Albert L Faber + * Copyright (c) 2008 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_UTIL_H +#define LAME_UTIL_H + +#include "l3side.h" +#include "id3tag.h" +#include "lame_global_flags.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************** +* +* Global Definitions +* +***********************************************************************/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifdef UINT_MAX +# define MAX_U_32_NUM UINT_MAX +#else +# define MAX_U_32_NUM 0xFFFFFFFF +#endif + +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846 +# endif +#endif + + +#ifdef M_LN2 +# define LOG2 M_LN2 +#else +# define LOG2 0.69314718055994530942 +#endif + +#ifdef M_LN10 +# define LOG10 M_LN10 +#else +# define LOG10 2.30258509299404568402 +#endif + + +#ifdef M_SQRT2 +# define SQRT2 M_SQRT2 +#else +# define SQRT2 1.41421356237309504880 +#endif + + +#define CRC16_POLYNOMIAL 0x8005 + +#define MAX_BITS_PER_CHANNEL 4095 +#define MAX_BITS_PER_GRANULE 7680 + +/* "bit_stream.h" Definitions */ +#define BUFFER_SIZE LAME_MAXMP3BUFFER + +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#define Max(A, B) ((A) > (B) ? (A) : (B)) + +/* log/log10 approximations */ +#ifdef USE_FAST_LOG +#define FAST_LOG10(x) (fast_log2(x)*(LOG2/LOG10)) +#define FAST_LOG(x) (fast_log2(x)*LOG2) +#define FAST_LOG10_X(x,y) (fast_log2(x)*(LOG2/LOG10*(y))) +#define FAST_LOG_X(x,y) (fast_log2(x)*(LOG2*(y))) +#else +#define FAST_LOG10(x) log10(x) +#define FAST_LOG(x) log(x) +#define FAST_LOG10_X(x,y) (log10(x)*(y)) +#define FAST_LOG_X(x,y) (log(x)*(y)) +#endif + + + struct replaygain_data; +#ifndef replaygain_data_defined +#define replaygain_data_defined + typedef struct replaygain_data replaygain_t; +#endif + struct plotting_data; +#ifndef plotting_data_defined +#define plotting_data_defined + typedef struct plotting_data plotting_data; +#endif + +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + + typedef struct { + void *aligned; /* pointer to ie. 128 bit aligned memory */ + void *pointer; /* to use with malloc/free */ + } aligned_pointer_t; + + void calloc_aligned(aligned_pointer_t * ptr, unsigned int size, unsigned int bytes); + void free_aligned(aligned_pointer_t * ptr); + + + /* "bit_stream.h" Type Definitions */ + + typedef struct bit_stream_struc { + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + int 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 */ + + /* format of file in rd mode (BINARY/ASCII) */ + } Bit_stream_struc; + + + + typedef struct { + int sum; /* what we have seen so far */ + int seen; /* how many frames we have seen in this chunk */ + int want; /* how many frames we want to collect into one chunk */ + int pos; /* actual position in our bag */ + int size; /* size of our bag */ + int *bag; /* pointer to our bag */ + unsigned int nVbrNumFrames; + unsigned long nBytesWritten; + /* VBR tag data */ + unsigned int TotalFrameSize; + } VBR_seek_info_t; + + + /** + * ATH related stuff, if something new ATH related has to be added, + * please plugg it here into the ATH_t struct + */ + typedef struct { + int use_adjust; /* method for the auto adjustment */ + FLOAT aa_sensitivity_p; /* factor for tuning the (sample power) + point below which adaptive threshold + of hearing adjustment occurs */ + FLOAT adjust_factor; /* lowering based on peak volume, 1 = no lowering */ + FLOAT adjust_limit; /* limit for dynamic ATH adjust */ + FLOAT decay; /* determined to lower x dB each second */ + FLOAT floor; /* lowest ATH value */ + FLOAT l[SBMAX_l]; /* ATH for sfbs in long blocks */ + FLOAT s[SBMAX_s]; /* ATH for sfbs in short blocks */ + FLOAT psfb21[PSFB21]; /* ATH for partitionned sfb21 in long blocks */ + FLOAT psfb12[PSFB12]; /* ATH for partitionned sfb12 in short blocks */ + FLOAT cb_l[CBANDS]; /* ATH for long block convolution bands */ + FLOAT cb_s[CBANDS]; /* ATH for short block convolution bands */ + FLOAT eql_w[BLKSIZE / 2]; /* equal loudness weights (based on ATH) */ + } ATH_t; + + /** + * PSY Model related stuff + */ + + typedef struct { + FLOAT masking_lower[CBANDS]; + FLOAT minval[CBANDS]; + FLOAT rnumlines[CBANDS]; + FLOAT mld_cb[CBANDS]; + FLOAT mld[Max(SBMAX_l,SBMAX_s)]; + FLOAT bo_weight[Max(SBMAX_l,SBMAX_s)]; /* band weight long scalefactor bands, at transition */ + FLOAT attack_threshold; /* short block tuning */ + int s3ind[CBANDS][2]; + int numlines[CBANDS]; + int bm[Max(SBMAX_l,SBMAX_s)]; + int bo[Max(SBMAX_l,SBMAX_s)]; + int npart; + int n_sb; /* SBMAX_l or SBMAX_s */ + FLOAT *s3; + } PsyConst_CB2SB_t; + + + /** + * global data constants + */ + typedef struct { + FLOAT window[BLKSIZE], window_s[BLKSIZE_s / 2]; + PsyConst_CB2SB_t l; + PsyConst_CB2SB_t s; + PsyConst_CB2SB_t l_to_s; + FLOAT attack_threshold[4]; + FLOAT decay; + int force_short_block_calc; + } PsyConst_t; + + + typedef struct { + + FLOAT nb_l1[4][CBANDS], nb_l2[4][CBANDS]; + FLOAT nb_s1[4][CBANDS], nb_s2[4][CBANDS]; + + III_psy_xmin thm[4]; + III_psy_xmin en[4]; + + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq_save[2]; /* account for granule delay of L3psycho_anal */ + + FLOAT tot_ener[4]; + + FLOAT last_en_subshort[4][9]; + int last_attacks[4]; + + int blocktype_old[2]; + } PsyStateVar_t; + + + typedef struct { + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq[2][2]; /* loudness^2 approx. per granule and channel */ + } PsyResult_t; + + + /* variables used by encoder.c */ + typedef struct { + /* variables for newmdct.c */ + FLOAT sb_sample[2][2][18][SBLIMIT]; + FLOAT amp_filter[32]; + + /* variables used by util.c */ + /* BPC = maximum number of filter convolution windows to precompute */ +#define BPC 320 + double itime[2]; /* float precision seems to be not enough */ + sample_t *inbuf_old[2]; + sample_t *blackfilt[2 * BPC + 1]; + + FLOAT pefirbuf[19]; + + /* used for padding */ + int frac_SpF; + int slot_lag; + + /* variables for bitstream.c */ + /* mpeg1: buffer=511 bytes smallest frame: 96-38(sideinfo)=58 + * max number of frames in reservoir: 8 + * mpeg2: buffer=255 bytes. smallest frame: 24-23bytes=1 + * with VBR, if you are encoding all silence, it is possible to + * have 8kbs/24khz frames with 1byte of data each, which means we need + * to buffer up to 255 headers! */ + /* also, max_header_buf has to be a power of two */ +#define MAX_HEADER_BUF 256 +#define MAX_HEADER_LEN 40 /* max size of header is 38 */ + struct { + int write_timing; + int ptr; + char buf[MAX_HEADER_LEN]; + } header[MAX_HEADER_BUF]; + + int h_ptr; + int w_ptr; + int ancillary_flag; + + /* variables for reservoir.c */ + int ResvSize; /* in bits */ + int ResvMax; /* in bits */ + + int in_buffer_nsamples; + sample_t *in_buffer_0; + sample_t *in_buffer_1; + +#ifndef MFSIZE +# define MFSIZE ( 3*1152 + ENCDELAY - MDCTDELAY ) +#endif + sample_t mfbuf[2][MFSIZE]; + + int mf_samples_to_encode; + int mf_size; + + } EncStateVar_t; + + + typedef struct { + /* simple statistics */ + int bitrate_channelmode_hist[16][4 + 1]; + int bitrate_blocktype_hist[16][4 + 1 + 1]; /*norm/start/short/stop/mixed(short)/sum */ + + int bitrate_index; + int frame_number; /* number of frames encoded */ + int padding; /* padding for the current frame? */ + int mode_ext; + int encoder_delay; + int encoder_padding; /* number of samples of padding appended to input */ + } EncResult_t; + + + /* variables used by quantize.c */ + typedef struct { + /* variables for nspsytune */ + FLOAT longfact[SBMAX_l]; + FLOAT shortfact[SBMAX_s]; + FLOAT masking_lower; + FLOAT mask_adjust; /* the dbQ stuff */ + FLOAT mask_adjust_short; /* the dbQ stuff */ + int OldValue[2]; + int CurrentStep[2]; + int pseudohalf[SFBMAX]; + int sfb21_extra; /* will be set in lame_init_params */ + int substep_shaping; /* 0 = no substep + 1 = use substep shaping at last step(VBR only) + (not implemented yet) + 2 = use substep inside loop + 3 = use substep inside loop and last step + */ + + + char bv_scf[576]; + } QntStateVar_t; + + + typedef struct { + replaygain_t *rgdata; + /* ReplayGain */ + } RpgStateVar_t; + + + typedef struct { + FLOAT noclipScale; /* user-specified scale factor required for preventing clipping */ + sample_t PeakSample; + int RadioGain; + int noclipGainChange; /* gain change required for preventing clipping */ + } RpgResult_t; + + + typedef struct { + int version; /* 0=MPEG-2/2.5 1=MPEG-1 */ + int samplerate_index; + int sideinfo_len; + + int noise_shaping; /* 0 = none + 1 = ISO AAC model + 2 = allow scalefac_select=1 + */ + + int subblock_gain; /* 0 = no, 1 = yes */ + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + int noise_shaping_amp; /* 0 = ISO model: amplify all distorted bands + 1 = amplify within 50% of max (on db scale) + 2 = amplify only most distorted band + 3 = method 1 and refine with method 2 + */ + + int noise_shaping_stop; /* 0 = stop at over=0, all scalefacs amplified or + a scalefac has reached max value + 1 = stop when all scalefacs amplified or + a scalefac has reached max value + 2 = stop when all scalefacs amplified + */ + + + int full_outer_loop; /* 0 = stop early after 0 distortion found. 1 = full search */ + + int lowpassfreq; + int highpassfreq; + int samplerate_in; /* input_samp_rate in Hz. default=44.1 kHz */ + int samplerate_out; /* output_samp_rate. */ + int channels_in; /* number of channels in the input data stream (PCM or decoded PCM) */ + int channels_out; /* number of channels in the output data stream (not used for decoding) */ + int mode_gr; /* granules per frame */ + int force_ms; /* force M/S mode. requires mode=1 */ + + int quant_comp; + int quant_comp_short; + + int use_temporal_masking_effect; + int use_safe_joint_stereo; + + int preset; + + vbr_mode vbr; + int vbr_avg_bitrate_kbps; + int vbr_min_bitrate_index; /* min bitrate index */ + int vbr_max_bitrate_index; /* max bitrate index */ + int avg_bitrate; + int enforce_min_bitrate; /* strictly enforce VBR_min_bitrate normaly, it will be violated for analog silence */ + + int findReplayGain; /* find the RG value? default=0 */ + int findPeakSample; + int decode_on_the_fly; /* decode on the fly? default=0 */ + int analysis; + int disable_reservoir; + int buffer_constraint; /* enforce ISO spec as much as possible */ + int free_format; + int write_lame_tag; /* add Xing VBR tag? */ + + int error_protection; /* use 2 bytes per frame for a CRC checksum. default=0 */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int extension; /* the MP3 'private extension' bit. Meaningless */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + + + MPEG_mode mode; + short_block_t short_blocks; + + float interChRatio; + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + float ATH_offset_db;/* add to ATH this many db */ + float ATH_offset_factor;/* change ATH by this factor, derived from ATH_offset_db */ + float ATHcurve; /* change ATH formula 4 shape */ + int ATHtype; + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + + float ATHfixpoint; + + float adjust_alto_db; + float adjust_bass_db; + float adjust_treble_db; + float adjust_sfb21_db; + + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + /* lowpass and highpass filter control */ + FLOAT lowpass1, lowpass2; /* normalized frequency bounds of passband */ + FLOAT highpass1, highpass2; /* normalized frequency bounds of passband */ + + /* scale input by this amount before encoding at least not used for MP3 decoding */ + FLOAT pcm_transform[2][2]; + + FLOAT minval; + } SessionConfig_t; + + + struct lame_internal_flags { + + /******************************************************************** + * internal variables NOT set by calling program, and should not be * + * modified by the calling program * + ********************************************************************/ + + /* + * Some remarks to the Class_ID field: + * The Class ID is an Identifier for a pointer to this struct. + * It is very unlikely that a pointer to lame_global_flags has the same 32 bits + * in it's structure (large and other special properties, for instance prime). + * + * To test that the structure is right and initialized, use: + * if ( gfc -> Class_ID == LAME_ID ) ... + * Other remark: + * If you set a flag to 0 for uninit data and 1 for init data, the right test + * should be "if (flag == 1)" and NOT "if (flag)". Unintended modification + * of this element will be otherwise misinterpreted as an init. + */ +# define LAME_ID 0xFFF88E3B + unsigned long class_id; + + int lame_init_params_successful; + int lame_encode_frame_init; + int iteration_init_init; + int fill_buffer_resample_init; + + SessionConfig_t cfg; + + /* variables used by lame.c */ + Bit_stream_struc bs; + III_side_info_t l3_side; + + scalefac_struct scalefac_band; + + PsyStateVar_t sv_psy; /* DATA FROM PSYMODEL.C */ + PsyResult_t ov_psy; + EncStateVar_t sv_enc; /* DATA FROM ENCODER.C */ + EncResult_t ov_enc; + QntStateVar_t sv_qnt; /* DATA FROM QUANTIZE.C */ + + RpgStateVar_t sv_rpg; + RpgResult_t ov_rpg; + + /* optional ID3 tags, used in id3tag.c */ + struct id3tag_spec tag_spec; + uint16_t nMusicCRC; + + uint16_t _unused; + + /* CPU features */ + struct { + unsigned int MMX:1; /* Pentium MMX, Pentium II...IV, K6, K6-2, + K6-III, Athlon */ + unsigned int AMD_3DNow:1; /* K6-2, K6-III, Athlon */ + unsigned int SSE:1; /* Pentium III, Pentium 4 */ + unsigned int SSE2:1; /* Pentium 4, K8 */ + unsigned int _unused:28; + } CPU_features; + + + VBR_seek_info_t VBR_seek_table; /* used for Xing VBR header */ + + ATH_t *ATH; /* all ATH related stuff */ + + PsyConst_t *cd_psy; + + /* used by the frame analyzer */ + plotting_data *pinfo; + hip_t hip; + + /* functions to replace with CPU feature optimized versions in takehiro.c */ + int (*choose_table) (const int *ix, const int *const end, int *const s); + void (*fft_fht) (FLOAT *, int); + void (*init_xrpow_core) (gr_info * const cod_info, FLOAT xrpow[576], int upper, + FLOAT * sum); + + lame_report_function report_msg; + lame_report_function report_dbg; + lame_report_function report_err; + }; + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined + typedef struct lame_internal_flags lame_internal_flags; +#endif + + +/*********************************************************************** +* +* Global Function Prototype Declarations +* +***********************************************************************/ + void freegfc(lame_internal_flags * const gfc); + void free_id3tag(lame_internal_flags * const gfc); + extern int BitrateIndex(int, int, int); + extern int FindNearestBitrate(int, int, int); + extern int map2MP3Frequency(int freq); + extern int SmpFrqIndex(int, int *const); + extern int nearestBitrateFullIndex(uint16_t brate); + extern FLOAT ATHformula(SessionConfig_t const *cfg, FLOAT freq); + extern FLOAT freq2bark(FLOAT freq); + void disable_FPE(void); + +/* log/log10 approximations */ + extern void init_log_table(void); + extern ieee754_float32_t fast_log2(ieee754_float32_t x); + + int isResamplingNecessary(SessionConfig_t const* cfg); + + void fill_buffer(lame_internal_flags * gfc, + sample_t *const mfbuf[2], + sample_t const *const in_buffer[2], int nsamples, int *n_in, int *n_out); + +/* same as lame_decode1 (look in lame.h), but returns + unclipped raw floating-point samples. It is declared + here, not in lame.h, because it returns LAME's + internal type sample_t. No more than 1152 samples + per channel are allowed. */ + int hip_decode1_unclipped(hip_t hip, unsigned char *mp3buf, + size_t len, sample_t pcm_l[], sample_t pcm_r[]); + + + extern int has_MMX(void); + extern int has_3DNow(void); + extern int has_SSE(void); + extern int has_SSE2(void); + + + +/*********************************************************************** +* +* Macros about Message Printing and Exit +* +***********************************************************************/ + + extern void lame_report_def(const char* format, va_list args); + extern void lame_report_fnc(lame_report_function print_f, const char *, ...); + extern void lame_errorf(const lame_internal_flags * gfc, const char *, ...); + extern void lame_debugf(const lame_internal_flags * gfc, const char *, ...); + extern void lame_msgf(const lame_internal_flags * gfc, const char *, ...); +#define DEBUGF lame_debugf +#define ERRORF lame_errorf +#define MSGF lame_msgf + + int is_lame_internal_flags_valid(const lame_internal_flags * gfp); + + extern void hip_set_pinfo(hip_t hip, plotting_data* pinfo); + +#ifdef __cplusplus +} +#endif +#endif /* LAME_UTIL_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.c new file mode 100644 index 00000000..0f703b75 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.c @@ -0,0 +1,1580 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2000-2012 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: vbrquantize.c,v 1.142 2012/02/07 13:36:35 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "vbrquantize.h" +#include "quantize_pvt.h" + + + + +struct algo_s; +typedef struct algo_s algo_t; + +typedef void (*alloc_sf_f) (const algo_t *, const int *, const int *, int); +typedef uint8_t (*find_sf_f) (const FLOAT *, const FLOAT *, FLOAT, unsigned int, uint8_t); + +struct algo_s { + alloc_sf_f alloc; + find_sf_f find; + const FLOAT *xr34orig; + lame_internal_flags *gfc; + gr_info *cod_info; + int mingain_l; + int mingain_s[3]; +}; + + + +/* Remarks on optimizing compilers: + * + * the MSVC compiler may get into aliasing problems when accessing + * memory through the fi_union. declaring it volatile does the trick here + * + * the calc_sfb_noise_* functions are not inlined because the intel compiler + * optimized executeables won't work as expected anymore + */ + +#ifdef _MSC_VER +# if _MSC_VER < 1400 +# define VOLATILE volatile +# else +# define VOLATILE +# endif +#else +# define VOLATILE +#endif + +typedef VOLATILE union { + float f; + int i; +} fi_union; + + + +#ifdef TAKEHIRO_IEEE754_HACK +#define DOUBLEX double +#else +#define DOUBLEX FLOAT +#endif + +#define MAGIC_FLOAT_def (65536*(128)) +#define MAGIC_INT_def 0x4b000000 + +#ifdef TAKEHIRO_IEEE754_HACK +#else +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + *********************************************************************/ +# define QUANTFAC(rx) adj43[rx] +# define ROUNDFAC_def 0.4054f +# define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#endif + +static int const MAGIC_INT = MAGIC_INT_def; +#ifndef TAKEHIRO_IEEE754_HACK +static DOUBLEX const ROUNDFAC = ROUNDFAC_def; +#endif +static DOUBLEX const MAGIC_FLOAT = MAGIC_FLOAT_def; + + +inline static float +vec_max_c(const float * xr34, unsigned int bw) +{ + float xfsf = 0; + unsigned int i = bw >> 2u; + unsigned int const remaining = (bw & 0x03u); + + while (i-- > 0) { + if (xfsf < xr34[0]) { + xfsf = xr34[0]; + } + if (xfsf < xr34[1]) { + xfsf = xr34[1]; + } + if (xfsf < xr34[2]) { + xfsf = xr34[2]; + } + if (xfsf < xr34[3]) { + xfsf = xr34[3]; + } + xr34 += 4; + } + switch( remaining ) { + case 3: if (xfsf < xr34[2]) xfsf = xr34[2]; + case 2: if (xfsf < xr34[1]) xfsf = xr34[1]; + case 1: if (xfsf < xr34[0]) xfsf = xr34[0]; + default: break; + } + return xfsf; +} + + +inline static uint8_t +find_lowest_scalefac(const FLOAT xr34) +{ + uint8_t sf_ok = 255; + uint8_t sf = 128, delsf = 64; + uint8_t i; + FLOAT const ixmax_val = IXMAX_VAL; + for (i = 0; i < 8; ++i) { + FLOAT const xfsf = ipow20[sf] * xr34; + if (xfsf <= ixmax_val) { + sf_ok = sf; + sf -= delsf; + } + else { + sf += delsf; + } + delsf >>= 1; + } + return sf_ok; +} + + +inline static void +k_34_4(DOUBLEX x[4], int l3[4]) +{ +#ifdef TAKEHIRO_IEEE754_HACK + fi_union fi[4]; + + assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL); + x[0] += MAGIC_FLOAT; + fi[0].f = x[0]; + x[1] += MAGIC_FLOAT; + fi[1].f = x[1]; + x[2] += MAGIC_FLOAT; + fi[2].f = x[2]; + x[3] += MAGIC_FLOAT; + fi[3].f = x[3]; + fi[0].f = x[0] + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x[1] + adj43asm[fi[1].i - MAGIC_INT]; + fi[2].f = x[2] + adj43asm[fi[2].i - MAGIC_INT]; + fi[3].f = x[3] + adj43asm[fi[3].i - MAGIC_INT]; + l3[0] = fi[0].i - MAGIC_INT; + l3[1] = fi[1].i - MAGIC_INT; + l3[2] = fi[2].i - MAGIC_INT; + l3[3] = fi[3].i - MAGIC_INT; +#else + assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL); + XRPOW_FTOI(x[0], l3[0]); + XRPOW_FTOI(x[1], l3[1]); + XRPOW_FTOI(x[2], l3[2]); + XRPOW_FTOI(x[3], l3[3]); + x[0] += QUANTFAC(l3[0]); + x[1] += QUANTFAC(l3[1]); + x[2] += QUANTFAC(l3[2]); + x[3] += QUANTFAC(l3[3]); + XRPOW_FTOI(x[0], l3[0]); + XRPOW_FTOI(x[1], l3[1]); + XRPOW_FTOI(x[2], l3[2]); + XRPOW_FTOI(x[3], l3[3]); +#endif +} + + + + + +/* do call the calc_sfb_noise_* functions only with sf values + * for which holds: sfpow34*xr34 <= IXMAX_VAL + */ + +static FLOAT +calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, unsigned int bw, uint8_t sf) +{ + DOUBLEX x[4]; + int l3[4]; + const FLOAT sfpow = pow20[sf + Q_MAX2]; /*pow(2.0,sf/4.0); */ + const FLOAT sfpow34 = ipow20[sf]; /*pow(sfpow,-3.0/4.0); */ + + FLOAT xfsf = 0; + unsigned int i = bw >> 2u; + unsigned int const remaining = (bw & 0x03u); + + while (i-- > 0) { + x[0] = sfpow34 * xr34[0]; + x[1] = sfpow34 * xr34[1]; + x[2] = sfpow34 * xr34[2]; + x[3] = sfpow34 * xr34[3]; + + k_34_4(x, l3); + + x[0] = fabsf(xr[0]) - sfpow * pow43[l3[0]]; + x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]]; + x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]]; + x[3] = fabsf(xr[3]) - sfpow * pow43[l3[3]]; + xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]); + + xr += 4; + xr34 += 4; + } + if (remaining) { + x[0] = x[1] = x[2] = x[3] = 0; + switch( remaining ) { + case 3: x[2] = sfpow34 * xr34[2]; + case 2: x[1] = sfpow34 * xr34[1]; + case 1: x[0] = sfpow34 * xr34[0]; + } + + k_34_4(x, l3); + x[0] = x[1] = x[2] = x[3] = 0; + + switch( remaining ) { + case 3: x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]]; + case 2: x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]]; + case 1: x[0] = fabsf(xr[0]) - sfpow * pow43[l3[0]]; + } + xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]); + } + return xfsf; +} + + + +struct calc_noise_cache { + int valid; + FLOAT value; +}; + +typedef struct calc_noise_cache calc_noise_cache_t; + + +static uint8_t +tri_calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, + uint8_t sf, calc_noise_cache_t * did_it) +{ + if (did_it[sf].valid == 0) { + did_it[sf].valid = 1; + did_it[sf].value = calc_sfb_noise_x34(xr, xr34, bw, sf); + } + if (l3_xmin < did_it[sf].value) { + return 1; + } + if (sf < 255) { + uint8_t const sf_x = sf + 1; + if (did_it[sf_x].valid == 0) { + did_it[sf_x].valid = 1; + did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x); + } + if (l3_xmin < did_it[sf_x].value) { + return 1; + } + } + if (sf > 0) { + uint8_t const sf_x = sf - 1; + if (did_it[sf_x].valid == 0) { + did_it[sf_x].valid = 1; + did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x); + } + if (l3_xmin < did_it[sf_x].value) { + return 1; + } + } + return 0; +} + + +/** + * Robert Hegemann 2001-05-01 + * calculates quantization step size determined by allowed masking + */ +static int +calc_scalefac(FLOAT l3_xmin, int bw) +{ + FLOAT const c = 5.799142446; /* 10 * 10^(2/3) * log10(4/3) */ + return 210 + (int) (c * log10f(l3_xmin / bw) - .5f); +} + +static uint8_t +guess_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, uint8_t sf_min) +{ + int const guess = calc_scalefac(l3_xmin, bw); + if (guess < sf_min) return sf_min; + if (guess >= 255) return 255; + (void) xr; + (void) xr34; + return guess; +} + + +/* the find_scalefac* routines calculate + * a quantization step size which would + * introduce as much noise as is allowed. + * The larger the step size the more + * quantization noise we'll get. The + * scalefactors are there to lower the + * global step size, allowing limited + * differences in quantization step sizes + * per band (shaping the noise). + */ + +static uint8_t +find_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, + uint8_t sf_min) +{ + calc_noise_cache_t did_it[256]; + uint8_t sf = 128, sf_ok = 255, delsf = 128, seen_good_one = 0, i; + memset(did_it, 0, sizeof(did_it)); + for (i = 0; i < 8; ++i) { + delsf >>= 1; + if (sf <= sf_min) { + sf += delsf; + } + else { + uint8_t const bad = tri_calc_sfb_noise_x34(xr, xr34, l3_xmin, bw, sf, did_it); + if (bad) { /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + seen_good_one = 1; + } + } + } + /* returning a scalefac without distortion, if possible + */ + if (seen_good_one > 0) { + sf = sf_ok; + } + if (sf <= sf_min) { + sf = sf_min; + } + return sf; +} + + + +/*********************************************************************** + * + * calc_short_block_vbr_sf() + * calc_long_block_vbr_sf() + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-25 made functions of it + * + ***********************************************************************/ + +/* a variation for vbr-mtrh */ +static int +block_sf(algo_t * that, const FLOAT l3_xmin[SFBMAX], int vbrsf[SFBMAX], int vbrsfmin[SFBMAX]) +{ + FLOAT max_xr34; + const FLOAT *const xr = &that->cod_info->xr[0]; + const FLOAT *const xr34_orig = &that->xr34orig[0]; + const int *const width = &that->cod_info->width[0]; + const char *const energy_above_cutoff = &that->cod_info->energy_above_cutoff[0]; + unsigned int const max_nonzero_coeff = (unsigned int) that->cod_info->max_nonzero_coeff; + uint8_t maxsf = 0; + int sfb = 0, m_o = -1; + unsigned int j = 0, i = 0; + int const psymax = that->cod_info->psymax; + + assert(that->cod_info->max_nonzero_coeff >= 0); + + that->mingain_l = 0; + that->mingain_s[0] = 0; + that->mingain_s[1] = 0; + that->mingain_s[2] = 0; + while (j <= max_nonzero_coeff) { + unsigned int const w = (unsigned int) width[sfb]; + unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1); + unsigned int l = w; + uint8_t m1, m2; + if (l > m) { + l = m; + } + max_xr34 = vec_max_c(&xr34_orig[j], l); + + m1 = find_lowest_scalefac(max_xr34); + vbrsfmin[sfb] = m1; + if (that->mingain_l < m1) { + that->mingain_l = m1; + } + if (that->mingain_s[i] < m1) { + that->mingain_s[i] = m1; + } + if (++i > 2) { + i = 0; + } + if (sfb < psymax && w > 2) { /* mpeg2.5 at 8 kHz doesn't use all scalefactors, unused have width 2 */ + if (energy_above_cutoff[sfb]) { + m2 = that->find(&xr[j], &xr34_orig[j], l3_xmin[sfb], l, m1); +#if 0 + if (0) { + /** Robert Hegemann 2007-09-29: + * It seems here is some more potential for speed improvements. + * Current find method does 11-18 quantization calculations. + * Using a "good guess" may help to reduce this amount. + */ + uint8_t guess = calc_scalefac(l3_xmin[sfb], l); + DEBUGF(that->gfc, "sfb=%3d guess=%3d found=%3d diff=%3d\n", sfb, guess, m2, + m2 - guess); + } +#endif + if (maxsf < m2) { + maxsf = m2; + } + if (m_o < m2 && m2 < 255) { + m_o = m2; + } + } + else { + m2 = 255; + maxsf = 255; + } + } + else { + if (maxsf < m1) { + maxsf = m1; + } + m2 = maxsf; + } + vbrsf[sfb] = m2; + ++sfb; + j += w; + } + for (; sfb < SFBMAX; ++sfb) { + vbrsf[sfb] = maxsf; + vbrsfmin[sfb] = 0; + } + if (m_o > -1) { + maxsf = m_o; + for (sfb = 0; sfb < SFBMAX; ++sfb) { + if (vbrsf[sfb] == 255) { + vbrsf[sfb] = m_o; + } + } + } + return maxsf; +} + + + +/*********************************************************************** + * + * quantize xr34 based on scalefactors + * + * block_xr34 + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-20 made functions of them + * + ***********************************************************************/ + +static void +quantize_x34(const algo_t * that) +{ + DOUBLEX x[4]; + const FLOAT *xr34_orig = that->xr34orig; + gr_info *const cod_info = that->cod_info; + int const ifqstep = (cod_info->scalefac_scale == 0) ? 2 : 4; + int *l3 = cod_info->l3_enc; + unsigned int j = 0, sfb = 0; + unsigned int const max_nonzero_coeff = (unsigned int) cod_info->max_nonzero_coeff; + + assert(cod_info->max_nonzero_coeff >= 0); + assert(cod_info->max_nonzero_coeff < 576); + + while (j <= max_nonzero_coeff) { + int const s = + (cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0)) * ifqstep + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + uint8_t const sfac = (uint8_t) (cod_info->global_gain - s); + FLOAT const sfpow34 = ipow20[sfac]; + unsigned int const w = (unsigned int) cod_info->width[sfb]; + unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1); + unsigned int i, remaining; + + assert((cod_info->global_gain - s) >= 0); + assert(cod_info->width[sfb] >= 0); + j += w; + ++sfb; + + i = (w <= m) ? w : m; + remaining = (i & 0x03u); + i >>= 2u; + + while (i-- > 0) { + x[0] = sfpow34 * xr34_orig[0]; + x[1] = sfpow34 * xr34_orig[1]; + x[2] = sfpow34 * xr34_orig[2]; + x[3] = sfpow34 * xr34_orig[3]; + + k_34_4(x, l3); + + l3 += 4; + xr34_orig += 4; + } + if (remaining) { + int tmp_l3[4]; + x[0] = x[1] = x[2] = x[3] = 0; + switch( remaining ) { + case 3: x[2] = sfpow34 * xr34_orig[2]; + case 2: x[1] = sfpow34 * xr34_orig[1]; + case 1: x[0] = sfpow34 * xr34_orig[0]; + } + + k_34_4(x, tmp_l3); + + switch( remaining ) { + case 3: l3[2] = tmp_l3[2]; + case 2: l3[1] = tmp_l3[1]; + case 1: l3[0] = tmp_l3[0]; + } + + l3 += remaining; + xr34_orig += remaining; + } + } +} + + + +static const uint8_t max_range_short[SBMAX_s * 3] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 0 +}; + +static const uint8_t max_range_long[SBMAX_l] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0 +}; + +static const uint8_t max_range_long_lsf_pretab[SBMAX_l] = { + 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* + sfb=0..5 scalefac < 16 + sfb>5 scalefac < 8 + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= 8*cod_info->subblock_gain[i]; + ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i]; +*/ + +static void +set_subblock_gain(gr_info * cod_info, const int mingain_s[3], int sf[]) +{ + const int maxrange1 = 15, maxrange2 = 7; + const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2; + int *const sbg = cod_info->subblock_gain; + unsigned int const psymax = (unsigned int) cod_info->psymax; + unsigned int psydiv = 18; + int sbg0, sbg1, sbg2; + unsigned int sfb, i; + int min_sbg = 7; + + if (psydiv > psymax) { + psydiv = psymax; + } + for (i = 0; i < 3; ++i) { + int maxsf1 = 0, maxsf2 = 0, minsf = 1000; + /* see if we should use subblock gain */ + for (sfb = i; sfb < psydiv; sfb += 3) { /* part 1 */ + int const v = -sf[sfb]; + if (maxsf1 < v) { + maxsf1 = v; + } + if (minsf > v) { + minsf = v; + } + } + for (; sfb < SFBMAX; sfb += 3) { /* part 2 */ + int const v = -sf[sfb]; + if (maxsf2 < v) { + maxsf2 = v; + } + if (minsf > v) { + minsf = v; + } + } + + /* boost subblock gain as little as possible so we can + * reach maxsf1 with scalefactors + * 8*sbg >= maxsf1 + */ + { + int const m1 = maxsf1 - (maxrange1 << ifqstepShift); + int const m2 = maxsf2 - (maxrange2 << ifqstepShift); + + maxsf1 = Max(m1, m2); + } + if (minsf > 0) { + sbg[i] = minsf >> 3; + } + else { + sbg[i] = 0; + } + if (maxsf1 > 0) { + int const m1 = sbg[i]; + int const m2 = (maxsf1 + 7) >> 3; + sbg[i] = Max(m1, m2); + } + if (sbg[i] > 0 && mingain_s[i] > (cod_info->global_gain - sbg[i] * 8)) { + sbg[i] = (cod_info->global_gain - mingain_s[i]) >> 3; + } + if (sbg[i] > 7) { + sbg[i] = 7; + } + if (min_sbg > sbg[i]) { + min_sbg = sbg[i]; + } + } + sbg0 = sbg[0] * 8; + sbg1 = sbg[1] * 8; + sbg2 = sbg[2] * 8; + for (sfb = 0; sfb < SFBMAX; sfb += 3) { + sf[sfb + 0] += sbg0; + sf[sfb + 1] += sbg1; + sf[sfb + 2] += sbg2; + } + if (min_sbg > 0) { + for (i = 0; i < 3; ++i) { + sbg[i] -= min_sbg; + } + cod_info->global_gain -= min_sbg * 8; + } +} + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +static void +set_scalefacs(gr_info * cod_info, const int *vbrsfmin, int sf[], const uint8_t * max_range) +{ + const int ifqstep = (cod_info->scalefac_scale == 0) ? 2 : 4; + const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2; + int *const scalefac = cod_info->scalefac; + int const sfbmax = cod_info->sfbmax; + int sfb; + int const *const sbg = cod_info->subblock_gain; + int const *const window = cod_info->window; + int const preflag = cod_info->preflag; + + if (preflag) { + for (sfb = 11; sfb < sfbmax; ++sfb) { + sf[sfb] += pretab[sfb] * ifqstep; + } + } + for (sfb = 0; sfb < sfbmax; ++sfb) { + int const gain = cod_info->global_gain - (sbg[window[sfb]] * 8) + - ((preflag ? pretab[sfb] : 0) * ifqstep); + + if (sf[sfb] < 0) { + int const m = gain - vbrsfmin[sfb]; + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = (ifqstep - 1 - sf[sfb]) >> ifqstepShift; + + if (scalefac[sfb] > max_range[sfb]) { + scalefac[sfb] = max_range[sfb]; + } + if (scalefac[sfb] > 0 && (scalefac[sfb] << ifqstepShift) > m) { + scalefac[sfb] = m >> ifqstepShift; + } + } + else { + scalefac[sfb] = 0; + } + } + for (; sfb < SFBMAX; ++sfb) { + scalefac[sfb] = 0; /* sfb21 */ + } +} + + +#ifndef NDEBUG +static int +checkScalefactor(const gr_info * cod_info, const int vbrsfmin[SFBMAX]) +{ + int const ifqstep = cod_info->scalefac_scale == 0 ? 2 : 4; + int sfb; + for (sfb = 0; sfb < cod_info->psymax; ++sfb) { + const int s = + ((cod_info->scalefac[sfb] + + (cod_info->preflag ? pretab[sfb] : 0)) * ifqstep) + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + + if ((cod_info->global_gain - s) < vbrsfmin[sfb]) { + /* + fprintf( stdout, "sf %d\n", sfb ); + fprintf( stdout, "min %d\n", vbrsfmin[sfb] ); + fprintf( stdout, "ggain %d\n", cod_info->global_gain ); + fprintf( stdout, "scalefac %d\n", cod_info->scalefac[sfb] ); + fprintf( stdout, "pretab %d\n", (cod_info->preflag ? pretab[sfb] : 0) ); + fprintf( stdout, "scale %d\n", (cod_info->scalefac_scale + 1) ); + fprintf( stdout, "subgain %d\n", cod_info->subblock_gain[cod_info->window[sfb]] * 8 ); + fflush( stdout ); + exit(-1); + */ + return 0; + } + } + return 1; +} +#endif + + +/****************************************************************** + * + * short block scalefacs + * + ******************************************************************/ + +static void +short_block_constrain(const algo_t * that, const int vbrsf[SFBMAX], + const int vbrsfmin[SFBMAX], int vbrmax) +{ + gr_info *const cod_info = that->cod_info; + lame_internal_flags const *const gfc = that->gfc; + SessionConfig_t const *const cfg = &gfc->cfg; + int const maxminsfb = that->mingain_l; + int mover, maxover0 = 0, maxover1 = 0, delta = 0; + int v, v0, v1; + int sfb; + int const psymax = cod_info->psymax; + + for (sfb = 0; sfb < psymax; ++sfb) { + assert(vbrsf[sfb] >= vbrsfmin[sfb]); + v = vbrmax - vbrsf[sfb]; + if (delta < v) { + delta = v; + } + v0 = v - (4 * 14 + 2 * max_range_short[sfb]); + v1 = v - (4 * 14 + 4 * max_range_short[sfb]); + if (maxover0 < v0) { + maxover0 = v0; + } + if (maxover1 < v1) { + maxover1 = v1; + } + } + if (cfg->noise_shaping == 2) { + /* allow scalefac_scale=1 */ + mover = Min(maxover0, maxover1); + } + else { + mover = maxover0; + } + if (delta > mover) { + delta = mover; + } + vbrmax -= delta; + maxover0 -= mover; + maxover1 -= mover; + + if (maxover0 == 0) { + cod_info->scalefac_scale = 0; + } + else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + } + if (vbrmax < maxminsfb) { + vbrmax = maxminsfb; + } + cod_info->global_gain = vbrmax; + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + { + int sf_temp[SFBMAX]; + for (sfb = 0; sfb < SFBMAX; ++sfb) { + sf_temp[sfb] = vbrsf[sfb] - vbrmax; + } + set_subblock_gain(cod_info, &that->mingain_s[0], sf_temp); + set_scalefacs(cod_info, vbrsfmin, sf_temp, max_range_short); + } + assert(checkScalefactor(cod_info, vbrsfmin)); +} + + + +/****************************************************************** + * + * long block scalefacs + * + ******************************************************************/ + +static void +long_block_constrain(const algo_t * that, const int vbrsf[SFBMAX], const int vbrsfmin[SFBMAX], + int vbrmax) +{ + gr_info *const cod_info = that->cod_info; + lame_internal_flags const *const gfc = that->gfc; + SessionConfig_t const *const cfg = &gfc->cfg; + uint8_t const *max_rangep; + int const maxminsfb = that->mingain_l; + int sfb; + int maxover0, maxover1, maxover0p, maxover1p, mover, delta = 0; + int v, v0, v1, v0p, v1p, vm0p = 1, vm1p = 1; + int const psymax = cod_info->psymax; + + max_rangep = cfg->mode_gr == 2 ? max_range_long : max_range_long_lsf_pretab; + + maxover0 = 0; + maxover1 = 0; + maxover0p = 0; /* pretab */ + maxover1p = 0; /* pretab */ + + for (sfb = 0; sfb < psymax; ++sfb) { + assert(vbrsf[sfb] >= vbrsfmin[sfb]); + v = vbrmax - vbrsf[sfb]; + if (delta < v) { + delta = v; + } + v0 = v - 2 * max_range_long[sfb]; + v1 = v - 4 * max_range_long[sfb]; + v0p = v - 2 * (max_rangep[sfb] + pretab[sfb]); + v1p = v - 4 * (max_rangep[sfb] + pretab[sfb]); + if (maxover0 < v0) { + maxover0 = v0; + } + if (maxover1 < v1) { + maxover1 = v1; + } + if (maxover0p < v0p) { + maxover0p = v0p; + } + if (maxover1p < v1p) { + maxover1p = v1p; + } + } + if (vm0p == 1) { + int gain = vbrmax - maxover0p; + if (gain < maxminsfb) { + gain = maxminsfb; + } + for (sfb = 0; sfb < psymax; ++sfb) { + int const a = (gain - vbrsfmin[sfb]) - 2 * pretab[sfb]; + if (a <= 0) { + vm0p = 0; + vm1p = 0; + break; + } + } + } + if (vm1p == 1) { + int gain = vbrmax - maxover1p; + if (gain < maxminsfb) { + gain = maxminsfb; + } + for (sfb = 0; sfb < psymax; ++sfb) { + int const b = (gain - vbrsfmin[sfb]) - 4 * pretab[sfb]; + if (b <= 0) { + vm1p = 0; + break; + } + } + } + if (vm0p == 0) { + maxover0p = maxover0; + } + if (vm1p == 0) { + maxover1p = maxover1; + } + if (cfg->noise_shaping != 2) { + maxover1 = maxover0; + maxover1p = maxover0p; + } + mover = Min(maxover0, maxover0p); + mover = Min(mover, maxover1); + mover = Min(mover, maxover1p); + + if (delta > mover) { + delta = mover; + } + vbrmax -= delta; + if (vbrmax < maxminsfb) { + vbrmax = maxminsfb; + } + maxover0 -= mover; + maxover0p -= mover; + maxover1 -= mover; + maxover1p -= mover; + + if (maxover0 == 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 0; + max_rangep = max_range_long; + } + else if (maxover0p == 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 1; + } + else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 0; + max_rangep = max_range_long; + } + else if (maxover1p == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 1; + } + else { + assert(0); /* this should not happen */ + } + cod_info->global_gain = vbrmax; + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + { + int sf_temp[SFBMAX]; + for (sfb = 0; sfb < SFBMAX; ++sfb) { + sf_temp[sfb] = vbrsf[sfb] - vbrmax; + } + set_scalefacs(cod_info, vbrsfmin, sf_temp, max_rangep); + } + assert(checkScalefactor(cod_info, vbrsfmin)); +} + + + +static void +bitcount(const algo_t * that) +{ + int rc = scale_bitcount(that->gfc, that->cod_info); + + if (rc == 0) { + return; + } + /* this should not happen due to the way the scalefactors are selected */ + ERRORF(that->gfc, "INTERNAL ERROR IN VBR NEW CODE (986), please send bug report\n"); + exit(-1); +} + + + +static int +quantizeAndCountBits(const algo_t * that) +{ + quantize_x34(that); + that->cod_info->part2_3_length = noquant_count_bits(that->gfc, that->cod_info, 0); + return that->cod_info->part2_3_length; +} + + + + + +static int +tryGlobalStepsize(const algo_t * that, const int sfwork[SFBMAX], + const int vbrsfmin[SFBMAX], int delta) +{ + FLOAT const xrpow_max = that->cod_info->xrpow_max; + int sftemp[SFBMAX], i, nbits; + int gain, vbrmax = 0; + for (i = 0; i < SFBMAX; ++i) { + gain = sfwork[i] + delta; + if (gain < vbrsfmin[i]) { + gain = vbrsfmin[i]; + } + if (gain > 255) { + gain = 255; + } + if (vbrmax < gain) { + vbrmax = gain; + } + sftemp[i] = gain; + } + that->alloc(that, sftemp, vbrsfmin, vbrmax); + bitcount(that); + nbits = quantizeAndCountBits(that); + that->cod_info->xrpow_max = xrpow_max; + return nbits; +} + + + +static void +searchGlobalStepsizeMax(const algo_t * that, const int sfwork[SFBMAX], + const int vbrsfmin[SFBMAX], int target) +{ + gr_info const *const cod_info = that->cod_info; + const int gain = cod_info->global_gain; + int curr = gain; + int gain_ok = 1024; + int nbits = LARGE_BITS; + int l = gain, r = 512; + + assert(gain >= 0); + while (l <= r) { + curr = (l + r) >> 1; + nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); + if (nbits == 0 || (nbits + cod_info->part2_length) < target) { + r = curr - 1; + gain_ok = curr; + } + else { + l = curr + 1; + if (gain_ok == 1024) { + gain_ok = curr; + } + } + } + if (gain_ok != curr) { + curr = gain_ok; + nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); + } +} + + + +static int +sfDepth(const int sfwork[SFBMAX]) +{ + int m = 0; + unsigned int i, j; + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const di = 255 - sfwork[i]; + if (m < di) { + m = di; + } + assert(sfwork[i] >= 0); + assert(sfwork[i] <= 255); + } + assert(m >= 0); + assert(m <= 255); + return m; +} + + +static void +cutDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int cut) +{ + unsigned int i, j; + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const x = sfwork[i]; + sf_out[i] = x < cut ? x : cut; + } +} + + +static int +flattenDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int dm, int k, int p) +{ + unsigned int i, j; + int x, sfmax = 0; + if (dm > 0) { + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const di = p - sfwork[i]; + x = sfwork[i] + (k * di) / dm; + if (x < 0) { + x = 0; + } + else { + if (x > 255) { + x = 255; + } + } + sf_out[i] = x; + if (sfmax < x) { + sfmax = x; + } + } + } + else { + for (j = SFBMAX, i = 0; j > 0u; --j, ++i) { + x = sfwork[i]; + sf_out[i] = x; + if (sfmax < x) { + sfmax = x; + } + } + } + return sfmax; +} + + +static int +tryThatOne(algo_t const* that, const int sftemp[SFBMAX], const int vbrsfmin[SFBMAX], int vbrmax) +{ + FLOAT const xrpow_max = that->cod_info->xrpow_max; + int nbits = LARGE_BITS; + that->alloc(that, sftemp, vbrsfmin, vbrmax); + bitcount(that); + nbits = quantizeAndCountBits(that); + nbits += that->cod_info->part2_length; + that->cod_info->xrpow_max = xrpow_max; + return nbits; +} + + +static void +outOfBitsStrategy(algo_t const* that, const int sfwork[SFBMAX], const int vbrsfmin[SFBMAX], int target) +{ + int wrk[SFBMAX]; + int const dm = sfDepth(sfwork); + int const p = that->cod_info->global_gain; + int nbits; + + /* PART 1 */ + { + int bi = dm / 2; + int bi_ok = -1; + int bu = 0; + int bo = dm; + for (;;) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, bi, p); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + if (nbits <= target) { + bi_ok = bi; + bo = bi - 1; + } + else { + bu = bi + 1; + } + if (bu <= bo) { + bi = (bu + bo) / 2; + } + else { + break; + } + } + if (bi_ok >= 0) { + if (bi != bi_ok) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, bi_ok, p); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + } + return; + } + } + + /* PART 2: */ + { + int bi = (255 + p) / 2; + int bi_ok = -1; + int bu = p; + int bo = 255; + for (;;) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + if (nbits <= target) { + bi_ok = bi; + bo = bi - 1; + } + else { + bu = bi + 1; + } + if (bu <= bo) { + bi = (bu + bo) / 2; + } + else { + break; + } + } + if (bi_ok >= 0) { + if (bi != bi_ok) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi_ok); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + } + return; + } + } + + /* fall back to old code, likely to be never called */ + searchGlobalStepsizeMax(that, wrk, vbrsfmin, target); +} + + +static int +reduce_bit_usage(lame_internal_flags * gfc, int gr, int ch +#if 0 + , const FLOAT xr34orig[576], const FLOAT l3_xmin[SFBMAX], int maxbits +#endif + ) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + /* try some better scalefac storage + */ + best_scalefac_store(gfc, gr, ch, &gfc->l3_side); + + /* best huffman_divide may save some bits too + */ + if (cfg->use_best_huffman == 1) + best_huffman_divide(gfc, cod_info); + return cod_info->part2_3_length + cod_info->part2_length; +} + + + + +int +VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576], + const FLOAT l3_xmin[2][2][SFBMAX], const int max_bits[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfwork_[2][2][SFBMAX]; + int vbrsfmin_[2][2][SFBMAX]; + algo_t that_[2][2]; + int const ngr = cfg->mode_gr; + int const nch = cfg->channels_out; + int max_nbits_ch[2][2] = {{0, 0}, {0 ,0}}; + int max_nbits_gr[2] = {0, 0}; + int max_nbits_fr = 0; + int use_nbits_ch[2][2] = {{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1} + ,{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1}}; + int use_nbits_gr[2] = { MAX_BITS_PER_GRANULE+1, MAX_BITS_PER_GRANULE+1 }; + int use_nbits_fr = MAX_BITS_PER_GRANULE+MAX_BITS_PER_GRANULE; + int gr, ch; + int ok, sum_fr; + + /* set up some encoding parameters + */ + for (gr = 0; gr < ngr; ++gr) { + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + max_nbits_ch[gr][ch] = max_bits[gr][ch]; + use_nbits_ch[gr][ch] = 0; + max_nbits_gr[gr] += max_bits[gr][ch]; + max_nbits_fr += max_bits[gr][ch]; + that_[gr][ch].find = (cfg->full_outer_loop < 0) ? guess_scalefac_x34 : find_scalefac_x34; + that_[gr][ch].gfc = gfc; + that_[gr][ch].cod_info = &gfc->l3_side.tt[gr][ch]; + that_[gr][ch].xr34orig = xr34orig[gr][ch]; + if (that_[gr][ch].cod_info->block_type == SHORT_TYPE) { + that_[gr][ch].alloc = short_block_constrain; + } + else { + that_[gr][ch].alloc = long_block_constrain; + } + } /* for ch */ + } + /* searches scalefactors + */ + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + if (max_bits[gr][ch] > 0) { + algo_t *that = &that_[gr][ch]; + int *sfwork = sfwork_[gr][ch]; + int *vbrsfmin = vbrsfmin_[gr][ch]; + int vbrmax; + + vbrmax = block_sf(that, l3_xmin[gr][ch], sfwork, vbrsfmin); + that->alloc(that, sfwork, vbrsfmin, vbrmax); + bitcount(that); + } + else { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + * continue with next channel + */ + } + } /* for ch */ + } + /* encode 'as is' + */ + use_nbits_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + use_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + algo_t const *that = &that_[gr][ch]; + if (max_bits[gr][ch] > 0) { + memset(&that->cod_info->l3_enc[0], 0, sizeof(that->cod_info->l3_enc)); + (void) quantizeAndCountBits(that); + } + else { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + * continue with next channel + */ + } + use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); + use_nbits_gr[gr] += use_nbits_ch[gr][ch]; + } /* for ch */ + use_nbits_fr += use_nbits_gr[gr]; + } + + /* check bit constrains + */ + if (use_nbits_fr <= max_nbits_fr) { + ok = 1; + for (gr = 0; gr < ngr; ++gr) { + if (use_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + /* violates the rule that every granule has to use no more + * bits than MAX_BITS_PER_GRANULE + */ + ok = 0; + } + for (ch = 0; ch < nch; ++ch) { + if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + /* violates the rule that every gr_ch has to use no more + * bits than MAX_BITS_PER_CHANNEL + * + * This isn't explicitly stated in the ISO docs, but the + * part2_3_length field has only 12 bits, that makes it + * up to a maximum size of 4095 bits!!! + */ + ok = 0; + } + } + } + if (ok) { + return use_nbits_fr; + } + } + + /* OK, we are in trouble and have to define how many bits are + * to be used for each granule + */ + { + ok = 1; + sum_fr = 0; + + for (gr = 0; gr < ngr; ++gr) { + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL; + } + else { + max_nbits_ch[gr][ch] = use_nbits_ch[gr][ch]; + } + max_nbits_gr[gr] += max_nbits_ch[gr][ch]; + } + if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > 0) { + f[ch] = sqrt(sqrt(max_nbits_ch[gr][ch])); + s += f[ch]; + } + else { + f[ch] = 0; + } + } + for (ch = 0; ch < nch; ++ch) { + if (s > 0) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_GRANULE * f[ch] / s; + } + else { + max_nbits_ch[gr][ch] = 0; + } + } + if (nch > 1) { + if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { + max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; + max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; + max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; + } + if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { + max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; + max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; + max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; + } + if (max_nbits_ch[gr][0] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][0] = MAX_BITS_PER_CHANNEL; + } + if (max_nbits_ch[gr][1] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][1] = MAX_BITS_PER_CHANNEL; + } + } + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + max_nbits_gr[gr] += max_nbits_ch[gr][ch]; + } + } + sum_fr += max_nbits_gr[gr]; + } + if (sum_fr > max_nbits_fr) { + { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (gr = 0; gr < ngr; ++gr) { + if (max_nbits_gr[gr] > 0) { + f[gr] = sqrt(max_nbits_gr[gr]); + s += f[gr]; + } + else { + f[gr] = 0; + } + } + for (gr = 0; gr < ngr; ++gr) { + if (s > 0) { + max_nbits_gr[gr] = max_nbits_fr * f[gr] / s; + } + else { + max_nbits_gr[gr] = 0; + } + } + } + if (ngr > 1) { + if (max_nbits_gr[0] > use_nbits_gr[0] + 125) { + max_nbits_gr[1] += max_nbits_gr[0]; + max_nbits_gr[1] -= use_nbits_gr[0] + 125; + max_nbits_gr[0] = use_nbits_gr[0] + 125; + } + if (max_nbits_gr[1] > use_nbits_gr[1] + 125) { + max_nbits_gr[0] += max_nbits_gr[1]; + max_nbits_gr[0] -= use_nbits_gr[1] + 125; + max_nbits_gr[1] = use_nbits_gr[1] + 125; + } + for (gr = 0; gr < ngr; ++gr) { + if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + max_nbits_gr[gr] = MAX_BITS_PER_GRANULE; + } + } + } + for (gr = 0; gr < ngr; ++gr) { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > 0) { + f[ch] = sqrt(max_nbits_ch[gr][ch]); + s += f[ch]; + } + else { + f[ch] = 0; + } + } + for (ch = 0; ch < nch; ++ch) { + if (s > 0) { + max_nbits_ch[gr][ch] = max_nbits_gr[gr] * f[ch] / s; + } + else { + max_nbits_ch[gr][ch] = 0; + } + } + if (nch > 1) { + if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { + max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; + max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; + max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; + } + if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { + max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; + max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; + max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; + } + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL; + } + } + } + } + } + /* sanity check */ + sum_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + int sum_gr = 0; + for (ch = 0; ch < nch; ++ch) { + sum_gr += max_nbits_ch[gr][ch]; + if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + ok = 0; + } + } + sum_fr += sum_gr; + if (sum_gr > MAX_BITS_PER_GRANULE) { + ok = 0; + } + } + if (sum_fr > max_nbits_fr) { + ok = 0; + } + if (!ok) { + /* we must have done something wrong, fallback to 'on_pe' based constrain */ + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + max_nbits_ch[gr][ch] = max_bits[gr][ch]; + } + } + } + } + + /* we already called the 'best_scalefac_store' function, so we need to reset some + * variables before we can do it again. + */ + for (ch = 0; ch < nch; ++ch) { + gfc->l3_side.scfsi[ch][0] = 0; + gfc->l3_side.scfsi[ch][1] = 0; + gfc->l3_side.scfsi[ch][2] = 0; + gfc->l3_side.scfsi[ch][3] = 0; + } + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + gfc->l3_side.tt[gr][ch].scalefac_compress = 0; + } + } + + /* alter our encoded data, until it fits into the target bitrate + */ + use_nbits_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + use_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + algo_t const *that = &that_[gr][ch]; + use_nbits_ch[gr][ch] = 0; + if (max_bits[gr][ch] > 0) { + int *sfwork = sfwork_[gr][ch]; + int const *vbrsfmin = vbrsfmin_[gr][ch]; + cutDistribution(sfwork, sfwork, that->cod_info->global_gain); + outOfBitsStrategy(that, sfwork, vbrsfmin, max_nbits_ch[gr][ch]); + } + use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); + assert(use_nbits_ch[gr][ch] <= max_nbits_ch[gr][ch]); + use_nbits_gr[gr] += use_nbits_ch[gr][ch]; + } /* for ch */ + use_nbits_fr += use_nbits_gr[gr]; + } + + /* check bit constrains, but it should always be ok, iff there are no bugs ;-) + */ + if (use_nbits_fr <= max_nbits_fr) { + return use_nbits_fr; + } + + ERRORF(gfc, "INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report\n" + "maxbits=%d usedbits=%d\n", max_nbits_fr, use_nbits_fr); + exit(-1); +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.h new file mode 100644 index 00000000..1c0d18f0 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vbrquantize.h @@ -0,0 +1,28 @@ +/* + * MP3 VBR quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_VBRQUANTIZE_H +#define LAME_VBRQUANTIZE_H + +int VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576], + const FLOAT l3_xmin[2][2][SFBMAX], const int maxbits[2][2]); + +#endif /* LAME_VBRQUANTIZE_H */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/lame_intrin.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/lame_intrin.h new file mode 100644 index 00000000..bc4c1899 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/lame_intrin.h @@ -0,0 +1,33 @@ +/* + * lame_intrin.h include file + * + * Copyright (c) 2006 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifndef LAME_INTRIN_H +#define LAME_INTRIN_H + + +void +init_xrpow_core_sse(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum); + +void +fht_SSE2(FLOAT* , int); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/xmm_quantize_sub.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/xmm_quantize_sub.c new file mode 100644 index 00000000..d68f7618 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/vector/xmm_quantize_sub.c @@ -0,0 +1,240 @@ +/* + * MP3 quantization, intrinsics functions + * + * Copyright (c) 2005-2006 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "lame_intrin.h" + + + +#ifdef HAVE_XMMINTRIN_H + +#include <xmmintrin.h> + +typedef union { + int32_t _i_32[4]; /* unions are initialized by its first member */ + float _float[4]; + __m128 _m128; +} vecfloat_union; + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ +static const FLOAT costab[TRI_SIZE * 2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + + +/* make sure functions with SSE instructions maintain their own properly aligned stack */ +#if defined (__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))) +#define SSE_FUNCTION __attribute__((force_align_arg_pointer)) +#else +#define SSE_FUNCTION +#endif + + +SSE_FUNCTION void +init_xrpow_core_sse(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum) +{ + int i; + float tmp_max = 0; + float tmp_sum = 0; + int upper4 = (upper / 4) * 4; + int rest = upper-upper4; + + const vecfloat_union fabs_mask = {{ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }}; + const __m128 vec_fabs_mask = _mm_loadu_ps(&fabs_mask._float[0]); + vecfloat_union vec_xrpow_max; + vecfloat_union vec_sum; + vecfloat_union vec_tmp; + + _mm_prefetch((char *) cod_info->xr, _MM_HINT_T0); + _mm_prefetch((char *) xrpow, _MM_HINT_T0); + + vec_xrpow_max._m128 = _mm_set_ps1(0); + vec_sum._m128 = _mm_set_ps1(0); + + for (i = 0; i < upper4; i += 4) { + vec_tmp._m128 = _mm_loadu_ps(&(cod_info->xr[i])); /* load */ + vec_tmp._m128 = _mm_and_ps(vec_tmp._m128, vec_fabs_mask); /* fabs */ + vec_sum._m128 = _mm_add_ps(vec_sum._m128, vec_tmp._m128); + vec_tmp._m128 = _mm_sqrt_ps(_mm_mul_ps(vec_tmp._m128, _mm_sqrt_ps(vec_tmp._m128))); + vec_xrpow_max._m128 = _mm_max_ps(vec_xrpow_max._m128, vec_tmp._m128); /* retrieve max */ + _mm_storeu_ps(&(xrpow[i]), vec_tmp._m128); /* store into xrpow[] */ + } + vec_tmp._m128 = _mm_set_ps1(0); + switch (rest) { + case 3: vec_tmp._float[2] = cod_info->xr[upper4+2]; + case 2: vec_tmp._float[1] = cod_info->xr[upper4+1]; + case 1: vec_tmp._float[0] = cod_info->xr[upper4+0]; + vec_tmp._m128 = _mm_and_ps(vec_tmp._m128, vec_fabs_mask); /* fabs */ + vec_sum._m128 = _mm_add_ps(vec_sum._m128, vec_tmp._m128); + vec_tmp._m128 = _mm_sqrt_ps(_mm_mul_ps(vec_tmp._m128, _mm_sqrt_ps(vec_tmp._m128))); + vec_xrpow_max._m128 = _mm_max_ps(vec_xrpow_max._m128, vec_tmp._m128); /* retrieve max */ + switch (rest) { + case 3: xrpow[upper4+2] = vec_tmp._float[2]; + case 2: xrpow[upper4+1] = vec_tmp._float[1]; + case 1: xrpow[upper4+0] = vec_tmp._float[0]; + default: + break; + } + default: + break; + } + tmp_sum = vec_sum._float[0] + vec_sum._float[1] + vec_sum._float[2] + vec_sum._float[3]; + { + float ma = vec_xrpow_max._float[0] > vec_xrpow_max._float[1] + ? vec_xrpow_max._float[0] : vec_xrpow_max._float[1]; + float mb = vec_xrpow_max._float[2] > vec_xrpow_max._float[3] + ? vec_xrpow_max._float[2] : vec_xrpow_max._float[3]; + tmp_max = ma > mb ? ma : mb; + } + cod_info->xrpow_max = tmp_max; + *sum = tmp_sum; +} + + +SSE_FUNCTION static void +store4(__m128 v, float* f0, float* f1, float* f2, float* f3) +{ + vecfloat_union r; + r._m128 = v; + *f0 = r._float[0]; + *f1 = r._float[1]; + *f2 = r._float[2]; + *f3 = r._float[3]; +} + + +SSE_FUNCTION void +fht_SSE2(FLOAT * fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *gi; + FLOAT const *fn; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0, f1, f2, f3; + 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; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fi < fn); + c1 = tri[0]; + s1 = tri[1]; + for (i = 1; i < kx; i++) { + __m128 v_s2; + __m128 v_c2; + __m128 v_c1; + __m128 v_s1; + FLOAT c2, s2, s1_2 = s1+s1; + c2 = 1 - s1_2 * s1; + s2 = s1_2 * c1; + fi = fz + i; + gi = fz + k1 - i; + v_c1 = _mm_set_ps1(c1); + v_s1 = _mm_set_ps1(s1); + v_c2 = _mm_set_ps1(c2); + v_s2 = _mm_set_ps1(s2); + { + static const vecfloat_union sign_mask = {{0x80000000,0,0,0}}; + v_c1 = _mm_xor_ps(sign_mask._m128, v_c1); /* v_c1 := {-c1, +c1, +c1, +c1} */ + } + { + static const vecfloat_union sign_mask = {{0,0x80000000,0,0}}; + v_s1 = _mm_xor_ps(sign_mask._m128, v_s1); /* v_s1 := {+s1, -s1, +s1, +s1} */ + } + { + static const vecfloat_union sign_mask = {{0,0,0x80000000,0x80000000}}; + v_c2 = _mm_xor_ps(sign_mask._m128, v_c2); /* v_c2 := {+c2, +c2, -c2, -c2} */ + } + do { + __m128 p, q, r; + + q = _mm_setr_ps(fi[k1], fi[k3], gi[k1], gi[k3]); /* Q := {fi_k1,fi_k3,gi_k1,gi_k3}*/ + p = _mm_mul_ps(_mm_set_ps1(s2), q); /* P := s2 * Q */ + q = _mm_mul_ps(v_c2, q); /* Q := c2 * Q */ + q = _mm_shuffle_ps(q, q, _MM_SHUFFLE(1,0,3,2)); /* Q := {-c2*gi_k1,-c2*gi_k3,c2*fi_k1,c2*fi_k3} */ + p = _mm_add_ps(p, q); + + r = _mm_setr_ps(gi[0], gi[k2], fi[0], fi[k2]); /* R := {gi_0,gi_k2,fi_0,fi_k2} */ + q = _mm_sub_ps(r, p); /* Q := {gi_0-p0,gi_k2-p1,fi_0-p2,fi_k2-p3} */ + r = _mm_add_ps(r, p); /* R := {gi_0+p0,gi_k2+p1,fi_0+p2,fi_k2+p3} */ + p = _mm_shuffle_ps(q, r, _MM_SHUFFLE(2,0,2,0)); /* P := {q0,q2,r0,r2} */ + p = _mm_shuffle_ps(p, p, _MM_SHUFFLE(3,1,2,0)); /* P := {q0,r0,q2,r2} */ + q = _mm_shuffle_ps(q, r, _MM_SHUFFLE(3,1,3,1)); /* Q := {q1,q3,r1,r3} */ + r = _mm_mul_ps(v_c1, q); + q = _mm_mul_ps(v_s1, q); + q = _mm_shuffle_ps(q, q, _MM_SHUFFLE(0,1,2,3)); /* Q := {q3,q2,q1,q0} */ + q = _mm_add_ps(q, r); + + store4(_mm_sub_ps(p, q), &gi[k3], &gi[k2], &fi[k3], &fi[k2]); + store4(_mm_add_ps(p, q), &gi[k1], &gi[ 0], &fi[k1], &fi[ 0]); + + gi += k4; + fi += k4; + } while (fi < fn); + c2 = c1; + c1 = c2 * tri[0] - s1 * tri[1]; + s1 = c2 * tri[1] + s1 * tri[0]; + } + tri += 2; + } while (k4 < n); +} + +#endif /* HAVE_XMMINTRIN_H */ + diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.c b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.c new file mode 100644 index 00000000..29434062 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.c @@ -0,0 +1,254 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +/*! + \file version.c + \brief Version numbering for LAME. + + Contains functions which describe the version of LAME. + + \author A.L. Faber + \version \$Id: version.c,v 1.34 2011/11/18 09:51:02 robert Exp $ + \ingroup libmp3lame +*/ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" + +#include "version.h" /* macros of version numbers */ + + + + + +/*! Get the LAME version string. */ +/*! + \param void + \return a pointer to a string which describes the version of LAME. +*/ +const char * +get_lame_version(void) +{ /* primary to write screen reports */ + /* Here we can also add informations about compile time configurations */ + +#if LAME_ALPHA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " " + "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif LAME_BETA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " " + "(beta " STR(LAME_PATCH_VERSION) ", " __DATE__ ")"; +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION); +#else + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION); +#endif + + return str; +} + + +/*! Get the short LAME version string. */ +/*! + It's mainly for inclusion into the MP3 stream. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char * +get_lame_short_version(void) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (alpha " STR(LAME_PATCH_VERSION) ")"; +#elif LAME_BETA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (beta " STR(LAME_PATCH_VERSION) ")"; +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION); +#else + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION); +#endif + + return str; +} + +/*! Get the _very_ short LAME version string. */ +/*! + It's used in the LAME VBR tag only. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char * +get_lame_very_short_version(void) +{ + /* adding date and time to version string makes it harder for output + validation */ +#if LAME_ALPHA_VERSION +#define P "a" +#elif LAME_BETA_VERSION +#define P "b" +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) +#define P "r" +#else +#define P " " +#endif + static /*@observer@ */ const char *const str = +#if (LAME_PATCH_VERSION > 0) + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P STR(LAME_PATCH_VERSION) +#else + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P +#endif + ; + return str; +} + +/*! Get the _very_ short LAME version string. */ +/*! + It's used in the LAME VBR tag only, limited to 9 characters max. + Due to some 3rd party HW/SW decoders, it has to start with LAME. + + \param void + \return a pointer to the short version of the LAME version string. + */ +const char* +get_lame_tag_encoder_short_version(void) +{ + static /*@observer@ */ const char *const str = + /* FIXME: new scheme / new version counting / drop versioning here ? */ + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P + ; + return str; +} + +/*! Get the version string for GPSYCHO. */ +/*! + \param void + \return a pointer to a string which describes the version of GPSYCHO. +*/ +const char * +get_psy_version(void) +{ +#if PSY_ALPHA_VERSION > 0 + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION) + " (alpha " STR(PSY_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif PSY_BETA_VERSION > 0 + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION) + " (beta " STR(PSY_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION); +#endif + + return str; +} + + +/*! Get the URL for the LAME website. */ +/*! + \param void + \return a pointer to a string which is a URL for the LAME website. +*/ +const char * +get_lame_url(void) +{ + static /*@observer@ */ const char *const str = LAME_URL; + + return str; +} + + +/*! Get the numerical representation of the version. */ +/*! + Writes the numerical representation of the version of LAME and + GPSYCHO into lvp. + + \param lvp +*/ +void +get_lame_version_numerical(lame_version_t * lvp) +{ + static /*@observer@ */ const char *const features = ""; /* obsolete */ + + /* generic version */ + lvp->major = LAME_MAJOR_VERSION; + lvp->minor = LAME_MINOR_VERSION; +#if LAME_ALPHA_VERSION + lvp->alpha = LAME_PATCH_VERSION; + lvp->beta = 0; +#elif LAME_BETA_VERSION + lvp->alpha = 0; + lvp->beta = LAME_PATCH_VERSION; +#else + lvp->alpha = 0; + lvp->beta = 0; +#endif + + /* psy version */ + lvp->psy_major = PSY_MAJOR_VERSION; + lvp->psy_minor = PSY_MINOR_VERSION; + lvp->psy_alpha = PSY_ALPHA_VERSION; + lvp->psy_beta = PSY_BETA_VERSION; + + /* compile time features */ + /*@-mustfree@ */ + lvp->features = features; + /*@=mustfree@ */ +} + + +const char * +get_lame_os_bitness(void) +{ + static /*@observer@ */ const char *const strXX = ""; + static /*@observer@ */ const char *const str32 = "32bits"; + static /*@observer@ */ const char *const str64 = "64bits"; + + switch (sizeof(void *)) { + case 4: + return str32; + + case 8: + return str64; + + default: + return strXX; + } +} + +/* end of version.c */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.h b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.h new file mode 100644 index 00000000..f5fef508 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/libmp3lame/version.h @@ -0,0 +1,68 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAME_VERSION_H +#define LAME_VERSION_H + + +/* + * To make a string from a token, use the # operator: + */ +#ifndef STR +# define __STR(x) #x +# define STR(x) __STR(x) +#endif + +# define LAME_URL "http://lame.sf.net" + + +# define LAME_MAJOR_VERSION 3 /* Major version number */ +# define LAME_MINOR_VERSION 100 /* Minor version number */ +# define LAME_TYPE_VERSION 2 /* 0:alpha 1:beta 2:release */ +# define LAME_PATCH_VERSION 0 /* Patch level */ +# define LAME_ALPHA_VERSION (LAME_TYPE_VERSION==0) +# define LAME_BETA_VERSION (LAME_TYPE_VERSION==1) +# define LAME_RELEASE_VERSION (LAME_TYPE_VERSION==2) + +# define PSY_MAJOR_VERSION 1 /* Major version number */ +# define PSY_MINOR_VERSION 0 /* Minor version number */ +# define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */ +# define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */ + +#if LAME_ALPHA_VERSION +#define LAME_PATCH_LEVEL_STRING " alpha " STR(LAME_PATCH_VERSION) +#endif +#if LAME_BETA_VERSION +#define LAME_PATCH_LEVEL_STRING " beta " STR(LAME_PATCH_VERSION) +#endif +#if LAME_RELEASE_VERSION +#if LAME_PATCH_VERSION +#define LAME_PATCH_LEVEL_STRING " release " STR(LAME_PATCH_VERSION) +#else +#define LAME_PATCH_LEVEL_STRING "" +#endif +#endif + +# define LAME_VERSION_STRING STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) LAME_PATCH_LEVEL_STRING + +#endif /* LAME_VERSION_H */ + +/* End of version.h */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/AUTHORS b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/AUTHORS new file mode 100644 index 00000000..0a6a10b0 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/AUTHORS @@ -0,0 +1,16 @@ +Michael Hipp <mh@mpg123.de> Author of orignal mpglib version 0.2a. + +Albert L. Faber <afaber@users.sf.net> +Aleksander Korzynski <olcios@users.sf.net> +Alexander Leidinger <aleidinger@users.sf.net> +Frank Klemm <pfk@users.sf.net> +Gabriel Bouvigne <bouvigne@users.sf.net> +Leigh Smith <leighsmith@users.sf.net> +Mark Taylor <markt@users.sf.net> +Myers Carpenter <myers@users.sf.net> +Naoki Shibata <shibatch@users.sf.net> +Robert Hegemann <robert@users.sf.net> +Sigbjorn Skjaeret <cisc@users.sf.net> +Stefan Bellon <sbellon@users.sf.net> +Steve Lhomme <robux4@users.sf.net> +Takehiro TOMINAGA <takehiro@users.sf.net> diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.c new file mode 100644 index 00000000..b6ba1445 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.c @@ -0,0 +1,364 @@ +/* + * common.c: some common bitstream operations + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: common.c,v 1.42 2017/08/19 14:20:27 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <signal.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef macintosh +#include <types.h> +#include <stat.h> +#else +#include <sys/types.h> +#include <sys/stat.h> +#endif + +#include <assert.h> + +#include "common.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +/* In C++ the array first must be prototyped, why ? */ + + + /* *INDENT-OFF* */ +const int tabsel_123 [2] [3] [16] = { + { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, + {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, + {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, + + { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } +}; + +const long freqs[9] = { 44100, 48000, 32000, + 22050, 24000, 16000, + 11025, 12000, 8000 }; + + /* *INDENT-ON* */ + + +real muls[27][64]; + +#if 0 +static void +get_II_stuff(struct frame *fr) +{ + /* *INDENT-OFF* */ + static const int translate [3] [2] [16] = /* char ? */ + { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } , + { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } , + { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } , + { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } , + { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } , + { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; + /* *INDENT-ON* */ + + int table, sblim; + static const struct al_table2 *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3, alloc_4 }; + static int sblims[5] = { 27, 30, 8, 12, 30 }; + + if (fr->lsf) + table = 4; + else + table = translate[fr->sampling_frequency][2 - fr->stereo][fr->bitrate_index]; + sblim = sblims[table]; + + fr->alloc = tables[table]; + fr->II_sblimit = sblim; +} +#endif + +#define HDRCMPMASK 0xfffffd00 + +#define MAX_INPUT_FRAMESIZE 4096 + +int +head_check(unsigned long head, int check_layer) +{ + /* + look for a valid header. + if check_layer > 0, then require that + nLayer = check_layer. + */ + + /* bits 13-14 = layer 3 */ + int nLayer = 4 - ((head >> 17) & 3); + + if ((head & 0xffe00000) != 0xffe00000) { + /* syncword */ + return FALSE; + } + + if (nLayer == 4) + return FALSE; + + if (check_layer > 0 && nLayer != check_layer) + return FALSE; + + if (((head >> 12) & 0xf) == 0xf) { + /* bits 16,17,18,19 = 1111 invalid bitrate */ + return FALSE; + } + if (((head >> 10) & 0x3) == 0x3) { + /* bits 20,21 = 11 invalid sampling freq */ + return FALSE; + } + if ((head & 0x3) == 0x2) + /* invalid emphasis */ + return FALSE; + return TRUE; +} + + +#if 0 +static void +print_header(PMPSTR mp, struct frame *fr) +{ + static const char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; + static const char *layers[4] = { "Unknown", "I", "II", "III" }; + + lame_report_fnc(mp->report_msg, "MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay], freqs[fr->sampling_frequency], + modes[fr->mode], fr->mode_ext, fr->framesize + 4); + lame_report_fnc(mp->report_msg, "Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", + fr->stereo, fr->copyright ? "Yes" : "No", + fr->original ? "Yes" : "No", fr->error_protection ? "Yes" : "No", fr->emphasis); + lame_report_fnc(mp->report_msg, "Bitrate: %d Kbits/s, Extension value: %d\n", + tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index], fr->extension); +} + +static void +print_header_compact(PMPSTR mp, struct frame *fr) +{ + static const char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; + static const char *layers[4] = { "Unknown", "I", "II", "III" }; + + lame_report_fnc(mp->report_err, "MPEG %s layer %s, %d kbit/s, %ld Hz %s\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay], + tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index], + freqs[fr->sampling_frequency], modes[fr->mode]); +} + +#endif + +/* + * decode a header and write the information + * into the frame structure + */ +int +decode_header(PMPSTR mp, struct frame *fr, unsigned long newhead) +{ + + + if (newhead & (1 << 20)) { + fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1; + fr->mpeg25 = 0; + } + else { + fr->lsf = 1; + fr->mpeg25 = 1; + } + + + fr->lay = 4 - ((newhead >> 17) & 3); + + if (fr->lay != 3 && fr->mpeg25) { + lame_report_fnc(mp->report_err, "MPEG-2.5 is supported by Layer3 only\n"); + return 0; + } + if (((newhead >> 10) & 0x3) == 0x3) { + lame_report_fnc(mp->report_err, "Stream error\n"); + return 0; + } + if (fr->mpeg25) { + fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3); + } + else + fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3); + + fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1; + + if (fr->mpeg25) /* allow Bitrate change for 2.5 ... */ + fr->bitrate_index = ((newhead >> 12) & 0xf); + + fr->bitrate_index = ((newhead >> 12) & 0xf); + fr->padding = ((newhead >> 9) & 0x1); + fr->extension = ((newhead >> 8) & 0x1); + fr->mode = ((newhead >> 6) & 0x3); + fr->mode_ext = ((newhead >> 4) & 0x3); + fr->copyright = ((newhead >> 3) & 0x1); + fr->original = ((newhead >> 2) & 0x1); + fr->emphasis = newhead & 0x3; + + fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; + + switch (fr->lay) { + case 1: + fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize = ((fr->framesize + fr->padding) << 2) - 4; + fr->down_sample = 0; + fr->down_sample_sblimit = SBLIMIT >> (fr->down_sample); + break; + + case 2: + fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize += fr->padding - 4; + fr->down_sample = 0; + fr->down_sample_sblimit = SBLIMIT >> (fr->down_sample); + break; + + case 3: +#if 0 + fr->do_layer = do_layer3; + if (fr->lsf) + ssize = (fr->stereo == 1) ? 9 : 17; + else + ssize = (fr->stereo == 1) ? 17 : 32; +#endif + +#if 0 + if (fr->error_protection) + ssize += 2; +#endif + if (fr->framesize > MAX_INPUT_FRAMESIZE) { + lame_report_fnc(mp->report_err, "Frame size too big.\n"); + fr->framesize = MAX_INPUT_FRAMESIZE; + return (0); + } + + + if (fr->bitrate_index == 0) + fr->framesize = 0; + else { + fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency] << (fr->lsf); + fr->framesize = fr->framesize + fr->padding - 4; + } + break; + default: + lame_report_fnc(mp->report_err, "Sorry, layer %d not supported\n", fr->lay); + return (0); + } + /* print_header(mp, fr); */ + + return 1; +} + + +unsigned int +getbits(PMPSTR mp, int number_of_bits) +{ + unsigned long rval; + + if (number_of_bits <= 0 || !mp->wordpointer) + return 0; + + { + rval = mp->wordpointer[0]; + rval <<= 8; + rval |= mp->wordpointer[1]; + rval <<= 8; + rval |= mp->wordpointer[2]; + rval <<= mp->bitindex; + rval &= 0xffffff; + + mp->bitindex += number_of_bits; + + rval >>= (24 - number_of_bits); + + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + } + return rval; +} + +unsigned int +getbits_fast(PMPSTR mp, int number_of_bits) +{ + unsigned long rval; + + { + rval = mp->wordpointer[0]; + rval <<= 8; + rval |= mp->wordpointer[1]; + rval <<= mp->bitindex; + rval &= 0xffff; + mp->bitindex += number_of_bits; + + rval >>= (16 - number_of_bits); + + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + } + return rval; +} + +unsigned char +get_leq_8_bits(PMPSTR mp, unsigned int number_of_bits) +{ + assert(number_of_bits <= 8); + return (unsigned char) getbits_fast(mp, number_of_bits); +} + +unsigned short +get_leq_16_bits(PMPSTR mp, unsigned int number_of_bits) +{ + assert(number_of_bits <= 16); + return (unsigned short) getbits_fast(mp, number_of_bits); +} + +int +set_pointer(PMPSTR mp, long backstep) +{ + unsigned char *bsbufold; + + if (mp->fsizeold < 0 && backstep > 0) { + lame_report_fnc(mp->report_err, "hip: Can't step back %ld bytes!\n", backstep); + return MP3_ERR; + } + bsbufold = mp->bsspace[1 - mp->bsnum] + 512; + mp->wordpointer -= backstep; + if (backstep) + memcpy(mp->wordpointer, bsbufold + mp->fsizeold - backstep, (size_t) backstep); + mp->bitindex = 0; + return MP3_OK; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.h new file mode 100644 index 00000000..62cf17e5 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/common.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifndef COMMON_H_INCLUDED +#define COMMON_H_INCLUDED + +#include "mpg123.h" +#include "mpglib.h" + +extern const int tabsel_123[2][3][16]; +extern const long freqs[9]; + +extern real muls[27][64]; + + +int head_check(unsigned long head, int check_layer); +int decode_header(PMPSTR mp, struct frame *fr, unsigned long newhead); +unsigned int getbits(PMPSTR mp, int number_of_bits); +unsigned int getbits_fast(PMPSTR mp, int number_of_bits); +unsigned char get_leq_8_bits(PMPSTR mp, unsigned int number_of_bits); +unsigned short get_leq_16_bits(PMPSTR mp, unsigned int number_of_bits); +int set_pointer(PMPSTR mp, long backstep); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.c new file mode 100644 index 00000000..0bf1509e --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.c @@ -0,0 +1,348 @@ +/* + * dct64_i368.c + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * + * Discrete Cosine Tansform (DCT) for subband synthesis + * optimized for machines with no auto-increment. + * The performance is highly compiler dependend. Maybe + * the dct64.c version for 'normal' processor may be faster + * even for Intel processors. + */ + +/* $Id: dct64_i386.c,v 1.14 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "dct64_i386.h" +#include "tabinit.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +static void +dct64_1(real * out0, real * out1, real * b1, real * b2, real * samples) +{ + + { + real *costab = pnts[0]; + + b1[0x00] = samples[0x00] + samples[0x1F]; + b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; + + b1[0x01] = samples[0x01] + samples[0x1E]; + b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; + + b1[0x02] = samples[0x02] + samples[0x1D]; + b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; + + b1[0x03] = samples[0x03] + samples[0x1C]; + b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; + + b1[0x04] = samples[0x04] + samples[0x1B]; + b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; + + b1[0x05] = samples[0x05] + samples[0x1A]; + b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; + + b1[0x06] = samples[0x06] + samples[0x19]; + b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; + + b1[0x07] = samples[0x07] + samples[0x18]; + b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; + + b1[0x08] = samples[0x08] + samples[0x17]; + b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; + + b1[0x09] = samples[0x09] + samples[0x16]; + b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; + + b1[0x0A] = samples[0x0A] + samples[0x15]; + b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; + + b1[0x0B] = samples[0x0B] + samples[0x14]; + b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; + + b1[0x0C] = samples[0x0C] + samples[0x13]; + b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; + + b1[0x0D] = samples[0x0D] + samples[0x12]; + b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; + + b1[0x0E] = samples[0x0E] + samples[0x11]; + b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; + + b1[0x0F] = samples[0x0F] + samples[0x10]; + b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; + } + + + { + real *costab = pnts[1]; + + b2[0x00] = b1[0x00] + b1[0x0F]; + b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; + b2[0x01] = b1[0x01] + b1[0x0E]; + b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; + b2[0x02] = b1[0x02] + b1[0x0D]; + b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; + b2[0x03] = b1[0x03] + b1[0x0C]; + b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; + b2[0x04] = b1[0x04] + b1[0x0B]; + b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; + b2[0x05] = b1[0x05] + b1[0x0A]; + b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; + b2[0x06] = b1[0x06] + b1[0x09]; + b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; + b2[0x07] = b1[0x07] + b1[0x08]; + b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; + + b2[0x10] = b1[0x10] + b1[0x1F]; + b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; + b2[0x11] = b1[0x11] + b1[0x1E]; + b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; + b2[0x12] = b1[0x12] + b1[0x1D]; + b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; + b2[0x13] = b1[0x13] + b1[0x1C]; + b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; + b2[0x14] = b1[0x14] + b1[0x1B]; + b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; + b2[0x15] = b1[0x15] + b1[0x1A]; + b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; + b2[0x16] = b1[0x16] + b1[0x19]; + b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; + b2[0x17] = b1[0x17] + b1[0x18]; + b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; + } + + { + real *costab = pnts[2]; + + b1[0x00] = b2[0x00] + b2[0x07]; + b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; + b1[0x01] = b2[0x01] + b2[0x06]; + b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; + b1[0x02] = b2[0x02] + b2[0x05]; + b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; + b1[0x03] = b2[0x03] + b2[0x04]; + b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; + + b1[0x08] = b2[0x08] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; + b1[0x09] = b2[0x09] + b2[0x0E]; + b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; + b1[0x0A] = b2[0x0A] + b2[0x0D]; + b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; + b1[0x0B] = b2[0x0B] + b2[0x0C]; + b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; + + b1[0x10] = b2[0x10] + b2[0x17]; + b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; + b1[0x11] = b2[0x11] + b2[0x16]; + b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; + b1[0x12] = b2[0x12] + b2[0x15]; + b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; + b1[0x13] = b2[0x13] + b2[0x14]; + b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; + + b1[0x18] = b2[0x18] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; + b1[0x19] = b2[0x19] + b2[0x1E]; + b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; + b1[0x1A] = b2[0x1A] + b2[0x1D]; + b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; + b1[0x1B] = b2[0x1B] + b2[0x1C]; + b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; + } + + { + real const cos0 = pnts[3][0]; + real const cos1 = pnts[3][1]; + + b2[0x00] = b1[0x00] + b1[0x03]; + b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; + b2[0x01] = b1[0x01] + b1[0x02]; + b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; + + b2[0x04] = b1[0x04] + b1[0x07]; + b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; + b2[0x05] = b1[0x05] + b1[0x06]; + b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; + + b2[0x08] = b1[0x08] + b1[0x0B]; + b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; + b2[0x09] = b1[0x09] + b1[0x0A]; + b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; + + b2[0x0C] = b1[0x0C] + b1[0x0F]; + b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; + b2[0x0D] = b1[0x0D] + b1[0x0E]; + b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; + + b2[0x10] = b1[0x10] + b1[0x13]; + b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; + b2[0x11] = b1[0x11] + b1[0x12]; + b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; + + b2[0x14] = b1[0x14] + b1[0x17]; + b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; + b2[0x15] = b1[0x15] + b1[0x16]; + b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; + + b2[0x18] = b1[0x18] + b1[0x1B]; + b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; + b2[0x19] = b1[0x19] + b1[0x1A]; + b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; + + b2[0x1C] = b1[0x1C] + b1[0x1F]; + b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; + b2[0x1D] = b1[0x1D] + b1[0x1E]; + b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; + } + + { + real const cos0 = pnts[4][0]; + + b1[0x00] = b2[0x00] + b2[0x01]; + b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; + b1[0x02] = b2[0x02] + b2[0x03]; + b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; + b1[0x02] += b1[0x03]; + + b1[0x04] = b2[0x04] + b2[0x05]; + b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; + b1[0x06] = b2[0x06] + b2[0x07]; + b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; + b1[0x06] += b1[0x07]; + b1[0x04] += b1[0x06]; + b1[0x06] += b1[0x05]; + b1[0x05] += b1[0x07]; + + b1[0x08] = b2[0x08] + b2[0x09]; + b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; + b1[0x0A] = b2[0x0A] + b2[0x0B]; + b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; + b1[0x0A] += b1[0x0B]; + + b1[0x0C] = b2[0x0C] + b2[0x0D]; + b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; + b1[0x0E] = b2[0x0E] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; + b1[0x0E] += b1[0x0F]; + b1[0x0C] += b1[0x0E]; + b1[0x0E] += b1[0x0D]; + b1[0x0D] += b1[0x0F]; + + b1[0x10] = b2[0x10] + b2[0x11]; + b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; + b1[0x12] = b2[0x12] + b2[0x13]; + b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; + b1[0x12] += b1[0x13]; + + b1[0x14] = b2[0x14] + b2[0x15]; + b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; + b1[0x16] = b2[0x16] + b2[0x17]; + b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; + b1[0x16] += b1[0x17]; + b1[0x14] += b1[0x16]; + b1[0x16] += b1[0x15]; + b1[0x15] += b1[0x17]; + + b1[0x18] = b2[0x18] + b2[0x19]; + b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; + b1[0x1A] = b2[0x1A] + b2[0x1B]; + b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; + b1[0x1A] += b1[0x1B]; + + b1[0x1C] = b2[0x1C] + b2[0x1D]; + b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; + b1[0x1E] = b2[0x1E] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; + b1[0x1E] += b1[0x1F]; + b1[0x1C] += b1[0x1E]; + b1[0x1E] += b1[0x1D]; + b1[0x1D] += b1[0x1F]; + } + + out0[0x10 * 16] = b1[0x00]; + out0[0x10 * 12] = b1[0x04]; + out0[0x10 * 8] = b1[0x02]; + out0[0x10 * 4] = b1[0x06]; + out0[0x10 * 0] = b1[0x01]; + out1[0x10 * 0] = b1[0x01]; + out1[0x10 * 4] = b1[0x05]; + out1[0x10 * 8] = b1[0x03]; + out1[0x10 * 12] = b1[0x07]; + + b1[0x08] += b1[0x0C]; + out0[0x10 * 14] = b1[0x08]; + b1[0x0C] += b1[0x0a]; + out0[0x10 * 10] = b1[0x0C]; + b1[0x0A] += b1[0x0E]; + out0[0x10 * 6] = b1[0x0A]; + b1[0x0E] += b1[0x09]; + out0[0x10 * 2] = b1[0x0E]; + b1[0x09] += b1[0x0D]; + out1[0x10 * 2] = b1[0x09]; + b1[0x0D] += b1[0x0B]; + out1[0x10 * 6] = b1[0x0D]; + b1[0x0B] += b1[0x0F]; + out1[0x10 * 10] = b1[0x0B]; + out1[0x10 * 14] = b1[0x0F]; + + b1[0x18] += b1[0x1C]; + out0[0x10 * 15] = b1[0x10] + b1[0x18]; + out0[0x10 * 13] = b1[0x18] + b1[0x14]; + b1[0x1C] += b1[0x1a]; + out0[0x10 * 11] = b1[0x14] + b1[0x1C]; + out0[0x10 * 9] = b1[0x1C] + b1[0x12]; + b1[0x1A] += b1[0x1E]; + out0[0x10 * 7] = b1[0x12] + b1[0x1A]; + out0[0x10 * 5] = b1[0x1A] + b1[0x16]; + b1[0x1E] += b1[0x19]; + out0[0x10 * 3] = b1[0x16] + b1[0x1E]; + out0[0x10 * 1] = b1[0x1E] + b1[0x11]; + b1[0x19] += b1[0x1D]; + out1[0x10 * 1] = b1[0x11] + b1[0x19]; + out1[0x10 * 3] = b1[0x19] + b1[0x15]; + b1[0x1D] += b1[0x1B]; + out1[0x10 * 5] = b1[0x15] + b1[0x1D]; + out1[0x10 * 7] = b1[0x1D] + b1[0x13]; + b1[0x1B] += b1[0x1F]; + out1[0x10 * 9] = b1[0x13] + b1[0x1B]; + out1[0x10 * 11] = b1[0x1B] + b1[0x17]; + out1[0x10 * 13] = b1[0x17] + b1[0x1F]; + out1[0x10 * 15] = b1[0x1F]; +} + +/* + * the call via dct64 is a trick to force GCC to use + * (new) registers for the b1,b2 pointer to the bufs[xx] field + */ +void +dct64(real * a, real * b, real * c) +{ + real bufs[0x40]; + dct64_1(a, b, bufs, bufs + 0x20, c); +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.h new file mode 100644 index 00000000..a140ee71 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/dct64_i386.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef MPGLIB_DCT64_I386_H_INCLUDED +#define MPGLIB_DCT64_I386_H_INCLUDED + +#include "common.h" + +void dct64(real * a, real * b, real * c); + + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.c new file mode 100644 index 00000000..8ffcab36 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.c @@ -0,0 +1,224 @@ +/* + * decode_i396.c: Mpeg Layer-1,2,3 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * + * Slighlty optimized for machines without autoincrement/decrement. + * The performance is highly compiler dependend. Maybe + * the decode.c version for 'normal' processor may be faster + * even for Intel processors. + */ + +/* $Id: decode_i386.c,v 1.22 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include <math.h> +#endif + +#include "decode_i386.h" +#include "dct64_i386.h" +#include "tabinit.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + + /* old WRITE_SAMPLE_CLIPPED */ +#define WRITE_SAMPLE_CLIPPED(TYPE,samples,sum,clip) \ + if( (sum) > 32767.0) { *(samples) = 0x7fff; (clip)++; } \ + else if( (sum) < -32768.0) { *(samples) = -0x8000; (clip)++; } \ + else { *(samples) = (TYPE)((sum)>0 ? (sum)+0.5 : (sum)-0.5) ; } + +#define WRITE_SAMPLE_UNCLIPPED(TYPE,samples,sum,clip) \ + *samples = (TYPE)sum; + + /* *INDENT-OFF* */ + + /* versions: clipped (when TYPE == short) and unclipped (when TYPE == real) of synth_1to1_mono* functions */ +#define SYNTH_1TO1_MONO_CLIPCHOICE(TYPE,SYNTH_1TO1) \ + TYPE samples_tmp[64]; \ + TYPE *tmp1 = samples_tmp; \ + int i,ret; \ + int pnt1 = 0; \ + \ + ret = SYNTH_1TO1 (mp,bandPtr,0,(unsigned char *) samples_tmp,&pnt1); \ + out += *pnt; \ + \ + for(i=0;i<32;i++) { \ + *( (TYPE *) out) = *tmp1; \ + out += sizeof(TYPE); \ + tmp1 += 2; \ + } \ + *pnt += 32*sizeof(TYPE); \ + \ + return ret; + + /* *INDENT-ON* */ + + +int +synth_1to1_mono(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_MONO_CLIPCHOICE(short, synth_1to1) +} int +synth_1to1_mono_unclipped(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_MONO_CLIPCHOICE(real, synth_1to1_unclipped) +} + + /* *INDENT-OFF* */ +/* versions: clipped (when TYPE == short) and unclipped (when TYPE == real) of synth_1to1* functions */ +#define SYNTH_1TO1_CLIPCHOICE(TYPE,WRITE_SAMPLE) \ + static const int step = 2; \ + int bo; \ + TYPE *samples = (TYPE *) (out + *pnt); \ + \ + real *b0,(*buf)[0x110]; \ + int clip = 0; \ + int bo1; \ + \ + bo = mp->synth_bo; \ + \ + if(!channel) { \ + bo--; \ + bo &= 0xf; \ + buf = mp->synth_buffs[0]; \ + } \ + else { \ + samples++; \ + buf = mp->synth_buffs[1]; \ + } \ + \ + if(bo & 0x1) { \ + b0 = buf[0]; \ + bo1 = bo; \ + dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr); \ + } \ + else { \ + b0 = buf[1]; \ + bo1 = bo+1; \ + dct64(buf[0]+bo,buf[1]+bo+1,bandPtr); \ + } \ + \ + mp->synth_bo = bo; \ + \ + { \ + int j; \ + real *window = decwin + 16 - bo1; \ + \ + for (j=16;j;j--,b0+=0x10,window+=0x20,samples+=step) \ + { \ + real sum; \ + sum = window[0x0] * b0[0x0]; \ + sum -= window[0x1] * b0[0x1]; \ + sum += window[0x2] * b0[0x2]; \ + sum -= window[0x3] * b0[0x3]; \ + sum += window[0x4] * b0[0x4]; \ + sum -= window[0x5] * b0[0x5]; \ + sum += window[0x6] * b0[0x6]; \ + sum -= window[0x7] * b0[0x7]; \ + sum += window[0x8] * b0[0x8]; \ + sum -= window[0x9] * b0[0x9]; \ + sum += window[0xA] * b0[0xA]; \ + sum -= window[0xB] * b0[0xB]; \ + sum += window[0xC] * b0[0xC]; \ + sum -= window[0xD] * b0[0xD]; \ + sum += window[0xE] * b0[0xE]; \ + sum -= window[0xF] * b0[0xF]; \ + \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + } \ + \ + { \ + real sum; \ + sum = window[0x0] * b0[0x0]; \ + sum += window[0x2] * b0[0x2]; \ + sum += window[0x4] * b0[0x4]; \ + sum += window[0x6] * b0[0x6]; \ + sum += window[0x8] * b0[0x8]; \ + sum += window[0xA] * b0[0xA]; \ + sum += window[0xC] * b0[0xC]; \ + sum += window[0xE] * b0[0xE]; \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + b0-=0x10,window-=0x20,samples+=step; \ + } \ + window += bo1<<1; \ + \ + for (j=15;j;j--,b0-=0x10,window-=0x20,samples+=step) \ + { \ + real sum; \ + sum = -window[-0x1] * b0[0x0]; \ + sum -= window[-0x2] * b0[0x1]; \ + sum -= window[-0x3] * b0[0x2]; \ + sum -= window[-0x4] * b0[0x3]; \ + sum -= window[-0x5] * b0[0x4]; \ + sum -= window[-0x6] * b0[0x5]; \ + sum -= window[-0x7] * b0[0x6]; \ + sum -= window[-0x8] * b0[0x7]; \ + sum -= window[-0x9] * b0[0x8]; \ + sum -= window[-0xA] * b0[0x9]; \ + sum -= window[-0xB] * b0[0xA]; \ + sum -= window[-0xC] * b0[0xB]; \ + sum -= window[-0xD] * b0[0xC]; \ + sum -= window[-0xE] * b0[0xD]; \ + sum -= window[-0xF] * b0[0xE]; \ + sum -= window[-0x0] * b0[0xF]; \ + \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + } \ + } \ + *pnt += 64*sizeof(TYPE); \ + \ + return clip; + /* *INDENT-ON* */ + + +int +synth_1to1(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_CLIPCHOICE(short, WRITE_SAMPLE_CLIPPED) +} int +synth_1to1_unclipped(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_CLIPCHOICE(real, WRITE_SAMPLE_UNCLIPPED) +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.h new file mode 100644 index 00000000..8fc9dbe8 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/decode_i386.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef DECODE_I386_H_INCLUDED +#define DECODE_I386_H_INCLUDED + +#include "common.h" + +int synth_1to1_mono(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt); +int synth_1to1(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt); + +int synth_1to1_mono_unclipped(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt); +int synth_1to1_unclipped(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/huffman.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/huffman.h new file mode 100644 index 00000000..7d73a74b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/huffman.h @@ -0,0 +1,353 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * huffman tables ... recalcualted to work with my optimzed + * decoder scheme (MH) + * + * probably we could save a few bytes of memory, because the + * smaller tables are often the part of a bigger table + */ + +/* *INDENT-OFF* */ + + +struct newhuff +{ + const unsigned int linbits; + const short * const table; +}; + +static const short tab0[] = +{ + 0 +}; + +static const short tab1[] = +{ + -5, -3, -1, 17, 1, 16, 0 +}; + +static const short tab2[] = +{ + -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, 16, 0 +}; + +static const short tab3[] = +{ + -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, + 1, 0 +}; + +static const short tab5[] = +{ + -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, + 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, + 0 +}; + +static const short tab6[] = +{ + -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, + 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, + 0 +}; + +static const short tab7[] = +{ + -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, + -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, + 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, + -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, + -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 +}; + +static const short tab8[] = +{ + -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, + -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, + 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, + 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, + 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 +}; + +static const short tab9[] = +{ + -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, + 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, + -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, + -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, + 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 +}; + +static const short tab10[] = +{ +-125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, + 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, + -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, + 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, + -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, + -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, + -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, + 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, + 2, 32, 17, -1, 1, 16, 0 +}; + +static const short tab11[] = +{ +-121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, + -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, + -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, + -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, + -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, + 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, + 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, + -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, + 32, 17, -3, -1, 1, 16, 0 +}; + +static const short tab12[] = +{ +-115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, + 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, + 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, + 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, + -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, + 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, + 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, + -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, + 2, 32, 0, 17, -1, 1, 16 +}; + +static const short tab13[] = +{ +-509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, + -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, + 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, + 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, + 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, + -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, + 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, + 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, + 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, + -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, + 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, + 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, + 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, + -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, + 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, + -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, + 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, + 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, + 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, + -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, + -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, + -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, + 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, + -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, + -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, + 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, + 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, + 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, + -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, + -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, + 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, + -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, + -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, + -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static const short tab15[] = +{ +-495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, + -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, + 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, + -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, + -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, + -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, + -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, + -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, + 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, + 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, + 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, + -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, + -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, + 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, + 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, + -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, + -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, + 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, + -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, + -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, + -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, + -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, + 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, + 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, + -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, + -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, + -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, + -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, + 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, + -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, + -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, + 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, + 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, + 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, + 0 +}; + +static const short tab16[] = +{ +-509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, + 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, + -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, + -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, + -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, + 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, + -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, + 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, + -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, + -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, + -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, + 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, + -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, + -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, + 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, + 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, + 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, + -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, + -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, + -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, + 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, + 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, + -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, + -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, + -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, + 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, + -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, + 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, + -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, + 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, + -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, + -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, + -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, + 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static const short tab24[] = +{ +-451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, + 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, + -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, + 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, + 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, + 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, + -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, + -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, +-143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, + -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, + -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, + 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, + 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, + 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, + -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, + -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, + -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, + 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, + 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, + 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, + 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, + 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, + -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, + -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, + -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, + -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, + -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, + 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, + -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, + -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, + 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, + 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, + -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, + 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, + 0 +}; + +static const short tab_c0[] = +{ + -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, + 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, + 0 +}; + +static const short tab_c1[] = +{ + -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, + 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, + 0 +}; + + + +static const struct newhuff ht[] = +{ + { /* 0 */ 0 , tab0 } , + { /* 2 */ 0 , tab1 } , + { /* 3 */ 0 , tab2 } , + { /* 3 */ 0 , tab3 } , + { /* 0 */ 0 , tab0 } , + { /* 4 */ 0 , tab5 } , + { /* 4 */ 0 , tab6 } , + { /* 6 */ 0 , tab7 } , + { /* 6 */ 0 , tab8 } , + { /* 6 */ 0 , tab9 } , + { /* 8 */ 0 , tab10 } , + { /* 8 */ 0 , tab11 } , + { /* 8 */ 0 , tab12 } , + { /* 16 */ 0 , tab13 } , + { /* 0 */ 0 , tab0 } , + { /* 16 */ 0 , tab15 } , + + { /* 16 */ 1 , tab16 } , + { /* 16 */ 2 , tab16 } , + { /* 16 */ 3 , tab16 } , + { /* 16 */ 4 , tab16 } , + { /* 16 */ 6 , tab16 } , + { /* 16 */ 8 , tab16 } , + { /* 16 */ 10, tab16 } , + { /* 16 */ 13, tab16 } , + { /* 16 */ 4 , tab24 } , + { /* 16 */ 5 , tab24 } , + { /* 16 */ 6 , tab24 } , + { /* 16 */ 7 , tab24 } , + { /* 16 */ 8 , tab24 } , + { /* 16 */ 9 , tab24 } , + { /* 16 */ 11, tab24 } , + { /* 16 */ 13, tab24 } +}; + +static const struct newhuff htc[] = +{ + { /* 1 , 1 , */ 0 , tab_c0 } , + { /* 1 , 1 , */ 0 , tab_c1 } +}; + + /* *INDENT-ON* */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.c new file mode 100644 index 00000000..9719ff99 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.c @@ -0,0 +1,718 @@ +/* + * interface.c + * + * Copyright (C) 1999-2012 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: interface.c,v 1.69 2017/09/06 15:07:30 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> + +#include "common.h" +#include "interface.h" +#include "tabinit.h" +#include "layer3.h" +#include "lame.h" +#include "machine.h" +#include "VbrTag.h" +#include "decode_i386.h" + +#include "layer1.h" +#include "layer2.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +extern void lame_report_def(const char* format, va_list args); + +/* #define HIP_DEBUG */ + +int +InitMP3(PMPSTR mp) +{ + hip_init_tables_layer1(); + hip_init_tables_layer2(); + hip_init_tables_layer3(); + + if (mp) { + memset(mp, 0, sizeof(MPSTR)); + + mp->framesize = 0; + mp->num_frames = 0; + mp->enc_delay = -1; + mp->enc_padding = -1; + mp->vbr_header = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + mp->free_format = 0; + mp->old_free_format = 0; + mp->ssize = 0; + mp->dsize = 0; + mp->fsizeold = -1; + mp->bsize = 0; + mp->head = mp->tail = NULL; + mp->fr.single = -1; + mp->bsnum = 0; + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + mp->bitindex = 0; + mp->synth_bo = 1; + mp->sync_bitstream = 1; + + mp->report_dbg = &lame_report_def; + mp->report_err = &lame_report_def; + mp->report_msg = &lame_report_def; + } + make_decode_tables(32767); + + return 1; +} + +void +ExitMP3(PMPSTR mp) +{ + if (mp) { + struct buf *b, *bn; + + b = mp->tail; + while (b) { + free(b->pnt); + bn = b->next; + free(b); + b = bn; + } + } +} + +static struct buf * +addbuf(PMPSTR mp, unsigned char *buf, int size) +{ + struct buf *nbuf; + + nbuf = (struct buf *) malloc(sizeof(struct buf)); + if (!nbuf) { + lame_report_fnc(mp->report_err, "hip: addbuf() Out of memory!\n"); + return NULL; + } + nbuf->pnt = (unsigned char *) malloc((size_t) size); + if (!nbuf->pnt) { + free(nbuf); + return NULL; + } + nbuf->size = size; + memcpy(nbuf->pnt, buf, (size_t) size); + nbuf->next = NULL; + nbuf->prev = mp->head; + nbuf->pos = 0; + + if (!mp->tail) { + mp->tail = nbuf; + } + else { + mp->head->next = nbuf; + } + + mp->head = nbuf; + mp->bsize += size; + + return nbuf; +} + +void +remove_buf(PMPSTR mp) +{ + struct buf *buf = mp->tail; + + mp->tail = buf->next; + if (mp->tail) + mp->tail->prev = NULL; + else { + mp->tail = mp->head = NULL; + } + + free(buf->pnt); + free(buf); + +} + +static int +read_buf_byte(PMPSTR mp) +{ + unsigned int b; + + int pos; + + + pos = mp->tail->pos; + while (pos >= mp->tail->size) { + remove_buf(mp); + if (!mp->tail) { + lame_report_fnc(mp->report_err, "hip: Fatal error! tried to read past mp buffer\n"); + exit(1); + } + pos = mp->tail->pos; + } + + b = mp->tail->pnt[pos]; + mp->bsize--; + mp->tail->pos++; + + + return b; +} + + + +static void +read_head(PMPSTR mp) +{ + unsigned long head; + + head = read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + + mp->header = head; +} + + + + +static void +copy_mp(PMPSTR mp, int size, unsigned char *ptr) +{ + int len = 0; + + while (len < size && mp->tail) { + int nlen; + int blen = mp->tail->size - mp->tail->pos; + if ((size - len) <= blen) { + nlen = size - len; + } + else { + nlen = blen; + } + memcpy(ptr + len, mp->tail->pnt + mp->tail->pos, (size_t) nlen); + len += nlen; + mp->tail->pos += nlen; + mp->bsize -= nlen; + if (mp->tail->pos == mp->tail->size) { + remove_buf(mp); + } + } +} + +/* number of bytes needed by GetVbrTag to parse header */ +#define XING_HEADER_SIZE 194 + +/* +traverse mp data structure without changing it +(just like sync_buffer) +pull out Xing bytes +call vbr header check code from LAME +if we find a header, parse it and also compute the VBR header size +if no header, do nothing. + +bytes = number of bytes before MPEG header. skip this many bytes +before starting to read +return value: number of bytes in VBR header, including syncword +*/ +static int +check_vbr_header(PMPSTR mp, int bytes) +{ + int i, pos; + struct buf *buf = mp->tail; + unsigned char xing[XING_HEADER_SIZE]; + VBRTAGDATA pTagData; + + pos = buf->pos; + /* skip to valid header */ + for (i = 0; i < bytes; ++i) { + while (pos >= buf->size) { + buf = buf->next; + if (!buf) + return -1; /* fatal error */ + pos = buf->pos; + } + ++pos; + } + /* now read header */ + for (i = 0; i < XING_HEADER_SIZE; ++i) { + while (pos >= buf->size) { + buf = buf->next; + if (!buf) + return -1; /* fatal error */ + pos = buf->pos; + } + xing[i] = buf->pnt[pos]; + ++pos; + } + + /* check first bytes for Xing header */ + mp->vbr_header = GetVbrTag(&pTagData, xing); + if (mp->vbr_header) { + mp->num_frames = pTagData.frames; + mp->enc_delay = pTagData.enc_delay; + mp->enc_padding = pTagData.enc_padding; + + /* lame_report_fnc(mp->report_msg,"hip: delays: %i %i \n",mp->enc_delay,mp->enc_padding); */ + /* lame_report_fnc(mp->report_msg,"hip: Xing VBR header dectected. MP3 file has %i frames\n", pTagData.frames); */ + if (pTagData.headersize < 1) + return 1; + return pTagData.headersize; + } + return 0; +} + + + + + +static int +sync_buffer(PMPSTR mp, int free_match) +{ + /* traverse mp structure without modifying pointers, looking + * for a frame valid header. + * if free_format, valid header must also have the same + * samplerate. + * return number of bytes in mp, before the header + * return -1 if header is not found + */ + unsigned int b[4] = { 0, 0, 0, 0 }; + int i, h, pos; + struct buf *buf = mp->tail; + if (!buf) + return -1; + + pos = buf->pos; + for (i = 0; i < mp->bsize; i++) { + /* get 4 bytes */ + + b[0] = b[1]; + b[1] = b[2]; + b[2] = b[3]; + while (pos >= buf->size) { + buf = buf->next; + if (!buf) { + return -1; + /* not enough data to read 4 bytes */ + } + pos = buf->pos; + } + b[3] = buf->pnt[pos]; + ++pos; + + if (i >= 3) { + struct frame *fr = &mp->fr; + unsigned long head; + + head = b[0]; + head <<= 8; + head |= b[1]; + head <<= 8; + head |= b[2]; + head <<= 8; + head |= b[3]; + h = head_check(head, fr->lay); + + if (h && free_match) { + /* just to be even more thorough, match the sample rate */ + int mode, stereo, sampling_frequency, mpeg25, lsf; + + if (head & (1 << 20)) { + lsf = (head & (1 << 19)) ? 0x0 : 0x1; + mpeg25 = 0; + } + else { + lsf = 1; + mpeg25 = 1; + } + + mode = ((head >> 6) & 0x3); + stereo = (mode == MPG_MD_MONO) ? 1 : 2; + + if (mpeg25) + sampling_frequency = 6 + ((head >> 10) & 0x3); + else + sampling_frequency = ((head >> 10) & 0x3) + (lsf * 3); + h = ((stereo == fr->stereo) && (lsf == fr->lsf) && (mpeg25 == fr->mpeg25) && + (sampling_frequency == fr->sampling_frequency)); + } + + if (h) { + return i - 3; + } + } + } + return -1; +} + + +void +decode_reset(PMPSTR mp) +{ +#if 0 + remove_buf(mp); + /* start looking for next frame */ + /* mp->fsizeold = mp->framesize; */ + mp->fsizeold = -1; + mp->old_free_format = mp->free_format; + mp->framesize = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + mp->sync_bitstream = 1; /* TODO check if this is right */ +#else + InitMP3(mp); /* Less error prone to just to reinitialise. */ +#endif +} + +int +audiodata_precedesframes(PMPSTR mp) +{ + if (mp->fr.lay == 3) + return layer3_audiodata_precedesframes(mp); + else + return 0; /* For Layer 1 & 2 the audio data starts at the frame that describes it, so no audio data precedes. */ +} + +static int +decodeMP3_clipchoice(PMPSTR mp, unsigned char *in, int isize, char *out, int *done, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)) +{ + int i, iret, bits, bytes; + + if (in && isize && addbuf(mp, in, isize) == NULL) + return MP3_ERR; + + /* First decode header */ + if (!mp->header_parsed) { + + if (mp->fsizeold == -1 || mp->sync_bitstream) { + int vbrbytes; + mp->sync_bitstream = 0; + + /* This is the very first call. sync with anything */ + /* bytes= number of bytes before header */ + bytes = sync_buffer(mp, 0); + + /* now look for Xing VBR header */ + if (mp->bsize >= bytes + XING_HEADER_SIZE) { + /* vbrbytes = number of bytes in entire vbr header */ + vbrbytes = check_vbr_header(mp, bytes); + } + else { + /* not enough data to look for Xing header */ +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: not enough data to look for Xing header\n"); +#endif + return MP3_NEED_MORE; + } + + if (mp->vbr_header) { + /* do we have enough data to parse entire Xing header? */ + if (bytes + vbrbytes > mp->bsize) { + /* lame_report_fnc(mp->report_err,"hip: not enough data to parse entire Xing header\n"); */ + return MP3_NEED_MORE; + } + + /* read in Xing header. Buffer data in case it + * is used by a non zero main_data_begin for the next + * frame, but otherwise dont decode Xing header */ +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: found xing header, skipping %i bytes\n", vbrbytes + bytes); +#endif + for (i = 0; i < vbrbytes + bytes; ++i) + read_buf_byte(mp); + /* now we need to find another syncword */ + /* just return and make user send in more data */ + + return MP3_NEED_MORE; + } + } + else { + /* match channels, samplerate, etc, when syncing */ + bytes = sync_buffer(mp, 1); + } + + /* buffer now synchronized */ + if (bytes < 0) { + /* lame_report_fnc(mp->report_err,"hip: need more bytes %d\n", bytes); */ + return MP3_NEED_MORE; + } + if (bytes > 0) { + /* there were some extra bytes in front of header. + * bitstream problem, but we are now resynced + * should try to buffer previous data in case new + * frame has nonzero main_data_begin, but we need + * to make sure we do not overflow buffer + */ + int size; + if (mp->fsizeold != -1) { + lame_report_fnc(mp->report_err, "hip: bitstream problem, resyncing skipping %d bytes...\n", bytes); + } + mp->old_free_format = 0; +#if 1 + /* FIXME: correct ??? */ + mp->sync_bitstream = 1; +#endif + /* skip some bytes, buffer the rest */ + size = (int) (mp->wordpointer - (mp->bsspace[mp->bsnum] + 512)); + + if (size > MAXFRAMESIZE) { + /* wordpointer buffer is trashed. probably cant recover, but try anyway */ + lame_report_fnc(mp->report_err, "hip: wordpointer trashed. size=%i (%i) bytes=%i \n", + size, MAXFRAMESIZE, bytes); + size = 0; + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + } + + /* buffer contains 'size' data right now + we want to add 'bytes' worth of data, but do not + exceed MAXFRAMESIZE, so we through away 'i' bytes */ + i = (size + bytes) - MAXFRAMESIZE; + for (; i > 0; --i) { + --bytes; + read_buf_byte(mp); + } + + copy_mp(mp, bytes, mp->wordpointer); + mp->fsizeold += bytes; + } + + read_head(mp); + if (!decode_header(mp, &mp->fr, mp->header)) + return MP3_ERR; + mp->header_parsed = 1; + mp->framesize = mp->fr.framesize; + mp->free_format = (mp->framesize == 0); + + if (mp->fr.lsf) + mp->ssize = (mp->fr.stereo == 1) ? 9 : 17; + else + mp->ssize = (mp->fr.stereo == 1) ? 17 : 32; + if (mp->fr.error_protection) + mp->ssize += 2; + + mp->bsnum = 1 - mp->bsnum; /* toggle buffer */ + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + mp->bitindex = 0; + + /* for very first header, never parse rest of data */ + if (mp->fsizeold == -1) { +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: not parsing the rest of the data of the first header\n"); +#endif + return MP3_NEED_MORE; + } + } /* end of header parsing block */ + + /* now decode side information */ + if (!mp->side_parsed) { + + /* Layer 3 only */ + if (mp->fr.lay == 3) { + if (mp->bsize < mp->ssize) + return MP3_NEED_MORE; + + copy_mp(mp, mp->ssize, mp->wordpointer); + + if (mp->fr.error_protection) + getbits(mp, 16); + bits = decode_layer3_sideinfo(mp); + /* bits = actual number of bits needed to parse this frame */ + /* can be negative, if all bits needed are in the reservoir */ + if (bits < 0) + bits = 0; + + /* read just as many bytes as necessary before decoding */ + mp->dsize = (bits + 7) / 8; + + if (!mp->free_format) { + /* do not read more than framsize data */ + int framesize = mp->fr.framesize - mp->ssize; + if (mp->dsize > framesize) { + lame_report_fnc(mp->report_err, + "hip: error audio data exceeds framesize by %d bytes\n", + mp->dsize - framesize); + mp->dsize = framesize; + } + } +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, + "hip: %d bits needed to parse layer III frame, number of bytes to read before decoding dsize = %d\n", + bits, mp->dsize); +#endif + + /* this will force mpglib to read entire frame before decoding */ + /* mp->dsize= mp->framesize - mp->ssize; */ + + } + else { + /* Layers 1 and 2 */ + + /* check if there is enough input data */ + if (mp->fr.framesize > mp->bsize) + return MP3_NEED_MORE; + + /* takes care that the right amount of data is copied into wordpointer */ + mp->dsize = mp->fr.framesize; + mp->ssize = 0; + } + + mp->side_parsed = 1; + } + + /* now decode main data */ + iret = MP3_NEED_MORE; + if (!mp->data_parsed) { + if (mp->dsize > mp->bsize) { + return MP3_NEED_MORE; + } + + copy_mp(mp, mp->dsize, mp->wordpointer); + + *done = 0; + + /*do_layer3(&mp->fr,(unsigned char *) out,done); */ + switch (mp->fr.lay) { + case 1: + if (mp->fr.error_protection) + getbits(mp, 16); + + if (decode_layer1_frame(mp, (unsigned char *) out, done) < 0) + return MP3_ERR; + break; + + case 2: + if (mp->fr.error_protection) + getbits(mp, 16); + + decode_layer2_frame(mp, (unsigned char *) out, done); + break; + + case 3: + decode_layer3_frame(mp, (unsigned char *) out, done, synth_1to1_mono_ptr, synth_1to1_ptr); + break; + default: + lame_report_fnc(mp->report_err, "hip: invalid layer %d\n", mp->fr.lay); + } + + mp->wordpointer = mp->bsspace[mp->bsnum] + 512 + mp->ssize + mp->dsize; + + mp->data_parsed = 1; + iret = MP3_OK; + } + + + /* remaining bits are ancillary data, or reservoir for next frame + * If free format, scan stream looking for next frame to determine + * mp->framesize */ + if (mp->free_format) { + if (mp->old_free_format) { + /* free format. bitrate must not vary */ + mp->framesize = mp->fsizeold_nopadding + (mp->fr.padding); + } + else { + bytes = sync_buffer(mp, 1); + if (bytes < 0) + return iret; + mp->framesize = bytes + mp->ssize + mp->dsize; + mp->fsizeold_nopadding = mp->framesize - mp->fr.padding; +#if 0 + lame_report_fnc(mp->report_dbg,"hip: freeformat bitstream: estimated bitrate=%ikbs \n", + 8*(4+mp->framesize)*freqs[mp->fr.sampling_frequency]/ + (1000*576*(2-mp->fr.lsf))); +#endif + } + } + + /* buffer the ancillary data and reservoir for next frame */ + bytes = mp->framesize - (mp->ssize + mp->dsize); + if (bytes > mp->bsize) { + return iret; + } + + if (bytes > 0) { + int size; +#if 1 + /* FIXME: while loop OK ??? */ + while (bytes > 512) { + read_buf_byte(mp); + bytes--; + mp->framesize--; + } +#endif + copy_mp(mp, bytes, mp->wordpointer); + mp->wordpointer += bytes; + + size = (int) (mp->wordpointer - (mp->bsspace[mp->bsnum] + 512)); + if (size > MAXFRAMESIZE) { + lame_report_fnc(mp->report_err, "hip: fatal error. MAXFRAMESIZE not large enough.\n"); + } + + } + + /* the above frame is completely parsed. start looking for next frame */ + mp->fsizeold = mp->framesize; + mp->old_free_format = mp->free_format; + mp->framesize = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + + return iret; +} + +int +decodeMP3(PMPSTR mp, unsigned char *in, int isize, char *out, int osize, int *done) +{ + if (osize < 4608) { + lame_report_fnc(mp->report_err, "hip: Insufficient memory for decoding buffer %d\n", osize); + return MP3_ERR; + } + + /* passing pointers to the functions which clip the samples */ + return decodeMP3_clipchoice(mp, in, isize, out, done, synth_1to1_mono, synth_1to1); +} + +int +decodeMP3_unclipped(PMPSTR mp, unsigned char *in, int isize, char *out, int osize, int *done) +{ + /* we forbid input with more than 1152 samples per channel for output in unclipped mode */ + if (osize < (int) (1152 * 2 * sizeof(real))) { + lame_report_fnc(mp->report_err, "hip: out space too small for unclipped mode\n"); + return MP3_ERR; + } + + /* passing pointers to the functions which don't clip the samples */ + return decodeMP3_clipchoice(mp, in, isize, out, done, synth_1to1_mono_unclipped, + synth_1to1_unclipped); +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.h new file mode 100644 index 00000000..f713b466 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/interface.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef INTERFACE_H_INCLUDED +#define INTERFACE_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common.h" + + int InitMP3(PMPSTR mp); + int decodeMP3(PMPSTR mp, unsigned char *inmemory, int inmemsize, char *outmemory, + int outmemsize, int *done); + void ExitMP3(PMPSTR mp); + +/* added decodeMP3_unclipped to support returning raw floating-point values of samples. The representation + of the floating-point numbers is defined in mpg123.h as #define real. It is 64-bit double by default. + No more than 1152 samples per channel are allowed. */ + int decodeMP3_unclipped(PMPSTR mp, unsigned char *inmemory, int inmemsize, char *outmemory, + int outmemsize, int *done); + +/* added remove_buf to support mpglib seeking */ + void remove_buf(PMPSTR mp); + +/* added audiodata_precedesframes to return the number of bitstream frames the audio data will precede the + current frame by for Layer 3 data. Aids seeking. + */ + int audiodata_precedesframes(PMPSTR mp); + +/* Resets decoding. Aids seeking. */ + void decode_reset(PMPSTR mp); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/l2tables.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/l2tables.h new file mode 100644 index 00000000..6a3deace --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/l2tables.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * Layer 2 Alloc tables .. + * most other tables are calculated on program start (which is (of course) + * not ISO-conform) .. + * Layer-3 huffman table is in huffman.h + */ + +const struct al_table2 alloc_0[] = { + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767} +}; + +const struct al_table2 alloc_1[] = { + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767} +}; + +const struct al_table2 alloc_2[] = { + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63} +}; + +const struct al_table2 alloc_3[] = { + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63} +}; + +const struct al_table2 alloc_4[] = { + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9} +}; diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.c new file mode 100644 index 00000000..7101a466 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.c @@ -0,0 +1,232 @@ +/* + * layer1.c: Mpeg Layer-1 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: layer1.c,v 1.31 2017/08/23 13:22:23 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include "common.h" +#include "decode_i386.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +#include "layer1.h" + +static int gd_are_hip_tables_layer1_initialized = 0; + +void +hip_init_tables_layer1(void) +{ + if (gd_are_hip_tables_layer1_initialized) { + return; + } + gd_are_hip_tables_layer1_initialized = 1; +} + +typedef struct sideinfo_layer_I_struct +{ + unsigned char allocation[SBLIMIT][2]; + unsigned char scalefactor[SBLIMIT][2]; +} sideinfo_layer_I; + +static int +I_step_one(PMPSTR mp, sideinfo_layer_I* si) +{ + struct frame *fr = &(mp->fr); + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : 32; + int i; + int illegal_value_detected = 0; + unsigned char const ba15 = 15; /* bit pattern not allowed, looks like sync(?) */ + memset(si, 0, sizeof(*si)); + assert(fr->stereo == 1 || fr->stereo == 2); + + if (fr->stereo == 2) { + for (i = 0; i < jsbound; i++) { + unsigned char b0 = get_leq_8_bits(mp, 4); /* values 0-15 */ + unsigned char b1 = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b0; + si->allocation[i][1] = b1; + if (b0 == ba15 || b1 == ba15) + illegal_value_detected = 1; + } + for (i = jsbound; i < SBLIMIT; i++) { + unsigned char b = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b; + si->allocation[i][1] = b; + if (b == ba15) + illegal_value_detected = 1; + } + for (i = 0; i < SBLIMIT; i++) { + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + unsigned char b1 = n1 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + si->scalefactor[i][0] = b0; + si->scalefactor[i][1] = b1; + } + } + else { + for (i = 0; i < SBLIMIT; i++) { + unsigned char b0 = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b0; + if (b0 == ba15) + illegal_value_detected = 1; + } + for (i = 0; i < SBLIMIT; i++) { + unsigned char n0 = si->allocation[i][0]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + si->scalefactor[i][0] = b0; + } + } + return illegal_value_detected; +} + +static void +I_step_two(PMPSTR mp, sideinfo_layer_I *si, real fraction[2][SBLIMIT]) +{ + double r0, r1; + struct frame *fr = &(mp->fr); + int ds_limit = fr->down_sample_sblimit; + int i; + + assert(fr->stereo == 1 || fr->stereo == 2); + if (fr->stereo == 2) { + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : 32; + for (i = 0; i < jsbound; i++) { + unsigned char i0 = si->scalefactor[i][0]; + unsigned char i1 = si->scalefactor[i][1]; + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + assert( i0 < 64 ); + assert( i1 < 64 ); + assert( n0 < 16 ); + assert( n1 < 16 ); + if (n0 > 0) { + unsigned short v = get_leq_16_bits(mp, n0 + 1); /* 0-65535 */ + r0 = (((-1) << n0) + v + 1) * muls[n0 + 1][i0]; + } + else { + r0 = 0; + } + if (n1 > 0) { + unsigned short v = get_leq_16_bits(mp, n1 + 1); /* 0-65535 */ + r1 = (((-1) << n1) + v + 1) * muls[n1 + 1][i1]; + } + else { + r1 = 0; + } + fraction[0][i] = (real)r0; + fraction[1][i] = (real)r1; + } + for (i = jsbound; i < SBLIMIT; i++) { + unsigned char i0 = si->scalefactor[i][0]; + unsigned char i1 = si->scalefactor[i][1]; + unsigned char n = si->allocation[i][0]; + assert( i0 < 64 ); + assert( i1 < 64 ); + assert( n < 16 ); + if (n > 0) { + unsigned short v = get_leq_16_bits(mp, n + 1); /* 0-65535 */ + unsigned int w = (((-1) << n) + v + 1); + r0 = w * muls[n + 1][i0]; + r1 = w * muls[n + 1][i1]; + } + else { + r0 = r1 = 0; + } + fraction[0][i] = (real)r0; + fraction[1][i] = (real)r1; + } + for (i = ds_limit; i < SBLIMIT; i++) { + fraction[0][i] = 0.0; + fraction[1][i] = 0.0; + } + } + else { + for (i = 0; i < SBLIMIT; i++) { + unsigned char n = si->allocation[i][0]; + unsigned char j = si->scalefactor[i][0]; + assert( j < 64 ); + assert( n < 16 ); + if (n > 0) { + unsigned short v = get_leq_16_bits(mp, n + 1); + r0 = (((-1) << n) + v + 1) * muls[n + 1][j]; + } + else { + r0 = 0; + } + fraction[0][i] = (real)r0; + } + for (i = ds_limit; i < SBLIMIT; i++) { + fraction[0][i] = 0.0; + } + } +} + +int +decode_layer1_sideinfo(PMPSTR mp) +{ + (void) mp; + /* FIXME: extract side information and check values */ + return 0; +} + +int +decode_layer1_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point) +{ + real fraction[2][SBLIMIT]; /* FIXME: change real -> double ? */ + sideinfo_layer_I si; + struct frame *fr = &(mp->fr); + int single = fr->single; + int i, clip = 0; + + if (I_step_one(mp, &si)) { + lame_report_fnc(mp->report_err, "hip: Aborting layer 1 decode, illegal bit allocation value\n"); + return -1; + } + if (fr->stereo == 1 || single == 3) + single = 0; + + if (single >= 0) { + /* decoding one of possibly two channels */ + for (i = 0; i < SCALE_BLOCK; i++) { + I_step_two(mp, &si, fraction); + clip += synth_1to1_mono(mp, (real *) fraction[single], pcm_sample, pcm_point); + } + } + else { + for (i = 0; i < SCALE_BLOCK; i++) { + int p1 = *pcm_point; + I_step_two(mp, &si, fraction); + clip += synth_1to1(mp, (real *) fraction[0], 0, pcm_sample, &p1); + clip += synth_1to1(mp, (real *) fraction[1], 1, pcm_sample, pcm_point); + } + } + + return clip; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.h new file mode 100644 index 00000000..308c4379 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer1.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAYER1_H_INCLUDED +#define LAYER1_H_INCLUDED + +void hip_init_tables_layer1(void); +int decode_layer1_sideinfo(PMPSTR mp); +int decode_layer1_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.c new file mode 100644 index 00000000..d3f869d9 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.c @@ -0,0 +1,403 @@ +/* + * layer2.c: Mpeg Layer-2 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: layer2.c,v 1.34 2017/08/22 23:31:07 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "common.h" +#include "layer2.h" +#include "l2tables.h" +#include "decode_i386.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif +#include <assert.h> + +static int gd_are_hip_tables_layer2_initialized = 0; + +static unsigned char grp_3tab[32 * 3] = { 0, }; /* used: 27 */ +static unsigned char grp_5tab[128 * 3] = { 0, }; /* used: 125 */ +static unsigned char grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ + + +void +hip_init_tables_layer2(void) +{ + static const double mulmul[27] = { + 0.0, -2.0 / 3.0, 2.0 / 3.0, + 2.0 / 7.0, 2.0 / 15.0, 2.0 / 31.0, 2.0 / 63.0, 2.0 / 127.0, 2.0 / 255.0, + 2.0 / 511.0, 2.0 / 1023.0, 2.0 / 2047.0, 2.0 / 4095.0, 2.0 / 8191.0, + 2.0 / 16383.0, 2.0 / 32767.0, 2.0 / 65535.0, + -4.0 / 5.0, -2.0 / 5.0, 2.0 / 5.0, 4.0 / 5.0, + -8.0 / 9.0, -4.0 / 9.0, -2.0 / 9.0, 2.0 / 9.0, 4.0 / 9.0, 8.0 / 9.0 + }; + static const unsigned char base[3][9] = { + {1, 0, 2,}, + {17, 18, 0, 19, 20,}, + {21, 1, 22, 23, 0, 24, 25, 2, 26} + }; + int i, j, k, l, len; + real *table; + static const int tablen[3] = { 3, 5, 9 }; + static unsigned char *itable, *tables[3] = { grp_3tab, grp_5tab, grp_9tab }; + + if (gd_are_hip_tables_layer2_initialized) { + return; + } + gd_are_hip_tables_layer2_initialized = 1; + + for (i = 0; i < 3; i++) { + itable = tables[i]; + len = tablen[i]; + for (j = 0; j < len; j++) + for (k = 0; k < len; k++) + for (l = 0; l < len; l++) { + *itable++ = base[i][l]; + *itable++ = base[i][k]; + *itable++ = base[i][j]; + } + } + + for (k = 0; k < 27; k++) { + double m = mulmul[k]; + table = muls[k]; + for (j = 3, i = 0; i < 63; i++, j--) + *table++ = (real) (m * pow(2.0, (double) j / 3.0)); + *table++ = 0.0; + } +} + + +static unsigned char* +grp_table_select(short d1, unsigned int idx) +{ + /* RH: it seems to be common, that idx is larger than the table's sizes. + is it OK to return a zero vector in this case? FIXME + /*/ + static unsigned char dummy_table[] = { 0,0,0 }; + unsigned int x; + switch (d1) { + case 3: + x = 3*3*3; + idx = idx < x ? idx : x; + return &grp_3tab[3 * idx]; + case 5: + x = 5*5*5; + idx = idx < x ? idx : x; + return &grp_5tab[3 * idx]; + case 9: + x = 9*9*9; + idx = idx < x ? idx : x; + return &grp_9tab[3 * idx]; + default: + /* fatal error */ + assert(0); + } + return &dummy_table[0]; +} + +typedef struct sideinfo_layer_II_struct +{ + unsigned char allocation[SBLIMIT][2]; + unsigned char scalefactor[SBLIMIT][2][3]; /* subband / channel / block */ +} sideinfo_layer_II; + + + +static void +II_step_one(PMPSTR mp, sideinfo_layer_II *si, struct frame *fr) +{ + int nch = fr->stereo; + int sblimit = fr->II_sblimit; + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : fr->II_sblimit; + struct al_table2 const *alloc1 = fr->alloc; + unsigned char scfsi[SBLIMIT][2]; + int i, ch; + + memset(si, 0, sizeof(*si)); + if (jsbound > sblimit) + jsbound = sblimit; + if (nch == 2) { + for (i = 0; i < jsbound; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + unsigned char b1 = get_leq_8_bits(mp, step); + alloc1 += ((size_t)1 << step); + si->allocation[i][0] = b0; + si->allocation[i][1] = b1; + } + for (i = jsbound; i < sblimit; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + alloc1 += ((size_t)1 << step); + si->allocation[i][0] = b0; + si->allocation[i][1] = b0; + } + for (i = 0; i < sblimit; ++i) { + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 2) : 0; + unsigned char b1 = n1 ? get_leq_8_bits(mp, 2) : 0; + scfsi[i][0] = b0; + scfsi[i][1] = b1; + } + } + else { /* mono */ + for (i = 0; i < sblimit; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + alloc1 += ((size_t)1 << step); + si->allocation[i][0] = b0; + } + for (i = 0; i < sblimit; ++i) { + unsigned char n0 = si->allocation[i][0]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 2) : 0; + scfsi[i][0] = b0; + } + } + for (i = 0; i < sblimit; ++i) { + for (ch = 0; ch < nch; ++ch) { + unsigned char s0 = 0, s1 = 0, s2 = 0; + if (si->allocation[i][ch]) { + switch (scfsi[i][ch]) { + case 0: + s0 = get_leq_8_bits(mp, 6); + s1 = get_leq_8_bits(mp, 6); + s2 = get_leq_8_bits(mp, 6); + break; + case 1: + s0 = get_leq_8_bits(mp, 6); + s1 = s0; + s2 = get_leq_8_bits(mp, 6); + break; + case 2: + s0 = get_leq_8_bits(mp, 6); + s1 = s0; + s2 = s0; + break; + case 3: + s0 = get_leq_8_bits(mp, 6); + s1 = get_leq_8_bits(mp, 6); + s2 = s1; + break; + default: + assert(0); + } + } + si->scalefactor[i][ch][0] = s0; + si->scalefactor[i][ch][1] = s1; + si->scalefactor[i][ch][2] = s2; + } + } +} + +static void +II_step_two(PMPSTR mp, sideinfo_layer_II* si, struct frame *fr, int gr, real fraction[2][4][SBLIMIT]) +{ + struct al_table2 const *alloc1 = fr->alloc; + int sblimit = fr->II_sblimit; + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : fr->II_sblimit; + int i, ch, nch = fr->stereo; + double cm, r0, r1, r2; + + if (jsbound > sblimit) + jsbound = sblimit; + for (i = 0; i < jsbound; ++i) { + short step = alloc1->bits; + for (ch = 0; ch < nch; ++ch) { + unsigned char ba = si->allocation[i][ch]; + if (ba) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + struct al_table2 const *alloc2 = alloc1 + ba; + short k = alloc2->bits; + short d1 = alloc2->d; + assert( k <= 16 ); + k = (k <= 16) ? k : 16; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + if (d1 < 0) { + int v0 = getbits(mp, k); + int v1 = getbits(mp, k); + int v2 = getbits(mp, k); + cm = muls[k][x1]; + r0 = (v0 + d1) * cm; + r1 = (v1 + d1) * cm; + r2 = (v2 + d1) * cm; + } + else { + unsigned int idx = getbits(mp, k); + unsigned char *tab = grp_table_select(d1, idx); + unsigned char k0 = tab[0]; + unsigned char k1 = tab[1]; + unsigned char k2 = tab[2]; + r0 = muls[k0][x1]; + r1 = muls[k1][x1]; + r2 = muls[k2][x1]; + } + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + else { + fraction[ch][0][i] = fraction[ch][1][i] = fraction[ch][2][i] = 0.0; + } + } + alloc1 += ((size_t)1 << step); + } + + for (i = jsbound; i < sblimit; i++) { + short step = alloc1->bits; + unsigned char ba = si->allocation[i][0]; + if (ba) { + struct al_table2 const *alloc2 = alloc1 + ba; + short k = alloc2->bits; + short d1 = alloc2->d; + assert( k <= 16 ); + k = (k <= 16) ? k : 16; + if (d1 < 0) { + int v0 = getbits(mp, k); + int v1 = getbits(mp, k); + int v2 = getbits(mp, k); + for (ch = 0; ch < nch; ++ch) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + cm = muls[k][x1]; + r0 = (v0 + d1) * cm; + r1 = (v1 + d1) * cm; + r2 = (v2 + d1) * cm; + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + } + else { + unsigned int idx = getbits(mp, k); + unsigned char *tab = grp_table_select(d1, idx); + unsigned char k0 = tab[0]; + unsigned char k1 = tab[1]; + unsigned char k2 = tab[2]; + for (ch = 0; ch < nch; ++ch) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + r0 = muls[k0][x1]; + r1 = muls[k1][x1]; + r2 = muls[k2][x1]; + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + } + } + else { + fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = 0.0; + fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; + } + alloc1 += ((size_t)1 << step); + } + if (sblimit > fr->down_sample_sblimit) { + sblimit = fr->down_sample_sblimit; + } + for (ch = 0; ch < nch; ++ch) { + for (i = sblimit; i < SBLIMIT; ++i) { + fraction[ch][0][i] = fraction[ch][1][i] = fraction[ch][2][i] = 0.0; + } + } +} + +static void +II_select_table(struct frame *fr) +{ + /* *INDENT-OFF* */ + static const int translate[3][2][16] = + { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } , + { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } , + { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } , + { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } , + { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } , + { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; + /* *INDENT-ON* */ + + int table, sblim; + static const struct al_table2 *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3, alloc_4 }; + static const int sblims[5] = { 27, 30, 8, 12, 30 }; + + if (fr->lsf) + table = 4; + else + table = translate[fr->sampling_frequency][2 - fr->stereo][fr->bitrate_index]; + sblim = sblims[table]; + + fr->alloc = (struct al_table2 const *) tables[table]; + fr->II_sblimit = sblim; +} + + +int +decode_layer2_sideinfo(PMPSTR mp) +{ + (void) mp; + /* FIXME: extract side information and check values */ + return 0; +} + +int +decode_layer2_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point) +{ + real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ + sideinfo_layer_II si; + struct frame *fr = &(mp->fr); + int single = fr->single; + int i, j, clip = 0; + + II_select_table(fr); + II_step_one(mp, &si, fr); + + if (fr->stereo == 1 || single == 3) + single = 0; + + if (single >= 0) { + for (i = 0; i < SCALE_BLOCK; i++) { + II_step_two(mp, &si, fr, i >> 2, fraction); + for (j = 0; j < 3; j++) { + clip += synth_1to1_mono(mp, fraction[single][j], pcm_sample, pcm_point); + } + } + } + else { + for (i = 0; i < SCALE_BLOCK; i++) { + II_step_two(mp, &si, fr, i >> 2, fraction); + for (j = 0; j < 3; j++) { + int p1 = *pcm_point; + clip += synth_1to1(mp, fraction[0][j], 0, pcm_sample, &p1); + clip += synth_1to1(mp, fraction[1][j], 1, pcm_sample, pcm_point); + } + } + } + + return clip; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.h new file mode 100644 index 00000000..fafc9a73 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer2.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + + +#ifndef LAYER2_H_INCLUDED +#define LAYER2_H_INCLUDED + + +struct al_table2 { + short bits; + short d; +}; + + + +void hip_init_tables_layer2(void); +int decode_layer2_sideinfo(PMPSTR mp); +int decode_layer2_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point); + + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.c new file mode 100644 index 00000000..af5b69e7 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.c @@ -0,0 +1,1969 @@ +/* + * layer3.c: Mpeg Layer-3 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: layer3.c,v 1.69 2017/08/20 20:06:57 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include "common.h" +#include "huffman.h" +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "lame-analysis.h" +#include "decode_i386.h" +#include "layer3.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + +static int gd_are_hip_tables_layer3_initialized = 0; + +static real ispow[8207]; +static real aa_ca[8], aa_cs[8]; +static real COS1[12][6]; +static real win[4][36]; +static real win1[4][36]; +static real gainpow2[256 + 118 + 4]; +static real COS9[9]; +static real COS6_1, COS6_2; +static real tfcos36[9]; +static real tfcos12[3]; + +struct bandInfoStruct { + short longIdx[23]; + short longDiff[22]; + short shortIdx[14]; + short shortDiff[13]; +}; + +static int longLimit[9][23]; +static int shortLimit[9][14]; + +/* *INDENT-OFF* */ + +static const struct bandInfoStruct bandInfo[9] = { + +/* MPEG 1.0 */ + { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, + {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, + {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, + {4,4,4,4,6,8,10,12,14,18,22,30,56} } , + + { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, + {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, + {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, + {4,4,4,4,6,6,10,12,14,16,20,26,66} } , + + { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , + {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , + {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , + {4,4,4,4,6,8,12,16,20,26,34,42,12} } , + +/* MPEG 2.0 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , + {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , + {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , + /* docs: 332. mpg123: 330 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576}, + {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36 } , + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , + {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , + + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, + {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , +/* MPEG 2.5 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, + {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, + {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, + {8,8,8,12,16,20,24,28,36,2,2,2,26} } , +}; +/* *INDENT-ON* */ + +static int mapbuf0[9][152]; +static int mapbuf1[9][156]; +static int mapbuf2[9][44]; +static int *map[9][3]; +static int *mapend[9][3]; + +static unsigned int n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ +static unsigned int i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ + +static real tan1_1[16], tan2_1[16], tan1_2[16], tan2_2[16]; +static real pow1_1[2][16], pow2_1[2][16], pow1_2[2][16], pow2_2[2][16]; + +static unsigned int +get1bit(PMPSTR mp) +{ + unsigned char rval; + rval = *mp->wordpointer << mp->bitindex; + + mp->bitindex++; + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + + return rval >> 7; +} + +static real +get_gain(real const* gain_ptr, int idx, int* overflow) +{ + static const real* const gainpow2_end_ptr = gainpow2 + (sizeof(gainpow2)/sizeof(gainpow2[0])) -1; + real const * ptr = &gain_ptr[idx]; + if (&gain_ptr[idx] > gainpow2_end_ptr) { + ptr = gainpow2_end_ptr; + if (overflow) *overflow = 1; + } + return *ptr; +} + + +/* + * init tables for layer-3 + */ +void +hip_init_tables_layer3(void) +{ + int i, j, k; + + if (gd_are_hip_tables_layer3_initialized) { + return; + } + gd_are_hip_tables_layer3_initialized = 1; + + for (i = -256; i < 118 + 4; i++) + gainpow2[i + 256] = pow((double) 2.0, -0.25 * (double) (i + 210)); + + for (i = 0; i < 8207; i++) + ispow[i] = pow((double) i, (double) 4.0 / 3.0); + + for (i = 0; i < 8; i++) { + static const double Ci[8] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 }; + double sq = sqrt(1.0 + Ci[i] * Ci[i]); + aa_cs[i] = 1.0 / sq; + aa_ca[i] = Ci[i] / sq; + } + + for (i = 0; i < 18; i++) { + win[0][i] = win[1][i] = + 0.5 * sin(M_PI / 72.0 * (double) (2 * (i + 0) + 1)) / cos(M_PI * + (double) (2 * (i + 0) + + 19) / 72.0); + win[0][i + 18] = win[3][i + 18] = + 0.5 * sin(M_PI / 72.0 * (double) (2 * (i + 18) + 1)) / cos(M_PI * + (double) (2 * (i + 18) + + 19) / 72.0); + } + for (i = 0; i < 6; i++) { + win[1][i + 18] = 0.5 / cos(M_PI * (double) (2 * (i + 18) + 19) / 72.0); + win[3][i + 12] = 0.5 / cos(M_PI * (double) (2 * (i + 12) + 19) / 72.0); + win[1][i + 24] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 13)) / cos(M_PI * + (double) (2 * (i + 24) + + 19) / 72.0); + win[1][i + 30] = win[3][i] = 0.0; + win[3][i + 6] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double) (2 * (i + 6) + 19) / + 72.0); + } + + for (i = 0; i < 9; i++) + COS9[i] = cos(M_PI / 18.0 * (double) i); + + for (i = 0; i < 9; i++) + tfcos36[i] = 0.5 / cos(M_PI * (double) (i * 2 + 1) / 36.0); + for (i = 0; i < 3; i++) + tfcos12[i] = 0.5 / cos(M_PI * (double) (i * 2 + 1) / 12.0); + + COS6_1 = cos(M_PI / 6.0 * (double) 1); + COS6_2 = cos(M_PI / 6.0 * (double) 2); + + for (i = 0; i < 12; i++) { + win[2][i] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double) (2 * i + 7) / 24.0); + for (j = 0; j < 6; j++) + COS1[i][j] = cos(M_PI / 24.0 * (double) ((2 * i + 7) * (2 * j + 1))); + } + + for (j = 0; j < 4; j++) { + static int const len[4] = { 36, 36, 12, 36 }; + for (i = 0; i < len[j]; i += 2) + win1[j][i] = +win[j][i]; + for (i = 1; i < len[j]; i += 2) + win1[j][i] = -win[j][i]; + } + + for (i = 0; i < 16; i++) { + double t = tan((double) i * M_PI / 12.0); + tan1_1[i] = t / (1.0 + t); + tan2_1[i] = 1.0 / (1.0 + t); + tan1_2[i] = M_SQRT2 * t / (1.0 + t); + tan2_2[i] = M_SQRT2 / (1.0 + t); + + for (j = 0; j < 2; j++) { + double base = pow(2.0, -0.25 * (j + 1.0)); + double p1 = 1.0, p2 = 1.0; + if (i > 0) { + if (i & 1) + p1 = pow(base, (i + 1.0) * 0.5); + else + p2 = pow(base, i * 0.5); + } + pow1_1[j][i] = p1; + pow2_1[j][i] = p2; + pow1_2[j][i] = M_SQRT2 * p1; + pow2_2[j][i] = M_SQRT2 * p2; + } + } + + for (j = 0; j < 9; j++) { + struct bandInfoStruct const *bi = (struct bandInfoStruct const *) &bandInfo[j]; + int *mp; + int cb, lwin; + short const *bdf; + int switch_idx = (j < 3) ? 8 : 6; + + mp = map[j][0] = mapbuf0[j]; + bdf = bi->longDiff; + for (i = 0, cb = 0; cb < switch_idx; cb++, i += *bdf++) { + *mp++ = (*bdf) >> 1; + *mp++ = i; + *mp++ = 3; + *mp++ = cb; + } + bdf = bi->shortDiff + 3; + for (cb = 3; cb < 13; cb++) { + int l = (*bdf++) >> 1; + for (lwin = 0; lwin < 3; lwin++) { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mapend[j][0] = mp; + + mp = map[j][1] = mapbuf1[j]; + bdf = bi->shortDiff + 0; + for (i = 0, cb = 0; cb < 13; cb++) { + int l = (*bdf++) >> 1; + for (lwin = 0; lwin < 3; lwin++) { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mapend[j][1] = mp; + + mp = map[j][2] = mapbuf2[j]; + bdf = bi->longDiff; + for (cb = 0; cb < 22; cb++) { + *mp++ = (*bdf++) >> 1; + *mp++ = cb; + } + mapend[j][2] = mp; + + } + + for (j = 0; j < 9; j++) { + for (i = 0; i < 23; i++) { + longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; + if (longLimit[j][i] > SBLIMIT) + longLimit[j][i] = SBLIMIT; + } + for (i = 0; i < 14; i++) { + shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1; + if (shortLimit[j][i] > SBLIMIT) + shortLimit[j][i] = SBLIMIT; + } + } + + for (i = 0; i < 5; i++) { + for (j = 0; j < 6; j++) { + for (k = 0; k < 6; k++) { + int n = k + j * 6 + i * 36; + i_slen2[n] = i | (j << 3) | (k << 6) | (3 << 12); + } + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + int n = k + j * 4 + i * 16; + i_slen2[n + 180] = i | (j << 3) | (k << 6) | (4 << 12); + } + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + int n = j + i * 3; + i_slen2[n + 244] = i | (j << 3) | (5 << 12); + n_slen2[n + 500] = i | (j << 3) | (2 << 12) | (1 << 15); + } + } + + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; k < 4; k++) { + int l; + for (l = 0; l < 4; l++) { + int n = l + k * 4 + j * 16 + i * 80; + n_slen2[n] = i | (j << 3) | (k << 6) | (l << 9) | (0 << 12); + } + } + } + } + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; k < 4; k++) { + int n = k + j * 4 + i * 20; + n_slen2[n + 400] = i | (j << 3) | (k << 6) | (1 << 12); + } + } + } +} + +/* + * read additional side information + */ + +static void +III_get_side_info_1(PMPSTR mp, int stereo, + int ms_stereo, long sfreq, int single) +{ + int ch, gr; + int powdiff = (single == 3) ? 4 : 0; + + mp->sideinfo.main_data_begin = getbits(mp, 9); + if (stereo == 1) + mp->sideinfo.private_bits = getbits_fast(mp, 5); + else + mp->sideinfo.private_bits = getbits_fast(mp, 3); + + for (ch = 0; ch < stereo; ch++) { + mp->sideinfo.ch[ch].gr[0].scfsi = -1; + mp->sideinfo.ch[ch].gr[1].scfsi = getbits_fast(mp, 4); + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < stereo; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + + gr_infos->part2_3_length = getbits(mp, 12); + gr_infos->big_values = getbits_fast(mp, 9); + if (gr_infos->big_values > 288) { + lame_report_fnc(mp->report_err, "big_values too large! %i\n", gr_infos->big_values); + gr_infos->big_values = 288; + } + { + unsigned int qss = getbits_fast(mp, 8); + gr_infos->pow2gain = gainpow2 + 256 - qss + powdiff; + if (mp->pinfo != NULL) { + mp->pinfo->qss[gr][ch] = qss; + } + } + if (ms_stereo) + gr_infos->pow2gain += 2; + gr_infos->scalefac_compress = getbits_fast(mp, 4); +/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ + if (get1bit(mp)) { + int i; + gr_infos->block_type = getbits_fast(mp, 2); + gr_infos->mixed_block_flag = get1bit(mp); + gr_infos->table_select[0] = getbits_fast(mp, 5); + gr_infos->table_select[1] = getbits_fast(mp, 5); + + + /* + * table_select[2] not needed, because there is no region2, + * but to satisfy some verifications tools we set it either. + */ + gr_infos->table_select[2] = 0; + for (i = 0; i < 3; i++) { + unsigned int sbg = (getbits_fast(mp, 3) << 3); + gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; + if (mp->pinfo != NULL) + mp->pinfo->sub_gain[gr][ch][i] = sbg / 8; + } + + if (gr_infos->block_type == 0) { + lame_report_fnc(mp->report_err, "Blocktype == 0 and window-switching == 1 not allowed.\n"); + /* error seems to be very good recoverable, so don't exit */ + /* exit(1); */ + } + /* region_count/start parameters are implicit in this case. */ + gr_infos->region1start = 36 >> 1; + gr_infos->region2start = 576 >> 1; + } + else { + unsigned int i, r0c, r1c, region0index, region1index; + for (i = 0; i < 3; i++) + gr_infos->table_select[i] = getbits_fast(mp, 5); + r0c = getbits_fast(mp, 4); + r1c = getbits_fast(mp, 3); + region0index = r0c+1; + if (region0index > 22) { + lame_report_fnc(mp->report_err, "region0index=%d > 22\n", region0index); + region0index = 22; + } + region1index = r0c+1 + r1c+1; + if (region1index > 22) { + lame_report_fnc(mp->report_err, "region1index=%d > 22\n", region1index); + region1index = 22; + } + gr_infos->region1start = bandInfo[sfreq].longIdx[region0index] >> 1; + gr_infos->region2start = bandInfo[sfreq].longIdx[region1index] >> 1; + gr_infos->block_type = 0; + gr_infos->mixed_block_flag = 0; + } + gr_infos->preflag = get1bit(mp); + gr_infos->scalefac_scale = get1bit(mp); + gr_infos->count1table_select = get1bit(mp); + } + } +} + +/* + * Side Info for MPEG 2.0 / LSF + */ +static void +III_get_side_info_2(PMPSTR mp, int stereo, int ms_stereo, long sfreq, int single) +{ + int ch; + int powdiff = (single == 3) ? 4 : 0; + + mp->sideinfo.main_data_begin = getbits(mp, 8); + + if (stereo == 1) + mp->sideinfo.private_bits = get1bit(mp); + else + mp->sideinfo.private_bits = getbits_fast(mp, 2); + + for (ch = 0; ch < stereo; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[0]); + unsigned int qss; + + gr_infos->part2_3_length = getbits(mp, 12); + gr_infos->big_values = getbits_fast(mp, 9); + if (gr_infos->big_values > 288) { + lame_report_fnc(mp->report_err, "big_values too large! %i\n", gr_infos->big_values); + gr_infos->big_values = 288; + } + qss = getbits_fast(mp, 8); + gr_infos->pow2gain = gainpow2 + 256 - qss + powdiff; + if (mp->pinfo != NULL) { + mp->pinfo->qss[0][ch] = qss; + } + + + if (ms_stereo) + gr_infos->pow2gain += 2; + gr_infos->scalefac_compress = getbits(mp, 9); +/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ + if (get1bit(mp)) { + int i; + gr_infos->block_type = getbits_fast(mp, 2); + gr_infos->mixed_block_flag = get1bit(mp); + gr_infos->table_select[0] = getbits_fast(mp, 5); + gr_infos->table_select[1] = getbits_fast(mp, 5); + /* + * table_select[2] not needed, because there is no region2, + * but to satisfy some verifications tools we set it either. + */ + gr_infos->table_select[2] = 0; + for (i = 0; i < 3; i++) { + unsigned int sbg = (getbits_fast(mp, 3) << 3); + gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; + if (mp->pinfo != NULL) + mp->pinfo->sub_gain[0][ch][i] = sbg / 8; + + } + + if (gr_infos->block_type == 0) { + lame_report_fnc(mp->report_err, "Blocktype == 0 and window-switching == 1 not allowed.\n"); + /* error seems to be very good recoverable, so don't exit */ + /* exit(1); */ + } + /* region_count/start parameters are implicit in this case. */ + if (gr_infos->block_type == 2) { + if (gr_infos->mixed_block_flag == 0) + gr_infos->region1start = 36 >> 1; + else + gr_infos->region1start = 48 >> 1; + } + else + gr_infos->region1start = 54 >> 1; + if (sfreq == 8) + gr_infos->region1start *= 2; + gr_infos->region2start = 576 >> 1; + } + else { + unsigned int i, r0c, r1c, region0index, region1index; + for (i = 0; i < 3; i++) + gr_infos->table_select[i] = getbits_fast(mp, 5); + r0c = getbits_fast(mp, 4); + r1c = getbits_fast(mp, 3); + region0index = r0c+1; + if (region0index > 22) { + lame_report_fnc(mp->report_err, "region0index=%d > 22\n", region0index); + region0index = 22; + } + region1index = r0c+1 + r1c+1; + if (region1index > 22) { + lame_report_fnc(mp->report_err, "region1index=%d > 22\n", region1index); + region1index = 22; + } + gr_infos->region1start = bandInfo[sfreq].longIdx[region0index] >> 1; + gr_infos->region2start = bandInfo[sfreq].longIdx[region1index] >> 1; + gr_infos->block_type = 0; + gr_infos->mixed_block_flag = 0; + } + gr_infos->scalefac_scale = get1bit(mp); + gr_infos->count1table_select = get1bit(mp); + } +} + +/* + * read scalefactors + */ + +static int +III_get_scale_factors_1(PMPSTR mp, int *scf, struct gr_info_s *gr_infos) +{ + static const unsigned char slen[2][16] = { + {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, + {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} + }; + int numbits; + int num0 = slen[0][gr_infos->scalefac_compress]; + int num1 = slen[1][gr_infos->scalefac_compress]; + + if (gr_infos->block_type == 2) { + int i = 18; + numbits = (num0 + num1) * 18; + + if (gr_infos->mixed_block_flag) { + for (i = 8; i; i--) + *scf++ = getbits_fast(mp, num0); + i = 9; + numbits -= num0; /* num0 * 17 + num1 * 18 */ + } + + for (; i; i--) + *scf++ = getbits_fast(mp, num0); + for (i = 18; i; i--) + *scf++ = getbits_fast(mp, num1); + *scf++ = 0; + *scf++ = 0; + *scf++ = 0; /* short[13][0..2] = 0 */ + } + else { + int i; + int scfsi = gr_infos->scfsi; + + if (scfsi < 0) { /* scfsi < 0 => granule == 0 */ + for (i = 11; i; i--) + *scf++ = getbits_fast(mp, num0); + for (i = 10; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits = (num0 + num1) * 10 + num0; + } + else { + numbits = 0; + if (!(scfsi & 0x8)) { + for (i = 6; i; i--) + *scf++ = getbits_fast(mp, num0); + numbits += num0 * 6; + } + else { + scf += 6; + } + + if (!(scfsi & 0x4)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num0); + numbits += num0 * 5; + } + else { + scf += 5; + } + + if (!(scfsi & 0x2)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits += num1 * 5; + } + else { + scf += 5; + } + + if (!(scfsi & 0x1)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits += num1 * 5; + } + else { + scf += 5; + } + } + + *scf++ = 0; /* no l[21] in original sources */ + } + return numbits; +} + + +static int +III_get_scale_factors_2(PMPSTR mp, int *scf, struct gr_info_s *gr_infos, int i_stereo) +{ + unsigned char const *pnt; + int i, j; + unsigned int slen; + int n = 0; + int numbits = 0; + + /* *INDENT-OFF* */ + static const unsigned char stab[3][6][4] = { + { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , + { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , + { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , + {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , + { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , + { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} } }; + /* *INDENT-ON* */ + + if (i_stereo) /* i_stereo AND second channel -> do_layer3() checks this */ + slen = i_slen2[gr_infos->scalefac_compress >> 1]; + else + slen = n_slen2[gr_infos->scalefac_compress]; + + gr_infos->preflag = (slen >> 15) & 0x1; + + n = 0; + if (gr_infos->block_type == 2) { + n++; + if (gr_infos->mixed_block_flag) + n++; + } + + pnt = (unsigned char const *) stab[n][(slen >> 12) & 0x7]; + + for (i = 0; i < 4; i++) { + int num = slen & 0x7; + slen >>= 3; + if (num) { + for (j = 0; j < (int) (pnt[i]); j++) + *scf++ = getbits_fast(mp, num); + numbits += pnt[i] * num; + } + else { + for (j = 0; j < (int) (pnt[i]); j++) + *scf++ = 0; + } + } + + n = (n << 1) + 1; + for (i = 0; i < n; i++) + *scf++ = 0; + + return numbits; +} + +/* *INDENT-OFF* */ +static const int pretab1 [22] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0}; /* char enough ? */ +static const int pretab2 [22] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +/* *INDENT-ON* */ + +/* + * don't forget to apply the same changes to III_dequantize_sample_ms() !!! + */ +static int +III_dequantize_sample(PMPSTR mp, real xr[SBLIMIT][SSLIMIT], int *scf, + struct gr_info_s *gr_infos, int sfreq, int part2bits) +{ + int shift = 1 + gr_infos->scalefac_scale; + real *xrpnt = (real *) xr, xr_value=0; + int l[3], l3; + int part2remain = gr_infos->part2_3_length - part2bits; + int *me; + real const * const xr_endptr = &xr[SBLIMIT-1][SSLIMIT-1]; + + int isbug = 0; + int bobug = 0; + int bobug_sb = 0, bobug_l3=0; +#define BUFFER_OVERFLOW_BUG() if(!bobug){bobug=1;bobug_sb=cb;bobug_l3=l3;}else + + /* lame_report_fnc(mp->report_dbg,"part2remain = %d, gr_infos->part2_3_length = %d, part2bits = %d\n", + part2remain, gr_infos->part2_3_length, part2bits); */ + + { + int i; + + for (i = (&xr[SBLIMIT][0] - xrpnt) >> 1; i > 0; i--) { + *xrpnt++ = 0.0; + *xrpnt++ = 0.0; + } + + xrpnt = (real *) xr; + } + + { + int bv = gr_infos->big_values; + int region1 = gr_infos->region1start; + int region2 = gr_infos->region2start; + + l3 = ((576 >> 1) - bv) >> 1; +/* + * we may lose the 'odd' bit here !! + * check this later again + */ + if (bv <= region1) { + l[0] = bv; + l[1] = 0; + l[2] = 0; + } + else { + l[0] = region1; + if (bv <= region2) { + l[1] = bv - l[0]; + l[2] = 0; + } + else { + l[1] = region2 - l[0]; + l[2] = bv - region2; + } + } + } + /* MDH crash fix */ + { + int i; + for (i = 0; i < 3; i++) { + if (l[i] < 0) { + lame_report_fnc(mp->report_err, "hip: Bogus region length (%d)\n", l[i]); + l[i] = 0; + } + } + } + /* end MDH crash fix */ + + if (gr_infos->block_type == 2) { + /* + * decoding with short or mixed mode BandIndex table + */ + int i, max[4]; + int step = 0, lwin = 0, cb = 0; + real v = 0.0; + int *m, mc; + + if (gr_infos->mixed_block_flag) { + max[3] = -1; + max[0] = max[1] = max[2] = 2; + m = map[sfreq][0]; + me = mapend[sfreq][0]; + } + else { + max[0] = max[1] = max[2] = max[3] = -1; + /* max[3] not really needed in this case */ + m = map[sfreq][1]; + me = mapend[sfreq][1]; + } + + mc = 0; + for (i = 0; i < 2; i++) { + int lp = l[i]; + struct newhuff const *h = (struct newhuff const *) (ht + gr_infos->table_select[i]); + for (; lp; lp--, mc--) { + int x, y; + if ((!mc)) { + mc = *m++; + xrpnt = ((real *) xr) + (*m++); + lwin = *m++; + cb = *m++; + if (lwin == 3) { + v = get_gain(gr_infos->pow2gain, (*scf++) << shift, &isbug); + step = 1; + } + else { + v = get_gain(gr_infos->full_gain[lwin], (*scf++) << shift, &isbug); + step = 3; + } + } + { + short const *val = (short const *) h->table; + while ((y = *val++) < 0) { + if (get1bit(mp)) + val -= y; + part2remain--; + } + x = y >> 4; + y &= 0xf; + } + if (x == 15) { + max[lwin] = cb; + part2remain -= h->linbits + 1; + x += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + xr_value = -ispow[x] * v; + else + xr_value = ispow[x] * v; + } + else if (x) { + max[lwin] = cb; + if (get1bit(mp)) + xr_value = -ispow[x] * v; + else + xr_value = ispow[x] * v; + part2remain--; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt = xr_value; + else + BUFFER_OVERFLOW_BUG(); + xrpnt += step; + if (y == 15) { + max[lwin] = cb; + part2remain -= h->linbits + 1; + y += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + xr_value = -ispow[y] * v; + else + xr_value = ispow[y] * v; + } + else if (y) { + max[lwin] = cb; + if (get1bit(mp)) + xr_value = -ispow[y] * v; + else + xr_value = ispow[y] * v; + part2remain--; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt = xr_value; + else + BUFFER_OVERFLOW_BUG(); + xrpnt += step; + } + } + for (; (l3 > 0) && (part2remain > 0); l3--) { + struct newhuff const *h = (struct newhuff const *) (htc + gr_infos->count1table_select); + short const *val = (short const *) h->table; + short a; + + while ((a = *val++) < 0) { + part2remain--; + if (part2remain < 0) { + part2remain++; + a = 0; + break; + } + if (get1bit(mp)) + val -= a; + } + for (i = 0; i < 4; i++) { + if (!(i & 1)) { + if (!mc) { + mc = *m++; + xrpnt = ((real *) xr) + (*m++); + lwin = *m++; + cb = *m++; + if (lwin == 3) { + v = get_gain(gr_infos->pow2gain, (*scf++) << shift, &isbug); + step = 1; + } + else { + v = get_gain(gr_infos->full_gain[lwin], (*scf++) << shift, &isbug); + step = 3; + } + } + mc--; + } + if ((a & (0x8 >> i))) { + max[lwin] = cb; + part2remain--; + if (part2remain < 0) { + part2remain++; + break; + } + if (get1bit(mp)) + xr_value = -v; + else + xr_value = v; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt = xr_value; + else + BUFFER_OVERFLOW_BUG(); + xrpnt += step; + } + } + while (m < me) { + if (!mc) { + mc = *m++; + xrpnt = ((real *) xr) + *m++; + if ((*m++) == 3) + step = 1; + else + step = 3; + m++; /* cb */ + } + mc--; + if (xrpnt <= xr_endptr) + *xrpnt = 0.0; + else + BUFFER_OVERFLOW_BUG(); + xrpnt += step; + if (xrpnt <= xr_endptr) + *xrpnt = 0.0; + else + BUFFER_OVERFLOW_BUG(); + xrpnt += step; +/* we could add a little opt. here: + * if we finished a band for window 3 or a long band + * further bands could copied in a simple loop without a + * special 'map' decoding + */ + } + + gr_infos->maxband[0] = max[0] + 1; + gr_infos->maxband[1] = max[1] + 1; + gr_infos->maxband[2] = max[2] + 1; + gr_infos->maxbandl = max[3] + 1; + + { + int rmax = max[0] > max[1] ? max[0] : max[1]; + rmax = (rmax > max[2] ? rmax : max[2]) + 1; + gr_infos->maxb = rmax ? shortLimit[sfreq][rmax] : longLimit[sfreq][max[3] + 1]; + } + + } + else { + /* + * decoding with 'long' BandIndex table (block_type != 2) + */ + int const *pretab = (int const *) (gr_infos->preflag ? pretab1 : pretab2); + int i, max = -1; + int cb = 0; + int *m = map[sfreq][2]; + real v = 0.0; + int mc = 0; + + /* + * long hash table values + */ + for (i = 0; i < 3; i++) { + int lp = l[i]; + struct newhuff const *h = (struct newhuff const *) (ht + gr_infos->table_select[i]); + + for (; lp; lp--, mc--) { + int x, y; + + if (!mc) { + mc = *m++; + v = get_gain(gr_infos->pow2gain, ((*scf++) + (*pretab++)) << shift, &isbug); + cb = *m++; + } + { + short const *val = (short const *) h->table; + while ((y = *val++) < 0) { + if (get1bit(mp)) + val -= y; + part2remain--; + } + x = y >> 4; + y &= 0xf; + } + if (x == 15) { + max = cb; + part2remain -= h->linbits + 1; + x += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + xr_value = -ispow[x] * v; + else + xr_value = ispow[x] * v; + } + else if (x) { + max = cb; + if (get1bit(mp)) + xr_value = -ispow[x] * v; + else + xr_value = ispow[x] * v; + part2remain--; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt++ = xr_value; + else + BUFFER_OVERFLOW_BUG(); + + if (y == 15) { + max = cb; + part2remain -= h->linbits + 1; + y += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + xr_value = -ispow[y] * v; + else + xr_value = ispow[y] * v; + } + else if (y) { + max = cb; + if (get1bit(mp)) + xr_value = -ispow[y] * v; + else + xr_value = ispow[y] * v; + part2remain--; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt++ = xr_value; + else + BUFFER_OVERFLOW_BUG(); + } + } + + /* + * short (count1table) values + */ + for (; l3 && (part2remain > 0); l3--) { + struct newhuff const *h = (struct newhuff const *) (htc + gr_infos->count1table_select); + short const *val = (short const *) h->table; + short a; + + while ((a = *val++) < 0) { + part2remain--; + if (part2remain < 0) { + part2remain++; + a = 0; + break; + } + if (get1bit(mp)) + val -= a; + } + for (i = 0; i < 4; i++) { + if (!(i & 1)) { + if (!mc) { + mc = *m++; + cb = *m++; + v = get_gain(gr_infos->pow2gain, ((*scf++) + (*pretab++)) << shift, &isbug); + } + mc--; + } + if ((a & (0x8 >> i))) { + max = cb; + part2remain--; + if (part2remain < 0) { + part2remain++; + break; + } + if (get1bit(mp)) + xr_value = -v; + else + xr_value = v; + } + else + xr_value = 0.0; + + if (xrpnt <= xr_endptr) + *xrpnt++ = xr_value; + else + BUFFER_OVERFLOW_BUG(); + } + } + + /* + * zero part + */ + while (xrpnt <= xr_endptr) + *xrpnt++ = 0.0; + + gr_infos->maxbandl = max + 1; + gr_infos->maxb = longLimit[sfreq][gr_infos->maxbandl]; + } +#undef BUFFER_OVERFLOW_BUG + if (bobug) { + /* well, there was a bug report, where this happened! + The problem was, that mixed blocks summed up to over 576, + because of a wrong long/short switching index. + It's likely, that the buffer overflow is fixed now, after correcting mixed block map. + */ + lame_report_fnc + (mp->report_err + ,"hip: OOPS, part2remain=%d l3=%d cb=%d bv=%d region1=%d region2=%d b-type=%d mixed=%d\n" + ,part2remain + ,bobug_l3 + ,bobug_sb + ,gr_infos->big_values + ,gr_infos->region1start + ,gr_infos->region2start + ,gr_infos->block_type + ,gr_infos->mixed_block_flag + ); + } + if (isbug) { + /* there is a bug report, where there is trouble with IS coded short block gain. + Is intensity stereo coding implementation correct? Likely not. + */ + int i_stereo = 0; + if (mp->fr.mode == MPG_MD_JOINT_STEREO) { + i_stereo = mp->fr.mode_ext & 0x1; + } + lame_report_fnc + (mp->report_err + ,"hip: OOPS, 'gainpow2' buffer overflow lsf=%d i-stereo=%d b-type=%d mixed=%d\n" + ,mp->fr.lsf + ,i_stereo + ,gr_infos->block_type + ,gr_infos->mixed_block_flag + ); + } + + while (part2remain > 16) { + getbits(mp, 16); /* Dismiss stuffing Bits */ + part2remain -= 16; + } + if (part2remain > 0) + getbits(mp, part2remain); + else if (part2remain < 0) { + lame_report_fnc(mp->report_err, "hip: Can't rewind stream by %d bits!\n", -part2remain); + return 1; /* -> error */ + } + return 0; +} + +/* intensity position, transmitted via a scalefactor value, allowed range is 0 - 15 */ +static +int scalefac_to_is_pos(int sf) +{ + if (0 <= sf && sf <= 15) + return sf; + return (sf < 0 ? 0 : 15); +} + +/* + * III_stereo: calculate real channel values for Joint-I-Stereo-mode + */ +static void +III_i_stereo(real xr_buf[2][SBLIMIT][SSLIMIT], int *scalefac, + struct gr_info_s *gr_infos, int sfreq, int ms_stereo, int lsf) +{ + real(*xr)[SBLIMIT * SSLIMIT] = (real(*)[SBLIMIT * SSLIMIT]) xr_buf; + struct bandInfoStruct const *bi = (struct bandInfoStruct const *) &bandInfo[sfreq]; + real *tabl1, *tabl2; + + if (lsf) { + int p = gr_infos->scalefac_compress & 0x1; + if (ms_stereo) { + tabl1 = pow1_2[p]; + tabl2 = pow2_2[p]; + } + else { + tabl1 = pow1_1[p]; + tabl2 = pow2_1[p]; + } + } + else { + if (ms_stereo) { + tabl1 = tan1_2; + tabl2 = tan2_2; + } + else { + tabl1 = tan1_1; + tabl2 = tan2_1; + } + } + + if (gr_infos->block_type == 2) { + int lwin, do_l = 0; + if (gr_infos->mixed_block_flag) + do_l = 1; + + for (lwin = 0; lwin < 3; lwin++) { /* process each window */ + /* get first band with zero values */ + int is_p, sb, idx, sfb = gr_infos->maxband[lwin]; /* sfb is minimal 3 for mixed mode */ + if (sfb > 3) + do_l = 0; + + for (; sfb < 12; sfb++) { + is_p = scalefac[sfb * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + is_p = scalefac_to_is_pos(is_p); + if (is_p != 7) { + real t1, t2; + sb = bi->shortDiff[sfb]; + idx = bi->shortIdx[sfb] + lwin; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx += 3) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } + +#if 1 +/* in the original: copy 10 to 11 , here: copy 11 to 12 +maybe still wrong??? (copy 12 to 13?) */ + is_p = scalefac[11 * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + sb = bi->shortDiff[12]; + idx = bi->shortIdx[12] + lwin; +#else + is_p = scalefac[10 * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + sb = bi->shortDiff[11]; + idx = bi->shortIdx[11] + lwin; +#endif + is_p = scalefac_to_is_pos(is_p); + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx += 3) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* end for(lwin; .. ; . ) */ + + if (do_l) { +/* also check l-part, if ALL bands in the three windows are 'empty' + * and mode = mixed_mode + */ + int sfb = gr_infos->maxbandl; + int idx = bi->longIdx[sfb]; + + for (; sfb < 8; sfb++) { + int sb = bi->longDiff[sfb]; + int is_p = scalefac[sfb]; /* scale: 0-15 */ + is_p = scalefac_to_is_pos(is_p); + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + } + } + else { /* ((gr_infos->block_type != 2)) */ + + int sfb = gr_infos->maxbandl; + int is_p, idx = bi->longIdx[sfb]; + for (; sfb < 21; sfb++) { + int sb = bi->longDiff[sfb]; + is_p = scalefac[sfb]; /* scale: 0-15 */ + is_p = scalefac_to_is_pos(is_p); + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + + is_p = scalefac[20]; /* copy l-band 20 to l-band 21 */ + is_p = scalefac_to_is_pos(is_p); + idx = bi->longIdx[21]; + if (is_p != 7) { + int sb; + real t1 = tabl1[is_p], t2 = tabl2[is_p]; + + for (sb = bi->longDiff[21]; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* ... */ +} + +static void +III_antialias(real xr[SBLIMIT][SSLIMIT], struct gr_info_s *gr_infos) +{ + int sblim; + + if (gr_infos->block_type == 2) { + if (!gr_infos->mixed_block_flag) + return; + sblim = 1; + } + else { + sblim = gr_infos->maxb - 1; + } + + /* 31 alias-reduction operations between each pair of sub-bands */ + /* with 8 butterflies between each pair */ + + { + int sb; + real *xr1 = (real *) xr[1]; + + for (sb = sblim; sb; sb--, xr1 += 10) { + int ss; + real *cs = aa_cs, *ca = aa_ca; + real *xr2 = xr1; + + for (ss = 7; ss >= 0; ss--) { /* upper and lower butterfly inputs */ + real bu = *--xr2, bd = *xr1; + *xr2 = (bu * (*cs)) - (bd * (*ca)); + *xr1++ = (bd * (*cs++)) + (bu * (*ca++)); + } + } + } +} + + +/* *INDENT-OFF* */ + +/* + DCT insipired by Jeff Tsay's DCT from the maplay package + this is an optimized version with manual unroll. + + References: + [1] S. Winograd: "On Computing the Discrete Fourier Transform", + Mathematics of Computation, Volume 32, Number 141, January 1978, + Pages 175-199 +*/ + +static void dct36(real *inbuf,real *o1,real *o2,real *wintab,real *tsbuf) +{ + { + real *in = inbuf; + + in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; + in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; + in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; + in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; + in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; + in[2] +=in[1]; in[1] +=in[0]; + + in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; + in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; + + { + +#define MACRO0(v) { \ + real tmp; \ + out2[9+(v)] = (tmp = sum0 + sum1) * w[27+(v)]; \ + out2[8-(v)] = tmp * w[26-(v)]; } \ + sum0 -= sum1; \ + ts[SBLIMIT*(8-(v))] = out1[8-(v)] + sum0 * w[8-(v)]; \ + ts[SBLIMIT*(9+(v))] = out1[9+(v)] + sum0 * w[9+(v)]; +#define MACRO1(v) { \ + real sum0,sum1; \ + sum0 = tmp1a + tmp2a; \ + sum1 = (tmp1b + tmp2b) * tfcos36[(v)]; \ + MACRO0(v); } +#define MACRO2(v) { \ + real sum0,sum1; \ + sum0 = tmp2a - tmp1a; \ + sum1 = (tmp2b - tmp1b) * tfcos36[(v)]; \ + MACRO0(v); } + + const real *c = COS9; + real *out2 = o2; + real *w = wintab; + real *out1 = o1; + real *ts = tsbuf; + + real ta33,ta66,tb33,tb66; + + ta33 = in[2*3+0] * c[3]; + ta66 = in[2*6+0] * c[6]; + tb33 = in[2*3+1] * c[3]; + tb66 = in[2*6+1] * c[6]; + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[1] + ta33 + in[2*5+0] * c[5] + in[2*7+0] * c[7]; + tmp1b = in[2*1+1] * c[1] + tb33 + in[2*5+1] * c[5] + in[2*7+1] * c[7]; + tmp2a = in[2*0+0] + in[2*2+0] * c[2] + in[2*4+0] * c[4] + ta66 + in[2*8+0] * c[8]; + tmp2b = in[2*0+1] + in[2*2+1] * c[2] + in[2*4+1] * c[4] + tb66 + in[2*8+1] * c[8]; + + MACRO1(0); + MACRO2(8); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = ( in[2*1+0] - in[2*5+0] - in[2*7+0] ) * c[3]; + tmp1b = ( in[2*1+1] - in[2*5+1] - in[2*7+1] ) * c[3]; + tmp2a = ( in[2*2+0] - in[2*4+0] - in[2*8+0] ) * c[6] - in[2*6+0] + in[2*0+0]; + tmp2b = ( in[2*2+1] - in[2*4+1] - in[2*8+1] ) * c[6] - in[2*6+1] + in[2*0+1]; + + MACRO1(1); + MACRO2(7); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[5] - ta33 - in[2*5+0] * c[7] + in[2*7+0] * c[1]; + tmp1b = in[2*1+1] * c[5] - tb33 - in[2*5+1] * c[7] + in[2*7+1] * c[1]; + tmp2a = in[2*0+0] - in[2*2+0] * c[8] - in[2*4+0] * c[2] + ta66 + in[2*8+0] * c[4]; + tmp2b = in[2*0+1] - in[2*2+1] * c[8] - in[2*4+1] * c[2] + tb66 + in[2*8+1] * c[4]; + + MACRO1(2); + MACRO2(6); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[7] - ta33 + in[2*5+0] * c[1] - in[2*7+0] * c[5]; + tmp1b = in[2*1+1] * c[7] - tb33 + in[2*5+1] * c[1] - in[2*7+1] * c[5]; + tmp2a = in[2*0+0] - in[2*2+0] * c[4] + in[2*4+0] * c[8] + ta66 - in[2*8+0] * c[2]; + tmp2b = in[2*0+1] - in[2*2+1] * c[4] + in[2*4+1] * c[8] + tb66 - in[2*8+1] * c[2]; + + MACRO1(3); + MACRO2(5); + } + + { + real sum0,sum1; + sum0 = in[2*0+0] - in[2*2+0] + in[2*4+0] - in[2*6+0] + in[2*8+0]; + sum1 = (in[2*0+1] - in[2*2+1] + in[2*4+1] - in[2*6+1] + in[2*8+1] ) * tfcos36[4]; + MACRO0(4); + } + } + + } +} + + +/* + * new DCT12 + */ +static void dct12(real *in,real *rawout1,real *rawout2,real *wi,real *ts) +{ +#define DCT12_PART1 \ + in5 = in[5*3]; \ + in5 += (in4 = in[4*3]); \ + in4 += (in3 = in[3*3]); \ + in3 += (in2 = in[2*3]); \ + in2 += (in1 = in[1*3]); \ + in1 += (in0 = in[0*3]); \ + \ + in5 += in3; in3 += in1; \ + \ + in2 *= COS6_1; \ + in3 *= COS6_1; \ + +#define DCT12_PART2 \ + in0 += in4 * COS6_2; \ + \ + in4 = in0 + in2; \ + in0 -= in2; \ + \ + in1 += in5 * COS6_2; \ + \ + in5 = (in1 + in3) * tfcos12[0]; \ + in1 = (in1 - in3) * tfcos12[2]; \ + \ + in3 = in4 + in5; \ + in4 -= in5; \ + \ + in2 = in0 + in1; \ + in0 -= in1; + + + { + real in0,in1,in2,in3,in4,in5; + real *out1 = rawout1; + ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; + ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; + ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; + ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; + ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; + } + + DCT12_PART2 + + ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; + ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; + ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; + ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; + + ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; + ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; + ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; + ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; + } + + in++; + + { + real in0,in1,in2,in3,in4,in5; + real *out2 = rawout2; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[5-1] = tmp0 * wi[11-1]; + out2[0+1] = tmp0 * wi[6+1]; + ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; + ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[5-0] = in2 * wi[11-0]; + out2[0+0] = in2 * wi[6+0]; + out2[0+2] = in3 * wi[6+2]; + out2[5-2] = in3 * wi[11-2]; + + ts[(12+0)*SBLIMIT] += in0 * wi[0]; + ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; + ts[(12+2)*SBLIMIT] += in4 * wi[2]; + ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; + } + + in++; + + { + real in0,in1,in2,in3,in4,in5; + real *out2 = rawout2; + out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[11-1] = tmp0 * wi[11-1]; + out2[6 +1] = tmp0 * wi[6+1]; + out2[0+1] += tmp1 * wi[1]; + out2[5-1] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[11-0] = in2 * wi[11-0]; + out2[6 +0] = in2 * wi[6+0]; + out2[6 +2] = in3 * wi[6+2]; + out2[11-2] = in3 * wi[11-2]; + + out2[0+0] += in0 * wi[0]; + out2[5-0] += in0 * wi[5-0]; + out2[0+2] += in4 * wi[2]; + out2[5-2] += in4 * wi[5-2]; + } +} +/* *INDENT-ON* */ + +/* + * III_hybrid + */ +static void +III_hybrid(PMPSTR mp, real fsIn[SBLIMIT][SSLIMIT], real tsOut[SSLIMIT][SBLIMIT], + int ch, struct gr_info_s *gr_infos) +{ + real *tspnt = (real *) tsOut; + real(*block)[2][SBLIMIT * SSLIMIT] = mp->hybrid_block; + int *blc = mp->hybrid_blc; + real *rawout1, *rawout2; + int bt; + int sb = 0; + + { + int b = blc[ch]; + rawout1 = block[b][ch]; + b = -b + 1; + rawout2 = block[b][ch]; + blc[ch] = b; + } + + + if (gr_infos->mixed_block_flag) { + sb = 2; + dct36(fsIn[0], rawout1, rawout2, win[0], tspnt); + dct36(fsIn[1], rawout1 + 18, rawout2 + 18, win1[0], tspnt + 1); + rawout1 += 36; + rawout2 += 36; + tspnt += 2; + } + + bt = gr_infos->block_type; + if (bt == 2) { + for (; sb < (int) gr_infos->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { + dct12(fsIn[sb], rawout1, rawout2, win[2], tspnt); + dct12(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, win1[2], tspnt + 1); + } + } + else { + for (; sb < (int) gr_infos->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { + dct36(fsIn[sb], rawout1, rawout2, win[bt], tspnt); + dct36(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, win1[bt], tspnt + 1); + } + } + + for (; sb < SBLIMIT; sb++, tspnt++) { + int i; + for (i = 0; i < SSLIMIT; i++) { + tspnt[i * SBLIMIT] = *rawout1++; + *rawout2++ = 0.0; + } + } +} + +/* + * main layer3 handler + */ + +int +layer3_audiodata_precedesframes(PMPSTR mp) +{ + int audioDataInFrame; + int framesToBacktrack; + + /* specific to Layer 3, since Layer 1 & 2 the audio data starts at the frame that describes it. */ + /* determine how many bytes and therefore bitstream frames the audio data precedes it's matching frame */ + /* lame_report_fnc(mp->report_err, "hip: main_data_begin = %d, mp->bsize %d, mp->fsizeold %d, mp->ssize %d\n", + sideinfo.main_data_begin, mp->bsize, mp->fsizeold, mp->ssize); */ + /* compute the number of frames to backtrack, 4 for the header, ssize already holds the CRC */ + /* TODO Erroneously assumes current frame is same as previous frame. */ + audioDataInFrame = mp->bsize - 4 - mp->ssize; + framesToBacktrack = (mp->sideinfo.main_data_begin + audioDataInFrame - 1) / audioDataInFrame; + /* lame_report_fnc(mp->report_err, "hip: audioDataInFrame %d framesToBacktrack %d\n", audioDataInFrame, framesToBacktrack); */ + return framesToBacktrack; +} + +int +decode_layer3_sideinfo(PMPSTR mp) +{ + struct frame *fr = &mp->fr; + int stereo = fr->stereo; + int single = fr->single; + int ms_stereo; + int sfreq = fr->sampling_frequency; + int granules; + int ch, gr, databits; + + if (stereo == 1) { /* stream is mono */ + single = 0; + } + + if (fr->mode == MPG_MD_JOINT_STEREO) { + ms_stereo = fr->mode_ext & 0x2; + } + else + ms_stereo = 0; + + + if (fr->lsf) { + granules = 1; + III_get_side_info_2(mp, stereo, ms_stereo, sfreq, single); + } + else { + granules = 2; + III_get_side_info_1(mp, stereo, ms_stereo, sfreq, single); + } + + databits = 0; + for (gr = 0; gr < granules; ++gr) { + for (ch = 0; ch < stereo; ++ch) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + databits += gr_infos->part2_3_length; + } + } + return databits - 8 * mp->sideinfo.main_data_begin; +} + + + +int +decode_layer3_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)) +{ + int gr, ch, ss, clip = 0; + int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ + /* struct III_sideinfo sideinfo; */ + struct frame *fr = &(mp->fr); + int stereo = fr->stereo; + int single = fr->single; + int ms_stereo, i_stereo; + int sfreq = fr->sampling_frequency; + int stereo1, granules; + real hybridIn[2][SBLIMIT][SSLIMIT]; + real hybridOut[2][SSLIMIT][SBLIMIT]; + + if (set_pointer(mp, (int) mp->sideinfo.main_data_begin) == MP3_ERR) + return 0; + + if (stereo == 1) { /* stream is mono */ + stereo1 = 1; + single = 0; + } + else if (single >= 0) /* stream is stereo, but force to mono */ + stereo1 = 1; + else + stereo1 = 2; + + if (fr->mode == MPG_MD_JOINT_STEREO) { + ms_stereo = fr->mode_ext & 0x2; + i_stereo = fr->mode_ext & 0x1; + } + else + ms_stereo = i_stereo = 0; + + + if (fr->lsf) { + granules = 1; + } + else { + granules = 2; + } + + for (gr = 0; gr < granules; gr++) { + + { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[0].gr[gr]); + long part2bits; + + if (fr->lsf) + part2bits = III_get_scale_factors_2(mp, scalefacs[0], gr_infos, 0); + else { + part2bits = III_get_scale_factors_1(mp, scalefacs[0], gr_infos); + } + if (mp->pinfo != NULL) { + int i; + mp->pinfo->sfbits[gr][0] = part2bits; + for (i = 0; i < 39; i++) + mp->pinfo->sfb_s[gr][0][i] = scalefacs[0][i]; + } + + /* lame_report_fnc(mp->report_err, "calling III dequantize sample 1 gr_infos->part2_3_length %d\n", gr_infos->part2_3_length); */ + if (III_dequantize_sample(mp, hybridIn[0], scalefacs[0], gr_infos, sfreq, part2bits)) + return clip; + } + if (stereo == 2) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[1].gr[gr]); + long part2bits; + if (fr->lsf) + part2bits = III_get_scale_factors_2(mp, scalefacs[1], gr_infos, i_stereo); + else { + part2bits = III_get_scale_factors_1(mp, scalefacs[1], gr_infos); + } + if (mp->pinfo != NULL) { + int i; + mp->pinfo->sfbits[gr][1] = part2bits; + for (i = 0; i < 39; i++) + mp->pinfo->sfb_s[gr][1][i] = scalefacs[1][i]; + } + + /* lame_report_fnc(mp->report_err, "calling III dequantize sample 2 gr_infos->part2_3_length %d\n", gr_infos->part2_3_length); */ + if (III_dequantize_sample(mp, hybridIn[1], scalefacs[1], gr_infos, sfreq, part2bits)) + return clip; + + if (ms_stereo) { + int i; + for (i = 0; i < SBLIMIT * SSLIMIT; i++) { + real tmp0, tmp1; + tmp0 = ((real *) hybridIn[0])[i]; + tmp1 = ((real *) hybridIn[1])[i]; + ((real *) hybridIn[1])[i] = tmp0 - tmp1; + ((real *) hybridIn[0])[i] = tmp0 + tmp1; + } + } + + if (i_stereo) + III_i_stereo(hybridIn, scalefacs[1], gr_infos, sfreq, ms_stereo, fr->lsf); + + if (ms_stereo || i_stereo || (single == 3)) { + if (gr_infos->maxb > mp->sideinfo.ch[0].gr[gr].maxb) + mp->sideinfo.ch[0].gr[gr].maxb = gr_infos->maxb; + else + gr_infos->maxb = mp->sideinfo.ch[0].gr[gr].maxb; + } + + switch (single) { + case 3: + { + int i; + real *in0 = (real *) hybridIn[0], *in1 = (real *) hybridIn[1]; + for (i = 0; i < (int) (SSLIMIT * gr_infos->maxb); i++, in0++) + *in0 = (*in0 + *in1++); /* *0.5 done by pow-scale */ + } + break; + case 1: + { + int i; + real *in0 = (real *) hybridIn[0], *in1 = (real *) hybridIn[1]; + for (i = 0; i < (int) (SSLIMIT * gr_infos->maxb); i++) + *in0++ = *in1++; + } + break; + } + } + + if (mp->pinfo != NULL) { + int i, sb; + float ifqstep; + + mp->pinfo->bitrate = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index]; + mp->pinfo->sampfreq = freqs[sfreq]; + mp->pinfo->emph = fr->emphasis; + mp->pinfo->crc = fr->error_protection; + mp->pinfo->padding = fr->padding; + mp->pinfo->stereo = fr->stereo; + mp->pinfo->js = (fr->mode == MPG_MD_JOINT_STEREO); + mp->pinfo->ms_stereo = ms_stereo; + mp->pinfo->i_stereo = i_stereo; + mp->pinfo->maindata = mp->sideinfo.main_data_begin; + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + mp->pinfo->big_values[gr][ch] = gr_infos->big_values; + mp->pinfo->scalefac_scale[gr][ch] = gr_infos->scalefac_scale; + mp->pinfo->mixed[gr][ch] = gr_infos->mixed_block_flag; + mp->pinfo->mpg123blocktype[gr][ch] = gr_infos->block_type; + mp->pinfo->mainbits[gr][ch] = gr_infos->part2_3_length; + mp->pinfo->preflag[gr][ch] = gr_infos->preflag; + if (gr == 1) + mp->pinfo->scfsi[ch] = gr_infos->scfsi; + } + + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + ifqstep = (mp->pinfo->scalefac_scale[gr][ch] == 0) ? .5 : 1.0; + if (2 == gr_infos->block_type) { + for (i = 0; i < 3; i++) { + for (sb = 0; sb < 12; sb++) { + int j = 3 * sb + i; + /* + is_p = scalefac[sfb*3+lwin-gr_infos->mixed_block_flag]; + */ + /* scalefac was copied into pinfo->sfb_s[] above */ + mp->pinfo->sfb_s[gr][ch][j] = + -ifqstep * mp->pinfo->sfb_s[gr][ch][j - gr_infos->mixed_block_flag]; + mp->pinfo->sfb_s[gr][ch][j] -= 2 * (mp->pinfo->sub_gain[gr][ch][i]); + } + mp->pinfo->sfb_s[gr][ch][3 * sb + i] = + -2 * (mp->pinfo->sub_gain[gr][ch][i]); + } + } + else { + for (sb = 0; sb < 21; sb++) { + /* scalefac was copied into pinfo->sfb[] above */ + mp->pinfo->sfb[gr][ch][sb] = mp->pinfo->sfb_s[gr][ch][sb]; + if (gr_infos->preflag) + mp->pinfo->sfb[gr][ch][sb] += pretab1[sb]; + mp->pinfo->sfb[gr][ch][sb] *= -ifqstep; + } + mp->pinfo->sfb[gr][ch][21] = 0; + } + } + + + + for (ch = 0; ch < stereo1; ch++) { + int j = 0; + for (sb = 0; sb < SBLIMIT; sb++) + for (ss = 0; ss < SSLIMIT; ss++, j++) + mp->pinfo->mpg123xr[gr][ch][j] = hybridIn[ch][sb][ss]; + } + } + + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + III_antialias(hybridIn[ch], gr_infos); + III_hybrid(mp, hybridIn[ch], hybridOut[ch], ch, gr_infos); + } + + for (ss = 0; ss < SSLIMIT; ss++) { + if (single >= 0) { + clip += (*synth_1to1_mono_ptr) (mp, hybridOut[0][ss], pcm_sample, pcm_point); + } + else { + int p1 = *pcm_point; + clip += (*synth_1to1_ptr) (mp, hybridOut[0][ss], 0, pcm_sample, &p1); + clip += (*synth_1to1_ptr) (mp, hybridOut[1][ss], 1, pcm_sample, pcm_point); + } + } + } + + return clip; +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.h new file mode 100644 index 00000000..2e301920 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/layer3.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef LAYER3_H_INCLUDED +#define LAYER3_H_INCLUDED + +void hip_init_tables_layer3(void); +int decode_layer3_sideinfo(PMPSTR mp); +int decode_layer3_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)); +int layer3_audiodata_precedesframes(PMPSTR mp); + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpg123.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpg123.h new file mode 100644 index 00000000..6ac8b67c --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpg123.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ +#ifndef MPG123_H_INCLUDED +#define MPG123_H_INCLUDED + +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include <signal.h> + + +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include <math.h> +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#undef REAL_IS_FLOAT +#define REAL_IS_FLOAT + +#ifdef REAL_IS_FLOAT +# define real float +#elif defined(REAL_IS_LONG_DOUBLE) +# define real long double +#else +# define real double +#endif + +#define FALSE 0 +#define TRUE 1 + +#define SBLIMIT 32 +#define SSLIMIT 18 + +#define MPG_MD_STEREO 0 +#define MPG_MD_JOINT_STEREO 1 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + +#define MAXFRAMESIZE 2880 + +/* AF: ADDED FOR LAYER1/LAYER2 */ +#define SCALE_BLOCK 12 + + +/* Pre Shift fo 16 to 8 bit converter table */ +#define AUSHIFT (3) + +struct frame { + int stereo; + int single; /* single channel (monophonic) */ + int lsf; /* 0 = MPEG-1, 1 = MPEG-2/2.5 */ + int mpeg25; /* 1 = MPEG-2.5, 0 = MPEG-1/2 */ + int header_change; + int lay; /* Layer */ + int error_protection; /* 1 = CRC-16 code following header */ + int bitrate_index; + int sampling_frequency; /* sample rate of decompressed audio in Hz */ + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; + int framesize; /* computed framesize */ + + /* AF: ADDED FOR LAYER1/LAYER2 */ + int II_sblimit; + struct al_table2 const *alloc; + int down_sample_sblimit; + int down_sample; + + +}; + +struct gr_info_s { + int scfsi; + unsigned part2_3_length; + unsigned big_values; + unsigned scalefac_compress; + unsigned block_type; + unsigned mixed_block_flag; + unsigned table_select[3]; + unsigned subblock_gain[3]; + unsigned maxband[3]; + unsigned maxbandl; + unsigned maxb; + unsigned region1start; + unsigned region2start; + unsigned preflag; + unsigned scalefac_scale; + unsigned count1table_select; + real *full_gain[3]; + real *pow2gain; +}; + +struct III_sideinfo { + unsigned main_data_begin; + unsigned private_bits; + struct { + struct gr_info_s gr[2]; + } ch[2]; +}; + + +#endif diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpglib.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpglib.h new file mode 100644 index 00000000..7ab4d5f4 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/mpglib.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ +#ifndef _MPGLIB_H_ +#define _MPGLIB_H_ + +#include "lame.h" + +#ifndef plotting_data_defined +#define plotting_data_defined +struct plotting_data; +typedef struct plotting_data plotting_data; +#endif + + +extern void lame_report_fnc(lame_report_function f, const char *format, ...); + +struct buf { + unsigned char *pnt; + long size; + long pos; + struct buf *next; + struct buf *prev; +}; + +struct framebuf { + struct buf *buf; + long pos; + struct frame *next; + struct frame *prev; +}; + +typedef struct mpstr_tag { + struct buf *head, *tail; /* buffer linked list pointers, tail points to oldest buffer */ + int vbr_header; /* 1 if valid Xing vbr header detected */ + int num_frames; /* set if vbr header present */ + int enc_delay; /* set if vbr header present */ + int enc_padding; /* set if vbr header present */ + /* header_parsed, side_parsed and data_parsed must be all set 1 + before the full frame has been parsed */ + int header_parsed; /* 1 = header of current frame has been parsed */ + int side_parsed; /* 1 = header of sideinfo of current frame has been parsed */ + int data_parsed; + int free_format; /* 1 = free format frame */ + int old_free_format; /* 1 = last frame was free format */ + int bsize; + int framesize; + int ssize; /* number of bytes used for side information, including 2 bytes for CRC-16 if present */ + int dsize; + int fsizeold; /* size of previous frame, -1 for first */ + int fsizeold_nopadding; + struct frame fr; /* holds the parameters decoded from the header */ + struct III_sideinfo sideinfo; + unsigned char bsspace[2][MAXFRAMESIZE + 1024]; /* bit stream space used ???? */ /* MAXFRAMESIZE */ + real hybrid_block[2][2][SBLIMIT * SSLIMIT]; + int hybrid_blc[2]; + unsigned long header; + int bsnum; + real synth_buffs[2][2][0x110]; + int synth_bo; + int sync_bitstream; /* 1 = bitstream is yet to be synchronized */ + + int bitindex; + unsigned char *wordpointer; + plotting_data *pinfo; + + lame_report_function report_msg; + lame_report_function report_dbg; + lame_report_function report_err; +} MPSTR, *PMPSTR; + + +#define MP3_ERR -1 +#define MP3_OK 0 +#define MP3_NEED_MORE 1 + + + +#endif /* _MPGLIB_H_ */ diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.c b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.c new file mode 100644 index 00000000..7eeaca47 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.c @@ -0,0 +1,152 @@ +/* + * tabinit.c + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: tabinit.c,v 1.17 2017/09/06 15:07:30 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include "tabinit.h" +#include "mpg123.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +static int table_init_called = 0; + +real decwin[512 + 32]; +static real cos64[16], cos32[8], cos16[4], cos8[2], cos4[1]; +real *pnts[] = { cos64, cos32, cos16, cos8, cos4 }; + +/* *INDENT-OFF* */ + +static const double dewin[512] = { + 0.000000000,-0.000015259,-0.000015259,-0.000015259, + -0.000015259,-0.000015259,-0.000015259,-0.000030518, + -0.000030518,-0.000030518,-0.000030518,-0.000045776, + -0.000045776,-0.000061035,-0.000061035,-0.000076294, + -0.000076294,-0.000091553,-0.000106812,-0.000106812, + -0.000122070,-0.000137329,-0.000152588,-0.000167847, + -0.000198364,-0.000213623,-0.000244141,-0.000259399, + -0.000289917,-0.000320435,-0.000366211,-0.000396729, + -0.000442505,-0.000473022,-0.000534058,-0.000579834, + -0.000625610,-0.000686646,-0.000747681,-0.000808716, + -0.000885010,-0.000961304,-0.001037598,-0.001113892, + -0.001205444,-0.001296997,-0.001388550,-0.001480103, + -0.001586914,-0.001693726,-0.001785278,-0.001907349, + -0.002014160,-0.002120972,-0.002243042,-0.002349854, + -0.002456665,-0.002578735,-0.002685547,-0.002792358, + -0.002899170,-0.002990723,-0.003082275,-0.003173828, + -0.003250122,-0.003326416,-0.003387451,-0.003433228, + -0.003463745,-0.003479004,-0.003479004,-0.003463745, + -0.003417969,-0.003372192,-0.003280640,-0.003173828, + -0.003051758,-0.002883911,-0.002700806,-0.002487183, + -0.002227783,-0.001937866,-0.001617432,-0.001266479, + -0.000869751,-0.000442505, 0.000030518, 0.000549316, + 0.001098633, 0.001693726, 0.002334595, 0.003005981, + 0.003723145, 0.004486084, 0.005294800, 0.006118774, + 0.007003784, 0.007919312, 0.008865356, 0.009841919, + 0.010848999, 0.011886597, 0.012939453, 0.014022827, + 0.015121460, 0.016235352, 0.017349243, 0.018463135, + 0.019577026, 0.020690918, 0.021789551, 0.022857666, + 0.023910522, 0.024932861, 0.025909424, 0.026840210, + 0.027725220, 0.028533936, 0.029281616, 0.029937744, + 0.030532837, 0.031005859, 0.031387329, 0.031661987, + 0.031814575, 0.031845093, 0.031738281, 0.031478882, + 0.031082153, 0.030517578, 0.029785156, 0.028884888, + 0.027801514, 0.026535034, 0.025085449, 0.023422241, + 0.021575928, 0.019531250, 0.017257690, 0.014801025, + 0.012115479, 0.009231567, 0.006134033, 0.002822876, + -0.000686646,-0.004394531,-0.008316040,-0.012420654, + -0.016708374,-0.021179199,-0.025817871,-0.030609131, + -0.035552979,-0.040634155,-0.045837402,-0.051132202, + -0.056533813,-0.061996460,-0.067520142,-0.073059082, + -0.078628540,-0.084182739,-0.089706421,-0.095169067, + -0.100540161,-0.105819702,-0.110946655,-0.115921021, + -0.120697021,-0.125259399,-0.129562378,-0.133590698, + -0.137298584,-0.140670776,-0.143676758,-0.146255493, + -0.148422241,-0.150115967,-0.151306152,-0.151962280, + -0.152069092,-0.151596069,-0.150497437,-0.148773193, + -0.146362305,-0.143264771,-0.139450073,-0.134887695, + -0.129577637,-0.123474121,-0.116577148,-0.108856201, + -0.100311279,-0.090927124,-0.080688477,-0.069595337, + -0.057617187,-0.044784546,-0.031082153,-0.016510010, + -0.001068115, 0.015228271, 0.032379150, 0.050354004, + 0.069168091, 0.088775635, 0.109161377, 0.130310059, + 0.152206421, 0.174789429, 0.198059082, 0.221984863, + 0.246505737, 0.271591187, 0.297210693, 0.323318481, + 0.349868774, 0.376800537, 0.404083252, 0.431655884, + 0.459472656, 0.487472534, 0.515609741, 0.543823242, + 0.572036743, 0.600219727, 0.628295898, 0.656219482, + 0.683914185, 0.711318970, 0.738372803, 0.765029907, + 0.791213989, 0.816864014, 0.841949463, 0.866363525, + 0.890090942, 0.913055420, 0.935195923, 0.956481934, + 0.976852417, 0.996246338, 1.014617920, 1.031936646, + 1.048156738, 1.063217163, 1.077117920, 1.089782715, + 1.101211548, 1.111373901, 1.120223999, 1.127746582, + 1.133926392, 1.138763428, 1.142211914, 1.144287109, + 1.144989014 +}; +/* *INDENT-ON* */ + +void +make_decode_tables(long scaleval) +{ + int i, j, k, kr, divv; + real *table, *costab; + + if (table_init_called) + return; + + table_init_called = 1; + + for (i = 0; i < 5; i++) { + kr = 0x10 >> i; + divv = 0x40 >> i; + costab = pnts[i]; + for (k = 0; k < kr; k++) + costab[k] = (real) (1.0 / (2.0 * cos(M_PI * ((double) k * 2.0 + 1.0) / (double) divv))); + } + + table = decwin; + scaleval = -scaleval; + for (i = 0, j = 0; i < 256; i++, j++, table += 32) { + if (table < decwin + 512 + 16) + table[16] = table[0] = (real) (dewin[j] * scaleval); + if (i % 32 == 31) + table -= 1023; + if (i % 64 == 63) + scaleval = -scaleval; + } + + for ( /* i=256 */ ; i < 512; i++, j--, table += 32) { + if (table < decwin + 512 + 16) + table[16] = table[0] = (real) (dewin[j] * scaleval); + if (i % 32 == 31) + table -= 1023; + if (i % 64 == 63) + scaleval = -scaleval; + } +} diff --git a/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.h b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.h new file mode 100644 index 00000000..76f4c42a --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/lame/mpglib/tabinit.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef MPGLIB_TABINIT_H_INCLUDED +#define MPGLIB_TABINIT_H_INCLUDED + +#include "mpg123.h" + +extern real decwin[512 + 32]; +extern real *pnts[5]; + +void make_decode_tables(long scale); + +#endif |