From 28ff64db0ad1aa621afb34d6e2edac84e5d48cb8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 17 Apr 2001 19:31:03 +0000 Subject: [PATCH] Added ac3dec 0.6.1 with native ALSA driver. --- ac3dec/COPYING | 340 +++++++++++++++++++ ac3dec/Changelog | 58 ++++ ac3dec/Makefile.am | 19 ++ ac3dec/README | 52 +++ ac3dec/TODO | 22 ++ ac3dec/ac3dec.c | 99 ++++++ ac3dec/configure.in | 27 ++ ac3dec/libac3/Makefile.am | 15 + ac3dec/libac3/ac3.h | 62 ++++ ac3dec/libac3/ac3_internal.h | 344 +++++++++++++++++++ ac3dec/libac3/bit_allocate.c | 494 +++++++++++++++++++++++++++ ac3dec/libac3/bit_allocate.h | 24 ++ ac3dec/libac3/bitstream.c | 129 +++++++ ac3dec/libac3/bitstream.h | 76 +++++ ac3dec/libac3/coeff.c | 353 +++++++++++++++++++ ac3dec/libac3/coeff.h | 24 ++ ac3dec/libac3/crc.c | 96 ++++++ ac3dec/libac3/crc.h | 27 ++ ac3dec/libac3/debug.c | 58 ++++ ac3dec/libac3/debug.h | 37 ++ ac3dec/libac3/decode.c | 149 ++++++++ ac3dec/libac3/decode.h | 22 ++ ac3dec/libac3/dither.c | 115 +++++++ ac3dec/libac3/dither.h | 37 ++ ac3dec/libac3/downmix.c | 535 +++++++++++++++++++++++++++++ ac3dec/libac3/downmix.h | 28 ++ ac3dec/libac3/exponent.c | 135 ++++++++ ac3dec/libac3/exponent.h | 28 ++ ac3dec/libac3/imdct.c | 479 ++++++++++++++++++++++++++ ac3dec/libac3/imdct.h | 26 ++ ac3dec/libac3/parse.c | 637 +++++++++++++++++++++++++++++++++++ ac3dec/libac3/parse.h | 28 ++ ac3dec/libac3/rematrix.c | 83 +++++ ac3dec/libac3/rematrix.h | 25 ++ ac3dec/libac3/sanity_check.c | 131 +++++++ ac3dec/libac3/sanity_check.h | 27 ++ ac3dec/libac3/stats.c | 178 ++++++++++ ac3dec/libac3/stats.h | 27 ++ ac3dec/output.c | 153 +++++++++ ac3dec/output.h | 29 ++ ac3dec/output_irix.c | 154 +++++++++ ac3dec/output_linux.c | 113 +++++++ ac3dec/output_solaris.c | 124 +++++++ ac3dec/plot_spectrum.m | 17 + ac3dec/test/Makefile.am | 37 ++ ac3dec/test/dither_test.c | 43 +++ ac3dec/test/imdct_test.c | 38 +++ ac3dec/test/timing.h | 14 + ac3dec/tools/Makefile.am | 12 + ac3dec/tools/extract_ac3.c | 314 +++++++++++++++++ 50 files changed, 6094 insertions(+) create mode 100644 ac3dec/COPYING create mode 100644 ac3dec/Changelog create mode 100644 ac3dec/Makefile.am create mode 100644 ac3dec/README create mode 100644 ac3dec/TODO create mode 100644 ac3dec/ac3dec.c create mode 100644 ac3dec/configure.in create mode 100644 ac3dec/libac3/Makefile.am create mode 100644 ac3dec/libac3/ac3.h create mode 100644 ac3dec/libac3/ac3_internal.h create mode 100644 ac3dec/libac3/bit_allocate.c create mode 100644 ac3dec/libac3/bit_allocate.h create mode 100644 ac3dec/libac3/bitstream.c create mode 100644 ac3dec/libac3/bitstream.h create mode 100644 ac3dec/libac3/coeff.c create mode 100644 ac3dec/libac3/coeff.h create mode 100644 ac3dec/libac3/crc.c create mode 100644 ac3dec/libac3/crc.h create mode 100644 ac3dec/libac3/debug.c create mode 100644 ac3dec/libac3/debug.h create mode 100644 ac3dec/libac3/decode.c create mode 100644 ac3dec/libac3/decode.h create mode 100644 ac3dec/libac3/dither.c create mode 100644 ac3dec/libac3/dither.h create mode 100644 ac3dec/libac3/downmix.c create mode 100644 ac3dec/libac3/downmix.h create mode 100644 ac3dec/libac3/exponent.c create mode 100644 ac3dec/libac3/exponent.h create mode 100644 ac3dec/libac3/imdct.c create mode 100644 ac3dec/libac3/imdct.h create mode 100644 ac3dec/libac3/parse.c create mode 100644 ac3dec/libac3/parse.h create mode 100644 ac3dec/libac3/rematrix.c create mode 100644 ac3dec/libac3/rematrix.h create mode 100644 ac3dec/libac3/sanity_check.c create mode 100644 ac3dec/libac3/sanity_check.h create mode 100644 ac3dec/libac3/stats.c create mode 100644 ac3dec/libac3/stats.h create mode 100644 ac3dec/output.c create mode 100644 ac3dec/output.h create mode 100644 ac3dec/output_irix.c create mode 100644 ac3dec/output_linux.c create mode 100644 ac3dec/output_solaris.c create mode 100644 ac3dec/plot_spectrum.m create mode 100644 ac3dec/test/Makefile.am create mode 100644 ac3dec/test/dither_test.c create mode 100644 ac3dec/test/imdct_test.c create mode 100644 ac3dec/test/timing.h create mode 100644 ac3dec/tools/Makefile.am create mode 100644 ac3dec/tools/extract_ac3.c diff --git a/ac3dec/COPYING b/ac3dec/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/ac3dec/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ac3dec/Changelog b/ac3dec/Changelog new file mode 100644 index 0000000..fba3daf --- /dev/null +++ b/ac3dec/Changelog @@ -0,0 +1,58 @@ +ac3dec-0.6.1 Mon Mar 27 20:27:06 EST 2000 +-Fix another 2.0 problem (rematrix was wrong). +-Fix the never resync on a bad crc bug. + +ac3dec-0.6.0 Sat Mar 18 19:43:25 EST 2000 +-New library interface +-Fix bug wrt coupling channels that was causing sound quality problems. +-Fix 2.0 mode problems (aka the I forgot to implement the phase flags bug). +-All around speed improvements (almost twice as fast) +-Improved robustness when fed bad data. The entire frame is checksummed before playback. + +ac3dec-0.5.6 Tue Nov 16 00:37:34 EST 1999 +-Irix support +-Alpha fixes +-Minor performance enhancements to downmix and imdct +-OpenBSD fixes +-extract_ac3 can now read from stdin +-Change output_linux to block on write instead of using the + ring buffer. Let me know if this causes/fixes any problems + +ac3dec-0.5.5 Wed Aug 25 15:36:44 EDT 1999 +-Fixed a cut and paste bug (argh!) in parse.c which potentially + screwed up delta bit allocation info. +-Martin Mueller informed me that I was missing + some corrections from the AC-3 errata document. It turns out that + I used an earlier version of the errata when I initially wrote ac3dec. + Fortunately the errata fix the outstanding bugs that I was pulling + my hair out on for a long time. Woohoo! Thanks Martin. Kudos to Dolby + Labs for keeping their documentation up to date as well. +-stereo downmixing (downmix.c) is now in. Matrix encoded surround + (Dolby Prologic Surround) should work too. +-clipping due to high level signals has been fixed. We normalize a + block of samples by its maximum absolute value if the max exceeds + the %100 digital level. This shouldn't be a problem, but for some + reason some channels have a dynamic range that exceeds [-1.0,1.0]. + I blame the encoder :) +-Multiple track support in extract_ac3. Simply just give it the track + number you want [1,8] after the filename. + +ac3dec-0.5.4 Thu Jul 29 16:55:10 PDT 1999 +-Fixed a stupid bug with the coupling channel that was causing + high frequencies to be attenuated. +-Re-wrote the extract_ac3 tool. +-Added to a tool to verify the checksums on a given AC3 stream. + (tools/verify_ac3) + +ac3dec-0.5.3 Mon Jul 12 10:45:56 PDT 1999 +-Fixed problems related to streams with coupling channel enabled. +-Minor performance enhancements + +ac3dec-0.5.2 Sun Jul 4 12:00:25 PDT 1999 +-output_linux.c patch provided by Michael Holzt + +ac3dec-0.5.1 Wed Jun 30 17:48:52 PDT 1999 +-Compiles and dies gracefully under Linux now. + +ac3dec-0.5.0 Wed Jun 23 11:06:06 EDT 1999 +-First public release of ac3dec. diff --git a/ac3dec/Makefile.am b/ac3dec/Makefile.am new file mode 100644 index 0000000..4cc18ce --- /dev/null +++ b/ac3dec/Makefile.am @@ -0,0 +1,19 @@ +# # Process this file with automake to produce Makefile.in. +AUTOMAKE_OPTIONS = 1.3 foreign + +CFLAGS = -Wall -Werror -O3 -g + +bin_PROGRAMS = ac3dec + +ac3dec_LDADD= -L./libac3 -lac3 -lm -lasound + +noinst_HEADERS = output.h +ac3dec_SOURCES = ac3dec.c output.c +ac3dec_DEPENDENCIES = libac3/libac3.a + + +EXTRA_DIST = README Changelog TODO plot_spectrum.m autogen.sh\ + output_linux.c output_irix.c output_solaris.c + +SUBDIRS = libac3 tools test . + diff --git a/ac3dec/README b/ac3dec/README new file mode 100644 index 0000000..19e3a49 --- /dev/null +++ b/ac3dec/README @@ -0,0 +1,52 @@ +ac3dec - a free AC-3 stream decoder + +Written by Aaron Holtzman (aholtzma@engr.uvic.ca) + +Contributors: + Michael Holzt - OSS output.c and misc errata + Jim Miller - IRIX output.c + Angelos Keromytis - OpenBSD fixes + Don Mahurin - stdin support for extract_ac3 + Takefumi SAYO - FreeBSD tweak + Charles M. Hannum - fixes + + +See the file COPYING for license details. + +The currently supported platforms are Linux, Solaris, IRIX, OpenBSD, and +FreeBSD. If you want support for other platforms, take a look at +output_*.c for an idea of what you need to do. + +This software is completely useless to 99.99 percent of users +out there. It is mostly of use to those interested in audio +coding research and evaluating codecs. It could theoretically +be used as a portion of a DVD playback system for unix systems. + +HOW TO COMPILE + +Building ac3dec should be easy. Here's how: + +./configure && make all + +USAGE + +To find AC-3 streams on the internet, use www.google.com and +search for "vob trailer". A vob is a "Video Object" which is +just an MPEG-2 stream. The site www.hollywood.com has a +few good MPEG-2s with AC-3 audio. The program tools/extract_ac3 +will take an MPEG-2 stream and spit out AC-3 audio to stdout if +it exists. You can easily pipe this data to the ac3 player like +this: + + ./tools/extract_ac3 foo.vob | ./ac3dec/ + +You can also get AC-3 streams on a DVD. Check out +http://www.linuxvideo.org for details. + +DEBUG OUTPUT + +You can get a whole pile of debug info by setting the environment +variable AC3_DEBUG=1. Be sure to pipe stderr to a file or you probably +won't get realtime playback. You can pipe stderr to a file like so: + + ./ac3dec foo.ac3 2> debug.out diff --git a/ac3dec/TODO b/ac3dec/TODO new file mode 100644 index 0000000..02e0894 --- /dev/null +++ b/ac3dec/TODO @@ -0,0 +1,22 @@ +- Detect hrtime on solaris and enable it via config.h +- Add multilevel debug output +- change the divides/moduluos in coeff_get_mantissa to table + lookups. Need to look at stats first though. +- rewrite imdct to use split 2/4 radix fft +- investigate strangeness in 256 point imdct (weird transients?) + + +DONE +- fix the bitstream interface to allow on aligned buffers - Feb 2000 -AH +- change dither.c, crc.c to use a lookup table - March 2000 -AH +- the output signal from the IMDCT sometimes is outside the rand + of [-1.0,1.0]. This is why there is the normalization pass in + output.c. Need to investigate and hopefully we can move the + normalization. - Feb 2000 -AH +- Mute frame on error. Feb 2000 -AH +- Revisit convert_to_float and use int->float with scaling - Feb 2000 -AH +- Use proper frame sizes in auxdata parsing - July 1999 - AH +- fix clipping in output (normalize to max digital output) - Aug 99 -AH +- Fix coupling channel support - July 1999 - AH +- Add delta bit allocation support - July 1999 - AH +- Add downmixing support - Sept 1999 - AH, Yeqing Deng diff --git a/ac3dec/ac3dec.c b/ac3dec/ac3dec.c new file mode 100644 index 0000000..81111b2 --- /dev/null +++ b/ac3dec/ac3dec.c @@ -0,0 +1,99 @@ +/* + * ac3dec.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + + +#include +#include +#include +#include +#include + +#include "libac3/ac3.h" +#include "output.h" + +#define CHUNK_SIZE 2047 +uint_8 buf[CHUNK_SIZE]; +FILE *in_file; + +void fill_buffer(uint_8 **start,uint_8 **end) +{ + uint_32 bytes_read; + + *start = buf; + + bytes_read = fread(*start,1,CHUNK_SIZE,in_file); + + //FIXME hack... + if(bytes_read < CHUNK_SIZE) + exit(0); + + *end= *start + bytes_read; +} + +int main(int argc,char *argv[]) +{ + ac3_frame_t *ac3_frame; + ac3_config_t ac3_config; + int idx, channels = 2; + + + /* If we get an argument then use it as a filename... otherwise use + * stdin */ + idx = 1; + if (idx < argc && !strcmp(argv[idx], "-4")) { + channels = 4; idx++; + } else if (idx < argc && !strcmp(argv[idx], "-6")) { + channels = 6; idx++; + } + if (idx < argc && argv[idx] != NULL) { + in_file = fopen(argv[idx],"r"); + if(!in_file) + { + fprintf(stderr,"%s - Couldn't open file %s\n",strerror(errno),argv[1]); + exit(1); + } + } + else + in_file = stdin; + + ac3_config.fill_buffer_callback = fill_buffer; + ac3_config.num_output_ch = channels; + ac3_config.flags = 0; + + ac3_init(&ac3_config); + + ac3_frame = ac3_decode_frame(); + output_open(16,ac3_frame->sampling_rate,channels); + + do + { + //Send the samples to the output device + output_play(ac3_frame->audio_data, 256 * 6); + } + while((ac3_frame = ac3_decode_frame())); + + output_close(); + fclose(in_file); + return 0; +} diff --git a/ac3dec/configure.in b/ac3dec/configure.in new file mode 100644 index 0000000..ad26828 --- /dev/null +++ b/ac3dec/configure.in @@ -0,0 +1,27 @@ +dnl Autoconf configuration script ac3dec +dnl +dnl Aaron Holtzman - May 1999 +dnl +AC_INIT(ac3dec.c) +AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST +AC_PREREQ(2.13) +AM_INIT_AUTOMAKE(ac3dec, 0.6.1) + +AM_MAINTAINER_MODE +AC_PROG_CC +AC_PROG_GCC_TRADITIONAL +AC_PROG_RANLIB + +AC_CHECK_LIB(ossaudio, _oss_ioctl, LIBS="$LIBS -lossaudio") + +dnl Set the appropriate architecture define +case "$host" in +i?86-*) AC_DEFINE(__i386__);; +alpha*-*) AC_DEFINE(__alpha__);; +sparc-*) AC_DEFINE(__sparc__);; +ppc-*) AC_DEFINE(__ppc__);; +*) echo "$host is not currently supported by ac3dec"; exit 1;; +esac + +AC_OUTPUT(libac3/Makefile tools/Makefile test/Makefile Makefile ) diff --git a/ac3dec/libac3/Makefile.am b/ac3dec/libac3/Makefile.am new file mode 100644 index 0000000..d977b33 --- /dev/null +++ b/ac3dec/libac3/Makefile.am @@ -0,0 +1,15 @@ +# # Process this file with automake to produce Makefile.in. +AUTOMAKE_OPTIONS = 1.3 foreign + +CFLAGS = -Wall -Werror -O1 -g + +noinst_LIBRARIES = libac3.a + +libac3_a_SOURCES = bitstream.c decode.c imdct.c coeff.c exponent.c stats.c\ + bit_allocate.c parse.c crc.c debug.c rematrix.c downmix.c dither.c \ + sanity_check.c + +noinst_HEADERS = ac3_internal.h bitstream.h decode.h imdct.h ac3.h stats.h coeff.h\ + exponent.h bit_allocate.h parse.h crc.h debug.h rematrix.h downmix.h dither.h \ + sanity_check.h + diff --git a/ac3dec/libac3/ac3.h b/ac3dec/libac3/ac3.h new file mode 100644 index 0000000..30d7116 --- /dev/null +++ b/ac3dec/libac3/ac3.h @@ -0,0 +1,62 @@ +/* + * ac3.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifndef AARONS_TYPES +#define AARONS_TYPES +typedef unsigned long long uint_64; +typedef unsigned int uint_32; +typedef unsigned short uint_16; +typedef unsigned char uint_8; + +typedef signed long long sint_64; +typedef signed int sint_32; +typedef signed short sint_16; +typedef signed char sint_8; +#endif + +#define AC3_DOLBY_SURR_ENABLE 0x1 +#define AC3_3DNOW_ENABLE 0x2 +#define AC3_MMX_ENABLE 0x4 +#define AC3_ALTIVEC_ENABLE 0x8 + +typedef struct ac3_config_s +{ + //Bit flags that enable various things + uint_32 flags; + //Callback that points the decoder to new stream data + void (*fill_buffer_callback)(uint_8 **, uint_8 **); + //Number of discrete channels in final output (for downmixing) + uint_16 num_output_ch; + //Which channel of a dual mono stream to select + uint_16 dual_mono_ch_sel; +} ac3_config_t; + +typedef struct ac3_frame_s +{ + uint_32 sampling_rate; + sint_16 *audio_data; +} ac3_frame_t; + +void ac3_init(ac3_config_t *config); +ac3_frame_t* ac3_decode_frame(void); diff --git a/ac3dec/libac3/ac3_internal.h b/ac3dec/libac3/ac3_internal.h new file mode 100644 index 0000000..8de184a --- /dev/null +++ b/ac3dec/libac3/ac3_internal.h @@ -0,0 +1,344 @@ +/* + * ac3_internal.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __GNUC__ +#define inline +#endif + +/* Exponent strategy constants */ +#define EXP_REUSE (0) +#define EXP_D15 (1) +#define EXP_D25 (2) +#define EXP_D45 (3) + +/* Delta bit allocation constants */ +#define DELTA_BIT_REUSE (0) +#define DELTA_BIT_NEW (1) +#define DELTA_BIT_NONE (2) +#define DELTA_BIT_RESERVED (3) + +/* samples work structure */ +typedef float stream_samples_t[6][256]; + +/* global config structure */ +extern ac3_config_t ac3_config; +/* global error flag */ +extern uint_32 error_flag; + +/* Everything you wanted to know about band structure */ +/* + * The entire frequency domain is represented by 256 real + * floating point fourier coefficients. Only the lower 253 + * coefficients are actually utilized however. We use arrays + * of 256 to be efficient in some cases. + * + * The 5 full bandwidth channels (fbw) can have their higher + * frequencies coupled together. These coupled channels then + * share their high frequency components. + * + * This coupling band is broken up into 18 sub-bands starting + * at mantissa number 37. Each sub-band is 12 bins wide. + * + * There are 50 bit allocation sub-bands which cover the entire + * frequency range. The sub-bands are of non-uniform width, and + * approximate a 1/6 octave scale. + */ + +/* The following structures are filled in by their corresponding parse_* + * functions. See http://www.atsc.org/Standards/A52/a_52.pdf for + * full details on each field. Indented fields are used to denote + * conditional fields. + */ + +typedef struct syncinfo_s +{ + uint_32 magic; + /* Sync word == 0x0B77 */ + /* uint_16 syncword; */ + /* crc for the first 5/8 of the sync block */ + /* uint_16 crc1; */ + /* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */ + uint_16 fscod; + /* Frame size code */ + uint_16 frmsizecod; + + /* Information not in the AC-3 bitstream, but derived */ + /* Frame size in 16 bit words */ + uint_16 frame_size; + /* Bit rate in kilobits */ + uint_16 bit_rate; + /* sampling rate in hertz */ + uint_32 sampling_rate; + +} syncinfo_t; + +typedef struct bsi_s +{ + uint_32 magic; + /* Bit stream identification == 0x8 */ + uint_16 bsid; + /* Bit stream mode */ + uint_16 bsmod; + /* Audio coding mode */ + uint_16 acmod; + /* If we're using the centre channel then */ + /* centre mix level */ + uint_16 cmixlev; + /* If we're using the surround channel then */ + /* surround mix level */ + uint_16 surmixlev; + /* If we're in 2/0 mode then */ + /* Dolby surround mix level - NOT USED - */ + uint_16 dsurmod; + /* Low frequency effects on */ + uint_16 lfeon; + /* Dialogue Normalization level */ + uint_16 dialnorm; + /* Compression exists */ + uint_16 compre; + /* Compression level */ + uint_16 compr; + /* Language code exists */ + uint_16 langcode; + /* Language code */ + uint_16 langcod; + /* Audio production info exists*/ + uint_16 audprodie; + uint_16 mixlevel; + uint_16 roomtyp; + /* If we're in dual mono mode (acmod == 0) then extra stuff */ + uint_16 dialnorm2; + uint_16 compr2e; + uint_16 compr2; + uint_16 langcod2e; + uint_16 langcod2; + uint_16 audprodi2e; + uint_16 mixlevel2; + uint_16 roomtyp2; + /* Copyright bit */ + uint_16 copyrightb; + /* Original bit */ + uint_16 origbs; + /* Timecode 1 exists */ + uint_16 timecod1e; + /* Timecode 1 */ + uint_16 timecod1; + /* Timecode 2 exists */ + uint_16 timecod2e; + /* Timecode 2 */ + uint_16 timecod2; + /* Additional bit stream info exists */ + uint_16 addbsie; + /* Additional bit stream length - 1 (in bytes) */ + uint_16 addbsil; + /* Additional bit stream information (max 64 bytes) */ + uint_8 addbsi[64]; + + /* Information not in the AC-3 bitstream, but derived */ + /* Number of channels (excluding LFE) + * Derived from acmod */ + uint_16 nfchans; +} bsi_t; + + +/* more pain */ +typedef struct audblk_s +{ + uint_32 magic1; + /* block switch bit indexed by channel num */ + uint_16 blksw[5]; + /* dither enable bit indexed by channel num */ + uint_16 dithflag[5]; + /* dynamic range gain exists */ + uint_16 dynrnge; + /* dynamic range gain */ + uint_16 dynrng; + /* if acmod==0 then */ + /* dynamic range 2 gain exists */ + uint_16 dynrng2e; + /* dynamic range 2 gain */ + uint_16 dynrng2; + /* coupling strategy exists */ + uint_16 cplstre; + /* coupling in use */ + uint_16 cplinu; + /* channel coupled */ + uint_16 chincpl[5]; + /* if acmod==2 then */ + /* Phase flags in use */ + uint_16 phsflginu; + /* coupling begin frequency code */ + uint_16 cplbegf; + /* coupling end frequency code */ + uint_16 cplendf; + /* coupling band structure bits */ + uint_16 cplbndstrc[18]; + /* Do coupling co-ords exist for this channel? */ + uint_16 cplcoe[5]; + /* Master coupling co-ordinate */ + uint_16 mstrcplco[5]; + /* Per coupling band coupling co-ordinates */ + uint_16 cplcoexp[5][18]; + uint_16 cplcomant[5][18]; + /* Phase flags for dual mono */ + uint_16 phsflg[18]; + /* Is there a rematrixing strategy */ + uint_16 rematstr; + /* Rematrixing bits */ + uint_16 rematflg[4]; + /* Coupling exponent strategy */ + uint_16 cplexpstr; + /* Exponent strategy for full bandwidth channels */ + uint_16 chexpstr[5]; + /* Exponent strategy for lfe channel */ + uint_16 lfeexpstr; + /* Channel bandwidth for independent channels */ + uint_16 chbwcod[5]; + /* The absolute coupling exponent */ + uint_16 cplabsexp; + /* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */ + uint_16 cplexps[18 * 12 / 3]; + /* Sanity checking constant */ + uint_32 magic2; + /* fbw channel exponents */ + uint_16 exps[5][252 / 3]; + /* channel gain range */ + uint_16 gainrng[5]; + /* low frequency exponents */ + uint_16 lfeexps[3]; + + /* Bit allocation info */ + uint_16 baie; + /* Slow decay code */ + uint_16 sdcycod; + /* Fast decay code */ + uint_16 fdcycod; + /* Slow gain code */ + uint_16 sgaincod; + /* dB per bit code */ + uint_16 dbpbcod; + /* masking floor code */ + uint_16 floorcod; + + /* SNR offset info */ + uint_16 snroffste; + /* coarse SNR offset */ + uint_16 csnroffst; + /* coupling fine SNR offset */ + uint_16 cplfsnroffst; + /* coupling fast gain code */ + uint_16 cplfgaincod; + /* fbw fine SNR offset */ + uint_16 fsnroffst[5]; + /* fbw fast gain code */ + uint_16 fgaincod[5]; + /* lfe fine SNR offset */ + uint_16 lfefsnroffst; + /* lfe fast gain code */ + uint_16 lfefgaincod; + + /* Coupling leak info */ + uint_16 cplleake; + /* coupling fast leak initialization */ + uint_16 cplfleak; + /* coupling slow leak initialization */ + uint_16 cplsleak; + + /* delta bit allocation info */ + uint_16 deltbaie; + /* coupling delta bit allocation exists */ + uint_16 cpldeltbae; + /* fbw delta bit allocation exists */ + uint_16 deltbae[5]; + /* number of cpl delta bit segments */ + uint_16 cpldeltnseg; + /* coupling delta bit allocation offset */ + uint_16 cpldeltoffst[8]; + /* coupling delta bit allocation length */ + uint_16 cpldeltlen[8]; + /* coupling delta bit allocation length */ + uint_16 cpldeltba[8]; + /* number of delta bit segments */ + uint_16 deltnseg[5]; + /* fbw delta bit allocation offset */ + uint_16 deltoffst[5][8]; + /* fbw delta bit allocation length */ + uint_16 deltlen[5][8]; + /* fbw delta bit allocation length */ + uint_16 deltba[5][8]; + + /* skip length exists */ + uint_16 skiple; + /* skip length */ + uint_16 skipl; + + //Removed Feb 2000 -ah + /* channel mantissas */ + //uint_16 chmant[5][256]; + + /* coupling mantissas */ + uint_16 cplmant[256]; + + //Removed Feb 2000 -ah + /* coupling mantissas */ + //uint_16 lfemant[7]; + + + /* -- Information not in the bitstream, but derived thereof -- */ + + /* Number of coupling sub-bands */ + uint_16 ncplsubnd; + + /* Number of combined coupling sub-bands + * Derived from ncplsubnd and cplbndstrc */ + uint_16 ncplbnd; + + /* Number of exponent groups by channel + * Derived from strmant, endmant */ + uint_16 nchgrps[5]; + + /* Number of coupling exponent groups + * Derived from cplbegf, cplendf, cplexpstr */ + uint_16 ncplgrps; + + /* End mantissa numbers of fbw channels */ + uint_16 endmant[5]; + + /* Start and end mantissa numbers for the coupling channel */ + uint_16 cplstrtmant; + uint_16 cplendmant; + + /* Decoded exponent info */ + uint_16 fbw_exp[5][256]; + uint_16 cpl_exp[256]; + uint_16 lfe_exp[7]; + + /* Bit allocation pointer results */ + uint_16 fbw_bap[5][256]; + uint_16 cpl_bap[256]; + uint_16 lfe_bap[7]; + + uint_32 magic3; +} audblk_t; + + diff --git a/ac3dec/libac3/bit_allocate.c b/ac3dec/libac3/bit_allocate.c new file mode 100644 index 0000000..053e09c --- /dev/null +++ b/ac3dec/libac3/bit_allocate.c @@ -0,0 +1,494 @@ +/* + * bit_allocate.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + + +static inline sint_16 logadd(sint_16 a,sint_16 b); +static sint_16 calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin); +static inline uint_16 min(sint_16 a,sint_16 b); +static inline uint_16 max(sint_16 a,sint_16 b); +static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[], + sint_16 psd[], sint_16 bndpsd[]); + +static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain, + sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[], + sint_16 excite[]); +static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod, + uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[], + uint_16 deltlen[], sint_16 excite[], sint_16 mask[]); +static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset, + sint_16 psd[], sint_16 mask[], sint_16 bap[]); + +/* Misc LUTs for bit allocation process */ + +static sint_16 slowdec[] = { 0x0f, 0x11, 0x13, 0x15 }; +static sint_16 fastdec[] = { 0x3f, 0x53, 0x67, 0x7b }; +static sint_16 slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 }; +static sint_16 dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 }; + +static uint_16 floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 }; +static sint_16 fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 }; + + +static sint_16 bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, + 34, 37, 40, 43, 46, 49, 55, 61, 67, 73, + 79, 85, 97, 109, 121, 133, 157, 181, 205, 229 }; + +static sint_16 bndsz[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, + 6, 12, 12, 12, 12, 24, 24, 24, 24, 24 }; + +static sint_16 masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29, + 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, + 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37, + 37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, + 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 }; + + +static sint_16 latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039, + 0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032, + 0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c, + 0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026, + 0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021, + 0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c, + 0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018, + 0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015, + 0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012, + 0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f, + 0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, + 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000}; + +static sint_16 hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0, + 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, + 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350, + 0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, + 0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420, + 0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800, + 0x0840, 0x0840 }, + + { 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0, + 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, + 0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, + 0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0, + 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0, + 0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630, + 0x0840, 0x0840 }, + + { 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0, + 0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, + 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390, + 0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330, + 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310, + 0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440, + 0x0450, 0x04e0 }}; + + +static sint_16 baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 }; + +static sint_16 sdecay; +static sint_16 fdecay; +static sint_16 sgain; +static sint_16 dbknee; +static sint_16 floor; +static sint_16 psd[256]; +static sint_16 bndpsd[256]; +static sint_16 excite[256]; +static sint_16 mask[256]; + +static inline uint_16 +max(sint_16 a,sint_16 b) +{ + return (a > b ? a : b); +} + +static inline uint_16 +min(sint_16 a,sint_16 b) +{ + return (a < b ? a : b); +} + +static inline sint_16 +logadd(sint_16 a,sint_16 b) +{ + sint_16 c; + sint_16 address; + + c = a - b; + address = min((abs(c) >> 1), 255); + + if (c >= 0) + return(a + latab[address]); + else + return(b + latab[address]); +} + + +void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk) +{ + uint_16 i; + sint_16 fgain; + sint_16 snroffset; + sint_16 start; + sint_16 end; + sint_16 fastleak; + sint_16 slowleak; + + /* Only perform bit_allocation if the exponents have changed or we + * have new sideband information */ + if (audblk->chexpstr[0] == 0 && audblk->chexpstr[1] == 0 && + audblk->chexpstr[2] == 0 && audblk->chexpstr[3] == 0 && + audblk->chexpstr[4] == 0 && audblk->cplexpstr == 0 && + audblk->lfeexpstr == 0 && audblk->baie == 0 && + audblk->snroffste == 0 && audblk->deltbaie == 0) + return; + + /* Do some setup before we do the bit alloc */ + sdecay = slowdec[audblk->sdcycod]; + fdecay = fastdec[audblk->fdcycod]; + sgain = slowgain[audblk->sgaincod]; + dbknee = dbpbtab[audblk->dbpbcod]; + floor = floortab[audblk->floorcod]; + + /* if all the SNR offset constants are zero then the whole block is zero */ + if(!audblk->csnroffst && !audblk->fsnroffst[0] && + !audblk->fsnroffst[1] && !audblk->fsnroffst[2] && + !audblk->fsnroffst[3] && !audblk->fsnroffst[4] && + !audblk->cplfsnroffst && !audblk->lfefsnroffst) + { + memset(audblk->fbw_bap,0,sizeof(uint_16) * 256 * 5); + memset(audblk->cpl_bap,0,sizeof(uint_16) * 256); + memset(audblk->lfe_bap,0,sizeof(uint_16) * 7); + return; + } + + + for(i = 0; i < bsi->nfchans; i++) + { + start = 0; + end = audblk->endmant[i] ; + fgain = fastgain[audblk->fgaincod[i]]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->fsnroffst[i]) << 2 ; + fastleak = 0; + slowleak = 0; + + ba_compute_psd(start, end, audblk->fbw_exp[i], psd, bndpsd); + + ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite); + + ba_compute_mask(start, end, fscod, audblk->deltbae[i], audblk->deltnseg[i], + audblk->deltoffst[i], audblk->deltba[i], audblk->deltlen[i], excite, mask); + + ba_compute_bap(start, end, snroffset, psd, mask, audblk->fbw_bap[i]); + } + + if(audblk->cplinu) + { + start = audblk->cplstrtmant; + end = audblk->cplendmant; + fgain = fastgain[audblk->cplfgaincod]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->cplfsnroffst) << 2 ; + fastleak = (audblk->cplfleak << 8) + 768; + slowleak = (audblk->cplsleak << 8) + 768; + + ba_compute_psd(start, end, audblk->cpl_exp, psd, bndpsd); + + ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite); + + ba_compute_mask(start, end, fscod, audblk->cpldeltbae, audblk->cpldeltnseg, + audblk->cpldeltoffst, audblk->cpldeltba, audblk->cpldeltlen, excite, mask); + + ba_compute_bap(start, end, snroffset, psd, mask, audblk->cpl_bap); + } + + if(bsi->lfeon) + { + start = 0; + end = 7; + fgain = fastgain[audblk->lfefgaincod]; + snroffset = (((audblk->csnroffst - 15) << 4) + audblk->lfefsnroffst) << 2 ; + fastleak = 0; + slowleak = 0; + + ba_compute_psd(start, end, audblk->lfe_exp, psd, bndpsd); + + ba_compute_excitation(start, end , fgain, fastleak, slowleak, 1, bndpsd, excite); + + /* Perform no delta bit allocation for lfe */ + ba_compute_mask(start, end, fscod, 2, 0, 0, 0, 0, excite, mask); + + ba_compute_bap(start, end, snroffset, psd, mask, audblk->lfe_bap); + } +} + + +static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[], + sint_16 psd[], sint_16 bndpsd[]) +{ + int bin,i,j,k; + sint_16 lastbin = 0; + + /* Map the exponents into dBs */ + for (bin=start; bin lastbin); +} + +static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain, + sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[], + sint_16 excite[]) +{ + int bin; + sint_16 bndstrt; + sint_16 bndend; + sint_16 lowcomp = 0; + sint_16 begin = 0; + + /* Compute excitation function */ + bndstrt = masktab[start]; + bndend = masktab[end - 1] + 1; + + if (bndstrt == 0) /* For fbw and lfe channels */ + { + lowcomp = calc_lowcomp(lowcomp, bndpsd[0], bndpsd[1], 0); + excite[0] = bndpsd[0] - fgain - lowcomp; + lowcomp = calc_lowcomp(lowcomp, bndpsd[1], bndpsd[2], 1); + excite[1] = bndpsd[1] - fgain - lowcomp; + begin = 7 ; + + /* Note: Do not call calc_lowcomp() for the last band of the lfe channel, (bin = 6) */ + for (bin = 2; bin < 7; bin++) + { + if (!(is_lfe && (bin == 6))) + lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin); + fastleak = bndpsd[bin] - fgain; + slowleak = bndpsd[bin] - sgain; + excite[bin] = fastleak - lowcomp; + + if (!(is_lfe && (bin == 6))) + { + if (bndpsd[bin] <= bndpsd[bin+1]) + { + begin = bin + 1 ; + break; + } + } + } + + for (bin = begin; bin < min(bndend, 22); bin++) + { + if (!(is_lfe && (bin == 6))) + lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin); + fastleak -= fdecay ; + fastleak = max(fastleak, bndpsd[bin] - fgain); + slowleak -= sdecay ; + slowleak = max(slowleak, bndpsd[bin] - sgain); + excite[bin] = max(fastleak - lowcomp, slowleak); + } + begin = 22; + } + else /* For coupling channel */ + { + begin = bndstrt; + } + + for (bin = begin; bin < bndend; bin++) + { + fastleak -= fdecay; + fastleak = max(fastleak, bndpsd[bin] - fgain); + slowleak -= sdecay; + slowleak = max(slowleak, bndpsd[bin] - sgain); + excite[bin] = max(fastleak, slowleak) ; + } +} + +static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod, + uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[], + uint_16 deltlen[], sint_16 excite[], sint_16 mask[]) +{ + int bin,k; + sint_16 bndstrt; + sint_16 bndend; + sint_16 delta; + + bndstrt = masktab[start]; + bndend = masktab[end - 1] + 1; + + /* Compute the masking curve */ + + for (bin = bndstrt; bin < bndend; bin++) + { + if (bndpsd[bin] < dbknee) + { + excite[bin] += ((dbknee - bndpsd[bin]) >> 2); + } + mask[bin] = max(excite[bin], hth[fscod][bin]); + } + + /* Perform delta bit modulation if necessary */ + if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW)) + { + sint_16 band = 0; + sint_16 seg = 0; + + for (seg = 0; seg < deltnseg+1; seg++) + { + band += deltoffst[seg]; + if (deltba[seg] >= 4) + { + delta = (deltba[seg] - 3) << 7; + } + else + { + delta = (deltba[seg] - 4) << 7; + } + + for (k = 0; k < deltlen[seg]; k++) + { + mask[band] += delta; + band++; + } + } + } +} + +static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset, + sint_16 psd[], sint_16 mask[], sint_16 bap[]) +{ + int i,j,k; + sint_16 lastbin = 0; + sint_16 address = 0; + + /* Compute the bit allocation pointer for each bin */ + i = start; + j = masktab[start]; + + do + { + lastbin = min(bndtab[j] + bndsz[j], end); + mask[j] -= snroffset; + mask[j] -= floor; + + if (mask[j] < 0) + mask[j] = 0; + + mask[j] &= 0x1fe0; + mask[j] += floor; + for (k = i; k < lastbin; k++) + { + address = (psd[i] - mask[j]) >> 5; + address = min(63, max(0, address)); + bap[i] = baptab[address]; + i++; + } + j++; + } while (end > lastbin); +} + +static sint_16 +calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin) +{ + + if (bin < 7) + { + if ((b0 + 256) == b1) + a = 384; + else if (b0 > b1) + a = max(0, a - 64); + } + else if (bin < 20) + { + if ((b0 + 256) == b1) + a = 320; + else if (b0 > b1) + a = max(0, a - 64) ; + } + else + a = max(0, a - 128); + + return(a); +} + diff --git a/ac3dec/libac3/bit_allocate.h b/ac3dec/libac3/bit_allocate.h new file mode 100644 index 0000000..e48b0b2 --- /dev/null +++ b/ac3dec/libac3/bit_allocate.h @@ -0,0 +1,24 @@ +/* + * bit_allocate.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk); diff --git a/ac3dec/libac3/bitstream.c b/ac3dec/libac3/bitstream.c new file mode 100644 index 0000000..fdaeaf7 --- /dev/null +++ b/ac3dec/libac3/bitstream.c @@ -0,0 +1,129 @@ +/* + * bitstream.c + * + * Copyright (C) Aaron Holtzman - Dec 1999 + * + * This file is part of ac3dec, a free AC-3 audio decoder + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include + +#include "ac3.h" +#include "ac3_internal.h" +#include "bitstream.h" + +#define BUFFER_SIZE 4096 + +static uint_8 buffer[BUFFER_SIZE]; + +static uint_8 *buffer_start, *buffer_end; +static uint_8 *chunk_start, *chunk_end; + +uint_32 bits_left; +uint_32 current_word; + +void (*bitstream_fill_buffer)(uint_8**,uint_8**); + +uint_8 bitstream_get_byte(void) +{ + if(chunk_start == chunk_end) + bitstream_fill_buffer(&chunk_start,&chunk_end); + + return (*chunk_start++); +} + +uint_8 *bitstream_get_buffer_start(void) +{ + return buffer_start; +} + +void +bitstream_buffer_frame(uint_32 frame_size) +{ + uint_32 bytes_read; + uint_32 num_bytes; + + bytes_read = 0; + + do + { + if(chunk_start > chunk_end) + printf("argh!\n"); + if(chunk_start == chunk_end) + bitstream_fill_buffer(&chunk_start,&chunk_end); + + num_bytes = chunk_end - chunk_start; + + if(bytes_read + num_bytes > frame_size) + num_bytes = frame_size - bytes_read; + + memcpy(&buffer[bytes_read], chunk_start, num_bytes); + + bytes_read += num_bytes; + chunk_start += num_bytes; + } + while (bytes_read != frame_size); + + buffer_start = buffer; + buffer_end = buffer + frame_size; + + bits_left = 0; +} + + +static inline void +bitstream_fill_current() +{ + current_word = *((uint_32*)buffer_start)++; + current_word = swab32(current_word); +} + +// +// The fast paths for _get is in the +// bitstream.h header file so it can be inlined. +// +// The "bottom half" of this routine is suffixed _bh +// +// -ah +// + +uint_32 +bitstream_get_bh(uint_32 num_bits) +{ + uint_32 result; + + num_bits -= bits_left; + result = (current_word << (32 - bits_left)) >> (32 - bits_left); + + bitstream_fill_current(); + + if(num_bits != 0) + result = (result << num_bits) | (current_word >> (32 - num_bits)); + + bits_left = 32 - num_bits; + + return result; +} + +void +bitstream_init(void(*fill_function)(uint_8**,uint_8**)) +{ + // Setup the buffer fill callback + bitstream_fill_buffer = fill_function; +} diff --git a/ac3dec/libac3/bitstream.h b/ac3dec/libac3/bitstream.h new file mode 100644 index 0000000..b2a148c --- /dev/null +++ b/ac3dec/libac3/bitstream.h @@ -0,0 +1,76 @@ +/* + * bitstream.h + * + * Copyright (C) Aaron Holtzman - Dec 1999 + * + * This file is part of ac3dec, a free AC-3 audio decoder + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +//My new and improved vego-matic endian swapping routine +//(stolen from the kernel) +#ifdef WORDS_BIGENDIAN + +# define swab32(x) (x) + +#else + +# if defined (__i386__) + +# define swab32(x) __i386_swab32(x) + static inline const uint_32 __i386_swab32(uint_32 x) + { + __asm__("bswap %0" : "=r" (x) : "0" (x)); + return x; + } + +# else + +# define swab32(x)\ +((((uint_8*)&x)[0] << 24) | (((uint_8*)&x)[1] << 16) | \ + (((uint_8*)&x)[2] << 8) | (((uint_8*)&x)[3])) + +# endif +#endif + +extern uint_32 bits_left; +extern uint_32 current_word; + +void bitstream_init(void(*fill_function)(uint_8**,uint_8**)); + +uint_8 bitstream_get_byte(void); + +uint_8 *bitstream_get_buffer_start(void); +void bitstream_buffer_frame(uint_32 frame_size); + +uint_32 bitstream_get_bh(uint_32 num_bits); + +static inline uint_32 +bitstream_get(uint_32 num_bits) +{ + uint_32 result; + + if(num_bits < bits_left) + { + result = (current_word << (32 - bits_left)) >> (32 - num_bits); + bits_left -= num_bits; + return result; + } + + return bitstream_get_bh(num_bits); +} + diff --git a/ac3dec/libac3/coeff.c b/ac3dec/libac3/coeff.c new file mode 100644 index 0000000..b9f03ff --- /dev/null +++ b/ac3dec/libac3/coeff.c @@ -0,0 +1,353 @@ +/* + * coeff.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "bitstream.h" +#include "dither.h" +#include "coeff.h" + +// +//Lookup tables of 0.15 two's complement quantization values +// +static const uint_16 q_1[3] = +{ + ( -2 << 15)/3, 0,( 2 << 15)/3 +}; + +static const uint_16 q_2[5] = +{ + ( -4 << 15)/5,( -2 << 15)/5, 0, + ( 2 << 15)/5,( 4 << 15)/5 +}; + +static const uint_16 q_3[7] = +{ + ( -6 << 15)/7,( -4 << 15)/7,( -2 << 15)/7, 0, + ( 2 << 15)/7,( 4 << 15)/7,( 6 << 15)/7 +}; + +static const uint_16 q_4[11] = +{ + (-10 << 15)/11,(-8 << 15)/11,(-6 << 15)/11, ( -4 << 15)/11,(-2 << 15)/11, 0, + ( 2 << 15)/11,( 4 << 15)/11,( 6 << 15)/11, ( 8 << 15)/11,(10 << 15)/11 +}; + +static const uint_16 q_5[15] = +{ + (-14 << 15)/15,(-12 << 15)/15,(-10 << 15)/15, + ( -8 << 15)/15,( -6 << 15)/15,( -4 << 15)/15, + ( -2 << 15)/15, 0 ,( 2 << 15)/15, + ( 4 << 15)/15,( 6 << 15)/15,( 8 << 15)/15, + ( 10 << 15)/15,( 12 << 15)/15,( 14 << 15)/15 +}; + +// +// Scale factors for convert_to_float +// + +static const uint_32 u32_scale_factors[25] = +{ + 0x38000000, //2 ^ -(0 + 15) + 0x37800000, //2 ^ -(1 + 15) + 0x37000000, //2 ^ -(2 + 15) + 0x36800000, //2 ^ -(3 + 15) + 0x36000000, //2 ^ -(4 + 15) + 0x35800000, //2 ^ -(5 + 15) + 0x35000000, //2 ^ -(6 + 15) + 0x34800000, //2 ^ -(7 + 15) + 0x34000000, //2 ^ -(8 + 15) + 0x33800000, //2 ^ -(9 + 15) + 0x33000000, //2 ^ -(10 + 15) + 0x32800000, //2 ^ -(11 + 15) + 0x32000000, //2 ^ -(12 + 15) + 0x31800000, //2 ^ -(13 + 15) + 0x31000000, //2 ^ -(14 + 15) + 0x30800000, //2 ^ -(15 + 15) + 0x30000000, //2 ^ -(16 + 15) + 0x2f800000, //2 ^ -(17 + 15) + 0x2f000000, //2 ^ -(18 + 15) + 0x2e800000, //2 ^ -(19 + 15) + 0x2e000000, //2 ^ -(20 + 15) + 0x2d800000, //2 ^ -(21 + 15) + 0x2d000000, //2 ^ -(22 + 15) + 0x2c800000, //2 ^ -(23 + 15) + 0x2c000000 //2 ^ -(24 + 15) +}; + +static float *scale_factor = (float*)u32_scale_factors; + +//These store the persistent state of the packed mantissas +static uint_16 m_1[3]; +static uint_16 m_2[3]; +static uint_16 m_4[2]; +static uint_16 m_1_pointer; +static uint_16 m_2_pointer; +static uint_16 m_4_pointer; + +//Conversion from bap to number of bits in the mantissas +//zeros account for cases 0,1,2,4 which are special cased +static uint_16 qnttztab[16] = { 0, 0, 0, 3, 0 , 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16}; + +static void coeff_reset(void); +static sint_16 coeff_get_mantissa(uint_16 bap, uint_16 dithflag); +static void coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch); + +// +// Convert a 0.15 fixed point number into IEEE single +// precision floating point and scale by 2^-exp +// +static inline float +convert_to_float(uint_16 exp, sint_16 mantissa) +{ + float x; + + //the scale by 2^-15 is built into the scale factor table + x = mantissa * scale_factor[exp]; + + return x; +} + +void +coeff_unpack(bsi_t *bsi, audblk_t *audblk, stream_samples_t samples) +{ + uint_16 i,j; + uint_32 done_cpl = 0; + sint_16 mantissa; + + coeff_reset(); + + for(i=0; i< bsi->nfchans; i++) + { + for(j=0; j < audblk->endmant[i]; j++) + { + mantissa = coeff_get_mantissa(audblk->fbw_bap[i][j],audblk->dithflag[i]); + samples[i][j] = convert_to_float(audblk->fbw_exp[i][j],mantissa); + } + + if(audblk->cplinu && audblk->chincpl[i] && !(done_cpl)) + { + // ncplmant is equal to 12 * ncplsubnd + // Don't dither coupling channel until channel separation so that + // interchannel noise is uncorrelated + for(j=audblk->cplstrtmant; j < audblk->cplendmant; j++) + audblk->cplmant[j] = coeff_get_mantissa(audblk->cpl_bap[j],0); + done_cpl = 1; + } + } + + //uncouple the channel if necessary + if(audblk->cplinu) + { + for(i=0; i< bsi->nfchans; i++) + { + if(audblk->chincpl[i]) + coeff_uncouple_ch(samples[i],bsi,audblk,i); + } + + } + + if(bsi->lfeon) + { + // There are always 7 mantissas for lfe, no dither for lfe + for(j=0; j < 7 ; j++) + { + mantissa = coeff_get_mantissa(audblk->lfe_bap[j],0); + samples[5][j] = convert_to_float(audblk->lfe_exp[j],mantissa); + } + } +} + +// +//Fetch a mantissa from the bitstream +// +//The mantissa returned is a signed 0.15 fixed point number +// +static sint_16 +coeff_get_mantissa(uint_16 bap, uint_16 dithflag) +{ + uint_16 mantissa; + uint_16 group_code; + + //If the bap is 0-5 then we have special cases to take care of + switch(bap) + { + case 0: + if(dithflag) + mantissa = dither_gen(); + else + mantissa = 0; + break; + + case 1: + if(m_1_pointer > 2) + { + group_code = bitstream_get(5); + + if(group_code > 26) + goto error; + + m_1[0] = group_code / 9; + m_1[1] = (group_code % 9) / 3; + m_1[2] = (group_code % 9) % 3; + m_1_pointer = 0; + } + mantissa = m_1[m_1_pointer++]; + mantissa = q_1[mantissa]; + break; + case 2: + + if(m_2_pointer > 2) + { + group_code = bitstream_get(7); + + if(group_code > 124) + goto error; + + m_2[0] = group_code / 25; + m_2[1] = (group_code % 25) / 5 ; + m_2[2] = (group_code % 25) % 5 ; + m_2_pointer = 0; + } + mantissa = m_2[m_2_pointer++]; + mantissa = q_2[mantissa]; + break; + + case 3: + mantissa = bitstream_get(3); + + if(mantissa > 6) + goto error; + + mantissa = q_3[mantissa]; + break; + + case 4: + if(m_4_pointer > 1) + { + group_code = bitstream_get(7); + + if(group_code > 120) + goto error; + + m_4[0] = group_code / 11; + m_4[1] = group_code % 11; + m_4_pointer = 0; + } + mantissa = m_4[m_4_pointer++]; + mantissa = q_4[mantissa]; + break; + + case 5: + mantissa = bitstream_get(4); + + if(mantissa > 14) + goto error; + + mantissa = q_5[mantissa]; + break; + + default: + mantissa = bitstream_get(qnttztab[bap]); + mantissa <<= 16 - qnttztab[bap]; + } + + return mantissa; + + + +error: + if(!error_flag) + fprintf(stderr,"** Invalid mantissa - skipping frame **\n"); + error_flag = 1; + + return 0; +} + +// +// Reset the mantissa state +// +static void +coeff_reset(void) +{ + m_1[2] = m_1[1] = m_1[0] = 0; + m_2[2] = m_2[1] = m_2[0] = 0; + m_4[1] = m_4[0] = 0; + m_1_pointer = m_2_pointer = m_4_pointer = 3; +} + +// +// Uncouple the coupling channel into a fbw channel +// +static void +coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch) +{ + uint_32 bnd = 0; + uint_32 sub_bnd = 0; + uint_32 i,j; + float cpl_coord = 1.0; + uint_32 cpl_exp_tmp; + uint_32 cpl_mant_tmp; + sint_16 mantissa; + + + for(i=audblk->cplstrtmant;icplendmant;) + { + if(!audblk->cplbndstrc[sub_bnd++]) + { + cpl_exp_tmp = audblk->cplcoexp[ch][bnd] + 3 * audblk->mstrcplco[ch]; + if(audblk->cplcoexp[ch][bnd] == 15) + cpl_mant_tmp = (audblk->cplcomant[ch][bnd]) << 11; + else + cpl_mant_tmp = ((0x10) | audblk->cplcomant[ch][bnd]) << 10; + + cpl_coord = convert_to_float(cpl_exp_tmp,cpl_mant_tmp) * 8.0f; + + //Invert the phase for the right channel if necessary + if(bsi->acmod == 0x2 && audblk->phsflginu && ch == 1 && audblk->phsflg[bnd]) + cpl_coord *= -1; + + bnd++; + } + + for(j=0;j < 12; j++) + { + //Get new dither values for each channel if necessary, so + //the channels are uncorrelated + if(audblk->dithflag[ch] && audblk->cpl_bap[i] == 0) + mantissa = dither_gen(); + else + mantissa = audblk->cplmant[i]; + + samples[i] = cpl_coord * convert_to_float(audblk->cpl_exp[i],mantissa); + + i++; + } + } +} diff --git a/ac3dec/libac3/coeff.h b/ac3dec/libac3/coeff.h new file mode 100644 index 0000000..dc822a9 --- /dev/null +++ b/ac3dec/libac3/coeff.h @@ -0,0 +1,24 @@ +/* + * coeff.h + * + * Copyright (C) Aaron Holtzman - Feb 2000 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +void coeff_unpack(bsi_t *bsi, audblk_t *audblk,stream_samples_t samples); diff --git a/ac3dec/libac3/crc.c b/ac3dec/libac3/crc.c new file mode 100644 index 0000000..3210ce7 --- /dev/null +++ b/ac3dec/libac3/crc.c @@ -0,0 +1,96 @@ +/* + * crc.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + +#include + +#include "crc.h" + +static const uint_16 crc_lut[256] = +{ + 0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011, + 0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022, + 0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072, + 0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041, + 0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2, + 0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1, + 0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1, + 0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082, + 0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192, + 0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1, + 0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1, + 0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2, + 0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151, + 0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162, + 0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132, + 0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101, + 0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312, + 0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321, + 0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371, + 0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342, + 0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1, + 0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2, + 0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2, + 0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381, + 0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291, + 0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2, + 0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2, + 0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1, + 0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252, + 0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261, + 0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231, + 0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202 +}; + +static uint_16 state; + +void +crc_init(void) +{ + state = 0; +} + + +inline void crc_process_byte(uint_8 data) +{ + state = crc_lut[data ^ (state>>8)] ^ (state<<8); +} + +void +crc_process_frame(uint_8 *data,uint_32 num_bytes) +{ + uint_32 i; + + for(i=0;i +#include "debug.h" + +static int debug_level = -1; + +// Determine is debug output is required. +// We could potentially have multiple levels of debug info +int debug_is_on(void) +{ + char *env_var; + + if(debug_level < 0) + { + env_var = getenv("AC3_DEBUG"); + + if (env_var) + { + debug_level = 1; + } + else + debug_level = 0; + } + + return debug_level; +} + +//If you don't have gcc, then ya don't get debug output +#ifndef __GNUC__ +void dprintf(char fmt[],...) +{ + int foo = 0; +} +#endif + diff --git a/ac3dec/libac3/debug.h b/ac3dec/libac3/debug.h new file mode 100644 index 0000000..f45cb5b --- /dev/null +++ b/ac3dec/libac3/debug.h @@ -0,0 +1,37 @@ +/* + * + * debug.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +int debug_is_on(void); + +#ifdef __GNUC__ +#define dprintf(format,args...)\ +{\ + if (debug_is_on())\ + {\ + fprintf(stderr,format,## args);\ + }\ +} +#else +void dprintf(char fmt[],...); +#endif diff --git a/ac3dec/libac3/decode.c b/ac3dec/libac3/decode.c new file mode 100644 index 0000000..f0d90d2 --- /dev/null +++ b/ac3dec/libac3/decode.c @@ -0,0 +1,149 @@ +/* + * decode.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include "ac3.h" +#include "ac3_internal.h" +#include "bitstream.h" +#include "imdct.h" +#include "exponent.h" +#include "coeff.h" +#include "bit_allocate.h" +#include "parse.h" +#include "crc.h" +#include "stats.h" +#include "rematrix.h" +#include "sanity_check.h" +#include "downmix.h" +#include "debug.h" + +//our global config structure +ac3_config_t ac3_config; +uint_32 error_flag = 0; + +static audblk_t audblk; +static bsi_t bsi; +static syncinfo_t syncinfo; +static uint_32 frame_count = 0; +static uint_32 done_banner; +static ac3_frame_t frame; + +//the floating point samples for one audblk +static stream_samples_t samples; + +//the integer samples for the entire frame (with enough space for 2 ch out) +//if this size change, be sure to change the size when muting +static sint_16 s16_samples[6 * 6 * 256]; + +void +ac3_init(ac3_config_t *config) +{ + memcpy(&ac3_config,config,sizeof(ac3_config_t)); + + bitstream_init(config->fill_buffer_callback); + imdct_init(); + sanity_check_init(&syncinfo,&bsi,&audblk); + + frame.audio_data = s16_samples; +} + +ac3_frame_t* +ac3_decode_frame(void) +{ + uint_32 i; + + //find a syncframe and parse + parse_syncinfo(&syncinfo); + if(error_flag) + goto error; + + dprintf("(decode) begin frame %d\n",frame_count++); + frame.sampling_rate = syncinfo.sampling_rate; + + parse_bsi(&bsi); + + if(!done_banner) + { + stats_print_banner(&syncinfo,&bsi); + done_banner = 1; + } + + for(i=0; i < 6; i++) + { + //Initialize freq/time sample storage + memset(samples,0,sizeof(float) * 256 * (bsi.nfchans + bsi.lfeon)); + + // Extract most of the audblk info from the bitstream + // (minus the mantissas + parse_audblk(&bsi,&audblk); + + // Take the differential exponent data and turn it into + // absolute exponents + exponent_unpack(&bsi,&audblk); + if(error_flag) + goto error; + + // Figure out how many bits per mantissa + bit_allocate(syncinfo.fscod,&bsi,&audblk); + + // Extract the mantissas from the stream and + // generate floating point frequency coefficients + coeff_unpack(&bsi,&audblk,samples); + if(error_flag) + goto error; + + if(bsi.acmod == 0x2) + rematrix(&audblk,samples); + + // Convert the frequency samples into time samples + imdct(&bsi,&audblk,samples); + + // Downmix into the requested number of channels + // and convert floating point to sint_16 + downmix(&bsi,samples,&s16_samples[i * ac3_config.num_output_ch * 256]); + + sanity_check(&syncinfo,&bsi,&audblk); + if(error_flag) + goto error; + } + parse_auxdata(&syncinfo); + + return &frame; + +error: + //mute the frame + memset(s16_samples,0,sizeof(sint_16) * 256 * 2 * 6); + + error_flag = 0; + return &frame; + +} diff --git a/ac3dec/libac3/decode.h b/ac3dec/libac3/decode.h new file mode 100644 index 0000000..bb84a11 --- /dev/null +++ b/ac3dec/libac3/decode.h @@ -0,0 +1,22 @@ +/* + * decode.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ diff --git a/ac3dec/libac3/dither.c b/ac3dec/libac3/dither.c new file mode 100644 index 0000000..31e74f6 --- /dev/null +++ b/ac3dec/libac3/dither.c @@ -0,0 +1,115 @@ +/* + * dither.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "dither.h" + + +const uint_16 dither_lut[256] = +{ + 0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055, + 0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb, + 0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198, + 0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176, + 0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf, + 0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321, + 0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202, + 0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec, + 0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761, + 0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f, + 0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac, + 0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642, + 0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb, + 0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415, + 0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536, + 0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8, + 0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c, + 0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2, + 0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1, + 0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f, + 0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6, + 0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58, + 0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b, + 0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95, + 0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918, + 0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6, + 0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5, + 0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b, + 0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82, + 0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c, + 0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f, + 0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1 +}; + +uint_16 lfsr_state = 1; + +// +// see dither_gen (inline-able) in dither.h +// + +#if 0 + +// +// this is the old dither_gen with is much slower than the new inlined +// lut version and is still here because it's easier to understand. +// + +/* + * Generate eight bits of pseudo-entropy using a 16 bit linear + * feedback shift register (LFSR). The primitive polynomial used + * is 1 + x^4 + x^14 + x^16. + * + * The distribution is uniform, over the range [-0.707,0.707] + * + */ + +uint_16 dither_gen(void) +{ + int i; + uint_32 state; + + //explicitly bring the state into a local var as gcc > 3.0? + //doesn't know how to optimize out the stores + state = lfsr_state; + + //Generate eight pseudo random bits + for(i=0;i<8;i++) + { + state <<= 1; + + if(state & 0x10000) + state ^= 0xa011; + } + + lfsr_state = state; + + return (((((sint_32)state<<8)>>8) * (sint_32) (0.707106 * 256.0))>>16); +} + +#endif diff --git a/ac3dec/libac3/dither.h b/ac3dec/libac3/dither.h new file mode 100644 index 0000000..6d68e1b --- /dev/null +++ b/ac3dec/libac3/dither.h @@ -0,0 +1,37 @@ +/* + * dither.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +extern uint_16 lfsr_state; +extern const uint_16 dither_lut[256]; + +static inline uint_16 dither_gen(void) +{ + sint_16 state; + + state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8); + + lfsr_state = (uint_16) state; + + return ((state * (sint_32) (0.707106 * 256.0))>>8); +} diff --git a/ac3dec/libac3/downmix.c b/ac3dec/libac3/downmix.c new file mode 100644 index 0000000..6d42342 --- /dev/null +++ b/ac3dec/libac3/downmix.c @@ -0,0 +1,535 @@ +/* + * + * downmix.c + * + * Copyright (C) Aaron Holtzman - Sept 1999 + * + * Originally based on code by Yuqing Deng. + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "downmix.h" +#include "debug.h" + + +//Pre-scaled downmix coefficients +static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 }; +static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0 , 0.2071 }; + +static void +downmix_3f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp; + float left_tmp; + float clev,slev; + float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + + clev = cmixlev_lut[bsi->cmixlev]; + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + clev * *centre + slev * *left_sur++; + right_tmp= 0.4142f * *right++ + clev * *centre++ + slev * *right_sur++; + + s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f); + // printf("[0] = %.6f, [1] = %.6f\n", left_tmp, right_tmp); + } +} + +static void +downmix_3f_2r_to_4ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp, left_tmp, rear_right_tmp, rear_left_tmp; + float clev,slev; + float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + + clev = cmixlev_lut[bsi->cmixlev]; + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + clev * *centre; + right_tmp= 0.4142f * *right++ + clev * *centre++; + rear_left_tmp = 0.4142f * *left_sur++; + rear_right_tmp = 0.4142f * *right_sur++; + + s16_samples[j * 4 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 4 + 1] = (sint_16) (right_tmp * 32767.0f); + s16_samples[j * 4 + 2] = (sint_16) (rear_left_tmp * 32767.0f); + s16_samples[j * 4 + 3] = (sint_16) (rear_right_tmp * 32767.0f); +#if 0 + printf("[0] = %.6f, [1] = %.6f, [2] = %.6f, [3] = %.6f\n", + left_tmp, right_tmp, rear_left_tmp, rear_right_tmp); +#endif + } +} + +static void +downmix_3f_2r_to_6ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp, centre_tmp, left_tmp, rear_right_tmp, rear_left_tmp, lfe_tmp; + float clev,slev; + float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0, *lfe = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + lfe = samples[5]; + + clev = cmixlev_lut[bsi->cmixlev]; + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++; + right_tmp= 0.4142f * *right++; + centre_tmp = 0.4142f * *centre++; + rear_left_tmp = 0.4142f * *left_sur++; + rear_right_tmp = 0.4142f * *right_sur++; + lfe_tmp = bsi->lfeon ? 0.4142f * *lfe++ : (float)0.0; + + s16_samples[j * 6 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 6 + 1] = (sint_16) (right_tmp * 32767.0f); + s16_samples[j * 6 + 2] = (sint_16) (rear_left_tmp * 32767.0f); + s16_samples[j * 6 + 3] = (sint_16) (rear_right_tmp * 32767.0f); + s16_samples[j * 6 + 4] = (sint_16) (centre_tmp * 32767.0f); + s16_samples[j * 6 + 5] = (sint_16) (lfe_tmp * 32767.0f); +#if 0 + printf("[0] = %.6f, [1] = %.6f, [2] = %.6f, [3] = %.6f, [4] = %.6f, [5] = %.6f\n", + left_tmp, right_tmp, rear_left_tmp, rear_right_tmp, + centre_tmp, lfe_tmp); +#endif + } +} + +static void +downmix_2f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp; + float left_tmp; + float slev; + float *left = 0, *right = 0, *left_sur = 0, *right_sur = 0; + + left = samples[0]; + right = samples[1]; + left_sur = samples[2]; + right_sur = samples[3]; + + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + slev * *left_sur++; + right_tmp= 0.4142f * *right++ + slev * *right_sur++; + + s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f); + } +} + +static void +downmix_3f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp; + float left_tmp; + float clev,slev; + float *centre = 0, *left = 0, *right = 0, *sur = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + //Mono surround + sur = samples[3]; + + clev = cmixlev_lut[bsi->cmixlev]; + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + clev * *centre++ + slev * *sur; + right_tmp= 0.4142f * *right++ + clev * *centre + slev * *sur++; + + s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f); + } +} + + +static void +downmix_2f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp; + float left_tmp; + float slev; + float *left = 0, *right = 0, *sur = 0; + + left = samples[0]; + right = samples[1]; + //Mono surround + sur = samples[2]; + + slev = smixlev_lut[bsi->surmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + slev * *sur; + right_tmp= 0.4142f * *right++ + slev * *sur++; + + s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f); + } +} + +static void +downmix_3f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float right_tmp; + float left_tmp; + float clev; + float *centre = 0, *left = 0, *right = 0; + + left = samples[0]; + centre = samples[1]; + right = samples[2]; + + clev = cmixlev_lut[bsi->cmixlev]; + + for (j = 0; j < 256; j++) + { + left_tmp = 0.4142f * *left++ + clev * *centre; + right_tmp= 0.4142f * *right++ + clev * *centre++; + + s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f); + } +} + +static void +downmix_2f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + uint_32 j; + float *left = 0, *right = 0; + + left = samples[0]; + right = samples[1]; + + for (j = 0; j < 256; j++) + { + s16_samples[j * 2 ] = (sint_16) (*left++ * 32767.0f); + s16_samples[j * 2 + 1] = (sint_16) (*right++ * 32767.0f); + } +} + +static void +downmix_1f_0r_to_2ch(float *centre,sint_16 *s16_samples) +{ + uint_32 j; + float tmp; + + //Mono program! + + for (j = 0; j < 256; j++) + { + tmp = 32767.0f * 0.7071f * *centre++; + + s16_samples[j * 2 ] = s16_samples[j * 2 + 1] = (sint_16) tmp; + } +} + +// +// Downmix into 2 or 4 channels (4 ch isn't in quite yet) +// +// The downmix function names have the following format +// +// downmix_Xf_Yr_to_[2|4|6]ch[_dolby] +// +// where X = number of front channels +// Y = number of rear channels +// [2|4] = number of output channels +// [_dolby] = with or without dolby surround mix +// + +void downmix(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples) +{ + if(bsi->acmod > 7) + dprintf("(downmix) invalid acmod number\n"); + + // + //There are two main cases, with or without Dolby Surround + // + if(ac3_config.flags & AC3_DOLBY_SURR_ENABLE) + { + fprintf(stderr,"Dolby Surround Mixes not currently enabled\n"); + exit(1); + } + + //Non-Dolby surround downmixes + switch(bsi->acmod) + { + // 3/2 + case 7: + switch (ac3_config.num_output_ch) { + case 2: + downmix_3f_2r_to_2ch(bsi,samples,s16_samples); + break; + case 4: + downmix_3f_2r_to_4ch(bsi,samples,s16_samples); + break; + case 6: + downmix_3f_2r_to_6ch(bsi,samples,s16_samples); + break; + default: + fprintf(stderr,"unsupported 3/2 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + break; + + // 2/2 + case 6: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 2/2 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_2f_2r_to_2ch(bsi,samples,s16_samples); + break; + + // 3/1 + case 5: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 3/1 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_3f_1r_to_2ch(bsi,samples,s16_samples); + break; + + // 2/1 + case 4: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 2/1 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_2f_1r_to_2ch(bsi,samples,s16_samples); + break; + + // 3/0 + case 3: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 3/0 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_3f_0r_to_2ch(bsi,samples,s16_samples); + break; + + // 2/0 + case 2: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 2/0 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_2f_0r_to_2ch(bsi,samples,s16_samples); + break; + + // 1/0 + case 1: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 1/0 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_1f_0r_to_2ch(samples[0],s16_samples); + break; + + // 1+1 + case 0: + if (ac3_config.num_output_ch != 2) { + fprintf(stderr,"unsupported 1/1 channels %d\n", ac3_config.num_output_ch); + exit(1); + } + downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples); + break; + } +} + + + +#if 0 + + //the dolby mixes lay here for the time being + switch(bsi->acmod) + { + // 3/2 + case 7: + left = samples[0]; + centre = samples[1]; + right = samples[2]; + left_sur = samples[3]; + right_sur = samples[4]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++; + left_tmp = -1 * right_tmp; + right_tmp += 0.3204f * *right++ + 0.2265f * *centre; + left_tmp += 0.3204f * *left++ + 0.2265f * *centre++; + + samples[1][j] = right_tmp; + samples[0][j] = left_tmp; + } + + break; + + // 2/2 + case 6: + left = samples[0]; + right = samples[1]; + left_sur = samples[2]; + right_sur = samples[3]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++; + left_tmp = -1 * right_tmp; + right_tmp += 0.3204f * *right++; + left_tmp += 0.3204f * *left++ ; + + samples[1][j] = right_tmp; + samples[0][j] = left_tmp; + } + break; + + // 3/1 + case 5: + left = samples[0]; + centre = samples[1]; + right = samples[2]; + //Mono surround + right_sur = samples[3]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.2265f * *right_sur++; + left_tmp = -1 * right_tmp; + right_tmp += 0.3204f * *right++ + 0.2265f * *centre; + left_tmp += 0.3204f * *left++ + 0.2265f * *centre++; + + samples[1][j] = right_tmp; + samples[0][j] = left_tmp; + } + break; + + // 2/1 + case 4: + left = samples[0]; + right = samples[1]; + //Mono surround + right_sur = samples[2]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.2265f * *right_sur++; + left_tmp = -1 * right_tmp; + right_tmp += 0.3204f * *right++; + left_tmp += 0.3204f * *left++; + + samples[1][j] = right_tmp; + samples[0][j] = left_tmp; + } + break; + + // 3/0 + case 3: + left = samples[0]; + centre = samples[1]; + right = samples[2]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.3204f * *right++ + 0.2265f * *centre; + left_tmp = 0.3204f * *left++ + 0.2265f * *centre++; + + samples[1][j] = right_tmp; + samples[0][j] = left_tmp; + } + break; + + // 2/0 + case 2: + //Do nothing! + break; + + // 1/0 + case 1: + //Mono program! + right = samples[0]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.7071f * *right++; + + samples[1][j] = right_tmp; + samples[0][j] = right_tmp; + } + + break; + + // 1+1 + case 0: + //Dual mono, output selected by user + right = samples[ac3_config.dual_mono_ch_sel]; + + for (j = 0; j < 256; j++) + { + right_tmp = 0.7071f * *right++; + + samples[1][j] = right_tmp; + samples[0][j] = right_tmp; + } + break; +#endif diff --git a/ac3dec/libac3/downmix.h b/ac3dec/libac3/downmix.h new file mode 100644 index 0000000..7537c62 --- /dev/null +++ b/ac3dec/libac3/downmix.h @@ -0,0 +1,28 @@ +/* + * + * downmix.h + * + * Copyright (C) Aaron Holtzman - Sept 1999 + * + * Originally based on code by Yeqing Deng. + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +void downmix(bsi_t* bsi, stream_samples_t stream_samples,sint_16 *s16_samples); diff --git a/ac3dec/libac3/exponent.c b/ac3dec/libac3/exponent.c new file mode 100644 index 0000000..98111a5 --- /dev/null +++ b/ac3dec/libac3/exponent.c @@ -0,0 +1,135 @@ +/* + * exponent.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "exponent.h" + + +static void exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp, + uint_16 exps[], uint_16 *dest); + +void +exponent_unpack( bsi_t *bsi, audblk_t *audblk) +{ + uint_16 i; + + for(i=0; i< bsi->nfchans; i++) + exp_unpack_ch(UNPACK_FBW, audblk->chexpstr[i], audblk->nchgrps[i], audblk->exps[i][0], + &audblk->exps[i][1], audblk->fbw_exp[i]); + + if(audblk->cplinu) + exp_unpack_ch(UNPACK_CPL, audblk->cplexpstr, audblk->ncplgrps, audblk->cplabsexp << 1, + audblk->cplexps, &audblk->cpl_exp[audblk->cplstrtmant]); + + if(bsi->lfeon) + exp_unpack_ch(UNPACK_LFE, audblk->lfeexpstr, 2, audblk->lfeexps[0], + &audblk->lfeexps[1], audblk->lfe_exp); +} + + +static void +exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp, + uint_16 exps[], uint_16 *dest) +{ + uint_16 i,j; + sint_16 exp_acc; + sint_16 exp_1,exp_2,exp_3; + + if(expstr == EXP_REUSE) + return; + + /* Handle the initial absolute exponent */ + exp_acc = initial_exp; + j = 0; + + /* In the case of a fbw channel then the initial absolute values is + * also an exponent */ + if(type != UNPACK_CPL) + dest[j++] = exp_acc; + + /* Loop through the groups and fill the dest array appropriately */ + for(i=0; i< ngrps; i++) + { + if(exps[i] > 124) + goto error; + + exp_1 = exps[i] / 25; + exp_2 = (exps[i] - (exp_1 * 25)) / 5; + exp_3 = exps[i] - (exp_1 * 25) - (exp_2 * 5) ; + + exp_acc += (exp_1 - 2); + + switch(expstr) + { + case EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case EXP_D25: + dest[j++] = exp_acc; + case EXP_D15: + dest[j++] = exp_acc; + } + + exp_acc += (exp_2 - 2); + + switch(expstr) + { + case EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case EXP_D25: + dest[j++] = exp_acc; + case EXP_D15: + dest[j++] = exp_acc; + } + + exp_acc += (exp_3 - 2); + + switch(expstr) + { + case EXP_D45: + dest[j++] = exp_acc; + dest[j++] = exp_acc; + case EXP_D25: + dest[j++] = exp_acc; + case EXP_D15: + dest[j++] = exp_acc; + } + } + + return; + + goto error; +error: + if(!error_flag) + fprintf(stderr,"** Invalid exponent - skipping frame **\n"); + error_flag = 1; +} + diff --git a/ac3dec/libac3/exponent.h b/ac3dec/libac3/exponent.h new file mode 100644 index 0000000..06c59db --- /dev/null +++ b/ac3dec/libac3/exponent.h @@ -0,0 +1,28 @@ +/* + * exponent.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define UNPACK_FBW 1 +#define UNPACK_CPL 2 +#define UNPACK_LFE 4 + +void exponent_unpack( bsi_t *bsi, audblk_t *audblk); diff --git a/ac3dec/libac3/imdct.c b/ac3dec/libac3/imdct.c new file mode 100644 index 0000000..6fa0e2a --- /dev/null +++ b/ac3dec/libac3/imdct.c @@ -0,0 +1,479 @@ +/* + * imdct.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "imdct.h" + +void imdct_do_256(float data[],float delay[]); +void imdct_do_512(float data[],float delay[]); + +typedef struct complex_s +{ + float real; + float imag; +} complex_t; + + +#define N 512 + + +/* 128 point bit-reverse LUT */ +static uint_8 bit_reverse_512[] = { + 0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70, + 0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78, + 0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74, + 0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c, + 0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72, + 0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a, + 0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76, + 0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e, + 0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71, + 0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79, + 0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75, + 0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d, + 0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73, + 0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b, + 0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77, + 0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f}; + +static uint_8 bit_reverse_256[] = { + 0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38, + 0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c, + 0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a, + 0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e, + 0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39, + 0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d, + 0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b, + 0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f}; + +static complex_t buf[128]; + +/* Twiddle factor LUT */ +static complex_t *w[7]; +static complex_t w_1[1]; +static complex_t w_2[2]; +static complex_t w_4[4]; +static complex_t w_8[8]; +static complex_t w_16[16]; +static complex_t w_32[32]; +static complex_t w_64[64]; + +/* Twiddle factors for IMDCT */ +static float xcos1[128]; +static float xsin1[128]; +static float xcos2[64]; +static float xsin2[64]; + +/* Delay buffer for time domain interleaving */ +static float delay[6][256]; + +/* Windowing function for Modified DCT - Thank you acroread */ +static float window[] = { + 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130, + 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443, + 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061, + 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121, + 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770, + 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153, + 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389, + 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563, + 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699, + 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757, + 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626, + 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126, + 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019, + 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031, + 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873, + 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269, + 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981, + 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831, + 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716, + 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610, + 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560, + 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674, + 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099, + 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994, + 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513, + 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788, + 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919, + 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974, + 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993, + 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999, + 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, + 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 }; + + +static inline void swap_cmplx(complex_t *a, complex_t *b) +{ + complex_t tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + + + +static inline complex_t cmplx_mult(complex_t a, complex_t b) +{ + complex_t ret; + + ret.real = a.real * b.real - a.imag * b.imag; + ret.imag = a.real * b.imag + a.imag * b.real; + + return ret; +} + +void imdct_init(void) +{ + int i,k; + complex_t angle_step; + complex_t current_angle; + + /* Twiddle factors to turn IFFT into IMDCT */ + for( i=0; i < 128; i++) + { + xcos1[i] = -cos(2.0f * M_PI * (8*i+1)/(8*N)) ; + xsin1[i] = -sin(2.0f * M_PI * (8*i+1)/(8*N)) ; + } + + /* More twiddle factors to turn IFFT into IMDCT */ + for( i=0; i < 64; i++) + { + xcos2[i] = -cos(2.0f * M_PI * (8*i+1)/(4*N)) ; + xsin2[i] = -sin(2.0f * M_PI * (8*i+1)/(4*N)) ; + } + + /* Canonical twiddle factors for FFT */ + w[0] = w_1; + w[1] = w_2; + w[2] = w_4; + w[3] = w_8; + w[4] = w_16; + w[5] = w_32; + w[6] = w_64; + + for( i = 0; i < 7; i++) + { + angle_step.real = cos(-2.0 * M_PI / (1 << (i+1))); + angle_step.imag = sin(-2.0 * M_PI / (1 << (i+1))); + + current_angle.real = 1.0; + current_angle.imag = 0.0; + + for (k = 0; k < 1 << i; k++) + { + w[i][k] = current_angle; + current_angle = cmplx_mult(current_angle,angle_step); + } + } +} + +void +imdct_do_512(float data[],float delay[]) +{ + int i,k; + int p,q; + int m; + int two_m; + int two_m_plus_one; + + float tmp_a_i; + float tmp_a_r; + float tmp_b_i; + float tmp_b_r; + + float *data_ptr; + float *delay_ptr; + float *window_ptr; + + // + // 512 IMDCT with source and dest data in 'data' + // + + // Pre IFFT complex multiply plus IFFT cmplx conjugate + for( i=0; i < 128; i++) + { + /* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) ; */ + buf[i].real = (data[256-2*i-1] * xcos1[i]) - (data[2*i] * xsin1[i]); + buf[i].imag = -1.0 * ((data[2*i] * xcos1[i]) + (data[256-2*i-1] * xsin1[i])); + } + + //Bit reversed shuffling + for(i=0; i<128; i++) + { + k = bit_reverse_512[i]; + if (k < i) + swap_cmplx(&buf[i],&buf[k]); + } + + /* FFT Merge */ + for (m=0; m < 7; m++) + { + if(m) + two_m = (1 << m); + else + two_m = 1; + + two_m_plus_one = (1 << (m+1)); + + for(k = 0; k < two_m; k++) + { + for(i = 0; i < 128; i += two_m_plus_one) + { + p = k + i; + q = p + two_m; + tmp_a_r = buf[p].real; + tmp_a_i = buf[p].imag; + tmp_b_r = buf[q].real * w[m][k].real - buf[q].imag * w[m][k].imag; + tmp_b_i = buf[q].imag * w[m][k].real + buf[q].real * w[m][k].imag; + buf[p].real = tmp_a_r + tmp_b_r; + buf[p].imag = tmp_a_i + tmp_b_i; + buf[q].real = tmp_a_r - tmp_b_r; + buf[q].imag = tmp_a_i - tmp_b_i; + + } + } + } + + /* Post IFFT complex multiply plus IFFT complex conjugate*/ + for( i=0; i < 128; i++) + { + /* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */ + tmp_a_r = buf[i].real; + tmp_a_i = -1.0 * buf[i].imag; + buf[i].real =(tmp_a_r * xcos1[i]) - (tmp_a_i * xsin1[i]); + buf[i].imag =(tmp_a_r * xsin1[i]) + (tmp_a_i * xcos1[i]); + } + + data_ptr = data; + delay_ptr = delay; + window_ptr = window; + + /* Window and convert to real valued signal */ + for(i=0; i< 64; i++) + { + *data_ptr++ = 2.0f * (-buf[64+i].imag * *window_ptr++ + *delay_ptr++); + *data_ptr++ = 2.0f * ( buf[64-i-1].real * *window_ptr++ + *delay_ptr++); + } + + for(i=0; i< 64; i++) + { + *data_ptr++ = 2.0f * (-buf[i].real * *window_ptr++ + *delay_ptr++); + *data_ptr++ = 2.0f * ( buf[128-i-1].imag * *window_ptr++ + *delay_ptr++); + } + + /* The trailing edge of the window goes into the delay line */ + delay_ptr = delay; + + for(i=0; i< 64; i++) + { + *delay_ptr++ = -buf[64+i].real * *--window_ptr; + *delay_ptr++ = buf[64-i-1].imag * *--window_ptr; + } + + for(i=0; i<64; i++) + { + *delay_ptr++ = buf[i].imag * *--window_ptr; + *delay_ptr++ = -buf[128-i-1].real * *--window_ptr; + } +} + +void +imdct_do_256(float data[],float delay[]) +{ + int i,k; + int p,q; + int m; + int two_m; + int two_m_plus_one; + + float tmp_a_i; + float tmp_a_r; + float tmp_b_i; + float tmp_b_r; + + float *data_ptr; + float *delay_ptr; + float *window_ptr; + + complex_t *buf_1, *buf_2; + + buf_1 = &buf[0]; + buf_2 = &buf[64]; + + /* Pre IFFT complex multiply plus IFFT cmplx conjugate */ + for(k=0; k<64; k++) + { + /* X1[k] = X[2*k] */ + /* X2[k] = X[2*k+1] */ + + p = 2 * (128-2*k-1); + q = 2 * (2 * k); + + /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */ + buf_1[k].real = data[p] * xcos2[k] - data[q] * xsin2[k]; + buf_1[k].imag = -1.0f * (data[q] * xcos2[k] + data[p] * xsin2[k]); + /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */ + buf_2[k].real = data[p + 1] * xcos2[k] - data[q + 1] * xsin2[k]; + buf_2[k].imag = -1.0f * ( data[q + 1] * xcos2[k] + data[p + 1] * xsin2[k]); + } + + //IFFT Bit reversed shuffling + for(i=0; i<64; i++) + { + k = bit_reverse_256[i]; + if (k < i) + { + swap_cmplx(&buf_1[i],&buf_1[k]); + swap_cmplx(&buf_2[i],&buf_2[k]); + } + } + + /* FFT Merge */ + for (m=0; m < 6; m++) + { + two_m = (1 << m); + two_m_plus_one = (1 << (m+1)); + + //FIXME + if(m) + two_m = (1 << m); + else + two_m = 1; + + for(k = 0; k < two_m; k++) + { + for(i = 0; i < 64; i += two_m_plus_one) + { + p = k + i; + q = p + two_m; + //Do block 1 + tmp_a_r = buf_1[p].real; + tmp_a_i = buf_1[p].imag; + tmp_b_r = buf_1[q].real * w[m][k].real - buf_1[q].imag * w[m][k].imag; + tmp_b_i = buf_1[q].imag * w[m][k].real + buf_1[q].real * w[m][k].imag; + buf_1[p].real = tmp_a_r + tmp_b_r; + buf_1[p].imag = tmp_a_i + tmp_b_i; + buf_1[q].real = tmp_a_r - tmp_b_r; + buf_1[q].imag = tmp_a_i - tmp_b_i; + + //Do block 2 + tmp_a_r = buf_2[p].real; + tmp_a_i = buf_2[p].imag; + tmp_b_r = buf_2[q].real * w[m][k].real - buf_2[q].imag * w[m][k].imag; + tmp_b_i = buf_2[q].imag * w[m][k].real + buf_2[q].real * w[m][k].imag; + buf_2[p].real = tmp_a_r + tmp_b_r; + buf_2[p].imag = tmp_a_i + tmp_b_i; + buf_2[q].real = tmp_a_r - tmp_b_r; + buf_2[q].imag = tmp_a_i - tmp_b_i; + + } + } + } + + /* Post IFFT complex multiply */ + for( i=0; i < 64; i++) + { + /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */ + tmp_a_r = buf_1[i].real; + tmp_a_i = -buf_1[i].imag; + buf_1[i].real =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]); + buf_1[i].imag =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]); + /* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */ + tmp_a_r = buf_2[i].real; + tmp_a_i = -buf_2[i].imag; + buf_2[i].real =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]); + buf_2[i].imag =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]); + } + + data_ptr = data; + delay_ptr = delay; + window_ptr = window; + + /* Window and convert to real valued signal */ + for(i=0; i< 64; i++) + { + *data_ptr++ = 2.0f * (-buf_1[i].imag * *window_ptr++ + *delay_ptr++); + *data_ptr++ = 2.0f * ( buf_1[64-i-1].real * *window_ptr++ + *delay_ptr++); + } + + for(i=0; i< 64; i++) + { + *data_ptr++ = 2.0f * (-buf_1[i].real * *window_ptr++ + *delay_ptr++); + *data_ptr++ = 2.0f * ( buf_1[64-i-1].imag * *window_ptr++ + *delay_ptr++); + } + + delay_ptr = delay; + + for(i=0; i< 64; i++) + { + *delay_ptr++ = -buf_2[i].real * *--window_ptr; + *delay_ptr++ = buf_2[64-i-1].imag * *--window_ptr; + } + + for(i=0; i< 64; i++) + { + *delay_ptr++ = buf_2[i].imag * *--window_ptr; + *delay_ptr++ = -buf_2[64-i-1].real * *--window_ptr; + } +} + +//FIXME remove - for timing code +///#include +//FIXME remove + +void +imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples) { + int i; + + //handy timing code + //struct timeval start,end; + + //gettimeofday(&start,0); + + for(i=0; infchans;i++) + { + if(audblk->blksw[i]) + imdct_do_256(samples[i],delay[i]); + else + imdct_do_512(samples[i],delay[i]); + } + //gettimeofday(&end,0); + //printf("imdct %ld us\n",(end.tv_sec - start.tv_sec) * 1000000 + + //end.tv_usec - start.tv_usec); + + //XXX We don't bother with the IMDCT for the LFE as it's currently + //unused. + //if (bsi->lfeon) + // imdct_do_512(coeffs->lfe,samples->channel[5],delay[5]); + // +} diff --git a/ac3dec/libac3/imdct.h b/ac3dec/libac3/imdct.h new file mode 100644 index 0000000..750aa87 --- /dev/null +++ b/ac3dec/libac3/imdct.h @@ -0,0 +1,26 @@ +/* + * imdct.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +void imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples); +void imdct_init(void); diff --git a/ac3dec/libac3/parse.c b/ac3dec/libac3/parse.c new file mode 100644 index 0000000..86e031c --- /dev/null +++ b/ac3dec/libac3/parse.c @@ -0,0 +1,637 @@ +/* + * parse.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "bitstream.h" +#include "stats.h" +#include "debug.h" +#include "crc.h" +#include "parse.h" + +/* Misc LUT */ +static const uint_16 nfchans[8] = {2,1,2,3,3,4,4,5}; + +struct frmsize_s +{ + uint_16 bit_rate; + uint_16 frm_size[3]; +}; + +static const struct frmsize_s frmsizecod_tbl[64] = +{ + { 32 ,{64 ,69 ,96 } }, + { 32 ,{64 ,70 ,96 } }, + { 40 ,{80 ,87 ,120 } }, + { 40 ,{80 ,88 ,120 } }, + { 48 ,{96 ,104 ,144 } }, + { 48 ,{96 ,105 ,144 } }, + { 56 ,{112 ,121 ,168 } }, + { 56 ,{112 ,122 ,168 } }, + { 64 ,{128 ,139 ,192 } }, + { 64 ,{128 ,140 ,192 } }, + { 80 ,{160 ,174 ,240 } }, + { 80 ,{160 ,175 ,240 } }, + { 96 ,{192 ,208 ,288 } }, + { 96 ,{192 ,209 ,288 } }, + { 112 ,{224 ,243 ,336 } }, + { 112 ,{224 ,244 ,336 } }, + { 128 ,{256 ,278 ,384 } }, + { 128 ,{256 ,279 ,384 } }, + { 160 ,{320 ,348 ,480 } }, + { 160 ,{320 ,349 ,480 } }, + { 192 ,{384 ,417 ,576 } }, + { 192 ,{384 ,418 ,576 } }, + { 224 ,{448 ,487 ,672 } }, + { 224 ,{448 ,488 ,672 } }, + { 256 ,{512 ,557 ,768 } }, + { 256 ,{512 ,558 ,768 } }, + { 320 ,{640 ,696 ,960 } }, + { 320 ,{640 ,697 ,960 } }, + { 384 ,{768 ,835 ,1152 } }, + { 384 ,{768 ,836 ,1152 } }, + { 448 ,{896 ,975 ,1344 } }, + { 448 ,{896 ,976 ,1344 } }, + { 512 ,{1024 ,1114 ,1536 } }, + { 512 ,{1024 ,1115 ,1536 } }, + { 576 ,{1152 ,1253 ,1728 } }, + { 576 ,{1152 ,1254 ,1728 } }, + { 640 ,{1280 ,1393 ,1920 } }, + { 640 ,{1280 ,1394 ,1920 } } +}; + +/* Parse a syncinfo structure, minus the sync word */ +void +parse_syncinfo(syncinfo_t *syncinfo) +{ + uint_32 tmp = 0; + uint_16 sync_word = 0; + uint_32 time_out = 1<<16; + + // + // Find a ac3 sync frame. Time out if we read 64k without finding + // one. + // + while(time_out--) + { + sync_word = (sync_word << 8) + bitstream_get_byte(); + + if(sync_word == 0x0b77) + break; + } + + // + // We need to read in the entire syncinfo struct (0x0b77 + 24 bits) + // in order to determine how big the frame is + // + tmp = (tmp << 8) + bitstream_get_byte(); + tmp = (tmp << 8) + bitstream_get_byte(); + tmp = (tmp << 8) + bitstream_get_byte(); + + // Get the sampling rate + syncinfo->fscod = (tmp >> 6) & 0x3; + + if(syncinfo->fscod == 3) + { + //invalid sampling rate code + error_flag = 1; + return; + } + else if(syncinfo->fscod == 2) + syncinfo->sampling_rate = 32000; + else if(syncinfo->fscod == 1) + syncinfo->sampling_rate = 44100; + else + syncinfo->sampling_rate = 48000; + + // Get the frame size code + syncinfo->frmsizecod = tmp & 0x3f; + + // Calculate the frame size and bitrate + syncinfo->frame_size = + frmsizecod_tbl[syncinfo->frmsizecod].frm_size[syncinfo->fscod]; + syncinfo->bit_rate = frmsizecod_tbl[syncinfo->frmsizecod].bit_rate; + + + // Buffer the entire syncframe + bitstream_buffer_frame(syncinfo->frame_size * 2 - 5); + + // Check the crc over the entire frame + crc_init(); + + crc_process_byte(tmp>>16); + crc_process_byte((tmp>>8) & 0xff); + crc_process_byte(tmp & 0xff); + crc_process_frame(bitstream_get_buffer_start(),syncinfo->frame_size * 2 - 5); + + if(!crc_validate()) + { + error_flag = 1; + fprintf(stderr,"** CRC failed - skipping frame **\n"); + return; + } + + stats_print_syncinfo(syncinfo); +} + +/* + * This routine fills a bsi struct from the AC3 stream + */ + +void +parse_bsi(bsi_t *bsi) +{ + uint_32 i; + + /* Check the AC-3 version number */ + bsi->bsid = bitstream_get(5); + + /* Get the audio service provided by the steram */ + bsi->bsmod = bitstream_get(3); + + /* Get the audio coding mode (ie how many channels)*/ + bsi->acmod = bitstream_get(3); + /* Predecode the number of full bandwidth channels as we use this + * number a lot */ + bsi->nfchans = nfchans[bsi->acmod]; + + /* If it is in use, get the centre channel mix level */ + if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1)) + bsi->cmixlev = bitstream_get(2); + + /* If it is in use, get the surround channel mix level */ + if (bsi->acmod & 0x4) + bsi->surmixlev = bitstream_get(2); + + /* Get the dolby surround mode if in 2/0 mode */ + if(bsi->acmod == 0x2) + bsi->dsurmod= bitstream_get(2); + + /* Is the low frequency effects channel on? */ + bsi->lfeon = bitstream_get(1); + + /* Get the dialogue normalization level */ + bsi->dialnorm = bitstream_get(5); + + /* Does compression gain exist? */ + bsi->compre = bitstream_get(1); + if (bsi->compre) + { + /* Get compression gain */ + bsi->compr = bitstream_get(8); + } + + /* Does language code exist? */ + bsi->langcode = bitstream_get(1); + if (bsi->langcode) + { + /* Get langauge code */ + bsi->langcod = bitstream_get(8); + } + + /* Does audio production info exist? */ + bsi->audprodie = bitstream_get(1); + if (bsi->audprodie) + { + /* Get mix level */ + bsi->mixlevel = bitstream_get(5); + + /* Get room type */ + bsi->roomtyp = bitstream_get(2); + } + + /* If we're in dual mono mode then get some extra info */ + if (bsi->acmod ==0) + { + /* Get the dialogue normalization level two */ + bsi->dialnorm2 = bitstream_get(5); + + /* Does compression gain two exist? */ + bsi->compr2e = bitstream_get(1); + if (bsi->compr2e) + { + /* Get compression gain two */ + bsi->compr2 = bitstream_get(8); + } + + /* Does language code two exist? */ + bsi->langcod2e = bitstream_get(1); + if (bsi->langcod2e) + { + /* Get langauge code two */ + bsi->langcod2 = bitstream_get(8); + } + + /* Does audio production info two exist? */ + bsi->audprodi2e = bitstream_get(1); + if (bsi->audprodi2e) + { + /* Get mix level two */ + bsi->mixlevel2 = bitstream_get(5); + + /* Get room type two */ + bsi->roomtyp2 = bitstream_get(2); + } + } + + /* Get the copyright bit */ + bsi->copyrightb = bitstream_get(1); + + /* Get the original bit */ + bsi->origbs = bitstream_get(1); + + /* Does timecode one exist? */ + bsi->timecod1e = bitstream_get(1); + + if(bsi->timecod1e) + bsi->timecod1 = bitstream_get(14); + + /* Does timecode two exist? */ + bsi->timecod2e = bitstream_get(1); + + if(bsi->timecod2e) + bsi->timecod2 = bitstream_get(14); + + /* Does addition info exist? */ + bsi->addbsie = bitstream_get(1); + + if(bsi->addbsie) + { + /* Get how much info is there */ + bsi->addbsil = bitstream_get(6); + + /* Get the additional info */ + for(i=0;i<(bsi->addbsil + 1);i++) + bsi->addbsi[i] = bitstream_get(8); + } + + stats_print_bsi(bsi); +} + +/* More pain inducing parsing */ +void +parse_audblk(bsi_t *bsi,audblk_t *audblk) +{ + int i,j; + + for (i=0;i < bsi->nfchans; i++) + { + /* Is this channel an interleaved 256 + 256 block ? */ + audblk->blksw[i] = bitstream_get(1); + } + + for (i=0;i < bsi->nfchans; i++) + { + /* Should we dither this channel? */ + audblk->dithflag[i] = bitstream_get(1); + } + + /* Does dynamic range control exist? */ + audblk->dynrnge = bitstream_get(1); + if (audblk->dynrnge) + { + /* Get dynamic range info */ + audblk->dynrng = bitstream_get(8); + } + + /* If we're in dual mono mode then get the second channel DR info */ + if (bsi->acmod == 0) + { + /* Does dynamic range control two exist? */ + audblk->dynrng2e = bitstream_get(1); + if (audblk->dynrng2e) + { + /* Get dynamic range info */ + audblk->dynrng2 = bitstream_get(8); + } + } + + /* Does coupling strategy exist? */ + audblk->cplstre = bitstream_get(1); + if (audblk->cplstre) + { + /* Is coupling turned on? */ + audblk->cplinu = bitstream_get(1); + if(audblk->cplinu) + { + for(i=0;i < bsi->nfchans; i++) + audblk->chincpl[i] = bitstream_get(1); + if(bsi->acmod == 0x2) + audblk->phsflginu = bitstream_get(1); + audblk->cplbegf = bitstream_get(4); + audblk->cplendf = bitstream_get(4); + audblk->ncplsubnd = (audblk->cplendf + 2) - audblk->cplbegf + 1; + + /* Calculate the start and end bins of the coupling channel */ + audblk->cplstrtmant = (audblk->cplbegf * 12) + 37 ; + audblk->cplendmant = ((audblk->cplendf + 3) * 12) + 37; + + /* The number of combined subbands is ncplsubnd minus each combined + * band */ + audblk->ncplbnd = audblk->ncplsubnd; + + for(i=1; i< audblk->ncplsubnd; i++) + { + audblk->cplbndstrc[i] = bitstream_get(1); + audblk->ncplbnd -= audblk->cplbndstrc[i]; + } + } + } + + if(audblk->cplinu) + { + /* Loop through all the channels and get their coupling co-ords */ + for(i=0;i < bsi->nfchans;i++) + { + if(!audblk->chincpl[i]) + continue; + + /* Is there new coupling co-ordinate info? */ + audblk->cplcoe[i] = bitstream_get(1); + + if(audblk->cplcoe[i]) + { + audblk->mstrcplco[i] = bitstream_get(2); + for(j=0;j < audblk->ncplbnd; j++) + { + audblk->cplcoexp[i][j] = bitstream_get(4); + audblk->cplcomant[i][j] = bitstream_get(4); + } + } + } + + /* If we're in dual mono mode, there's going to be some phase info */ + if( (bsi->acmod == 0x2) && audblk->phsflginu && + (audblk->cplcoe[0] || audblk->cplcoe[1])) + { + for(j=0;j < audblk->ncplbnd; j++) + audblk->phsflg[j] = bitstream_get(1); + + } + } + + /* If we're in dual mono mode, there may be a rematrix strategy */ + if(bsi->acmod == 0x2) + { + audblk->rematstr = bitstream_get(1); + if(audblk->rematstr) + { + if (audblk->cplinu == 0) + { + for(i = 0; i < 4; i++) + audblk->rematflg[i] = bitstream_get(1); + } + if((audblk->cplbegf > 2) && audblk->cplinu) + { + for(i = 0; i < 4; i++) + audblk->rematflg[i] = bitstream_get(1); + } + if((audblk->cplbegf <= 2) && audblk->cplinu) + { + for(i = 0; i < 3; i++) + audblk->rematflg[i] = bitstream_get(1); + } + if((audblk->cplbegf == 0) && audblk->cplinu) + for(i = 0; i < 2; i++) + audblk->rematflg[i] = bitstream_get(1); + + } + } + + if (audblk->cplinu) + { + /* Get the coupling channel exponent strategy */ + audblk->cplexpstr = bitstream_get(2); + audblk->ncplgrps = (audblk->cplendmant - audblk->cplstrtmant) / + (3 << (audblk->cplexpstr-1)); + } + + for(i = 0; i < bsi->nfchans; i++) + audblk->chexpstr[i] = bitstream_get(2); + + /* Get the exponent strategy for lfe channel */ + if(bsi->lfeon) + audblk->lfeexpstr = bitstream_get(1); + + /* Determine the bandwidths of all the fbw channels */ + for(i = 0; i < bsi->nfchans; i++) + { + uint_16 grp_size; + + if(audblk->chexpstr[i] != EXP_REUSE) + { + if (audblk->cplinu && audblk->chincpl[i]) + { + audblk->endmant[i] = audblk->cplstrtmant; + } + else + { + audblk->chbwcod[i] = bitstream_get(6); + audblk->endmant[i] = ((audblk->chbwcod[i] + 12) * 3) + 37; + } + + /* Calculate the number of exponent groups to fetch */ + grp_size = 3 * (1 << (audblk->chexpstr[i] - 1)); + audblk->nchgrps[i] = (audblk->endmant[i] - 1 + (grp_size - 3)) / grp_size; + } + } + + /* Get the coupling exponents if they exist */ + if(audblk->cplinu && (audblk->cplexpstr != EXP_REUSE)) + { + audblk->cplabsexp = bitstream_get(4); + for(i=0;i< audblk->ncplgrps;i++) + audblk->cplexps[i] = bitstream_get(7); + } + + /* Get the fwb channel exponents */ + for(i=0;i < bsi->nfchans; i++) + { + if(audblk->chexpstr[i] != EXP_REUSE) + { + audblk->exps[i][0] = bitstream_get(4); + for(j=1;j<=audblk->nchgrps[i];j++) + audblk->exps[i][j] = bitstream_get(7); + audblk->gainrng[i] = bitstream_get(2); + } + } + + /* Get the lfe channel exponents */ + if(bsi->lfeon && (audblk->lfeexpstr != EXP_REUSE)) + { + audblk->lfeexps[0] = bitstream_get(4); + audblk->lfeexps[1] = bitstream_get(7); + audblk->lfeexps[2] = bitstream_get(7); + } + + /* Get the parametric bit allocation parameters */ + audblk->baie = bitstream_get(1); + + if(audblk->baie) + { + audblk->sdcycod = bitstream_get(2); + audblk->fdcycod = bitstream_get(2); + audblk->sgaincod = bitstream_get(2); + audblk->dbpbcod = bitstream_get(2); + audblk->floorcod = bitstream_get(3); + } + + /* Get the SNR off set info if it exists */ + audblk->snroffste = bitstream_get(1); + + if(audblk->snroffste) + { + audblk->csnroffst = bitstream_get(6); + + if(audblk->cplinu) + { + audblk->cplfsnroffst = bitstream_get(4); + audblk->cplfgaincod = bitstream_get(3); + } + + for(i = 0;i < bsi->nfchans; i++) + { + audblk->fsnroffst[i] = bitstream_get(4); + audblk->fgaincod[i] = bitstream_get(3); + } + if(bsi->lfeon) + { + + audblk->lfefsnroffst = bitstream_get(4); + audblk->lfefgaincod = bitstream_get(3); + } + } + + /* Get coupling leakage info if it exists */ + if(audblk->cplinu) + { + audblk->cplleake = bitstream_get(1); + + if(audblk->cplleake) + { + audblk->cplfleak = bitstream_get(3); + audblk->cplsleak = bitstream_get(3); + } + } + + /* Get the delta bit alloaction info */ + audblk->deltbaie = bitstream_get(1); + + if(audblk->deltbaie) + { + if(audblk->cplinu) + audblk->cpldeltbae = bitstream_get(2); + + for(i = 0;i < bsi->nfchans; i++) + audblk->deltbae[i] = bitstream_get(2); + + if (audblk->cplinu && (audblk->cpldeltbae == DELTA_BIT_NEW)) + { + audblk->cpldeltnseg = bitstream_get(3); + for(i = 0;i < audblk->cpldeltnseg + 1; i++) + { + audblk->cpldeltoffst[i] = bitstream_get(5); + audblk->cpldeltlen[i] = bitstream_get(4); + audblk->cpldeltba[i] = bitstream_get(3); + } + } + + for(i = 0;i < bsi->nfchans; i++) + { + if (audblk->deltbae[i] == DELTA_BIT_NEW) + { + audblk->deltnseg[i] = bitstream_get(3); + for(j = 0; j < audblk->deltnseg[i] + 1; j++) + { + audblk->deltoffst[i][j] = bitstream_get(5); + audblk->deltlen[i][j] = bitstream_get(4); + audblk->deltba[i][j] = bitstream_get(3); + } + } + } + } + + /* Check to see if there's any dummy info to get */ + if((audblk->skiple = bitstream_get(1))) + { + uint_16 skip_data; + + audblk->skipl = bitstream_get(9); + //XXX remove + //fprintf(stderr,"(parse) skipping %d bytes\n",audblk->skipl); + + for(i = 0; i < audblk->skipl ; i++) + { + skip_data = bitstream_get(8); + //XXX remove + //fprintf(stderr,"skipped data %2x\n",skip_data); + //if(skip_data != 0) + //{ + //dprintf("(parse) Invalid skipped data %2x\n",skip_data); + //exit(1); + //} + } + } + + stats_print_audblk(bsi,audblk); +} + +void +parse_auxdata(syncinfo_t *syncinfo) +{ + //FIXME keep this now that we don't really need it? +#if 0 + int i; + int skip_length; + uint_16 crc; + uint_16 auxdatae; + + skip_length = (syncinfo->frame_size * 16) - bitstream_get_total_bits() - 17 - 1; + + //XXX remove + //dprintf("(auxdata) skipping %d auxbits\n",skip_length); + + for(i=0; i < skip_length; i++) + //printf("Skipped bit %i\n",(uint_16)bitstream_get(1)); + bitstream_get(1); + + //get the auxdata exists bit + auxdatae = bitstream_get(1); + + //XXX remove + //dprintf("auxdatae = %i\n",auxdatae); + + //Skip the CRC reserved bit + bitstream_get(1); + + //Get the crc + crc = bitstream_get(16); +#endif +} + + diff --git a/ac3dec/libac3/parse.h b/ac3dec/libac3/parse.h new file mode 100644 index 0000000..72aa32c --- /dev/null +++ b/ac3dec/libac3/parse.h @@ -0,0 +1,28 @@ +/* + * parse.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +void parse_syncinfo(syncinfo_t *syncinfo); +void parse_audblk(bsi_t *bsi,audblk_t *audblk); +void parse_bsi(bsi_t *bsi); +void parse_auxdata(syncinfo_t *syncinfo); + diff --git a/ac3dec/libac3/rematrix.c b/ac3dec/libac3/rematrix.c new file mode 100644 index 0000000..caa7094 --- /dev/null +++ b/ac3dec/libac3/rematrix.c @@ -0,0 +1,83 @@ +/* + * rematrix.c + * + * Copyright (C) Aaron Holtzman - July 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "rematrix.h" + +struct rematrix_band_s +{ + uint_32 start; + uint_32 end; +}; + +struct rematrix_band_s rematrix_band[] = { {13,24}, {25,36}, {37 ,60}, {61,252}}; + +static inline uint_32 min(uint_32 a,uint_32 b); + +static inline uint_32 +min(uint_32 a,uint_32 b) +{ + return (a < b ? a : b); +} + +/* This routine simply does stereo rematixing for the 2 channel + * stereo mode */ +void rematrix(audblk_t *audblk, stream_samples_t samples) +{ + uint_32 num_bands; + uint_32 start; + uint_32 end; + uint_32 i,j; + float left,right; + + if(!audblk->cplinu || audblk->cplbegf > 2) + num_bands = 4; + else if (audblk->cplbegf > 0) + num_bands = 3; + else + num_bands = 2; + + for(i=0;i < num_bands; i++) + { + if(!audblk->rematflg[i]) + continue; + + start = rematrix_band[i].start; + end = min(rematrix_band[i].end ,12 * audblk->cplbegf + 36); + + for(j=start;j < end; j++) + { + left = samples[0][j] + samples[1][j]; + right = samples[0][j] - samples[1][j]; + samples[0][j] = left; + samples[1][j] = right; + } + } +} diff --git a/ac3dec/libac3/rematrix.h b/ac3dec/libac3/rematrix.h new file mode 100644 index 0000000..0be6528 --- /dev/null +++ b/ac3dec/libac3/rematrix.h @@ -0,0 +1,25 @@ +/* + * rematrix.h + * + * Copyright (C) Aaron Holtzman - July 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +void rematrix(audblk_t *audblk, stream_samples_t samples); diff --git a/ac3dec/libac3/sanity_check.c b/ac3dec/libac3/sanity_check.c new file mode 100644 index 0000000..461f20e --- /dev/null +++ b/ac3dec/libac3/sanity_check.c @@ -0,0 +1,131 @@ +/* + * sanity_check.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" +#include "sanity_check.h" + + +void +sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk) +{ + syncinfo->magic = AC3_MAGIC_NUMBER; + bsi->magic = AC3_MAGIC_NUMBER; + audblk->magic1 = AC3_MAGIC_NUMBER; + audblk->magic2 = AC3_MAGIC_NUMBER; + audblk->magic3 = AC3_MAGIC_NUMBER; +} + +void +sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk) +{ + int i; + + if(syncinfo->magic != AC3_MAGIC_NUMBER) + { + fprintf(stderr,"\n** Sanity check failed -- syncinfo magic number **"); + error_flag = 1; + } + + if(bsi->magic != AC3_MAGIC_NUMBER) + { + fprintf(stderr,"\n** Sanity check failed -- bsi magic number **"); + error_flag = 1; + } + + if(audblk->magic1 != AC3_MAGIC_NUMBER) + { + fprintf(stderr,"\n** Sanity check failed -- audblk magic number 1 **"); + error_flag = 1; + } + + if(audblk->magic2 != AC3_MAGIC_NUMBER) + { + fprintf(stderr,"\n** Sanity check failed -- audblk magic number 2 **"); + error_flag = 1; + } + + if(audblk->magic3 != AC3_MAGIC_NUMBER) + { + fprintf(stderr,"\n** Sanity check failed -- audblk magic number 3 **"); + error_flag = 1; + } + + for(i = 0;i < 5 ; i++) + { + if (audblk->fbw_exp[i][255] !=0 || audblk->fbw_exp[i][254] !=0 || + audblk->fbw_exp[i][253] !=0) + { + fprintf(stderr,"\n** Sanity check failed -- fbw_exp out of bounds **"); + error_flag = 1; + } + + if (audblk->fbw_bap[i][255] !=0 || audblk->fbw_bap[i][254] !=0 || + audblk->fbw_bap[i][253] !=0) + { + fprintf(stderr,"\n** Sanity check failed -- fbw_bap out of bounds **"); + error_flag = 1; + } + + } + + if (audblk->cpl_exp[255] !=0 || audblk->cpl_exp[254] !=0 || + audblk->cpl_exp[253] !=0) + { + fprintf(stderr,"\n** Sanity check failed -- cpl_exp out of bounds **"); + error_flag = 1; + } + + if (audblk->cpl_bap[255] !=0 || audblk->cpl_bap[254] !=0 || + audblk->cpl_bap[253] !=0) + { + fprintf(stderr,"\n** Sanity check failed -- cpl_bap out of bounds **"); + error_flag = 1; + } + + if (audblk->cplmant[255] !=0 || audblk->cplmant[254] !=0 || + audblk->cplmant[253] !=0) + { + fprintf(stderr,"\n** Sanity check failed -- cpl_mant out of bounds **"); + error_flag = 1; + } + + if ((audblk->cplinu == 1) && (audblk->cplbegf > (audblk->cplendf+2))) + { + fprintf(stderr,"\n** Sanity check failed -- cpl params inconsistent **"); + error_flag = 1; + } + + for(i=0; i < bsi->nfchans; i++) + { + if((audblk->chincpl[i] == 0) && (audblk->chbwcod[i] > 60)) + { + fprintf(stderr,"\n** Sanity check failed -- chbwcod too big **"); + error_flag = 1; + } + } + + return; +} diff --git a/ac3dec/libac3/sanity_check.h b/ac3dec/libac3/sanity_check.h new file mode 100644 index 0000000..c4ca63a --- /dev/null +++ b/ac3dec/libac3/sanity_check.h @@ -0,0 +1,27 @@ +/* + * sanity_check.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define AC3_MAGIC_NUMBER 0xdeadbeef + +void sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk); +void sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk); diff --git a/ac3dec/libac3/stats.c b/ac3dec/libac3/stats.c new file mode 100644 index 0000000..2ac88e0 --- /dev/null +++ b/ac3dec/libac3/stats.c @@ -0,0 +1,178 @@ +/* + * stats.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "config.h" +#include "ac3.h" +#include "ac3_internal.h" + + +#include "decode.h" +#include "stats.h" +#include "debug.h" + + +static const char *service_ids[8] = +{ + "CM","ME","VI","HI", + "D", "C","E", "VO" +}; + +struct mixlev_s +{ + float clev; + char *desc; +}; + +static const struct mixlev_s cmixlev_tbl[4] = +{ + {0.707, "(-3.0 dB)"}, {0.595, "(-4.5 dB)"}, + {0.500, "(-6.0 dB)"}, {1.0, "Invalid"} +}; + +static const struct mixlev_s smixlev_tbl[4] = +{ + {0.707, "(-3.0 dB)"}, {0.500, "(-6.0 dB)"}, + { 0.0, "off "}, { 1.0, "Invalid"} +}; + +static const char *language[128] = +{ + "unknown", "Albanian", "Breton", "Catalan", "Croatian", "Welsh", "Czech", "Danish", + "German", "English", "Spanish", "Esperanto", "Estonian", "Basque", "Faroese", "French", + "Frisian", "Irish", "Gaelic", "Galician", "Icelandic", "Italian", "Lappish", "Latin", + "Latvian", "Luxembourgian", "Lithuanian", "Hungarian", "Maltese", "Dutch", "Norwegian", "Occitan", + "Polish", "Portugese", "Romanian", "Romansh", "Serbian", "Slovak", "Slovene", "Finnish", + "Swedish", "Turkish", "Flemish", "Walloon", "0x2c", "0x2d", "0x2e", "0x2f", + "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", + "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", + "background", "0x41", "0x42", "0x43", "0x44", "Zulu", "Vietnamese", "Uzbek", + "Urdu", "Ukrainian", "Thai", "Telugu", "Tatar", "Tamil", "Tadzhik", "Swahili", + "Sranan Tongo", "Somali", "Sinhalese", "Shona", "Serbo-Croat", "Ruthenian", "Russian", "Quechua", + "Pustu", "Punjabi", "Persian", "Papamiento", "Oriya", "Nepali", "Ndebele", "Marathi", + "Moldavian", "Malaysian", "Malagasay", "Macedonian", "Laotian", "Korean", "Khmer", "Kazakh", + "Kannada", "Japanese", "Indonesian", "Hindi", "Hebrew", "Hausa", "Gurani", "Gujurati", + "Greek", "Georgian", "Fulani", "Dari", "Churash", "Chinese", "Burmese", "Bulgarian", + "Bengali", "Belorussian", "Bambora", "Azerbijani", "Assamese", "Armenian", "Arabic", "Amharic" +}; + +void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi) +{ + fprintf(stdout,PACKAGE"-"VERSION" (C) 2000 Aaron Holtzman (aholtzma@ess.engr.uvic.ca)\n"); + + fprintf(stdout,"%d.%d Mode ",bsi->nfchans,bsi->lfeon); + fprintf(stdout,"%2.1f KHz",syncinfo->sampling_rate * 1e-3); + fprintf(stdout,"%4d kbps ",syncinfo->bit_rate); + if (bsi->langcode && (bsi->langcod < 128)) + fprintf(stdout,"%s ", language[bsi->langcod]); + + switch(bsi->bsmod) + { + case 0: + fprintf(stdout,"Complete Main Audio Service"); + break; + case 1: + fprintf(stdout,"Music and Effects Audio Service"); + case 2: + fprintf(stdout,"Visually Impaired Audio Service"); + break; + case 3: + fprintf(stdout,"Hearing Impaired Audio Service"); + break; + case 4: + fprintf(stdout,"Dialogue Audio Service"); + break; + case 5: + fprintf(stdout,"Commentary Audio Service"); + break; + case 6: + fprintf(stdout,"Emergency Audio Service"); + break; + case 7: + fprintf(stdout,"Voice Over Audio Service"); + break; + } + fprintf(stdout,"\n"); +} + +void stats_print_syncinfo(syncinfo_t *syncinfo) +{ + dprintf("(syncinfo) "); + + switch (syncinfo->fscod) + { + case 2: + dprintf("32 KHz "); + break; + case 1: + dprintf("44.1 KHz "); + break; + case 0: + dprintf("48 KHz "); + break; + default: + dprintf("Invalid sampling rate "); + break; + } + + dprintf("%4d kbps %4d words per frame\n",syncinfo->bit_rate, + syncinfo->frame_size); + +} + +void stats_print_bsi(bsi_t *bsi) +{ + dprintf("(bsi) "); + dprintf("%s",service_ids[bsi->bsmod]); + dprintf(" %d.%d Mode ",bsi->nfchans,bsi->lfeon); + if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1)) + dprintf(" Centre Mix Level %s ",cmixlev_tbl[bsi->cmixlev].desc); + if (bsi->acmod & 0x4) + dprintf(" Sur Mix Level %s ",smixlev_tbl[bsi->cmixlev].desc); + dprintf("\n"); + +} + +char *exp_strat_tbl[4] = {"R ","D15 ","D25 ","D45 "}; + +void stats_print_audblk(bsi_t *bsi,audblk_t *audblk) +{ + uint_32 i; + + dprintf("(audblk) "); + dprintf("%s ",audblk->cplinu ? "cpl on " : "cpl off"); + dprintf("%s ",audblk->baie? "bai " : " "); + dprintf("%s ",audblk->snroffste? "snroffst " : " "); + dprintf("%s ",audblk->deltbaie? "deltba " : " "); + dprintf("%s ",audblk->phsflginu? "phsflg " : " "); + dprintf("(%s %s %s %s %s) ",exp_strat_tbl[audblk->chexpstr[0]], + exp_strat_tbl[audblk->chexpstr[1]],exp_strat_tbl[audblk->chexpstr[2]], + exp_strat_tbl[audblk->chexpstr[3]],exp_strat_tbl[audblk->chexpstr[4]]); + dprintf("["); + for(i=0;infchans;i++) + dprintf("%1d",audblk->blksw[i]); + dprintf("]"); + + dprintf("\n"); +} diff --git a/ac3dec/libac3/stats.h b/ac3dec/libac3/stats.h new file mode 100644 index 0000000..8a9ecb6 --- /dev/null +++ b/ac3dec/libac3/stats.h @@ -0,0 +1,27 @@ +/* + * stats.h + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +void stats_print_syncinfo(syncinfo_t *syncinfo); +void stats_print_bsi(bsi_t *bsi); +void stats_print_audblk(bsi_t *bsi,audblk_t *audblk); +void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi); diff --git a/ac3dec/output.c b/ac3dec/output.c new file mode 100644 index 0000000..e48c762 --- /dev/null +++ b/ac3dec/output.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) by Jaroslav Kysela + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include + +typedef signed short sint_16; +typedef unsigned int uint_32; + +#include "output.h" + +static int pcm_channels; +static snd_pcm_t *pcm; + +/* + * open the audio device for writing to + */ +int output_open(int bits, int rate, int channels) +{ + char devstr[128]; + int card, dev; + snd_pcm_hw_params_t *params; + snd_pcm_sw_params_t *swparams; + snd_pcm_sframes_t buffer_time; + snd_pcm_sframes_t period_time; + int err; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_sw_params_alloca(&swparams); + + pcm_channels = channels; + + /* + * Open the device driver + */ + card = snd_defaults_pcm_card(); + dev = snd_defaults_pcm_device(); + if (card < 0 || dev < 0) { + fprintf(stderr, "defaults are not set\n"); + return -ENODEV; + } + switch (channels) { + case 1: + case 2: + sprintf(devstr, "plug:%d,%d", card, dev); + break; + case 4: + sprintf(devstr, "surround40:%d,%d", card, dev); + break; + case 6: + sprintf(devstr, "surround51:%d,%d", card, dev); + break; + default: + fprintf(stderr, "%d channels are not supported\n", channels); + return -EINVAL; + } + if ((err = snd_pcm_open(&pcm, devstr, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + fprintf(stderr, "snd_pcm_open: %s\n", snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_any(pcm, params); + if (err < 0) { + fprintf(stderr, "Broken configuration for this PCM: no configurations available"); + goto __close; + } + /* set interleaved access */ + err = snd_pcm_hw_params_set_access(pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) { + fprintf(stderr, "Access type not available"); + goto __close; + } + err = snd_pcm_hw_params_set_format(pcm, params, bits == 16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8); + if (err < 0) { + fprintf(stderr, "Sample format non available"); + goto __close; + } + err = snd_pcm_hw_params_set_channels(pcm, params, channels); + if (err < 0) { + fprintf(stderr, "Channels count non available"); + goto __close; + } + err = snd_pcm_hw_params_set_rate_near(pcm, params, rate, 0); + if (err < 0) { + fprintf(stderr, "Rate not available"); + goto __close; + } + buffer_time = snd_pcm_hw_params_set_buffer_time_near(pcm, params, + 500000, 0); + if (buffer_time < 0) { + fprintf(stderr, "Buffer time not available"); + goto __close; + } + period_time = snd_pcm_hw_params_set_period_time_near(pcm, params, + 100000, 0); + if (period_time < 0) { + fprintf(stderr, "Period time not available"); + goto __close; + } + if (buffer_time == period_time) { + fprintf(stderr, "Buffer time and period time match, could not use\n"); + goto __close; + } + if ((err = snd_pcm_hw_params(pcm, params)) < 0) { + fprintf(stderr, "PCM hw_params failed: %s\n", snd_strerror(err)); + goto __close; + } + + return 0; + + __close: + snd_pcm_close(pcm); + pcm = NULL; + return err; +} + +/* + * play the sample to the already opened file descriptor + */ +void output_play(sint_16* output_samples, uint_32 num_frames) +{ + snd_pcm_sframes_t res; + + res = snd_pcm_writei(pcm, (void *)output_samples, num_frames); + if (res < 0) + fprintf(stderr, "writei returned error: %s\n", snd_strerror(res)); + else if (res != num_frames) + fprintf(stderr, "writei retured %li (expected %li)\n", res, (long)(num_frames)); +} + + +void +output_close(void) +{ + snd_pcm_close(pcm); +} diff --git a/ac3dec/output.h b/ac3dec/output.h new file mode 100644 index 0000000..cb5a6aa --- /dev/null +++ b/ac3dec/output.h @@ -0,0 +1,29 @@ +/* + * + * output.h + * + * Based on original code by Angus Mackay (amackay@gus.ml.org) + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +int output_open(int bits, int rate, int channels); +void output_play(sint_16* output_samples, uint_32 num_bytes); +void output_close(void); diff --git a/ac3dec/output_irix.c b/ac3dec/output_irix.c new file mode 100644 index 0000000..931819b --- /dev/null +++ b/ac3dec/output_irix.c @@ -0,0 +1,154 @@ +/* + * + * output_irix.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * Port to IRIX by Jim Miller, SGI - Nov 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + + +typedef signed short sint_16; +typedef unsigned int uint_32; +#include "output.h" + +static int init = 0; +static ALport alport = 0; +static ALconfig alconfig = 0; +static int bytesPerWord = 1; +static int nChannels = 2; + + +/* + * open the audio device for writing to + */ +int output_open(int bits, int rate, int channels) +{ + ALpv params[2]; + int dev = AL_DEFAULT_OUTPUT; + int wsize = AL_SAMPLE_16; + + nChannels = channels; + + if (!init) { + init = 1; + alconfig = alNewConfig(); + + if (alSetQueueSize(alconfig, BUFFER_SIZE) < 0) { + fprintf(stderr, "alSetQueueSize failed: %s\n", + alGetErrorString(oserror())); + return 0; + } + + if (alSetChannels(alconfig, channels) < 0) { + fprintf(stderr, "alSetChannels(%d) failed: %s\n", + channels, alGetErrorString(oserror())); + return 0; + } + + if (alSetDevice(alconfig, dev) < 0) { + fprintf(stderr, "alSetDevice failed: %s\n", + alGetErrorString(oserror())); + return 0; + } + + if (alSetSampFmt(alconfig, AL_SAMPFMT_TWOSCOMP) < 0) { + fprintf(stderr, "alSetSampFmt failed: %s\n", + alGetErrorString(oserror())); + return 0; + } + + alport = alOpenPort("AC3Decode", "w", 0); + if (!alport) { + fprintf(stderr, "alOpenPort failed: %s\n", + alGetErrorString(oserror())); + return 0; + } + + switch (bits) { + case 8: + bytesPerWord = 1; + wsize = AL_SAMPLE_8; + break; + case 16: + bytesPerWord = 2; + wsize = AL_SAMPLE_16; + break; + case 24: + bytesPerWord = 4; + wsize = AL_SAMPLE_24; + break; + default: + printf("Irix audio: unsupported bit with %d\n", bits); + break; + } + + if (alSetWidth(alconfig, wsize) < 0) { + fprintf(stderr, "alSetWidth failed: %s\n", alGetErrorString(oserror())); + return 0; + } + + params[0].param = AL_RATE; + params[0].value.ll = alDoubleToFixed((double)rate); + params[1].param = AL_MASTER_CLOCK; + params[1].value.i = AL_CRYSTAL_MCLK_TYPE; + if ( alSetParams(dev, params, 1) < 0) { + printf("alSetParams() failed: %s\n", alGetErrorString(oserror())); + return 0; + } + } + + printf("I've synced the IRIX code with the mainline blindly.\n Let me know if it works.\n"); + + return 1; +} + +/* + * play the sample to the already opened file descriptor + */ + +void output_play(sint_16* output_samples, uint_32 num_bytes) +{ + alWriteFrames(alport, output_samples, 6 * 256); +} + +void +output_close(void) +{ + alClosePort(alport); + alFreeConfig(alconfig); + alport = 0; + alconfig = 0; + init = 0; +} diff --git a/ac3dec/output_linux.c b/ac3dec/output_linux.c new file mode 100644 index 0000000..9a467bd --- /dev/null +++ b/ac3dec/output_linux.c @@ -0,0 +1,113 @@ +/* + * + * output_linux.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#if defined(__OpenBSD__) +#include +#elif defined(__FreeBSD__) +#include +#else +#include +#endif +#include + +//this sux...types should go in config.h methinks +typedef signed short sint_16; +typedef unsigned int uint_32; + +#include "output.h" + + +static char dev[] = "/dev/dsp"; +static int fd; + + +/* + * open the audio device for writing to + */ +int output_open(int bits, int rate, int channels) +{ + int tmp; + + /* + * Open the device driver + */ + + fd=open(dev,O_WRONLY); + if(fd < 0) + { + fprintf(stderr,"%s: Opening audio device %s\n", + strerror(errno), dev); + goto ERR; + } + + tmp = channels == 2 ? 1 : 0; + ioctl(fd,SNDCTL_DSP_STEREO,&tmp); + + tmp = bits; + ioctl(fd,SNDCTL_DSP_SAMPLESIZE,&tmp); + + tmp = rate; + ioctl(fd,SNDCTL_DSP_SPEED, &tmp); + + //this is cheating + tmp = 256; +// ioctl(fd,SNDCTL_DSP_SETFRAGMENT,&tmp); + + + + return 1; + +ERR: + if(fd >= 0) { close(fd); } + return 0; +} + +/* + * play the sample to the already opened file descriptor + */ +void output_play(sint_16* output_samples, uint_32 num_bytes) +{ +// if(fd < 0) +// return; + + write(fd,output_samples,1024 * 6); +} + + +void +output_close(void) +{ + close(fd); +} diff --git a/ac3dec/output_solaris.c b/ac3dec/output_solaris.c new file mode 100644 index 0000000..df4e1ed --- /dev/null +++ b/ac3dec/output_solaris.c @@ -0,0 +1,124 @@ +/* + * + * output_solaris.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//FIXME broken solaris headers! +int usleep(unsigned int useconds); + + +//this sux...types should go in config.h methinks +typedef signed short sint_16; +typedef unsigned int uint_32; + +#include "output.h" + +/* Global to keep track of old state */ +static audio_info_t info; +static char dev[] = "/dev/audio"; +static int fd; + + +/* + * open the audio device for writing to + */ +int output_open(int bits, int rate, int channels) +{ + + /* + * Open the device driver + */ + + fd=open(dev,O_WRONLY); + if(fd < 0) + { + fprintf(stderr,"%s: Opening audio device %s\n", + strerror(errno), dev); + goto ERR; + } + fprintf(stderr,"Opened audio device \"%s\"\n",dev); + + /* Setup our parameters */ + AUDIO_INITINFO(&info); + + info.play.sample_rate = rate; + info.play.precision = bits; + info.play.channels = channels; + info.play.buffer_size = 1024; + info.play.encoding = AUDIO_ENCODING_LINEAR; + //info.play.port = AUDIO_SPEAKER; + //info.play.gain = 110; + + /* Write our configuration */ + /* An implicit GETINFO is also performed so we can get + * the buffer_size */ + + if(ioctl(fd, AUDIO_SETINFO, &info) < 0) + { + fprintf(stderr, "%s: Writing audio config block\n",strerror(errno)); + goto ERR; + } + + return 1; + +ERR: + if(fd >= 0) { close(fd); } + return 0; +} + +unsigned long j= 0 ; +/* + * play the sample to the already opened file descriptor + */ +void output_play(sint_16* output_samples, uint_32 num_bytes) +{ + write(fd,&output_samples[0 * 512],1024); + write(fd,&output_samples[1 * 512],1024); + write(fd,&output_samples[2 * 512],1024); + write(fd,&output_samples[3 * 512],1024); + write(fd,&output_samples[4 * 512],1024); + write(fd,&output_samples[5 * 512],1024); +} + + +void +output_close(void) +{ + close(fd); +} + diff --git a/ac3dec/plot_spectrum.m b/ac3dec/plot_spectrum.m new file mode 100644 index 0000000..43f4806 --- /dev/null +++ b/ac3dec/plot_spectrum.m @@ -0,0 +1,17 @@ + +window_size = 2048; +f = 0:48000/window_size:48000 * (1 - 1/window_size); +w = transpose(hamming(1536)); +n = size(foo,1); + +spectrum = zeros(1,window_size); + +for i = [1:n] + data = w .* foo(i,:); + spectrum = spectrum + abs(fft(data,window_size)); +end + +plot(f,10*log10(spectrum/max(spectrum))); +grid; +axis([0 24000 -40 0]); + diff --git a/ac3dec/test/Makefile.am b/ac3dec/test/Makefile.am new file mode 100644 index 0000000..4f3d0a6 --- /dev/null +++ b/ac3dec/test/Makefile.am @@ -0,0 +1,37 @@ +INCLUDES = -I../libac3 +noinst_PROGRAMS = imdct_test dither_test +#noinst_PROGRAMS = bitstream_test imdct_test imdct_timing uncouple_timing\ + #crc_timing +noinst_HEADERS = timing.h + +#bitstream_test_SOURCES = bitstream_test.c +#bitstream_test_LDADD = ../bitstream.o ../crc.o +# +dither_test_SOURCES = dither_test.c +dither_test_LDADD = ../libac3/dither.o + +imdct_test_SOURCES = imdct_test.c +imdct_test_LDADD = ../libac3/imdct.o -lm +# +#imdct_timing_SOURCES = imdct_timing.c timing.c +#imdct_timing_LDADD = ../imdct.o -lm +# +#uncouple_timing_SOURCES = uncouple_timing.c timing.c +#uncouple_timing_LDADD = ../uncouple.o ../dither.o -lm +# +#crc_timing_SOURCES = crc_timing.c timing.c +#crc_timing_LDADD = ../crc.o -lm + +check: + #rm -f bitstream_test.out + #./bitstream_test > bitstream_test.out + #diff bitstream_test.out bitstream_test.out.ref + #rm -f imdct_test.out + #./imdct_test > imdct_test.out + #diff imdct_test.out imdct_test.out.ref + rm -f dither_test.out + ./dither_test > dither_test.out + diff dither_test.out dither_test.out.ref + +clean: + rm -f *.out diff --git a/ac3dec/test/dither_test.c b/ac3dec/test/dither_test.c new file mode 100644 index 0000000..e45dc71 --- /dev/null +++ b/ac3dec/test/dither_test.c @@ -0,0 +1,43 @@ +/* + * dither_test.c + * + * Aaron Holtzman - May 1999 + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" +#include "dither.h" + +#include +#include + +int main(void) +{ + int i,j,foo; + struct timeval start,end; + + /* + for(i=0;i < 65538 ;i++) + //printf("%04x\n",dither_gen()); + printf("%f\n",((sint_16)dither_gen())/ 32768.0); + printf("\n"); + */ + + + + for(j=0;j < 10 ;j++) + { + gettimeofday(&start,0); + for(i=0;i < 10000 ;i++) + { + foo = dither_gen(); + } + gettimeofday(&end,0); + printf("%f us\n",((end.tv_sec - start.tv_sec) * 1000000 + + (end.tv_usec - start.tv_usec))/10000.0); + } + +} diff --git a/ac3dec/test/imdct_test.c b/ac3dec/test/imdct_test.c new file mode 100644 index 0000000..12572d1 --- /dev/null +++ b/ac3dec/test/imdct_test.c @@ -0,0 +1,38 @@ +/* + * imdct_test.c + * + * Aaron Holtzman - May 1999 + * + */ + +#include +#include +#include "ac3.h" +#include "ac3_internal.h" +#include "imdct.h" + +static stream_samples_t samples; +static bsi_t bsi; +static audblk_t audblk; + +int main(void) +{ + int i; + + samples[0][20] = 0.4; + samples[0][40] = 0.4; + samples[0][30] = 1.0; + + + imdct_init(); + bsi.nfchans = 1; + + imdct(&bsi,&audblk,samples); + + + for(i=0;i<256;i++) + printf("%1.8f\n",samples[0][i]); + + return 0; + +} diff --git a/ac3dec/test/timing.h b/ac3dec/test/timing.h new file mode 100644 index 0000000..9d8da62 --- /dev/null +++ b/ac3dec/test/timing.h @@ -0,0 +1,14 @@ +/* + * timing.h + * + * Aaron Holtzman - May 1999 + * + */ + +//uint_64 get_time(void); +uint_64 timing_init(void); + +void timing_test_2(void (*func)(void*,void*),void *arg_1,void *arg_2,char name[]); +void timing_test_3(void (*func)(void*,void*,void*),void *arg_1,void *arg_2,void *arg_3,char name[]); +double timing_once_3(void (*func)(void*,void*,void*),void *arg_1,void *arg_2,void *arg_3); + diff --git a/ac3dec/tools/Makefile.am b/ac3dec/tools/Makefile.am new file mode 100644 index 0000000..a56cb15 --- /dev/null +++ b/ac3dec/tools/Makefile.am @@ -0,0 +1,12 @@ +# # Process this file with automake to produce Makefile.in. +AUTOMAKE_OPTIONS = 1.3 foreign + +CFLAGS = -Wall -Werror -O3 -g + +bin_PROGRAMS = extract_ac3 + + +extract_ac3_SOURCES = extract_ac3.c +#verify is broken right now +#verify_ac3_SOURCES = verify_ac3.c +#verify_ac3_LDADD = ../parse.o ../bitstream.o ../crc.o ../debug.o ../stats.o diff --git a/ac3dec/tools/extract_ac3.c b/ac3dec/tools/extract_ac3.c new file mode 100644 index 0000000..e14cf5c --- /dev/null +++ b/ac3dec/tools/extract_ac3.c @@ -0,0 +1,314 @@ +/* + * extract_ac3.c + * + * Copyright (C) Aaron Holtzman - June 1999 + * + * Extracts an AC-3 audio stream from an MPEG-2 system stream + * and writes it to stdout + * + * Ideas and bitstream syntax info borrowed from code written + * by Nathan Laredo + * + * Multiple track support by Yuqing Deng + * + * + * This file is part of ac3dec, a free Dolby AC-3 stream decoder. + * + * ac3dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ac3dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Audio track to play */ +static unsigned char track_code = 0x80; +static unsigned char track_table[8] = +{ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 +}; + +#define BUFSIZE 512 /* needs to be as big as biggest header */ +static int vobf; +static unsigned char buf[BUFSIZE]; +static unsigned char *cur_pos; +static unsigned char *end_pos; + +void file_init(char file_name[]) +{ + if(file_name[0] == '-' && file_name[1] == '\0') + { + vobf = STDIN_FILENO; + } + else if ((vobf = open(file_name, O_RDONLY)) < 0) + { + fprintf(stderr,"File not found\n"); + exit(1); + } + cur_pos = buf; + end_pos = buf; +} + +inline void increment_position(long x) +{ + if(cur_pos + x <= end_pos) + { + cur_pos += x; + if(cur_pos == end_pos) + { + cur_pos = buf; + end_pos = buf; + } + } + else + { + long size = 0; + x -= (long)(end_pos - cur_pos); +#ifdef SEEK_PIPES + if(lseek(vobf, x, SEEK_CUR) < 0) + { + fprintf(stderr, "Error: unexpected end of stream\n"); + exit(1); + } +#else + while(x) + { + size = (x > BUFSIZE) ? BUFSIZE : x; + if(read(vobf, buf, size) < size) + { + fprintf(stderr, "Error: unexpected end of stream\n"); + exit(1); + } + x-=size; + } +#endif + cur_pos = buf; + end_pos = buf; + } +} + +inline static void load_next_bytes(long count) +{ + if(cur_pos + count <= end_pos) + return; + if(cur_pos + count > buf + BUFSIZE - 1 ) + { + printf ("No buffer space to read %ld bytes\n", count); + exit(1); + } + + count -= (long)(end_pos - cur_pos); + if(read(vobf, end_pos, count) < count) + { + fprintf(stderr, "Error: unexpected end of stream\n"); + exit(1); + } + end_pos += count; +} + +inline int next_24_bits(long x) +{ + load_next_bytes(3); + if (cur_pos[0] != ((x >> 16) & 0xff)) + return 0; + if (cur_pos[1] != ((x >> 8) & 0xff)) + return 0; + if (cur_pos[2] != ((x ) & 0xff)) + return 0; + + return 1; +} + +inline int next_32_bits(long x) +{ + load_next_bytes(4); + if (cur_pos[0] != ((x >> 24) & 0xff)) + return 0; + if (cur_pos[1] != ((x >> 16) & 0xff)) + return 0; + if (cur_pos[2] != ((x >> 8) & 0xff)) + return 0; + if (cur_pos[3] != ((x ) & 0xff)) + return 0; + + return 1; +} + +void read_write_next_bytes(long count, int outfd) +{ + long size; + size = (long)(end_pos - cur_pos); + if(size > count) + { + write(outfd, cur_pos, count); + cur_pos +=count; + if(cur_pos == end_pos) + { + cur_pos = buf; + end_pos = buf; + } + return; + } + else if(size > 0) + { + write(outfd, cur_pos, size); + } + + while(count) + { + size = (count > BUFSIZE) ? BUFSIZE : count; + if(read(vobf, buf, size) < size || + write(outfd, buf, size) < size) + { + fprintf(stderr, "Error: unexpected end of stream\n"); + } + count -= size; + } + cur_pos = buf; + end_pos = buf; +} + +void parse_pes(void) +{ + unsigned long data_length; + unsigned long header_length; + + load_next_bytes(9); + + //The header length is the PES_header_data_length byte plus 6 for the packet + //start code and packet size, 3 for the PES_header_data_length and two + //misc bytes, and finally 4 bytes for the mystery AC3 packet tag + header_length = cur_pos[8] + 6 + 3 + 4 ; + data_length =(cur_pos[4]<<8) + cur_pos[5]; + + + //If we have AC-3 audio then output it + if(cur_pos[3] == 0xbd) + { + load_next_bytes(header_length); +#if 0 + //Debugging printfs + fprintf(stderr,"start of pes curpos[] = %02x%02x%02x%02x\n", + cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]); + fprintf(stderr,"header_length = %d data_length = %x\n", + header_length, data_length); + fprintf(stderr,"extra crap 0x%02x%02x%02x%02x data size 0x%0lx\n",cur_pos[header_length-4], + cur_pos[header_length-3],cur_pos[header_length-2],cur_pos[header_length-1],data_length); +#endif + + //Only extract the track we want + if((cur_pos[header_length-4] == track_code )) + { + increment_position(header_length); + read_write_next_bytes(data_length - header_length + 6, STDOUT_FILENO); + + } + else + { + increment_position(data_length + 6); + } + } + else + { + //The packet size is data_length plus 6 bytes to account for the + //packet start code and the data_length itself. + increment_position(data_length + 6); + } +} + +void parse_pack(void) +{ + unsigned long skip_length; + + // Deal with the pack header + // The first 13 bytes are junk. The fourteenth byte + // contains the number of stuff bytes + load_next_bytes(14); + skip_length = cur_pos[13] & 0x7; + increment_position(14 + skip_length); + + // Deal with the system header if it exists + if(next_32_bits(0x000001bb)) + { + // Bytes 5 and 6 contain the length of the header minus 6 + load_next_bytes(6); + skip_length = (cur_pos[4] << 8) + cur_pos[5]; + increment_position(6 + skip_length); + } + + while(next_24_bits(0x000001) && !next_32_bits(0x000001ba)) + { + parse_pes(); + } +} + +int main(int argc, char *argv[]) +{ + int track = 0; + + if (argc < 2) { + fprintf(stderr, "usage: %s mpeg_stream [track number]\n", argv[0]); + exit(1); + } + + if (argc == 3) + { + track = strtol(argv[2], NULL, 0); + fprintf(stderr,"Extracting track %d\n",track); + } + + if (track < 0 || track > 7) + { + fprintf(stderr, "Invalid track number: %d\n", track); + exit(1); + } + + track_code = track_table[track]; + + + + file_init(argv[1]); + + if(!next_32_bits(0x000001ba)) + { + fprintf(stderr, "Non-program streams not handled - exiting\n\n"); + exit(1); + } + + do + { + parse_pack(); + } + while(next_32_bits(0x000001ba)); + + fprintf(stderr,"curpos[] = %x%x%x%x\n",cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]); + + if(!next_32_bits(0x000001b9)) + { + fprintf(stderr, "Error: expected end of stream code\n"); + exit(1); + } + + if(vobf != STDIN_FILENO) close(vobf); + return 0; +} -- 2.47.1