changeset 290:fbd06b4aa776 trunk

[svn] - add TrueAudio plugin
author yaz
date Wed, 22 Nov 2006 09:55:20 -0800
parents a60da24269dc
children 93c0da3f7a86
files ChangeLog configure.ac src/tta/Copying src/tta/Makefile src/tta/Readme src/tta/aud-support.h src/tta/aud-tta.c src/tta/crc32.h src/tta/filters.h src/tta/id3.c src/tta/id3genre.h src/tta/ttadec.c src/tta/ttadec.h src/tta/ttaid3tag.h src/tta/ttalib.h
diffstat 15 files changed, 2909 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Nov 22 09:53:40 2006 -0800
+++ b/ChangeLog	Wed Nov 22 09:55:20 2006 -0800
@@ -1,3 +1,11 @@
+2006-11-22 17:53:40 +0000  Yoshiki Yazawa <yaz@cc.rim.or.jp>
+  revision [624]
+  - bump version to 1.3.0
+  
+  trunk/configure.ac |    6 +++---
+  1 file changed, 3 insertions(+), 3 deletions(-)
+
+
 2006-11-22 12:51:29 +0000  Yoshiki Yazawa <yaz@cc.rim.or.jp>
   revision [616]
   - fix for buffer usage in cddb.c by Richard Chan <rspchan -at starhub.net.sg>
--- a/configure.ac	Wed Nov 22 09:53:40 2006 -0800
+++ b/configure.ac	Wed Nov 22 09:55:20 2006 -0800
@@ -993,6 +993,28 @@
 	AC_DEFINE(HAVE_XSPF_PLAYLIST, 1, [Define if XSPF playlists are available.])
 fi
 
+dnl *** TTA
+
+AC_ARG_ENABLE(tta,
+    [  --disable-tta           disable TrueAudio plugin (default=enabled) ],
+    [enable_tta=$enableval],
+    [enable_tta=yes]
+)
+
+if test "$enable_tta" = "yes"; then
+    AC_CHECK_HEADERS([id3tag.h], [enable_tta=yes], [enable_tta=no])
+    if test "$enable_tta" = "yes"; then
+        AC_CHECK_LIB([id3tag], [id3_file_open], [enable_tta=yes], [enable_tta=no])
+    fi
+else
+    AC_MSG_RESULT([*** TrueAudio plugin disabled per user request ***])
+    enable_tta=no
+fi
+
+if test "$enable_tta" = "yes"; then
+	INPUT_PLUGINS="$INPUT_PLUGINS tta"
+fi
+
 dnl *** End of all plugin checks ***
 
 AC_SUBST(ARCH_DEFINES)
@@ -1104,6 +1126,7 @@
 echo "  Apple Lossless Audio Codec (alac):      yes"
 echo "  WavPack 4.31+ (wavpack):                $have_wavpack"
 echo "  Musepack support (musepack):            $enable_musepack"
+echo "  TrueAudio (tta):                        $enable_tta"
 echo
 echo "  General"
 echo "  -------"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/Copying	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,459 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/Makefile	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,16 @@
