]> git.alsa-project.org Git - alsa-tools.git/commitdiff
Added ac3dec 0.6.1 with native ALSA driver.
authorJaroslav Kysela <perex@perex.cz>
Tue, 17 Apr 2001 19:31:03 +0000 (19:31 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 17 Apr 2001 19:31:03 +0000 (19:31 +0000)
50 files changed:
ac3dec/COPYING [new file with mode: 0644]
ac3dec/Changelog [new file with mode: 0644]
ac3dec/Makefile.am [new file with mode: 0644]
ac3dec/README [new file with mode: 0644]
ac3dec/TODO [new file with mode: 0644]
ac3dec/ac3dec.c [new file with mode: 0644]
ac3dec/configure.in [new file with mode: 0644]
ac3dec/libac3/Makefile.am [new file with mode: 0644]
ac3dec/libac3/ac3.h [new file with mode: 0644]
ac3dec/libac3/ac3_internal.h [new file with mode: 0644]
ac3dec/libac3/bit_allocate.c [new file with mode: 0644]
ac3dec/libac3/bit_allocate.h [new file with mode: 0644]
ac3dec/libac3/bitstream.c [new file with mode: 0644]
ac3dec/libac3/bitstream.h [new file with mode: 0644]
ac3dec/libac3/coeff.c [new file with mode: 0644]
ac3dec/libac3/coeff.h [new file with mode: 0644]
ac3dec/libac3/crc.c [new file with mode: 0644]
ac3dec/libac3/crc.h [new file with mode: 0644]
ac3dec/libac3/debug.c [new file with mode: 0644]
ac3dec/libac3/debug.h [new file with mode: 0644]
ac3dec/libac3/decode.c [new file with mode: 0644]
ac3dec/libac3/decode.h [new file with mode: 0644]
ac3dec/libac3/dither.c [new file with mode: 0644]
ac3dec/libac3/dither.h [new file with mode: 0644]
ac3dec/libac3/downmix.c [new file with mode: 0644]
ac3dec/libac3/downmix.h [new file with mode: 0644]
ac3dec/libac3/exponent.c [new file with mode: 0644]
ac3dec/libac3/exponent.h [new file with mode: 0644]
ac3dec/libac3/imdct.c [new file with mode: 0644]
ac3dec/libac3/imdct.h [new file with mode: 0644]
ac3dec/libac3/parse.c [new file with mode: 0644]
ac3dec/libac3/parse.h [new file with mode: 0644]
ac3dec/libac3/rematrix.c [new file with mode: 0644]
ac3dec/libac3/rematrix.h [new file with mode: 0644]
ac3dec/libac3/sanity_check.c [new file with mode: 0644]
ac3dec/libac3/sanity_check.h [new file with mode: 0644]
ac3dec/libac3/stats.c [new file with mode: 0644]
ac3dec/libac3/stats.h [new file with mode: 0644]
ac3dec/output.c [new file with mode: 0644]
ac3dec/output.h [new file with mode: 0644]
ac3dec/output_irix.c [new file with mode: 0644]
ac3dec/output_linux.c [new file with mode: 0644]
ac3dec/output_solaris.c [new file with mode: 0644]
ac3dec/plot_spectrum.m [new file with mode: 0644]
ac3dec/test/Makefile.am [new file with mode: 0644]
ac3dec/test/dither_test.c [new file with mode: 0644]
ac3dec/test/imdct_test.c [new file with mode: 0644]
ac3dec/test/timing.h [new file with mode: 0644]
ac3dec/tools/Makefile.am [new file with mode: 0644]
ac3dec/tools/extract_ac3.c [new file with mode: 0644]

diff --git a/ac3dec/COPYING b/ac3dec/COPYING
new file mode 100644 (file)
index 0000000..60549be
--- /dev/null
@@ -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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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.
+
+  <signature of Ty Coon>, 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 (file)
index 0000000..fba3daf
--- /dev/null
@@ -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 <mamueller@topmail.de> 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 <kju@flummi.de>
+
+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 (file)
index 0000000..4cc18ce
--- /dev/null
@@ -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 (file)
index 0000000..19e3a49
--- /dev/null
@@ -0,0 +1,52 @@
+ac3dec - a free AC-3 stream decoder
+
+Written by Aaron Holtzman (aholtzma@engr.uvic.ca)
+
+Contributors:
+  Michael Holzt <kju@flummi.de> - OSS output.c and misc errata
+       Jim Miller <jmiller@heli.engr.sgi.com> - IRIX output.c
+       Angelos Keromytis <angelos@dsl.cis.upenn.edu> - OpenBSD fixes
+       Don Mahurin <dmahurin@dma.org> - stdin support for extract_ac3
+       Takefumi SAYO <stake@niagara.shiojiri.ne.jp> - FreeBSD tweak
+       Charles M. Hannum <root@ihack.net> - 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 (file)
index 0000000..02e0894
--- /dev/null
@@ -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 (file)
index 0000000..81111b2
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <errno.h>
+
+#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 (file)
index 0000000..ad26828
--- /dev/null
@@ -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 (file)
index 0000000..d977b33
--- /dev/null
@@ -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 (file)
index 0000000..30d7116
--- /dev/null
@@ -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 (file)
index 0000000..8de184a
--- /dev/null
@@ -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 (file)
index 0000000..053e09c
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#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<end; bin++) 
+       { 
+               psd[bin] = (3072 - (exps[bin] << 7)); 
+       }
+
+       /* Integrate the psd function over each bit allocation band */
+       j = start; 
+       k = masktab[start]; 
+       
+       do 
+       { 
+               lastbin = min(bndtab[k] + bndsz[k], end); 
+               bndpsd[k] = psd[j]; 
+               j++; 
+
+               for (i = j; i < lastbin; i++) 
+               { 
+                       bndpsd[k] = logadd(bndpsd[k], psd[j]);
+                       j++; 
+               } 
+               
+               k++; 
+       } while (end > 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 (file)
index 0000000..e48b0b2
--- /dev/null
@@ -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 (file)
index 0000000..fdaeaf7
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+
+#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 (file)
index 0000000..b2a148c
--- /dev/null
@@ -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 (file)
index 0000000..b9f03ff
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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;i<audblk->cplendmant;)
+       {
+               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 (file)
index 0000000..dc822a9
--- /dev/null
@@ -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 (file)
index 0000000..3210ce7
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+#include <sys/time.h>
+
+#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<num_bytes;i++)
+               crc_process_byte(data[i]);
+}
+
+int
+crc_validate(void)
+{
+       return(state  == 0);
+}
diff --git a/ac3dec/libac3/crc.h b/ac3dec/libac3/crc.h
new file mode 100644 (file)
index 0000000..07d57b1
--- /dev/null
@@ -0,0 +1,27 @@
+/* 
+ *  crc.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 crc_validate(void);
+void crc_init(void);
+void crc_process_byte(uint_8 data);
+void crc_process_frame(uint_8 *data,uint_32 num_bytes);
diff --git a/ac3dec/libac3/debug.c b/ac3dec/libac3/debug.c
new file mode 100644 (file)
index 0000000..b7d6a3b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ * debug.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 <stdlib.h>
+#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 (file)
index 0000000..f45cb5b
--- /dev/null
@@ -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 (file)
index 0000000..f0d90d2
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#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 (file)
index 0000000..bb84a11
--- /dev/null
@@ -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 (file)
index 0000000..31e74f6
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..6d68e1b
--- /dev/null
@@ -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 (file)
index 0000000..6d42342
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#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 (file)
index 0000000..7537c62
--- /dev/null
@@ -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 (file)
index 0000000..98111a5
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..06c59db
--- /dev/null
@@ -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 (file)
index 0000000..6fa0e2a
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#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 <sys/time.h>
+//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; i<bsi->nfchans;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 (file)
index 0000000..750aa87
--- /dev/null
@@ -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 (file)
index 0000000..86e031c
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..72aa32c
--- /dev/null
@@ -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 (file)
index 0000000..caa7094
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..0be6528
--- /dev/null
@@ -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 (file)
index 0000000..461f20e
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..c4ca63a
--- /dev/null
@@ -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 (file)
index 0000000..2ac88e0
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#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;i<bsi->nfchans;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 (file)
index 0000000..8a9ecb6
--- /dev/null
@@ -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 (file)
index 0000000..e48c762
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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 <stdio.h>
+#include <errno.h>
+#include <sys/asoundlib.h>
+
+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(&params);
+       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 (file)
index 0000000..cb5a6aa
--- /dev/null
@@ -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 (file)
index 0000000..931819b
--- /dev/null
@@ -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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+
+#include <audio.h>
+
+
+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 (file)
index 0000000..9a467bd
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+#if defined(__OpenBSD__)
+#include <soundcard.h>
+#elif defined(__FreeBSD__)
+#include <machine/soundcard.h>
+#else
+#include <sys/soundcard.h>
+#endif
+#include <sys/ioctl.h>
+
+//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 (file)
index 0000000..df4e1ed
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/audioio.h>
+#include <sys/ioctl.h>
+#include <stropts.h>
+#include <signal.h>
+#include <math.h>
+
+//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 (file)
index 0000000..43f4806
--- /dev/null
@@ -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 (file)
index 0000000..4f3d0a6
--- /dev/null
@@ -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 (file)
index 0000000..e45dc71
--- /dev/null
@@ -0,0 +1,43 @@
+/* 
+ *  dither_test.c
+ *
+ *     Aaron Holtzman - May 1999
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+#include "dither.h"
+
+#include <sys/time.h>
+#include <unistd.h>
+
+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 (file)
index 0000000..12572d1
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ *  imdct_test.c
+ *
+ *     Aaron Holtzman - May 1999
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..9d8da62
--- /dev/null
@@ -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 (file)
index 0000000..a56cb15
--- /dev/null
@@ -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 (file)
index 0000000..e14cf5c
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ *  extract_ac3.c
+ *
+ *  Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - 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 <laredo@gnu.org>
+ *
+ *  Multiple track support by Yuqing Deng <deng@tinker.chem.brown.edu>
+ * 
+ *
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+
+/* 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;
+}