+include ../../mk/rules.mk
+include ../../mk/init.mk
+
+OBJECTIVE_LIBS = libtta.so
+
+LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR)
+
+SOURCES = aud-tta.c id3.c ttadec.c
+
+OBJECTS = ${SOURCES:.c=.o}
+
+CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) -I../../intl -I../..
+
+LIBADD = -lid3tag
+
+include ../../mk/objective.mk
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/Readme	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,72 @@
+TTA Input Plug-In for Beep Media Player
+=======================================
+
+Version 1.2, (c) 2004 Alexander Djourik. All rights reserved.
+
+* About Beep Media Player
+
+Beep Media Player is a media player for the X Window System that
+supports Winamp skins and that has a sophisticated plugin system
+that allows for easy extension of its abilities. Beep Media Player
+is able to deal with all common types of media files.
+
+For more information please visit a Beep Media Player homepage
+http://www.sosdg.org/~larne/w/BMP_Homepage
+
+* Introduction
+
+This Beep Media Player plug-in is a part of the TTA audio compressor
+which performs lossless compression on multichannel 8,16,24 integer
+and 32-bit IEEE floating-point data of the wav audio files.
+Being "lossless" means that no data/quality is lost in the
+compression - when uncompressed, the data will be identical to
+the original.
+
+At now, mostly all of the popular lossless compressors gives a same
+compression results (difference about 1-3%). TTA is a hardware-
+oriented format. It means that the TTA format has a reasonable
+compression level, but WAS NOT developed to show a top results in
+comparisons. TTA format supports both of ID3v1/v2 tags. Detailed
+format description is available at http://www.true-audio.com
+
+* Configuration
+
+1. Copy the file libtta.so out of your Beep Media Player input
+   plugins directory (usually ${INSTALL_PATH}/bmp/Input).
+2. Start Beep Media Player.
+3. Play TTA files and enjoy highest quality sound.
+
+* Requirements
+
+Nice sound card and good speakers.
+
+* Developers
+
+  Alexander Djourik <sasha@iszf.irk.ru>
+  Pavel Zhilin <pzh@iszf.irk.ru>
+
+* Copying
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA  02111-1307 USA
+
+Please see the file COPYING in this directory for full copyright
+information.
+
+* See also
+
+Please visit the TTA homepage at http://www.true-audio.com for the
+latest in news and downloads.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/aud-support.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,24 @@
+#include <audacious/vfs.h>
+
+#define FILE VFSFile
+#define fopen 	vfs_fopen
+#define fclose 	vfs_fclose
+#define fwrite  vfs_fwrite
+#define fread	vfs_fread
+#define frewind vfs_frewind
+#define ftell	vfs_ftell
+#define fseek	vfs_fseek
+
+size_t file_size (char *filename)
+{
+    VFSFile *f;
+    size_t size = -1;
+
+    if ((f = vfs_fopen (filename, "r")))
+    {
+	vfs_fseek (f, 0, SEEK_END);
+	size = vfs_ftell (f);
+	vfs_fclose (f); 
+    }
+    return size;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/aud-tta.c	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,968 @@
+/*
+ * aud--tta.c
+ *
+ * Description:	 TTA input plug-in for Audacious
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ * Audacious port: Yoshiki Yazawa <yaz@cc.rim.or.jp>
+ *
+ * Copyright (c) 2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <pthread.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include <audacious/util.h>
+#include <audacious/plugin.h>
+#include <audacious/titlestring.h>
+#include <audacious/vfs.h>
+#include "aud-support.h"
+#include "audacious/output.h"
+#include "audacious/util.h"
+
+#include <id3tag.h>
+
+
+
+#define  PLUGIN_VERSION "1.2"
+#define  PROJECT_URL "<http://www.true-audio.com>"
+
+#pragma pack (1)
+#include "ttalib.h"
+
+#define OUTPUT_ERROR (MEMORY_ERROR+1)
+#define MAX_BSIZE (MAX_BPS>>3)
+
+
+static void init ();
+static void cleanup ();
+static int  is_our_file (char *filename);
+static void play_file (char *filename);
+static void tta_pause (short paused);
+static void stop (void);
+static void seek (int time);
+static int  get_time (void);
+static void get_song_info (char *filename, char **title, int *length);
+static void file_info (char *filename);
+static void about ();
+static TitleInput *get_song_tuple(char *filename);
+static gchar *extname(const char *filename);
+
+InputPlugin tta_ip = 
+{
+    NULL,
+    NULL,
+    NULL,
+    init,
+    about,
+    NULL,
+    is_our_file,
+    NULL,
+    play_file,
+    stop,
+    tta_pause,
+    seek,
+    NULL,
+    get_time,
+    NULL,
+    NULL,
+    cleanup,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    get_song_info,
+    file_info,	
+    NULL,
+    get_song_tuple, // get_song_tuple
+    NULL, // set_song_tuple
+    NULL  // buffer
+};
+
+InputPlugin *
+get_iplugin_info (void)
+{
+    tta_ip.description = g_strdup_printf ("True Audio Plugin %s", PLUGIN_VERSION);
+    return &tta_ip;
+}
+
+static pthread_t decode_thread;
+static char sample_buffer[PCM_BUFFER_LENGTH * MAX_BSIZE * MAX_NCH];
+static tta_info info;		// currently playing file info
+static long seek_position = -1;
+static int  playing = FALSE;
+static int  read_samples = -1;
+
+static void
+tta_error (int error)
+{
+    char *message;
+    static GtkWidget *errorbox;
+    if (errorbox != NULL) return;
+
+    switch (error)
+    {
+      case OPEN_ERROR:
+	  message = "Can't open file\n";
+	  break;
+      case FORMAT_ERROR:
+	  message = "Not supported file format\n";
+	  break;
+      case FILE_ERROR:
+	  message = "File is corrupted\n";
+	  break;
+      case READ_ERROR:
+	  message = "Can't read from file\n";
+	  break;
+      case MEMORY_ERROR:
+	  message = "Insufficient memory available\n";
+	  break;
+      case OUTPUT_ERROR:
+	  message = "Output plugin error\n";
+	  break;
+    default:
+	  message = "Unknown error\n";
+	  break;
+    }
+
+    xmms_show_message ("TTA Decoder Error", message,
+	"Ok", FALSE, NULL, NULL);
+
+    gtk_signal_connect(GTK_OBJECT(errorbox), "destroy",
+        G_CALLBACK(gtk_widget_destroyed), &errorbox);
+}
+
+static gchar *
+get_title (char *filename, tta_info *ttainfo)
+{
+    char *name, *p;
+
+    if (ttainfo->id3v2.id3has &&
+	    (*ttainfo->id3v2.artist || *ttainfo->id3v2.title)) {
+	    if (*ttainfo->id3v2.artist && *ttainfo->id3v2.title)
+		    return g_strdup_printf("%s - %s", ttainfo->id3v2.artist, ttainfo->id3v2.title);
+	    else if (*ttainfo->id3v2.artist && *ttainfo->id3v2.album)
+		    return g_strdup_printf("%s - %s", ttainfo->id3v2.artist, ttainfo->id3v2.album);
+	    else if (*ttainfo->id3v2.artist) return g_strdup(ttainfo->id3v2.artist);
+	    else if (*ttainfo->id3v2.title)  return g_strdup(ttainfo->id3v2.title);
+    } else if (ttainfo->id3v1.id3has &&
+	    (*ttainfo->id3v1.artist || *ttainfo->id3v1.title)) {
+	    if (*ttainfo->id3v1.artist && *ttainfo->id3v1.title)
+		    return g_strdup_printf("%s - %s", ttainfo->id3v1.artist, ttainfo->id3v1.title);
+	    else if (*ttainfo->id3v1.artist && *ttainfo->id3v1.album)
+		    return g_strdup_printf("%s - %s", ttainfo->id3v1.artist, ttainfo->id3v1.album);
+	    else if (*ttainfo->id3v1.artist) return g_strdup(ttainfo->id3v1.artist);
+	    else if (*ttainfo->id3v1.title)  return g_strdup(ttainfo->id3v1.title);
+    }
+    name = g_strdup (g_basename(filename));
+    p = name + strlen(name);
+    while (*p != '.' && p >= name) p--;
+    if (*p == '.') *p = '\0';
+    p = g_strdup (name);
+    g_free (name);
+    return p;
+}
+
+static void *
+play_loop (void *arg)
+{
+    int  bufsize = PCM_BUFFER_LENGTH  * info.BSIZE * info.NCH;
+
+    ////////////////////////////////////////
+    // decode PCM_BUFFER_LENGTH samples
+    // into the current PCM buffer position
+
+    while (playing)
+    {
+	while ((read_samples = get_samples (sample_buffer)) > 0)
+	{
+
+	    while ((tta_ip.output->buffer_free () < bufsize)
+		   && seek_position == -1)
+	    {
+		if (!playing)
+		    goto DONE;
+		xmms_usleep (10000);
+	    }
+	    if (seek_position == -1)
+	    {
+		produce_audio(tta_ip.output->written_time(),
+			      ((info.BPS == 8) ? FMT_U8 : FMT_S16_LE),
+			      info.NCH,
+			      read_samples * info.NCH * info.BSIZE,
+			      sample_buffer,
+			      NULL);
+	    }
+	    else
+	    {
+		set_position (seek_position);
+		tta_ip.output->flush (seek_position * SEEK_STEP);
+		seek_position = -1;
+	    }
+	}
+	tta_ip.output->buffer_free ();
+	tta_ip.output->buffer_free ();
+	xmms_usleep(10000);
+    }
+  DONE:
+
+    ////////////////////////
+    // destroy memory pools
+    player_stop ();
+
+    ///////////////////////////////
+    // close currently playing file
+    close_tta_file (&info);
+
+    pthread_exit (NULL);
+}
+
+static void
+init ()
+{
+    memset (&info, 0, sizeof (tta_info));
+}
+
+static void
+cleanup ()
+{
+}
+
+static void
+about ()
+{
+    static GtkWidget *aboutbox;
+    if (aboutbox != NULL) return;
+
+    aboutbox = xmms_show_message(
+	"About True Audio Plugin",
+	"TTA input plugin" PLUGIN_VERSION "for BMP\n"
+	"Copyright (c) 2004 True Audio Software\n"
+	PROJECT_URL, "Ok", FALSE, NULL, NULL);
+
+    gtk_signal_connect(GTK_OBJECT(aboutbox), "destroy",
+        G_CALLBACK(gtk_widget_destroyed), &aboutbox);
+}
+
+static GtkWidget *window = NULL;
+static GtkWidget *filename_entry, *title_entry,
+		 *artist_entry, *album_entry,
+		 *year_entry, *tracknum_entry,
+		 *comment_entry, *genre_entry,
+		 *info_frame;
+
+extern char *genre[];
+
+static void
+file_info (char *filename)
+{
+    tta_info ttainfo;
+    char *title;
+    gchar *utf_filename = NULL;
+
+    if (!window) {
+	GtkWidget *vbox, *hbox, *left_vbox, *table;
+	GtkWidget *label, *filename_hbox, *button_ok;
+
+	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
+	gtk_signal_connect(GTK_OBJECT(window), "destroy",
+	    G_CALLBACK(gtk_widget_destroyed), &window);
+	gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+    
+	vbox = gtk_vbox_new(FALSE, 10);
+	gtk_container_add(GTK_CONTAINER(window), vbox);
+
+	filename_hbox = gtk_hbox_new(FALSE, 5);
+	gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0);
+	label = gtk_label_new("Filename:");
+	gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0);
+
+	filename_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
+	gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0);
+
+	hbox = gtk_hbox_new(FALSE, 10);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+	left_vbox = gtk_vbox_new(FALSE, 10);
+	gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
+
+	info_frame = gtk_frame_new("ID3 Tag:");
+	gtk_box_pack_start(GTK_BOX(left_vbox), info_frame, FALSE, FALSE, 0);
+
+	table = gtk_table_new(5, 5, FALSE);
+	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+	gtk_container_add(GTK_CONTAINER(info_frame), table);
+
+	label = gtk_label_new("Title:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 5, 5);
+
+	title_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(title_entry), FALSE);
+	gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	label = gtk_label_new("Artist:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	artist_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(artist_entry), FALSE);
+	gtk_table_attach(GTK_TABLE(table), artist_entry, 1, 4, 1, 2,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	label = gtk_label_new("Album:");
+	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	album_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(album_entry), FALSE);
+	    gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	label = gtk_label_new("Comment:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	comment_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(comment_entry), FALSE);
+	gtk_table_attach(GTK_TABLE(table), comment_entry, 1, 4, 3, 4,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	label = gtk_label_new("Year:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	year_entry = gtk_entry_new_with_max_length(4);
+	    gtk_editable_set_editable(GTK_EDITABLE(year_entry), FALSE);
+	    gtk_widget_set_usize(year_entry, 40, -1);
+	    gtk_table_attach(GTK_TABLE(table), year_entry, 1, 2, 4, 5,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+ 	label = gtk_label_new("Track number:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	tracknum_entry = gtk_entry_new_with_max_length(3);
+	gtk_editable_set_editable(GTK_EDITABLE(tracknum_entry), FALSE);
+	gtk_widget_set_usize(tracknum_entry, 40, -1);
+	gtk_table_attach(GTK_TABLE(table), tracknum_entry, 3, 4, 4, 5,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	label = gtk_label_new("Genre:");
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
+	    GTK_FILL, GTK_FILL, 5, 5);
+
+	genre_entry = gtk_entry_new_with_max_length(1024);
+	gtk_editable_set_editable(GTK_EDITABLE(genre_entry), FALSE);
+	gtk_widget_set_usize(genre_entry, 40, -1);
+	gtk_table_attach(GTK_TABLE(table), genre_entry, 1, 4, 5, 6,
+            GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+	    GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+	button_ok = gtk_button_new_with_label("Ok");
+	gtk_signal_connect_object(GTK_OBJECT(button_ok), "clicked",
+		  G_CALLBACK(gtk_widget_destroy), G_OBJECT(window));
+	GTK_WIDGET_SET_FLAGS(button_ok, GTK_CAN_DEFAULT);
+	gtk_box_pack_start(GTK_BOX(vbox), button_ok, TRUE, TRUE, 0);
+
+	gtk_widget_show_all (window);
+    }
+    
+    utf_filename = str_to_utf8(filename);
+    title = g_strdup_printf(_("File Info - %s"), g_basename(utf_filename));
+    gtk_window_set_title(GTK_WINDOW(window), title);
+    g_free(title);
+    
+    gtk_entry_set_text(GTK_ENTRY(filename_entry), utf_filename);
+    gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1);
+
+#if 1
+    title = g_strdup(g_basename(utf_filename));
+//    if ((tmp = strrchr(title, '.')) != NULL) *tmp = '\0';
+    gtk_entry_set_text(GTK_ENTRY(title_entry), title);
+    g_free(title);
+#endif
+    g_free(utf_filename);
+
+    if (open_tta_file (filename, &ttainfo, 0) >= 0)
+    {
+	gtk_entry_set_text(GTK_ENTRY(title_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(artist_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(album_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(year_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(tracknum_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(comment_entry), "");
+	gtk_entry_set_text(GTK_ENTRY(genre_entry), "");
+
+	if (ttainfo.id3v2.id3has)
+	{
+	    gtk_entry_set_text(GTK_ENTRY(title_entry), ttainfo.id3v2.title);
+	    gtk_entry_set_text(GTK_ENTRY(artist_entry), ttainfo.id3v2.artist);
+	    gtk_entry_set_text(GTK_ENTRY(album_entry), ttainfo.id3v2.album);
+	    gtk_entry_set_text(GTK_ENTRY(year_entry), ttainfo.id3v2.year);
+	    gtk_entry_set_text(GTK_ENTRY(tracknum_entry), ttainfo.id3v2.track);
+	    gtk_entry_set_text(GTK_ENTRY(comment_entry), ttainfo.id3v2.comment);
+	    gtk_entry_set_text(GTK_ENTRY(genre_entry), ttainfo.id3v2.genre);
+	}
+	else if (ttainfo.id3v1.id3has)
+	{ 
+	    gchar *track = g_strdup_printf ("%2d", ttainfo.id3v1.track);
+	    gtk_entry_set_text(GTK_ENTRY(title_entry), ttainfo.id3v1.title);
+	    gtk_entry_set_text(GTK_ENTRY(artist_entry), ttainfo.id3v1.artist);
+	    gtk_entry_set_text(GTK_ENTRY(album_entry), ttainfo.id3v1.album);
+	    gtk_entry_set_text(GTK_ENTRY(year_entry), ttainfo.id3v1.year);
+	    gtk_entry_set_text(GTK_ENTRY(tracknum_entry), track);
+	    gtk_entry_set_text(GTK_ENTRY(comment_entry), ttainfo.id3v1.comment);
+	    gtk_entry_set_text(GTK_ENTRY(genre_entry),
+		genre[ttainfo.id3v1.genre <= GENRES ? ttainfo.id3v1.genre : 12]);
+	    g_free (track);
+	}
+    }
+    close_tta_file (&ttainfo);
+
+    gtk_widget_set_sensitive(info_frame, TRUE);
+}
+
+static int
+is_our_file (char *filename)
+{
+    if (!strcasecmp (filename + strlen (filename) - 4, ".tta"))
+    {
+	return TRUE;
+    }
+    return FALSE;
+}
+
+static void
+play_file (char *filename)
+{
+    char *title;
+    long datasize, origsize, bitrate;
+
+    playing = FALSE;
+
+    ////////////////////////////////////////
+    // open TTA file
+    if (open_tta_file (filename, &info, 0) < 0)
+    {
+	tta_error (info.STATE);
+	close_tta_file (&info);
+	return;
+    }
+
+    ////////////////////////////////////////
+    // initialize TTA player
+    if (player_init (&info) < 0)
+    {
+	tta_error (info.STATE);
+	close_tta_file (&info);
+	return;
+    }
+
+
+    if (tta_ip.output->open_audio ((info.BPS == 8) ? FMT_U8 : FMT_S16_LE,
+				   info.SAMPLERATE, info.NCH) == 0)
+    {
+	tta_error (OUTPUT_ERROR);
+	close_tta_file (&info);
+	return;
+    }
+    title = get_title (filename, &info);
+    printf("title @1 = %s\n", title);
+    {
+	    TitleInput *tuple;
+
+	    tuple = get_song_tuple(filename);
+	    if(tuple->track_name) {
+		    g_free(title);
+		    title = g_strdup(tuple->track_name);
+		    printf("title @2 = %s\n", title);
+	    }
+
+	    bmp_title_input_free(tuple);
+    }
+
+    datasize = file_size(filename) - info.DATAPOS;
+    origsize = info.DATALENGTH * info.BSIZE * info.NCH;
+
+    bitrate  = (long) ((float) datasize / origsize *
+	        (info.SAMPLERATE * info.NCH * info.BPS));
+
+    tta_ip.set_info (title, 1000 * info.LENGTH, bitrate, info.SAMPLERATE, info.NCH);
+    
+    if (title)
+	g_free (title);
+
+    playing = TRUE;
+    seek_position = -1;
+    read_samples = -1;
+
+    pthread_create (&decode_thread, NULL, play_loop, NULL);
+}
+
+static void
+tta_pause (short paused)
+{
+    tta_ip.output->pause (paused);
+}
+static void
+stop (void)
+{
+    if (playing)
+    {
+	playing = FALSE;
+	pthread_join (decode_thread, NULL);
+	tta_ip.output->close_audio ();
+	close_tta_file (&info);
+	read_samples = 0;
+    }
+}
+
+static void
+seek (int time)
+{
+    if (playing)
+    {
+	seek_position = 1000 * time / SEEK_STEP;
+
+	while (seek_position != -1)
+	    xmms_usleep (10000);
+    }
+}
+
+static int
+get_time (void)
+{
+    if (playing && (read_samples || tta_ip.output->buffer_playing()))
+	return tta_ip.output->output_time();
+
+    return -1;
+}
+
+static void
+get_song_info (char *filename, char **title, int *length)
+{
+    tta_info ttainfo;
+
+    if (open_tta_file (filename, &ttainfo, 0) >= 0)
+    {
+	*title = get_title (filename, &ttainfo);
+	*length = ttainfo.LENGTH * 1000;
+    }
+    close_tta_file (&ttainfo);
+}
+
+
+
+static TitleInput *
+get_song_tuple(char *filename)
+{
+	TitleInput *tuple = NULL;
+	tta_info *ttainfo;
+	VFSFile *file;
+
+	ttainfo = g_malloc0(sizeof(tta_info));
+
+	if((file = vfs_fopen(filename, "rb")) != NULL) {
+
+#ifdef DEBUG
+		printf("about to open_tta_file\n");
+#endif
+		if(open_tta_file(filename, ttainfo, 0) >= 0) {
+			tuple = bmp_title_input_new();
+#ifdef DEBUG
+			printf("open_tta_file succeed\n");
+#endif
+			tuple->file_name = g_path_get_basename(filename);
+			tuple->file_path = g_path_get_dirname(filename);
+			tuple->file_ext = extname(filename);
+			tuple->length = ttainfo->LENGTH * 1000;
+
+			if (ttainfo->id3v2.id3has) {
+				if(ttainfo->id3v2.artist)
+					tuple->performer = g_strdup(ttainfo->id3v2.artist);
+
+				if(ttainfo->id3v2.album)
+					tuple->album_name = g_strdup(ttainfo->id3v2.album);
+
+				if(ttainfo->id3v2.title)
+					tuple->track_name = g_strdup(ttainfo->id3v2.title);
+
+				tuple->year = atoi(ttainfo->id3v2.year);
+
+				tuple->track_number = atoi(ttainfo->id3v2.track);
+
+				if(ttainfo->id3v2.genre){
+//					printf("genre = %s\n",ttainfo->id3v2.genre);
+					tuple->genre = g_strdup(ttainfo->id3v2.genre);
+				}
+				if(ttainfo->id3v2.comment)
+					tuple->comment = g_strdup(ttainfo->id3v2.comment);
+			} else if (ttainfo->id3v1.id3has) {
+				if(ttainfo->id3v1.artist)
+					tuple->performer = g_strdup(ttainfo->id3v1.artist);
+
+				if(ttainfo->id3v1.album)
+					tuple->album_name = g_strdup(ttainfo->id3v1.album);
+
+				if(ttainfo->id3v1.title)
+					tuple->track_name = g_strdup(ttainfo->id3v1.title);
+
+				tuple->year = atoi(ttainfo->id3v1.year);
+
+				tuple->track_number = (int)ttainfo->id3v1.track;
+
+				if(ttainfo->id3v1.genre)
+					tuple->genre = g_strdup(genre[ttainfo->id3v1.genre <= GENRES ? ttainfo->id3v1.genre : 12]);
+				if(ttainfo->id3v1.comment)
+					tuple->comment = g_strdup(ttainfo->id3v1.comment);
+			}
+
+			close_tta_file (ttainfo);
+		}
+
+		vfs_fclose(file);
+	}
+	return tuple;
+}
+
+static gchar *
+extname(const char *filename)
+{
+    gchar *ext = strrchr(filename, '.');
+
+    if (ext != NULL)
+        ++ext;
+
+    return ext;
+}
+
+/* return length in letters */
+size_t tta_ucs4len(id3_ucs4_t *ucs)
+{
+    id3_ucs4_t *ptr = ucs;
+    size_t len = 0;
+
+    while(*ptr++ != 0)
+        len++;
+
+    return len;
+}
+
+/* duplicate id3_ucs4_t string. new string will be terminated with 0. */
+id3_ucs4_t *tta_ucs4dup(id3_ucs4_t *org)
+{
+    id3_ucs4_t *new = NULL;
+    size_t len = tta_ucs4len(org);
+
+    new = g_malloc0((len + 1) * sizeof(id3_ucs4_t));
+    memcpy(new, org, len * sizeof(id3_ucs4_t));
+    *(new + len) = 0; //terminate
+
+    return new;
+}
+
+#define BYTES(x) ((x) * sizeof(id3_ucs4_t))
+
+id3_ucs4_t *tta_parse_genre(const id3_ucs4_t *string)
+{
+    id3_ucs4_t *ret = NULL;
+    id3_ucs4_t *tmp = NULL;
+    id3_ucs4_t *genre = NULL;
+    id3_ucs4_t *ptr, *end, *tail, *tp;
+    size_t ret_len = 0; //num of ucs4 char!
+    size_t tmp_len = 0;
+    gboolean is_num = TRUE;
+
+    tail = (id3_ucs4_t *)string + tta_ucs4len((id3_ucs4_t *)string);
+
+    ret = g_malloc0(1024);
+
+    for(ptr = (id3_ucs4_t *)string; *ptr != 0 && ptr <= tail; ptr++) {
+        if(*ptr == '(') {
+            if(*(++ptr) == '(') { // escaped text like: ((something)
+                for(end = ptr; *end != ')' && *end != 0;) { // copy "(something)"
+                    end++;
+                }
+                end++; //include trailing ')'
+                memcpy(ret, ptr, BYTES(end - ptr));
+                ret_len += (end - ptr);
+                *(ret + ret_len) = 0; //terminate
+                ptr = end + 1;
+            }
+            else {
+                // reference to an id3v1 genre code
+                for(end = ptr; *end != ')' && *end != 0;) {
+                    end++;
+                }
+
+                tmp = g_malloc0(BYTES(end - ptr + 1));
+                memcpy(tmp, ptr, BYTES(end - ptr));
+                *(tmp + (end - ptr)) = 0; //terminate
+                ptr += end - ptr;
+
+                genre = (id3_ucs4_t *)id3_genre_name((const id3_ucs4_t *)tmp);
+
+                g_free(tmp);
+                tmp = NULL;
+
+                tmp_len = tta_ucs4len(genre);
+
+                memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len));
+
+                ret_len += tmp_len;
+                *(ret + ret_len) = 0; //terminate
+            }
+        }
+        else {
+            for(end = ptr; *end != '(' && *end != 0; ) {
+                end++;
+            }
+            // scan string to determine whether a genre code number or not
+            tp = ptr;
+            is_num = TRUE;
+            while(tp < end) {
+                if(*tp < '0' || *tp > '9') { // anything else than number appears.
+                    is_num = FALSE;
+                    break;
+                }
+                tp++;
+            }
+            if(is_num) {
+#ifdef DEBUG
+                printf("is_num!\n");
+#endif
+                tmp = g_malloc0(BYTES(end - ptr + 1));
+                memcpy(tmp, ptr, BYTES(end - ptr));
+                *(tmp + (end - ptr)) = 0; //terminate
+                ptr += end - ptr;
+
+                genre = (id3_ucs4_t *)id3_genre_name((const id3_ucs4_t *)tmp);
+#ifdef DEBUG
+                printf("genre length = %d\n", tta_ucs4len(genre));
+#endif
+                g_free(tmp);
+                tmp = NULL;
+
+                tmp_len = tta_ucs4len(genre);
+
+                memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len));
+
+                ret_len += tmp_len;
+                *(ret + ret_len) = 0; //terminate
+            }
+            else { // plain text
+#ifdef DEBUG
+                printf("plain!\n");
+                printf("ret_len = %d\n", ret_len);
+#endif
+                memcpy(ret + BYTES(ret_len), ptr, BYTES(end - ptr));
+                ret_len = ret_len + (end - ptr);
+                *(ret + ret_len) = 0; //terminate
+                ptr += (end - ptr);
+            }
+        }
+    }
+    return ret;
+}
+
+gchar *tta_input_id3_get_string(struct id3_tag * tag, char *frame_name)
+{
+    gchar *rtn;
+    gchar *rtn2;
+    const id3_ucs4_t *string_const;
+    id3_ucs4_t *string;
+    id3_ucs4_t *ucsptr;
+    struct id3_frame *frame;
+    union id3_field *field;
+    gboolean flagutf = FALSE;
+
+    frame = id3_tag_findframe(tag, frame_name, 0);
+    if (!frame)
+        return NULL;
+
+    if (frame_name == ID3_FRAME_COMMENT)
+        field = id3_frame_field(frame, 3);
+    else
+        field = id3_frame_field(frame, 1);
+
+    if (!field)
+        return NULL;
+
+    if (frame_name == ID3_FRAME_COMMENT)
+        string_const = id3_field_getfullstring(field);
+    else
+        string_const = id3_field_getstrings(field, 0);
+
+    if (!string_const)
+        return NULL;
+
+    string = tta_ucs4dup((id3_ucs4_t *)string_const);
+
+    if (frame_name == ID3_FRAME_GENRE) {
+        id3_ucs4_t *string2 = NULL;
+        string2 = tta_parse_genre(string);
+        g_free((void *)string);
+        string = string2;
+    }
+
+    ucsptr = (id3_ucs4_t *)string;
+    while (*ucsptr) {
+        if (*ucsptr > 0x000000ffL) {
+            flagutf = TRUE;
+            break;
+        }
+        ucsptr++;
+    }
+
+    if (flagutf) {
+#ifdef DEBUG
+        g_message("aud-tta: flagutf!\n");
+#endif
+        rtn = id3_ucs4_utf8duplicate(string);
+    }
+    else {
+        rtn = id3_ucs4_latin1duplicate(string);
+        rtn2 = str_to_utf8(rtn);
+        free(rtn);
+        rtn = rtn2;
+    }
+    g_free(string);
+    string = NULL;
+#ifdef DEBUG
+    g_print("string = %s\n", rtn);
+#endif    
+    return rtn;
+}
+
+int get_id3_tags (const char *filename, tta_info *ttainfo) {
+	int id3v2_size;
+	gchar *str = NULL;
+
+	struct id3_file *id3file = NULL;
+	struct id3_tag  *tag = NULL;
+
+	ttainfo->id3v2.id3has = 0;
+	ttainfo->id3v1.id3has = 0;
+
+	  id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY);
+
+	  if (id3file) {
+		  tag = id3_file_tag (id3file);
+
+		  if (tag) {
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_ARTIST);
+			  if(str) {
+				strcpy(ttainfo->id3v2.artist, str);
+				strncpy(ttainfo->id3v1.artist, str, 30);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_ALBUM);
+			  if(str){
+				  strcpy(ttainfo->id3v2.album, str);
+				  strncpy(ttainfo->id3v1.album, str, 30);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_TITLE);
+			  if(str) {
+				  strcpy(ttainfo->id3v2.title, str);
+				  strncpy(ttainfo->id3v1.title, str, 30);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  // year
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_YEAR); //TDRC
+			  if(!str) {
+				  str = tta_input_id3_get_string (tag, "TYER");
+			  }
+
+			  if(str){
+				  strncpy(ttainfo->id3v2.year, str, 5);
+				  strncpy(ttainfo->id3v1.year, str, 5);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  // track number
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_TRACK);
+			  if(str)
+				  strcpy(ttainfo->id3v2.track, str);
+			  free(str);
+			  str = NULL;
+
+			  // genre
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_GENRE);
+			  if(str) {
+				  id3_ucs4_t *tmp = NULL;
+				  strcpy(ttainfo->id3v2.genre, str);
+				  tmp = id3_latin1_ucs4duplicate((id3_latin1_t *)str);
+				  ttainfo->id3v1.genre =  id3_genre_number(tmp);
+				  g_free(tmp);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  // comment
+			  str = tta_input_id3_get_string (tag, ID3_FRAME_COMMENT);
+			  if(str) {
+				  strcpy(ttainfo->id3v2.comment, str);
+				  strncpy(ttainfo->id3v2.comment, str, 30);
+			  }
+			  free(str);
+			  str = NULL;
+
+			  if(*(ttainfo->id3v2.title) && *(ttainfo->id3v2.artist)) {
+				  ttainfo->id3v2.id3has = 1;
+				  ttainfo->id3v2.id3has = 1;
+			  }
+		  }
+		  id3_file_close(id3file);
+	  }
+	return id3v2_size; // not used
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/crc32.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,114 @@
+/*
+ * crc32.h
+ *
+ * Description:	 CRC32 functions
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ *
+ * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+
+#ifndef CRC32_H
+#define CRC32_H
+
+const unsigned long crc32_table[256] = {
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+	0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+	0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+	0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+	0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+	0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+	0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+	0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+	0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+	0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+	0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+	0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+	0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+	0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+	0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+	0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+	0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+	0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+	0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+	0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+	0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+	0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+	0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+	0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+	0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+	0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+	0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+	0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+	0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+	0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+	0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+	0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+}; 
+
+#define UPDATE_CRC32(x, crc) crc = \
+	(((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF])
+
+static unsigned long 
+crc32 (unsigned char *buffer, unsigned long len) {
+	unsigned long	i;
+	unsigned long	crc = 0xFFFFFFFF;
+
+	for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc);
+
+	return (crc ^ 0xFFFFFFFF);
+}
+
+#endif	/* CRC32_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/filters.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,110 @@
+/*
+ * filters.h
+ *
+ * Description:	 TTAv1 filter functions
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ *
+ * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * 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
+ * aint with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+
+#ifndef FILTERS_H
+#define FILTERS_H
+
+///////// Filter Settings //////////
+static long flt_set[3] = {10, 9, 10};
+
+__inline void
+memshl (register long *pA, register long *pB) {
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA++ = *pB++;
+	*pA   = *pB;
+}
+
+__inline void
+hybrid_filter (fltst *fs, long *in) {
+	register long *pA = fs->dl;
+	register long *pB = fs->qm;
+	register long *pM = fs->dx;
+	register long sum = fs->round;
+
+	if (!fs->error) {
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++;
+		sum += *pA++ * *pB, pB++; pM += 8;
+	} else if (fs->error < 0) {
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+		sum += *pA++ * (*pB -= *pM++), pB++;
+	} else {
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+		sum += *pA++ * (*pB += *pM++), pB++;
+	}
+
+	*(pM-0) = ((*(pA-1) >> 30) | 1) << 2;
+	*(pM-1) = ((*(pA-2) >> 30) | 1) << 1;
+	*(pM-2) = ((*(pA-3) >> 30) | 1) << 1;
+	*(pM-3) = ((*(pA-4) >> 30) | 1);
+
+	fs->error = *in;
+	*in += (sum >> fs->shift);
+	*pA = *in;
+
+	*(pA-1) = *(pA-0) - *(pA-1);
+	*(pA-2) = *(pA-1) - *(pA-2);
+	*(pA-3) = *(pA-2) - *(pA-3);
+
+	memshl (fs->dl, fs->dl + 1);
+	memshl (fs->dx, fs->dx + 1);
+}
+
+void
+filter_init (fltst *fs, long shift) {
+	memset (fs, 0, sizeof(fltst));
+	fs->shift = shift;
+	fs->round = 1 << (shift - 1);
+}
+
+#endif	/* FILTERS_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/id3.c	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include "ttalib.h"
+#include "id3genre.h"
+#include "audacious/util.h"
+#include <stdlib.h>
+#include <audacious/titlestring.h>
+
+/***********************************************************************
+ * ID3 tags manipulation routines
+ *
+ * Provides read access to ID3v1 tags v1.1, ID3v2 tags v2.3.x and above
+ * Supported ID3v2 frames: Title, Artist, Album, Track, Year,
+ *                         Genre, Comment.
+ *
+ **********************************************************************/
+
+static unsigned int unpack_sint28 (const char *ptr) {
+	unsigned int value = 0;
+
+	if (ptr[0] & 0x80) return 0;
+
+	value =  value       | (ptr[0] & 0x7f);
+	value = (value << 7) | (ptr[1] & 0x7f);
+	value = (value << 7) | (ptr[2] & 0x7f);
+	value = (value << 7) | (ptr[3] & 0x7f);
+
+	return value;
+}
+
+static unsigned int unpack_sint32 (const char *ptr) {
+	unsigned int value = 0;
+
+	if (ptr[0] & 0x80) return 0;
+
+	value = (value << 8) | ptr[0];
+	value = (value << 8) | ptr[1];
+	value = (value << 8) | ptr[2];
+	value = (value << 8) | ptr[3];
+
+	return value;
+}
+
+static int get_frame_id (const char *id) {
+	if (!memcmp(id, "TIT2", 4)) return TIT2;	// Title
+	if (!memcmp(id, "TPE1", 4)) return TPE1;	// Artist
+	if (!memcmp(id, "TALB", 4)) return TALB;	// Album
+	if (!memcmp(id, "TRCK", 4)) return TRCK;	// Track
+	if (!memcmp(id, "TYER", 4)) return TYER;	// Year
+	if (!memcmp(id, "TCON", 4)) return TCON;	// Genre
+	if (!memcmp(id, "COMM", 4)) return COMM;	// Comment
+	return 0;
+}
+
+int skip_v2_header(tta_info *ttainfo) {
+	id3v2_tag id3v2;
+	id3v2_frame frame_header;
+	int id3v2_size;
+	unsigned char *buffer, *ptr;
+	gchar *utf;
+	gchar tmp[MAX_LINE];
+	gchar *tmpptr;
+	int tmplen;
+
+	if (!fread(&id3v2, 1, sizeof (id3v2_tag), ttainfo->HANDLE) || 
+	    memcmp(id3v2.id, "ID3", 3))
+	 {
+		fseek (ttainfo->HANDLE, 0, SEEK_SET);
+		return 0;
+	}
+
+	id3v2_size = unpack_sint28(id3v2.size) + 10;
+
+	fseek (ttainfo->HANDLE, id3v2_size, SEEK_SET);
+	ttainfo->id3v2.size = id3v2_size;
+
+	return id3v2_size;
+}
+
+/* eof */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/id3genre.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,155 @@
+/* ID3v1 names with Winamp extensions */
+
+
+char *genre[] = {
+  /*   0 */  "Blues",
+  /*   1 */  "Classic Rock",
+  /*   2 */  "Country",
+  /*   3 */  "Dance",
+  /*   4 */  "Disco",
+  /*   5 */  "Funk",
+  /*   6 */  "Grunge",
+  /*   7 */  "Hip-Hop",
+  /*   8 */  "Jazz",
+  /*   9 */  "Metal",
+  /*  10 */  "New Age",
+  /*  11 */  "Oldies",
+  /*  12 */  "Other",
+  /*  13 */  "Pop",
+  /*  14 */  "R&B",
+  /*  15 */  "Rap",
+  /*  16 */  "Reggae",
+  /*  17 */  "Rock",
+  /*  18 */  "Techno",
+  /*  19 */  "Industrial",
+  /*  20 */  "Alternative",
+  /*  21 */  "Ska",
+  /*  22 */  "Death Metal",
+  /*  23 */  "Pranks",
+  /*  24 */  "Soundtrack",
+  /*  25 */  "Euro-Techno",
+  /*  26 */  "Ambient",
+  /*  27 */  "Trip-Hop",
+  /*  28 */  "Vocal",
+  /*  29 */  "Jazz+Funk",
+  /*  30 */  "Fusion",
+  /*  31 */  "Trance",
+  /*  32 */  "Classical",
+  /*  33 */  "Instrumental",
+  /*  34 */  "Acid",
+  /*  35 */  "House",
+  /*  36 */  "Game",
+  /*  37 */  "Sound Clip",
+  /*  38 */  "Gospel",
+  /*  39 */  "Noise",
+  /*  40 */  "AlternRock",
+  /*  41 */  "Bass",
+  /*  42 */  "Soul",
+  /*  43 */  "Punk",
+  /*  44 */  "Space",
+  /*  45 */  "Meditative",
+  /*  46 */  "Instrumental Pop",
+  /*  47 */  "Instrumental Rock",
+  /*  48 */  "Ethnic",
+  /*  49 */  "Gothic",
+  /*  50 */  "Darkwave",
+  /*  51 */  "Techno-Industrial",
+  /*  52 */  "Electronic",
+  /*  53 */  "Pop-Folk",
+  /*  54 */  "Eurodance",
+  /*  55 */  "Dream",
+  /*  56 */  "Southern Rock",
+  /*  57 */  "Comedy",
+  /*  58 */  "Cult",
+  /*  59 */  "Gangsta",
+  /*  60 */  "Top 40",
+  /*  61 */  "Christian Rap",
+  /*  62 */  "Pop/Funk",
+  /*  63 */  "Jungle",
+  /*  64 */  "Native American",
+  /*  65 */  "Cabaret",
+  /*  66 */  "New Wave",
+  /*  67 */  "Psychedelic",
+  /*  68 */  "Rave",
+  /*  69 */  "Showtunes",
+  /*  70 */  "Trailer",
+  /*  71 */  "Lo-Fi",
+  /*  72 */  "Tribal",
+  /*  73 */  "Acid Punk",
+  /*  74 */  "Acid Jazz",
+  /*  75 */  "Polka",
+  /*  76 */  "Retro",
+  /*  77 */  "Musical",
+  /*  78 */  "Rock & Roll",
+  /*  79 */  "Hard Rock",
+  /*  80 */  "Folk",
+  /*  81 */  "Folk/Rock",
+  /*  82 */  "National Folk",
+  /*  83 */  "Swing",
+  /*  84 */  "Fast-Fusion",
+  /*  85 */  "Bebob",
+  /*  86 */  "Latin",
+  /*  87 */  "Revival",
+  /*  88 */  "Celtic",
+  /*  89 */  "Bluegrass",
+  /*  90 */  "Avantgarde",
+  /*  91 */  "Gothic Rock",
+  /*  92 */  "Progressive Rock",
+  /*  93 */  "Psychedelic Rock",
+  /*  94 */  "Symphonic Rock",
+  /*  95 */  "Slow Rock",
+  /*  96 */  "Big Band",
+  /*  97 */  "Chorus",
+  /*  98 */  "Easy Listening",
+  /*  99 */  "Acoustic",
+  /* 100 */  "Humour",
+  /* 101 */  "Speech",
+  /* 102 */  "Chanson",
+  /* 103 */  "Opera",
+  /* 104 */  "Chamber Music",
+  /* 105 */  "Sonata",
+  /* 106 */  "Symphony",
+  /* 107 */  "Booty Bass",
+  /* 108 */  "Primus",
+  /* 109 */  "Porn Groove",
+  /* 110 */  "Satire",
+  /* 111 */  "Slow Jam",
+  /* 112 */  "Club",
+  /* 113 */  "Tango",
+  /* 114 */  "Samba",
+  /* 115 */  "Folklore",
+  /* 116 */  "Ballad",
+  /* 117 */  "Power Ballad",
+  /* 118 */  "Rhythmic Soul",
+  /* 119 */  "Freestyle",
+  /* 120 */  "Duet",
+  /* 121 */  "Punk Rock",
+  /* 122 */  "Drum Solo",
+  /* 123 */  "A Cappella",
+  /* 124 */  "Euro-House",
+  /* 125 */  "Dance Hall",
+  /* 126 */  "Goa",
+  /* 127 */  "Drum & Bass",
+  /* 128 */  "Club-House",
+  /* 129 */  "Hardcore",
+  /* 130 */  "Terror",
+  /* 131 */  "Indie",
+  /* 132 */  "BritPop",
+  /* 133 */  "Negerpunk",
+  /* 134 */  "Polsk Punk",
+  /* 135 */  "Beat",
+  /* 136 */  "Christian Gangsta Rap",
+  /* 137 */  "Heavy Metal",
+  /* 138 */  "Black Metal",
+  /* 139 */  "Crossover",
+  /* 140 */  "Contemporary Christian",
+  /* 141 */  "Christian Rock",
+  /* 142 */  "Merengue",
+  /* 143 */  "Salsa",
+  /* 144 */  "Thrash Metal",
+  /* 145 */  "Anime",
+  /* 146 */  "JPop",
+  /* 147 */  "Synthpop"
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/ttadec.c	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,506 @@
+/*
+ * ttadec.c
+ *
+ * Description:	 TTAv1 decoder library for HW players.
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ *
+ * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ttalib.h"
+#include "ttadec.h"
+#include "crc32.h"
+#include "filters.h"
+
+/******************* static variables and structures *******************/
+
+static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4];
+static unsigned char *iso_buffers_end = isobuffers + ISO_BUFFERS_SIZE;
+static unsigned long pcm_buffer_size;
+
+static decoder	tta[MAX_NCH];	// decoder state
+static long	cache[MAX_NCH];		// decoder cache
+
+tta_info *ttainfo;	// currently playing file info
+
+static unsigned long fframes;	// number of frames in file
+static unsigned long framelen;	// the frame length in samples
+static unsigned long lastlen;	// the length of the last frame in samples
+static unsigned long data_pos;	// currently playing frame index
+static unsigned long data_cur;	// the playing position in frame
+
+static long maxvalue;	// output data max value
+static unsigned long *seek_table; // the playing position table
+static unsigned long st_state; //seek table status
+
+static unsigned long frame_crc32;
+static unsigned long bit_count;
+static unsigned long bit_cache;
+static unsigned char *bitpos;
+static unsigned long bitrate;
+
+void get_id3v1_tag (tta_info *ttainfo);
+int  get_id3v2_tag (tta_info *ttainfo);
+
+/************************* bit operations ******************************/
+
+static void init_buffer_read() {
+    frame_crc32 = 0xFFFFFFFFUL;
+    bit_count = bit_cache = 0;
+    bitpos = iso_buffers_end;
+}
+
+__inline void get_binary(unsigned long *value, unsigned long bits) {
+    while (bit_count < bits) {
+		if (bitpos == iso_buffers_end) {
+			long res = fread(isobuffers, 1,
+				ISO_BUFFERS_SIZE, ttainfo->HANDLE);
+			if (!res) {
+				ttainfo->STATE = READ_ERROR;
+				return;
+			}
+			bitpos = isobuffers;
+		}
+
+		UPDATE_CRC32(*bitpos, frame_crc32);
+		bit_cache |= *bitpos << bit_count;
+		bit_count += 8;
+		bitpos++;
+    }
+
+    *value = bit_cache & bit_mask[bits];
+    bit_cache >>= bits;
+    bit_count -= bits;
+    bit_cache &= bit_mask[bit_count];
+}
+
+__inline void get_unary(unsigned long *value) {
+    *value = 0;
+
+    while (!(bit_cache ^ bit_mask[bit_count])) {
+		if (bitpos == iso_buffers_end) {
+			long res = fread(isobuffers, 1,
+				ISO_BUFFERS_SIZE, ttainfo->HANDLE);
+			if (!res) {
+				ttainfo->STATE = READ_ERROR;
+				return;
+			}
+			bitpos = isobuffers;
+		}
+
+		*value += bit_count;
+		bit_cache = *bitpos++;
+		UPDATE_CRC32(bit_cache, frame_crc32);
+		bit_count = 8;
+    }
+
+    while (bit_cache & 1) {
+		(*value)++;
+		bit_cache >>= 1;
+		bit_count--;
+    }
+
+    bit_cache >>= 1;
+    bit_count--;
+}
+
+static long done_buffer_read() {
+    unsigned long crc32, rbytes, res;
+    frame_crc32 ^= 0xFFFFFFFFUL;
+
+    rbytes = iso_buffers_end - bitpos;
+    if (rbytes < sizeof(long)) {
+		memcpy(isobuffers, bitpos, 4);
+		res = fread(isobuffers + rbytes, 1,
+			ISO_BUFFERS_SIZE - rbytes, ttainfo->HANDLE);
+		if (!res) {
+			ttainfo->STATE = READ_ERROR;
+			return 0;
+		}
+		bitpos = isobuffers;
+    }
+
+    memcpy(&crc32, bitpos, 4);
+    crc32 = ENDSWAP_INT32(crc32);
+    bitpos += sizeof(long);
+    res = (crc32 != frame_crc32);
+
+    bit_cache = bit_count = 0;
+    frame_crc32 = 0xFFFFFFFFUL;
+
+    // calculate dynamic bitrate
+    if (data_pos < fframes) {
+		rbytes = seek_table[data_pos] -
+			seek_table[data_pos - 1];
+		bitrate = (rbytes << 3) / 1070;
+    }
+
+    return res;
+}
+
+/************************* decoder functions ****************************/
+
+static long skip_id3v2_header (FILE *infile) {
+	struct {
+		unsigned char	id[3];
+		unsigned short	version;
+		unsigned char	flags;
+		unsigned char	size[4];
+	} __ATTRIBUTE_PACKED__ id3v2;
+	unsigned long len = 0;
+
+	// read ID3V2 header
+	if (fread (&id3v2, sizeof(id3v2), 1, infile) == 0) {
+		fclose (infile);
+		ttainfo->STATE = READ_ERROR;
+		return -1;
+	}
+
+	// skip ID3V2 header
+	if (!memcmp (id3v2.id, "ID3", 3)) {
+		if (id3v2.size[0] & 0x80) {
+			fclose (infile);
+			ttainfo->STATE = FILE_ERROR;
+			return FILE_ERROR;
+		}
+		len = (id3v2.size[0] & 0x7f);
+		len = (len << 7) | (id3v2.size[1] & 0x7f);
+		len = (len << 7) | (id3v2.size[2] & 0x7f);
+		len = (len << 7) | (id3v2.size[3] & 0x7f);
+		len += 10;
+		if (id3v2.flags & (1 << 4)) len += 10;
+		fseek (infile, len, SEEK_SET);
+	} else fseek (infile, 0, SEEK_SET);
+
+	return len;
+}
+
+long open_tta_file (const char *filename, tta_info *info, unsigned long data_offset) {
+	FILE *infile;
+	tta_hdr ttahdr;
+	unsigned long checksum;
+
+	// clear the memory
+	memset (info, 0, sizeof(tta_info));
+
+//	printf("0: open_tta_file\n");
+	info->HANDLE = infile = fopen(filename, "rb");
+	if (!infile) return OPEN_ERROR;
+
+//	printf("1: data_offset %ld\n", data_offset);
+	// read id3v2 header
+	if (!data_offset) {
+//		data_offset = skip_id3v2_header(infile);
+//		data_offset = get_id3v2_tag(info);
+		data_offset = skip_v2_header(info);
+//		printf("2: data_offset %ld\n", data_offset);
+//		get_id3v1_tag (info);
+		if (data_offset < 0) return -1;
+	} else fseek (infile, data_offset, SEEK_SET);
+
+	get_id3_tags (filename, info);
+
+	// read TTA header
+	if (fread (&ttahdr, 1, sizeof (ttahdr), infile) == 0) {
+		fclose (infile);
+		info->STATE = READ_ERROR;
+		return -1;
+	}
+
+	// check for TTA3 signature
+	if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) {
+		fclose (infile);
+		info->STATE = FORMAT_ERROR;
+		return -1;
+	}
+
+	ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32);
+	checksum = crc32((unsigned char *) &ttahdr,
+	sizeof(tta_hdr) - sizeof(long));
+	if (checksum != ttahdr.CRC32) {
+		fclose (infile);
+		info->STATE = FILE_ERROR;
+		return -1;
+	}
+
+	ttahdr.AudioFormat = ENDSWAP_INT16(ttahdr.AudioFormat);
+	ttahdr.NumChannels = ENDSWAP_INT16(ttahdr.NumChannels);
+	ttahdr.BitsPerSample = ENDSWAP_INT16(ttahdr.BitsPerSample);
+	ttahdr.SampleRate = ENDSWAP_INT32(ttahdr.SampleRate);
+	ttahdr.DataLength = ENDSWAP_INT32(ttahdr.DataLength);
+
+	// check for player supported formats
+	if (ttahdr.AudioFormat != WAVE_FORMAT_PCM ||
+		ttahdr.NumChannels > MAX_NCH ||
+		ttahdr.BitsPerSample > MAX_BPS ||(
+		ttahdr.SampleRate != 16000 &&
+		ttahdr.SampleRate != 22050 &&
+		ttahdr.SampleRate != 24000 &&
+		ttahdr.SampleRate != 32000 &&
+		ttahdr.SampleRate != 44100 &&
+		ttahdr.SampleRate != 48000 &&
+		ttahdr.SampleRate != 64000 &&
+		ttahdr.SampleRate != 88200 &&
+		ttahdr.SampleRate != 96000)) {
+		fclose (infile);
+		info->STATE = FORMAT_ERROR;
+		return FORMAT_ERROR;
+	}
+
+	// fill the File Info
+	info->HANDLE = infile;
+	info->NCH = ttahdr.NumChannels;
+	info->BPS = ttahdr.BitsPerSample;
+	info->BSIZE = (ttahdr.BitsPerSample + 7)/8;
+	info->FORMAT = ttahdr.AudioFormat;
+	info->SAMPLERATE = ttahdr.SampleRate;
+	info->DATALENGTH = ttahdr.DataLength;
+	info->FRAMELEN = (long) (FRAME_TIME * ttahdr.SampleRate);
+	info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate;
+	info->DATAPOS = data_offset;
+
+
+	return 0;
+}
+
+static void rice_init(adapt *rice, unsigned long k0, unsigned long k1) {
+    rice->k0 = k0;
+    rice->k1 = k1;
+    rice->sum0 = shift_16[k0];
+    rice->sum1 = shift_16[k1];
+}
+
+static void decoder_init(decoder *tta, long nch, long byte_size) {
+    long shift = flt_set[byte_size - 1];
+    long i;
+
+    for (i = 0; i < nch; i++) {
+		filter_init(&tta[i].fst, shift);
+		rice_init(&tta[i].rice, 10, 10);
+		tta[i].last = 0;
+    }
+}
+
+static void seek_table_init (unsigned long *seek_table,
+	unsigned long len, unsigned long data_offset) {
+	unsigned long *st, frame_len;
+
+	for (st = seek_table; st < (seek_table + len); st++) {
+		frame_len = ENDSWAP_INT32(*st);
+		*st = data_offset;
+		data_offset += frame_len;
+	}
+}
+
+long set_position (unsigned long pos) {
+	unsigned long seek_pos;
+
+	if (pos >= fframes) return 0;
+	if (!st_state) {
+		ttainfo->STATE = FILE_ERROR;
+		return -1;
+	}
+
+	seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos];
+	fseek(ttainfo->HANDLE, seek_pos, SEEK_SET);
+
+	data_cur = 0;
+	framelen = 0;
+
+	// init bit reader
+	init_buffer_read();
+
+	return 0;
+}
+
+long player_init (tta_info *info) {
+	unsigned long checksum;
+	unsigned long data_offset;
+	unsigned long st_size;
+
+	ttainfo = info;
+
+	framelen = 0;
+	data_pos = 0;
+	data_cur = 0;
+	bitrate  = 0;
+
+	lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN;
+	fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1:0);
+	st_size = (fframes + 1) * sizeof(long);
+
+	seek_table = (unsigned long *) malloc(st_size);
+	if (!seek_table) {
+		ttainfo->STATE = MEMORY_ERROR;
+		return -1;
+	}
+
+	// read seek table
+	if (!fread(seek_table, st_size, 1, ttainfo->HANDLE)) {
+		ttainfo->STATE = READ_ERROR;
+		return -1;
+	}
+
+	checksum = crc32((unsigned char *) seek_table, st_size - sizeof(long));
+	st_state = (checksum == ENDSWAP_INT32(seek_table[fframes]));
+	data_offset = sizeof(tta_hdr) + st_size;
+
+	// init seek table
+	seek_table_init(seek_table, fframes, data_offset);
+
+	// init bit reader
+	init_buffer_read();
+
+	pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->BSIZE * ttainfo->NCH;
+	maxvalue = (1UL << ttainfo->BPS) - 1;
+
+	return 0;
+}
+
+void close_tta_file (tta_info *info) {
+	if (info->HANDLE) {
+		fclose (info->HANDLE);
+		info->HANDLE = NULL;
+	}
+}
+
+void player_stop () {
+	if (seek_table) {
+		free(seek_table);
+		seek_table = NULL;
+	}
+}
+
+long get_bitrate () {
+	return bitrate;
+}
+
+long get_samples (byte *buffer) {
+	unsigned long k, depth, unary, binary;
+	byte *p = buffer;
+	decoder *dec = tta;
+	long *prev = cache;
+	long value, res;
+
+	for (res = 0; p < buffer + pcm_buffer_size;) {
+		fltst *fst = &dec->fst;
+		adapt *rice = &dec->rice;
+		long  *last = &dec->last;
+
+		if (data_cur == framelen) {
+			if (data_pos == fframes) break;
+			if (framelen && done_buffer_read()) {
+				if (set_position(data_pos) < 0)
+					return -1;
+				if (res) break;
+			}
+
+			if (data_pos == fframes - 1 && lastlen)
+				framelen = lastlen;
+			else framelen = ttainfo->FRAMELEN;
+
+			decoder_init(tta, ttainfo->NCH, ttainfo->BSIZE);
+			data_pos++; data_cur = 0;
+		}
+
+		// decode Rice unsigned
+		get_unary(&unary);
+
+		switch (unary) {
+		case 0: depth = 0; k = rice->k0; break;
+		default:
+				depth = 1; k = rice->k1;
+				unary--;
+		}
+
+		if (k) {
+			get_binary(&binary, k);
+			value = (unary << k) + binary;
+		} else value = unary;
+
+		switch (depth) {
+		case 1: 
+			rice->sum1 += value - (rice->sum1 >> 4);
+			if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])
+				rice->k1--;
+			else if (rice->sum1 > shift_16[rice->k1 + 1])
+				rice->k1++;
+			value += bit_shift[rice->k0];
+		default:
+			rice->sum0 += value - (rice->sum0 >> 4);
+			if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])
+				rice->k0--;
+			else if (rice->sum0 > shift_16[rice->k0 + 1])
+			rice->k0++;
+		}
+
+		value = DEC(value);
+
+		// decompress stage 1: adaptive hybrid filter
+		hybrid_filter(fst, &value);
+
+		// decompress stage 2: fixed order 1 prediction
+		switch (ttainfo->BSIZE) {
+		case 1: value += PREDICTOR1(*last, 4); break;	// bps 8
+		case 2: value += PREDICTOR1(*last, 5); break;	// bps 16
+		case 3: value += PREDICTOR1(*last, 5); break;	// bps 24
+		case 4: value += *last; break;		// bps 32
+		} *last = value;
+
+		// check for errors
+		if (abs(value) > maxvalue) {
+			unsigned long tail =
+				pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res;
+			memset(buffer, 0, pcm_buffer_size);
+			data_cur += tail; res += tail;
+			break;
+		}
+
+		if (dec < tta + (ttainfo->NCH - 1)) {
+			*prev++ = value; dec++;
+		} else {
+			*prev = value;
+			if (ttainfo->NCH > 1) {
+				long *r = prev - 1;
+				for (*prev += *r/2; r >= cache; r--)
+					*r = *(r + 1) - *r;
+				for (r = cache; r < prev; r++)
+					WRITE_BUFFER(r, ttainfo->BSIZE, p)
+			}
+			WRITE_BUFFER(prev, ttainfo->BSIZE, p)
+			prev = cache;
+			data_cur++; res++;
+			dec = tta;
+		}
+	}
+
+	return res;
+}
+
+/* end */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/ttadec.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,136 @@
+/*
+ * ttadec.h
+ *
+ * Description:	 TTAv1 decoder definitions and prototypes
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ *
+ * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+
+#ifndef TTADEC_H_
+#define TTADEC_H_
+
+#ifdef _WIN32
+#pragma pack(1)
+#define __ATTRIBUTE_PACKED__
+#else
+#define __ATTRIBUTE_PACKED__	__attribute__((packed))
+#endif
+
+#define TTA1_SIGN	0x31415454
+#define FRAME_TIME	1.04489795918367346939
+#define MAX_ORDER	8
+
+#ifndef WAVE_FORMAT_PCM
+#define WAVE_FORMAT_PCM	1
+#endif
+
+#ifdef _WIN32
+	typedef unsigned __int64 uint64;
+#else
+	typedef unsigned long long uint64;
+#endif
+
+const unsigned long bit_mask[] = {
+    0x00000000, 0x00000001, 0x00000003, 0x00000007,
+    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+    0xffffffff
+};
+
+const unsigned long bit_shift[] = {
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x00000100, 0x00000200, 0x00000400, 0x00000800,
+    0x00001000, 0x00002000, 0x00004000, 0x00008000,
+    0x00010000, 0x00020000, 0x00040000, 0x00080000,
+    0x00100000, 0x00200000, 0x00400000, 0x00800000,
+    0x01000000, 0x02000000, 0x04000000, 0x08000000,
+    0x10000000, 0x20000000, 0x40000000, 0x80000000,
+    0x80000000, 0x80000000, 0x80000000, 0x80000000,
+    0x80000000, 0x80000000, 0x80000000, 0x80000000
+};
+
+const unsigned long *shift_16 = bit_shift + 4;
+
+typedef unsigned char byte;
+
+#ifdef _BIG_ENDIAN
+#define	ENDSWAP_INT16(x)	(((((x)>>8)&0xFF)|(((x)&0xFF)<<8)))
+#define	ENDSWAP_INT32(x)	(((((x)>>24)&0xFF)|(((x)>>8)&0xFF00)|(((x)&0xFF00)<<8)|(((x)&0xFF)<<24)))
+#define WRITE_BUFFER(x, bsize, out) { \
+	if (bsize > 2) *out++ = (byte)(*x >> 16); \
+	if (bsize > 1) *out++ = (byte)(*x >> 8); \
+	*out++ = (byte) *x; }
+#else
+#define	ENDSWAP_INT16(x)	(x)
+#define	ENDSWAP_INT32(x)	(x)
+#define WRITE_BUFFER(x, bsize, out) { \
+	*out++ = (byte) *x; \
+	if (bsize > 1) *out++ = (byte)(*x >> 8); \
+	if (bsize > 2) *out++ = (byte)(*x >> 16); }
+#endif
+
+#define PREDICTOR1(x, k)	((long)((((uint64)x << k) - x) >> k))
+#define DEC(x)			(((x)&1)?(++(x)>>1):(-(x)>>1))
+
+typedef struct {
+    unsigned long TTAid;
+    unsigned short AudioFormat;
+    unsigned short NumChannels;
+    unsigned short BitsPerSample;
+    unsigned long SampleRate;
+    unsigned long DataLength;
+    unsigned long CRC32;
+} __ATTRIBUTE_PACKED__ tta_hdr;
+
+typedef struct {
+	unsigned long k0;
+	unsigned long k1;
+	unsigned long sum0;
+	unsigned long sum1;
+} adapt;
+
+typedef struct {
+	long shift;
+	long round;
+	long error;
+	long mutex;
+	long qm[MAX_ORDER+1];
+	long dx[MAX_ORDER+1];
+	long dl[MAX_ORDER+1];
+} fltst;
+
+typedef struct {
+	fltst fst;
+	adapt rice;
+	long last;
+} decoder;
+
+#endif /* TTADEC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/ttaid3tag.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,95 @@
+/*
+ * id3tag.h
+ *
+ * Description:	ID3 functions prototypes
+ *
+ */
+
+#pragma pack(1)
+
+#define MAX_LINE 4096
+//#define ID3_VERSION 3
+
+/* ID3 common headers set */
+
+#define TIT2	1
+#define TPE1	2
+#define TALB	3
+#define TRCK	4
+#define TYER	5
+#define TCON	6
+#define COMM	7
+
+/* ID3 tag checked flags */
+
+#define ID3_UNSYNCHRONISATION_FLAG		0x80
+#define ID3_EXTENDEDHEADER_FLAG			0x40
+#define ID3_EXPERIMENTALTAG_FLAG		0x20
+#define ID3_FOOTERPRESENT_FLAG			0x10
+
+/* ID3 frame checked flags */
+
+#define FRAME_COMPRESSION_FLAG			0x0008
+#define FRAME_ENCRYPTION_FLAG			0x0004
+#define FRAME_UNSYNCHRONISATION_FLAG	0x0002
+
+/* ID3 field text encoding */
+
+#define FIELD_TEXT_ISO_8859_1	0x00
+#define FIELD_TEXT_UTF_16		0x01
+#define FIELD_TEXT_UTF_16BE		0x02
+#define FIELD_TEXT_UTF_8		0x03
+
+#define GENRES	148
+
+typedef struct {
+	unsigned char  id[3];
+	unsigned char  title[30];
+	unsigned char  artist[30];
+	unsigned char  album[30];
+	unsigned char  year[4];
+	unsigned char  comment[28];
+	unsigned char  zero;
+	unsigned char  track;
+	unsigned char  genre;
+} id3v1_tag;
+
+typedef struct {
+	unsigned char  id[3];
+	unsigned short version;
+	unsigned char  flags;
+	unsigned char  size[4];
+} id3v2_tag;
+
+typedef struct {
+	unsigned char  id[4];
+	unsigned char  size[4];
+	unsigned short flags;
+} id3v2_frame;
+
+typedef struct {
+	unsigned char  name[31];
+	unsigned char  title[31];
+	unsigned char  artist[31];
+	unsigned char  album[31];
+	unsigned char  comment[31];
+	unsigned char  year[5];
+	unsigned char  track;
+	unsigned char  genre;
+	unsigned char  id3has;
+} id3v1_data;
+
+typedef struct {
+	unsigned char  name[MAX_LINE];
+	unsigned char  title[MAX_LINE];
+	unsigned char  artist[MAX_LINE];
+	unsigned char  album[MAX_LINE];
+	unsigned char  comment[MAX_LINE];
+	unsigned char  year[5];
+	unsigned char  track[3];
+	unsigned char  genre[256];
+	unsigned char  id3has;
+	unsigned long  size;
+} id3v2_data;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tta/ttalib.h	Wed Nov 22 09:55:20 2006 -0800
@@ -0,0 +1,142 @@
+/*
+ * ttalib.h
+ *
+ * Description:	 TTAv1 player library prototypes
+ * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
+ *               Pavel Zhilin <pzh@iszf.irk.ru>
+ *
+ * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
+ *
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Please see the file COPYING in this directory for full copyright
+ * information.
+ */
+
+#ifndef TTALIB_H_
+#define TTALIB_H_
+
+#include "ttaid3tag.h"
+
+//#define _BIG_ENDIAN
+#define MAX_BPS         24	// Max supported Bit resolution
+#define MAX_NCH         8	// Max supported number of channels
+
+// return codes
+#define NO_ERROR        0
+#define OPEN_ERROR      1	// Can't open file
+#define FORMAT_ERROR    2	// Unknown TTA format version
+#define PLAYER_ERROR    3	// Not supported file format
+#define FILE_ERROR      4	// File is corrupted
+#define READ_ERROR      5	// Can't read from file
+#define MEMORY_ERROR    6	// Insufficient memory available
+
+#define FRAME_TIME		1.04489795918367346939
+#define SEEK_STEP		(int)(FRAME_TIME * 1000)
+
+#define ISO_BUFFER_LENGTH	(1024*32)
+#define ISO_NBUFFERS		(8)
+#define ISO_BUFFERS_SIZE	(ISO_BUFFER_LENGTH*ISO_NBUFFERS)
+#define PCM_BUFFER_LENGTH	(4608)
+
+typedef struct {
+	FILE            *HANDLE;	// file handle
+	unsigned short  NCH;		// number of channels
+	unsigned short  BPS;		// bits per sample
+	unsigned short  BSIZE;		// byte size
+	unsigned short  FORMAT;		// audio format
+	unsigned long   SAMPLERATE;	// samplerate (sps)
+	unsigned long   DATALENGTH;	// data length in samples
+	unsigned long   FRAMELEN;	// frame length
+	unsigned long   LENGTH;		// playback time (sec)
+	unsigned long   STATE;		// return code
+	unsigned long   DATAPOS;	// size of ID3v2 header
+	id3v1_data	id3v1;
+	id3v2_data	id3v2;
+} tta_info;
+
+/*********************** Library functions *************************/
+
+#ifdef  LIBTEST
+#ifndef DPRINTF
+#define DPRINTF(x) fprintf(stderr, (x))
+#endif /* DPRINTF */
+
+static void tta_error (int error) {
+	DPRINTF("TTA Decoder Error - ");
+	switch (error) {
+	case OPEN_ERROR:	DPRINTF("Can't open file\n"); break;
+	case FORMAT_ERROR:	DPRINTF("Not supported file format\n"); break;
+	case FILE_ERROR:	DPRINTF("File is corrupted\n"); break;
+	case READ_ERROR:	DPRINTF("Can't read from file\n"); break;
+	case MEMORY_ERROR:	DPRINTF("Insufficient memory available\n"); break;
+	}
+}
+#endif /* LIBTEST */
+
+long    open_tta_file (		// FUNCTION: opens TTA file
+        const char *filename,	// file to open
+        tta_info *info,		// file info structure
+        unsigned long offset);	// ID3v2 header size
+/*
+ * RETURN VALUE
+ * This function returns 0 if success. Otherwise, -1 is  returned
+ * and the variable STATE of the currently using info structure
+ * is set to indicate the error.
+ *
+ */
+
+void    close_tta_file (	// FUNCTION: closes currently playing file
+        tta_info *info);	// file info structure
+
+long    set_position (		// FUNCTION: sets playback position
+        unsigned long pos);	// seek position = seek_time_ms / SEEK_STEP
+/*
+ * RETURN VALUE
+ * This function returns 0 if success. Otherwise, -1 is  returned
+ * and the variable STATE of the currently using info structure
+ * is set to indicate the error.
+ *
+ */
+
+long    player_init (		// FUNCTION: initializes TTA player
+        tta_info *info);	// file info structure
+/*
+ * RETURN VALUE
+ * This function returns 0 if success. Otherwise, -1 is  returned
+ * and the variable STATE of the currently using info structure
+ * is set to indicate the error.
+ *
+ */
+
+void    player_stop (void);	// FUNCTION: destroys memory pools
+
+long    get_samples (		// FUNCTION: decode PCM_BUFFER_LENGTH samples
+        unsigned char *buffer);	// into the current PCM buffer position
+/*
+ * RETURN VALUE
+ * This function returns the number of samples successfully decoded.
+ * Otherwise, -1 is  returned and the variable STATE of the currently
+ * using info structure is set to indicate the error.
+ *
+ */
+
+long	get_bitrate (void);	// RETURN VALUE: TTA dynamic bitrate
+
+#endif /* TTALIB_H_ */
+