changeset 455:cbc2a4ffeeec

* Added support for loading DLS format instruments: Timidity_LoadDLS(), Timidity_FreeDLS(), Timidity_LoadDLSSong() * Added Timidity_Init_NoConfig()
author hercules
date Fri, 26 Sep 2003 20:51:58 +0000
parents 6bd7ca7d218b
children 24a59b3fdf42
files decoders/timidity/CHANGES decoders/timidity/COPYING decoders/timidity/Makefile.am decoders/timidity/dls1.h decoders/timidity/dls2.h decoders/timidity/instrum.c decoders/timidity/instrum_dls.c decoders/timidity/instrum_dls.h decoders/timidity/playmidi.c decoders/timidity/timidity.c decoders/timidity/timidity.h
diffstat 11 files changed, 2278 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/decoders/timidity/CHANGES	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/CHANGES	Fri Sep 26 20:51:58 2003 +0000
@@ -1,5 +1,5 @@
 This version of TiMidity should contain all the fixes from the
-December 13 2001 SDL_mixer CVS snapshot. In addition, I've made some
+September 25 2003 SDL_mixer CVS snapshot. In addition, I've made some
 changes of my own, e.g.:
 
 * All file access is done through SDL_RWops. This means the MIDI
@@ -70,3 +70,8 @@
 
 * config.h has been renamed as options.h to avoid confusion with the
   automatically generated config.h for SDL_sound.
+
+* Added support for loading DLS format instruments:
+	Timidity_LoadDLS(), Timidity_FreeDLS(), Timidity_LoadDLSSong()
+
+* Added Timidity_Init_NoConfig()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/timidity/COPYING	Fri Sep 26 20:51:58 2003 +0000
@@ -0,0 +1,519 @@
+Please note that the included source from Timidity, the MIDI decoder, is also
+ licensed under the following terms (GNU LGPL), but can also be used
+ separately under the GNU GPL, or the Perl Artistic License. Those licensing
+ terms are not reprinted here, but can be found on the web easily.
+
+If you want to use SDL_sound under a closed-source license, please contact
+ Ryan (icculus@clutteredmind.org), and we can discuss an alternate license for
+ money to be distributed between the contributors to this work, but I'd
+ encourage you to abide by the LGPL, since the usual concern is whether you
+ can use this library without releasing your own source code (you can).
+
+
+-------------------
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- a/decoders/timidity/Makefile.am	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/Makefile.am	Fri Sep 26 20:51:58 2003 +0000
@@ -6,8 +6,12 @@
 libtimidity_la_SOURCES =	\
 	common.c		\
 	common.h		\
+	dls1.h			\
+	dls2.h			\
 	instrum.c		\
 	instrum.h		\
+	instrum_dls.c		\
+	instrum_dls.h		\
 	mix.c			\
 	mix.h			\
 	options.h		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/timidity/dls1.h	Fri Sep 26 20:51:58 2003 +0000
@@ -0,0 +1,266 @@
+/*==========================================================================;
+//
+//  dls1.h
+//
+//
+//  Description:
+//
+//  Interface defines and structures for the Instrument Collection Form
+//  RIFF DLS.
+//
+//
+//  Written by Sonic Foundry 1996.  Released for public use.
+//
+//=========================================================================*/
+
+#ifndef _INC_DLS1
+#define _INC_DLS1
+
+/*//////////////////////////////////////////////////////////////////////////
+//
+//
+// Layout of an instrument collection:
+//
+//
+// RIFF [] 'DLS ' [dlid,colh,INSTLIST,WAVEPOOL,INFOLIST]
+//
+// INSTLIST
+// LIST [] 'lins'
+//               LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
+//               LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
+//               LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
+//
+// RGNLIST
+// LIST [] 'lrgn' 
+//               LIST [] 'rgn '  [rgnh,wsmp,wlnk,ARTLIST]
+//               LIST [] 'rgn '  [rgnh,wsmp,wlnk,ARTLIST]
+//               LIST [] 'rgn '  [rgnh,wsmp,wlnk,ARTLIST]
+//
+// ARTLIST
+// LIST [] 'lart'
+//         'art1' level 1 Articulation connection graph
+//         'art2' level 2 Articulation connection graph
+//         '3rd1' Possible 3rd party articulation structure 1
+//         '3rd2' Possible 3rd party articulation structure 2 .... and so on
+//
+// WAVEPOOL 
+// ptbl [] [pool table]
+// LIST [] 'wvpl'
+//               [path],
+//               [path],
+//               LIST [] 'wave' [dlid,RIFFWAVE]
+//               LIST [] 'wave' [dlid,RIFFWAVE]
+//               LIST [] 'wave' [dlid,RIFFWAVE]
+//               LIST [] 'wave' [dlid,RIFFWAVE]
+//               LIST [] 'wave' [dlid,RIFFWAVE]
+//
+// INFOLIST
+// LIST [] 'INFO' 
+//               'icmt' 'One of those crazy comments.'
+//               'icop' 'Copyright (C) 1996 Sonic Foundry'
+//
+/////////////////////////////////////////////////////////////////////////*/
+
+
+/*/////////////////////////////////////////////////////////////////////////
+// FOURCC's used in the DLS file
+/////////////////////////////////////////////////////////////////////////*/
+
+#define FOURCC_DLS   mmioFOURCC('D','L','S',' ')
+#define FOURCC_DLID  mmioFOURCC('d','l','i','d')
+#define FOURCC_COLH  mmioFOURCC('c','o','l','h')
+#define FOURCC_WVPL  mmioFOURCC('w','v','p','l')
+#define FOURCC_PTBL  mmioFOURCC('p','t','b','l')
+#define FOURCC_PATH  mmioFOURCC('p','a','t','h')
+#define FOURCC_wave  mmioFOURCC('w','a','v','e')
+#define FOURCC_LINS  mmioFOURCC('l','i','n','s')
+#define FOURCC_INS   mmioFOURCC('i','n','s',' ')
+#define FOURCC_INSH  mmioFOURCC('i','n','s','h')
+#define FOURCC_LRGN  mmioFOURCC('l','r','g','n')
+#define FOURCC_RGN   mmioFOURCC('r','g','n',' ')
+#define FOURCC_RGNH  mmioFOURCC('r','g','n','h')
+#define FOURCC_LART  mmioFOURCC('l','a','r','t')
+#define FOURCC_ART1  mmioFOURCC('a','r','t','1')
+#define FOURCC_WLNK  mmioFOURCC('w','l','n','k')
+#define FOURCC_WSMP  mmioFOURCC('w','s','m','p')
+#define FOURCC_VERS  mmioFOURCC('v','e','r','s')
+
+/*/////////////////////////////////////////////////////////////////////////
+// Articulation connection graph definitions 
+/////////////////////////////////////////////////////////////////////////*/
+
+/* Generic Sources */
+#define CONN_SRC_NONE              0x0000
+#define CONN_SRC_LFO               0x0001
+#define CONN_SRC_KEYONVELOCITY     0x0002
+#define CONN_SRC_KEYNUMBER         0x0003
+#define CONN_SRC_EG1               0x0004
+#define CONN_SRC_EG2               0x0005
+#define CONN_SRC_PITCHWHEEL        0x0006
+
+/* Midi Controllers 0-127 */
+#define CONN_SRC_CC1               0x0081
+#define CONN_SRC_CC7               0x0087
+#define CONN_SRC_CC10              0x008a
+#define CONN_SRC_CC11              0x008b
+
+/* Generic Destinations */
+#define CONN_DST_NONE              0x0000
+#define CONN_DST_ATTENUATION       0x0001
+#define CONN_DST_PITCH             0x0003
+#define CONN_DST_PAN               0x0004
+
+/* LFO Destinations */
+#define CONN_DST_LFO_FREQUENCY     0x0104
+#define CONN_DST_LFO_STARTDELAY    0x0105
+
+/* EG1 Destinations */
+#define CONN_DST_EG1_ATTACKTIME    0x0206
+#define CONN_DST_EG1_DECAYTIME     0x0207
+#define CONN_DST_EG1_RELEASETIME   0x0209
+#define CONN_DST_EG1_SUSTAINLEVEL  0x020a
+
+/* EG2 Destinations */
+#define CONN_DST_EG2_ATTACKTIME    0x030a
+#define CONN_DST_EG2_DECAYTIME     0x030b
+#define CONN_DST_EG2_RELEASETIME   0x030d
+#define CONN_DST_EG2_SUSTAINLEVEL  0x030e
+
+#define CONN_TRN_NONE              0x0000
+#define CONN_TRN_CONCAVE           0x0001
+
+typedef struct _DLSID {
+  ULONG    ulData1;
+  USHORT   usData2;
+  USHORT   usData3;
+  BYTE     abData4[8];
+} DLSID, FAR *LPDLSID;
+
+typedef struct _DLSVERSION {
+  DWORD    dwVersionMS;
+  DWORD    dwVersionLS;
+} DLSVERSION, FAR *LPDLSVERSION;
+                   
+
+typedef struct _CONNECTION {
+  USHORT   usSource;
+  USHORT   usControl;
+  USHORT   usDestination;
+  USHORT   usTransform;
+  LONG     lScale;
+} CONNECTION, FAR *LPCONNECTION;
+
+
+/* Level 1 Articulation Data */
+
+typedef struct _CONNECTIONLIST {
+  ULONG    cbSize;            /* size of the connection list structure */
+  ULONG    cConnections;      /* count of connections in the list */
+} CONNECTIONLIST, FAR *LPCONNECTIONLIST;
+
+
+
+/*/////////////////////////////////////////////////////////////////////////
+// Generic type defines for regions and instruments
+/////////////////////////////////////////////////////////////////////////*/
+
+typedef struct _RGNRANGE {
+  USHORT usLow;
+  USHORT usHigh;
+} RGNRANGE, FAR * LPRGNRANGE;
+
+#define F_INSTRUMENT_DRUMS      0x80000000
+
+typedef struct _MIDILOCALE {
+  ULONG ulBank;
+  ULONG ulInstrument;
+} MIDILOCALE, FAR *LPMIDILOCALE;
+
+/*/////////////////////////////////////////////////////////////////////////
+// Header structures found in an DLS file for collection, instruments, and
+// regions.
+/////////////////////////////////////////////////////////////////////////*/
+
+#define F_RGN_OPTION_SELFNONEXCLUSIVE  0x0001
+
+typedef struct _RGNHEADER {
+  RGNRANGE RangeKey;            /* Key range  */
+  RGNRANGE RangeVelocity;       /* Velocity Range  */
+  USHORT   fusOptions;          /* Synthesis options for this range */
+  USHORT   usKeyGroup;          /* Key grouping for non simultaneous play */
+                                /* 0 = no group, 1 up is group */
+                                /* for Level 1 only groups 1-15 are allowed */
+} RGNHEADER, FAR *LPRGNHEADER;
+
+typedef struct _INSTHEADER {
+  ULONG      cRegions;          /* Count of regions in this instrument */
+  MIDILOCALE Locale;            /* Intended MIDI locale of this instrument */
+} INSTHEADER, FAR *LPINSTHEADER;
+
+typedef struct _DLSHEADER {
+  ULONG      cInstruments;      /* Count of instruments in the collection */
+} DLSHEADER, FAR *LPDLSHEADER;
+
+/*////////////////////////////////////////////////////////////////////////////
+// definitions for the Wave link structure
+////////////////////////////////////////////////////////////////////////////*/
+
+/* ****  For level 1 only WAVELINK_CHANNEL_MONO is valid  **** */
+/* ulChannel allows for up to 32 channels of audio with each bit position */
+/* specifiying a channel of playback */
+
+#define WAVELINK_CHANNEL_LEFT    0x0001l
+#define WAVELINK_CHANNEL_RIGHT   0x0002l
+
+#define F_WAVELINK_PHASE_MASTER  0x0001
+
+typedef struct _WAVELINK { /* any paths or links are stored right after struct */
+  USHORT   fusOptions;     /* options flags for this wave */
+  USHORT   usPhaseGroup;   /* Phase grouping for locking channels */
+  ULONG    ulChannel;      /* channel placement */
+  ULONG    ulTableIndex;   /* index into the wave pool table, 0 based */
+} WAVELINK, FAR *LPWAVELINK;
+
+#define POOL_CUE_NULL  0xffffffffl
+
+typedef struct _POOLCUE { 
+  ULONG    ulOffset;       /* Offset to the entry in the list */
+} POOLCUE, FAR *LPPOOLCUE;
+
+typedef struct _POOLTABLE {
+  ULONG    cbSize;            /* size of the pool table structure */
+  ULONG    cCues;             /* count of cues in the list */
+} POOLTABLE, FAR *LPPOOLTABLE;
+
+/*////////////////////////////////////////////////////////////////////////////
+// Structures for the "wsmp" chunk
+////////////////////////////////////////////////////////////////////////////*/
+
+#define F_WSMP_NO_TRUNCATION     0x0001l
+#define F_WSMP_NO_COMPRESSION    0x0002l
+
+
+typedef struct _rwsmp {
+  ULONG   cbSize;
+  USHORT  usUnityNote;         /* MIDI Unity Playback Note */
+  SHORT   sFineTune;           /* Fine Tune in log tuning */
+  LONG    lAttenuation;        /* Overall Attenuation to be applied to data */
+  ULONG   fulOptions;          /* Flag options  */
+  ULONG   cSampleLoops;        /* Count of Sample loops, 0 loops is one shot */
+} WSMPL, FAR *LPWSMPL;
+
+
+/* This loop type is a normal forward playing loop which is continually */
+/* played until the envelope reaches an off threshold in the release */
+/* portion of the volume envelope */
+
+#define WLOOP_TYPE_FORWARD   0
+
+typedef struct _rloop {
+  ULONG cbSize;
+  ULONG ulType;              /* Loop Type */
+  ULONG ulStart;             /* Start of loop in samples */
+  ULONG ulLength;            /* Length of loop in samples */
+} WLOOP, FAR *LPWLOOP;
+
+#endif /*_INC_DLS1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/timidity/dls2.h	Fri Sep 26 20:51:58 2003 +0000
@@ -0,0 +1,130 @@
+/*
+ 
+ 	dls2.h
+ 	
+ 	Description:
+ 
+ 	Interface defines and structures for the DLS2 extensions of DLS.
+ 
+ 
+     Written by Microsoft 1998.  Released for public use.
+ 
+*/
+ 
+#ifndef _INC_DLS2
+#define _INC_DLS2
+ 
+/*
+     FOURCC's used in the DLS2 file, in addition to DLS1 chunks
+*/
+ 
+#define FOURCC_RGN2  mmioFOURCC('r','g','n','2')
+#define FOURCC_LAR2  mmioFOURCC('l','a','r','2')
+#define FOURCC_ART2  mmioFOURCC('a','r','t','2')
+#define FOURCC_CDL   mmioFOURCC('c','d','l',' ')
+#define FOURCC_DLID	 mmioFOURCC('d','l','i','d')
+ 
+/*
+     Articulation connection graph definitions. These are in addition to
+     the definitions in the DLS1 header.
+*/
+ 
+/* Generic Sources (in addition to DLS1 sources. */
+#define CONN_SRC_POLYPRESSURE		0x0007	/* Polyphonic Pressure */
+#define CONN_SRC_CHANNELPRESSURE		0x0008	/* Channel Pressure */
+#define CONN_SRC_VIBRATO			0x0009	/* Vibrato LFO */
+#define CONN_SRC_MONOPRESSURE       	0x000a  /* MIDI Mono pressure */
+ 
+ 
+/* Midi Controllers */
+#define CONN_SRC_CC91			0x00db	/* Reverb Send */
+#define CONN_SRC_CC93			0x00dd	/* Chorus Send */
+ 
+ 
+/* Generic Destinations */
+#define CONN_DST_GAIN			0x0001	/* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */
+#define CONN_DST_KEYNUMBER 0x0005  /* Key Number Generator */
+ 
+/* Audio Channel Output Destinations */
+#define CONN_DST_LEFT			0x0010	/* Left Channel Send */
+#define CONN_DST_RIGHT			0x0011	/* Right Channel Send */
+#define CONN_DST_CENTER			0x0012	/* Center Channel Send */
+#define CONN_DST_LEFTREAR			0x0013	/* Left Rear Channel Send */
+#define CONN_DST_RIGHTREAR			0x0014	/* Right Rear Channel Send */
+#define CONN_DST_LFE_CHANNEL		0x0015	/* LFE Channel Send */
+#define CONN_DST_CHORUS			0x0080	/* Chorus Send */
+#define CONN_DST_REVERB			0x0081	/* Reverb Send */
+ 
+/* Vibrato LFO Destinations */
+#define CONN_DST_VIB_FREQUENCY		0x0114	/* Vibrato Frequency */
+#define CONN_DST_VIB_STARTDELAY		0x0115	/* Vibrato Start Delay */
+ 
+/* EG1 Destinations */
+#define CONN_DST_EG1_DELAYTIME		0x020B	/* EG1 Delay Time */
+#define CONN_DST_EG1_HOLDTIME		0x020C	/* EG1 Hold Time */
+#define CONN_DST_EG1_SHUTDOWNTIME		0x020D	/* EG1 Shutdown Time */
+ 
+ 
+/*	EG2 Destinations */
+#define CONN_DST_EG2_DELAYTIME		0x030F	/* EG2 Delay Time */
+#define CONN_DST_EG2_HOLDTIME		0x0310	/* EG2 Hold Time */
+ 
+ 
+/* Filter Destinations */
+#define CONN_DST_FILTER_CUTOFF		0x0500	/* Filter Cutoff Frequency */
+#define CONN_DST_FILTER_Q			0x0501	/* Filter Resonance */
+ 
+ 
+/* Transforms */
+#define CONN_TRN_CONVEX			0x0002	/* Convex Transform */
+#define CONN_TRN_SWITCH			0x0003	/* Switch Transform */
+ 
+ 
+/*	Conditional chunk operators */
+ #define DLS_CDL_AND			0x0001	/* X = X & Y */
+ #define DLS_CDL_OR			0x0002	/* X = X | Y */
+ #define DLS_CDL_XOR			0x0003	/* X = X ^ Y */
+ #define DLS_CDL_ADD			0x0004	/* X = X + Y */
+ #define DLS_CDL_SUBTRACT		0x0005	/* X = X - Y */
+ #define DLS_CDL_MULTIPLY		0x0006	/* X = X * Y */
+ #define DLS_CDL_DIVIDE		0x0007	/* X = X / Y */
+ #define DLS_CDL_LOGICAL_AND	0x0008	/* X = X && Y */
+ #define DLS_CDL_LOGICAL_OR		0x0009	/* X = X || Y */
+ #define DLS_CDL_LT			0x000A	/* X = (X < Y) */
+ #define DLS_CDL_LE			0x000B	/* X = (X <= Y) */
+ #define DLS_CDL_GT			0x000C	/* X = (X > Y) */
+ #define DLS_CDL_GE			0x000D	/* X = (X >= Y) */
+ #define DLS_CDL_EQ			0x000E	/* X = (X == Y) */
+ #define DLS_CDL_NOT			0x000F	/* X = !X */
+ #define DLS_CDL_CONST		0x0010	/* 32-bit constant */
+ #define DLS_CDL_QUERY		0x0011	/* 32-bit value returned from query */
+ #define DLS_CDL_QUERYSUPPORTED	0x0012	/* Test to see if query is supported by synth */
+ 
+/*
+  Loop and release
+*/
+
+#define WLOOP_TYPE_RELEASE 1
+
+/*
+  WaveLink chunk <wlnk-ck>
+*/
+
+#define F_WAVELINK_MULTICHANNEL 0x0002
+
+
+/*
+  DLSID queries for <cdl-ck>
+*/
+
+DEFINE_GUID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+DEFINE_GUID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+DEFINE_GUID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+
+#endif	/* _INC_DLS2 */
--- a/decoders/timidity/instrum.c	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/instrum.c	Fri Sep 26 20:51:58 2003 +0000
@@ -40,6 +40,7 @@
 #include "options.h"
 #include "common.h"
 #include "instrum.h"
+#include "instrum_dls.h"
 #include "resample.h"
 #include "tables.h"
 
@@ -178,7 +179,7 @@
   if (!name) return 0;
   
   /* Open patch file */
-  if (!(rw=open_file(name)))
+  if ((rw=open_file(name)) == NULL)
     {
       noluck=1;
       /* Try with various extensions */
@@ -188,7 +189,7 @@
 	    {
 	      strcpy(tmp, name);
 	      strcat(tmp, patch_ext[i]);
-	      if ((rw=open_file(tmp)))
+	      if ((rw=open_file(tmp)) != NULL)
 		{
 		  noluck=0;
 		  break;
@@ -273,6 +274,8 @@
       READ_LONG(sp->low_freq);
       READ_LONG(sp->high_freq);
       READ_LONG(sp->root_freq);
+      sp->low_vel = 0;
+      sp->high_vel = 127;
       SDL_RWseek(rw, 2, SEEK_CUR); /* Why have a "root frequency" and then
 				    * "tuning"?? */
       
@@ -527,6 +530,11 @@
     {
       if (bank->instrument[i]==MAGIC_LOAD_INSTRUMENT)
 	{
+          bank->instrument[i]=load_instrument_dls(song, dr, b, i);
+          if (bank->instrument[i])
+            {
+              continue;
+            }
 	  if (!(bank->tone[i].name))
 	    {
 	      SNDDBG(("No instrument mapped to %s %d, program %d%s\n",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/timidity/instrum_dls.c	Fri Sep 26 20:51:58 2003 +0000
@@ -0,0 +1,1271 @@
+/*
+
+    TiMidity -- Experimental MIDI to WAVE converter
+    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   instrum.h
+
+   */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "SDL_rwops.h"
+
+#include "SDL_sound.h"
+
+#define __SDL_SOUND_INTERNAL__
+#include "SDL_sound_internal.h"
+
+#include "timidity.h"
+#include "options.h"
+#include "instrum.h"
+#include "tables.h"
+#include "common.h"
+
+/*-------------------------------------------------------------------------*/
+/* * * * * * * * * * * * * * * * * load_riff.h * * * * * * * * * * * * * * */
+/*-------------------------------------------------------------------------*/
+typedef struct _RIFF_Chunk {
+    Uint32 magic;
+    Uint32 length;
+    Uint32 subtype;
+    Uint8  *data;
+    struct _RIFF_Chunk *child;
+    struct _RIFF_Chunk *next;
+} RIFF_Chunk;
+
+extern DECLSPEC RIFF_Chunk* SDLCALL LoadRIFF(SDL_RWops *src);
+extern DECLSPEC void SDLCALL FreeRIFF(RIFF_Chunk *chunk);
+extern DECLSPEC void SDLCALL PrintRIFF(RIFF_Chunk *chunk, int level);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------*/
+/* * * * * * * * * * * * * * * * * load_riff.c * * * * * * * * * * * * * * */
+/*-------------------------------------------------------------------------*/
+#define RIFF        0x46464952        /* "RIFF" */
+#define LIST        0x5453494c        /* "LIST" */
+
+static RIFF_Chunk *AllocRIFFChunk()
+{
+    RIFF_Chunk *chunk = (RIFF_Chunk *)malloc(sizeof(*chunk));
+    if ( !chunk ) {
+        SDL_Error(SDL_ENOMEM);
+        return NULL;
+    }
+    memset(chunk, 0, sizeof(*chunk));
+    return chunk;
+}
+
+static void FreeRIFFChunk(RIFF_Chunk *chunk)
+{
+    if ( chunk->child ) {
+        FreeRIFFChunk(chunk->child);
+    }
+    while ( chunk->next ) {
+        RIFF_Chunk *freeable = chunk->next;
+        chunk->next = freeable->next;
+        FreeRIFFChunk(freeable);
+    }
+    free(chunk);
+}
+
+static int ChunkHasSubType(Uint32 magic)
+{
+    static Uint32 chunk_list[] = {
+        RIFF, LIST
+    };
+    int i;
+    for ( i = 0; i < SDL_TABLESIZE(chunk_list); ++i ) {
+        if ( magic == chunk_list[i] ) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int ChunkHasSubChunks(Uint32 magic)
+{
+    static Uint32 chunk_list[] = {
+        RIFF, LIST
+    };
+    int i;
+    for ( i = 0; i < SDL_TABLESIZE(chunk_list); ++i ) {
+        if ( magic == chunk_list[i] ) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static void LoadSubChunks(RIFF_Chunk *chunk, Uint8 *data, Uint32 left)
+{
+    Uint8 *subchunkData;
+    Uint32 subchunkDataLen;
+
+    while ( left > 8 ) {
+        RIFF_Chunk *child = AllocRIFFChunk();
+        RIFF_Chunk *next, *prev = NULL;
+        for ( next = chunk->child; next; next = next->next ) {
+            prev = next;
+        }
+        if ( prev ) {
+            prev->next = child;
+        } else {
+            chunk->child = child;
+        }
+            
+        child->magic = (data[0] <<  0) |
+                       (data[1] <<  8) |
+                       (data[2] << 16) |
+                       (data[3] << 24);
+        data += 4;
+        left -= 4;
+        child->length = (data[0] <<  0) |
+                        (data[1] <<  8) |
+                        (data[2] << 16) |
+                        (data[3] << 24);
+        data += 4;
+        left -= 4;
+        child->data = data;
+
+        if ( child->length > left ) {
+            child->length = left;
+        }
+
+        subchunkData = child->data;
+        subchunkDataLen = child->length;
+        if ( ChunkHasSubType(child->magic) && subchunkDataLen >= 4 ) {
+            child->subtype = (subchunkData[0] <<  0) |
+                     (subchunkData[1] <<  8) |
+                     (subchunkData[2] << 16) |
+                     (subchunkData[3] << 24);
+            subchunkData += 4;
+            subchunkDataLen -= 4;
+        }
+        if ( ChunkHasSubChunks(child->magic) ) {
+            LoadSubChunks(child, subchunkData, subchunkDataLen);
+        }
+
+        data += child->length;
+        left -= child->length;
+    }
+}
+
+RIFF_Chunk *LoadRIFF(SDL_RWops *src)
+{
+    RIFF_Chunk *chunk;
+    Uint8 *subchunkData;
+    Uint32 subchunkDataLen;
+
+    /* Allocate the chunk structure */
+    chunk = AllocRIFFChunk();
+
+    /* Make sure the file is in RIFF format */
+    chunk->magic    = SDL_ReadLE32(src);
+    chunk->length    = SDL_ReadLE32(src);
+    if ( chunk->magic != RIFF ) {
+        SDL_SetError("Not a RIFF file");
+        FreeRIFFChunk(chunk);
+        return NULL;
+    }
+    chunk->data = (Uint8 *)malloc(chunk->length);
+    if ( chunk->data == NULL ) {
+        SDL_Error(SDL_ENOMEM);
+        FreeRIFFChunk(chunk);
+        return NULL;
+    }
+    if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) {
+        SDL_Error(SDL_EFREAD);
+        FreeRIFF(chunk);
+        return NULL;
+    }
+    subchunkData = chunk->data;
+    subchunkDataLen = chunk->length;
+    if ( ChunkHasSubType(chunk->magic) && subchunkDataLen >= 4 ) {
+        chunk->subtype = (subchunkData[0] <<  0) |
+                 (subchunkData[1] <<  8) |
+                 (subchunkData[2] << 16) |
+                 (subchunkData[3] << 24);
+        subchunkData += 4;
+        subchunkDataLen -= 4;
+    }
+    if ( ChunkHasSubChunks(chunk->magic) ) {
+        LoadSubChunks(chunk, subchunkData, subchunkDataLen);
+    }
+    return chunk;
+}
+
+void FreeRIFF(RIFF_Chunk *chunk)
+{
+    free(chunk->data);
+    FreeRIFFChunk(chunk);
+}
+
+void PrintRIFF(RIFF_Chunk *chunk, int level)
+{
+    static char prefix[128];
+
+    if ( level == sizeof(prefix)-1 ) {
+        return;
+    }
+    if ( level > 0 ) {
+        prefix[(level-1)*2] = ' ';
+        prefix[(level-1)*2+1] = ' ';
+    }
+    prefix[level*2] = '\0';
+    printf("%sChunk: %c%c%c%c (%d bytes)", prefix,
+        ((chunk->magic >>  0) & 0xFF),
+        ((chunk->magic >>  8) & 0xFF),
+        ((chunk->magic >> 16) & 0xFF),
+        ((chunk->magic >> 24) & 0xFF), chunk->length);
+    if ( chunk->subtype ) {
+        printf(" subtype: %c%c%c%c",
+            ((chunk->subtype >>  0) & 0xFF),
+            ((chunk->subtype >>  8) & 0xFF),
+            ((chunk->subtype >> 16) & 0xFF),
+            ((chunk->subtype >> 24) & 0xFF));
+    }
+    printf("\n");
+    if ( chunk->child ) {
+        printf("%s{\n", prefix);
+        PrintRIFF(chunk->child, level + 1);
+        printf("%s}\n", prefix);
+    }
+    if ( chunk->next ) {
+        PrintRIFF(chunk->next, level);
+    }
+    if ( level > 0 ) {
+        prefix[(level-1)*2] = '\0';
+    }
+}
+
+#ifdef TEST_MAIN_RIFF
+
+main(int argc, char *argv[])
+{
+    int i;
+    for ( i = 1; i < argc; ++i ) {
+        RIFF_Chunk *chunk;
+        SDL_RWops *src = SDL_RWFromFile(argv[i], "rb");
+        if ( !src ) {
+            fprintf(stderr, "Couldn't open %s: %s", argv[i], SDL_GetError());
+            continue;
+        }
+        chunk = LoadRIFF(src);
+        if ( chunk ) {
+            PrintRIFF(chunk, 0);
+            FreeRIFF(chunk);
+        } else {
+            fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError());
+        }
+        SDL_RWclose(src);
+    }
+}
+
+#endif // TEST_MAIN
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------*/
+/* * * * * * * * * * * * * * * * * load_dls.h  * * * * * * * * * * * * * * */
+/*-------------------------------------------------------------------------*/
+/* This code is based on the DLS spec version 1.1, available at:
+    http://www.midi.org/about-midi/dls/dlsspec.shtml
+*/
+
+/* Some typedefs so the public dls headers don't need to be modified */
+#define FAR
+typedef Uint8   BYTE;
+typedef Sint16  SHORT;
+typedef Uint16  USHORT;
+typedef Uint16  WORD;
+typedef Sint32  LONG;
+typedef Uint32  ULONG;
+typedef Uint32  DWORD;
+#define mmioFOURCC(A, B, C, D)    \
+    (((A) <<  0) | ((B) <<  8) | ((C) << 16) | ((D) << 24))
+#define DEFINE_GUID(A, B, C, E, F, G, H, I, J, K, L, M)
+
+#include "dls1.h"
+#include "dls2.h"
+
+typedef struct _WaveFMT {
+    WORD wFormatTag;
+    WORD wChannels;
+    DWORD dwSamplesPerSec;
+    DWORD dwAvgBytesPerSec;
+    WORD wBlockAlign;
+    WORD wBitsPerSample;
+} WaveFMT;
+
+typedef struct _DLS_Wave {
+    WaveFMT *format;
+    Uint8 *data;
+    Uint32 length;
+    WSMPL *wsmp;
+    WLOOP *wsmp_loop;
+} DLS_Wave;
+
+typedef struct _DLS_Region {
+    RGNHEADER *header;
+    WAVELINK *wlnk;
+    WSMPL *wsmp;
+    WLOOP *wsmp_loop;
+    CONNECTIONLIST *art;
+    CONNECTION *artList;
+} DLS_Region;
+
+typedef struct _DLS_Instrument {
+    const char *name;
+    INSTHEADER *header;
+    DLS_Region *regions;
+    CONNECTIONLIST *art;
+    CONNECTION *artList;
+} DLS_Instrument;
+
+typedef struct _DLS_Data {
+    struct _RIFF_Chunk *chunk;
+
+    Uint32 cInstruments;
+    DLS_Instrument *instruments;
+
+    POOLTABLE *ptbl;
+    POOLCUE *ptblList;
+    DLS_Wave *waveList;
+
+    const char *name;
+    const char *artist;
+    const char *copyright;
+    const char *comments;
+} DLS_Data;
+
+extern DECLSPEC DLS_Data* SDLCALL LoadDLS(SDL_RWops *src);
+extern DECLSPEC void SDLCALL FreeDLS(DLS_Data *chunk);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------*/
+/* * * * * * * * * * * * * * * * * load_dls.c  * * * * * * * * * * * * * * */
+/*-------------------------------------------------------------------------*/
+
+#define FOURCC_LIST    0x5453494c   /* "LIST" */
+#define FOURCC_FMT     0x20746D66   /* "fmt " */
+#define FOURCC_DATA    0x61746164   /* "data" */
+#define FOURCC_INFO    mmioFOURCC('I','N','F','O')
+#define FOURCC_IARL    mmioFOURCC('I','A','R','L')
+#define FOURCC_IART    mmioFOURCC('I','A','R','T')
+#define FOURCC_ICMS    mmioFOURCC('I','C','M','S')
+#define FOURCC_ICMT    mmioFOURCC('I','C','M','T')
+#define FOURCC_ICOP    mmioFOURCC('I','C','O','P')
+#define FOURCC_ICRD    mmioFOURCC('I','C','R','D')
+#define FOURCC_IENG    mmioFOURCC('I','E','N','G')
+#define FOURCC_IGNR    mmioFOURCC('I','G','N','R')
+#define FOURCC_IKEY    mmioFOURCC('I','K','E','Y')
+#define FOURCC_IMED    mmioFOURCC('I','M','E','D')
+#define FOURCC_INAM    mmioFOURCC('I','N','A','M')
+#define FOURCC_IPRD    mmioFOURCC('I','P','R','D')
+#define FOURCC_ISBJ    mmioFOURCC('I','S','B','J')
+#define FOURCC_ISFT    mmioFOURCC('I','S','F','T')
+#define FOURCC_ISRC    mmioFOURCC('I','S','R','C')
+#define FOURCC_ISRF    mmioFOURCC('I','S','R','F')
+#define FOURCC_ITCH    mmioFOURCC('I','T','C','H')
+
+
+static void FreeRegions(DLS_Instrument *instrument)
+{
+    if ( instrument->regions ) {
+        free(instrument->regions);
+    }
+}
+
+static void AllocRegions(DLS_Instrument *instrument)
+{
+    int datalen = (instrument->header->cRegions * sizeof(DLS_Region));
+    FreeRegions(instrument);
+    instrument->regions = (DLS_Region *)malloc(datalen);
+    if ( instrument->regions ) {
+        memset(instrument->regions, 0, datalen);
+    }
+}
+
+static void FreeInstruments(DLS_Data *data)
+{
+    if ( data->instruments ) {
+        Uint32 i;
+        for ( i = 0; i < data->cInstruments; ++i ) {
+            FreeRegions(&data->instruments[i]);
+        }
+        free(data->instruments);
+    }
+}
+
+static void AllocInstruments(DLS_Data *data)
+{
+    int datalen = (data->cInstruments * sizeof(DLS_Instrument));
+    FreeInstruments(data);
+    data->instruments = (DLS_Instrument *)malloc(datalen);
+    if ( data->instruments ) {
+        memset(data->instruments, 0, datalen);
+    }
+}
+
+static void FreeWaveList(DLS_Data *data)
+{
+    if ( data->waveList ) {
+        free(data->waveList);
+    }
+}
+
+static void AllocWaveList(DLS_Data *data)
+{
+    int datalen = (data->ptbl->cCues * sizeof(DLS_Wave));
+    FreeWaveList(data);
+    data->waveList = (DLS_Wave *)malloc(datalen);
+    if ( data->waveList ) {
+        memset(data->waveList, 0, datalen);
+    }
+}
+
+static void Parse_colh(DLS_Data *data, RIFF_Chunk *chunk)
+{
+    data->cInstruments = SDL_SwapLE32(*(Uint32 *)chunk->data);
+    AllocInstruments(data);
+}
+
+static void Parse_insh(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument)
+{
+    INSTHEADER *header = (INSTHEADER *)chunk->data;
+    header->cRegions = SDL_SwapLE32(header->cRegions);
+    header->Locale.ulBank = SDL_SwapLE32(header->Locale.ulBank);
+    header->Locale.ulInstrument = SDL_SwapLE32(header->Locale.ulInstrument);
+    instrument->header = header;
+    AllocRegions(instrument);
+}
+
+static void Parse_rgnh(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region)
+{
+    RGNHEADER *header = (RGNHEADER *)chunk->data;
+    header->RangeKey.usLow = SDL_SwapLE16(header->RangeKey.usLow);
+    header->RangeKey.usHigh = SDL_SwapLE16(header->RangeKey.usHigh);
+    header->RangeVelocity.usLow = SDL_SwapLE16(header->RangeVelocity.usLow);
+    header->RangeVelocity.usHigh = SDL_SwapLE16(header->RangeVelocity.usHigh);
+    header->fusOptions = SDL_SwapLE16(header->fusOptions);
+    header->usKeyGroup = SDL_SwapLE16(header->usKeyGroup);
+    region->header = header;
+}
+
+static void Parse_wlnk(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region)
+{
+    WAVELINK *wlnk = (WAVELINK *)chunk->data;
+    wlnk->fusOptions = SDL_SwapLE16(wlnk->fusOptions);
+    wlnk->usPhaseGroup = SDL_SwapLE16(wlnk->usPhaseGroup);
+    wlnk->ulChannel = SDL_SwapLE16(wlnk->ulChannel);
+    wlnk->ulTableIndex = SDL_SwapLE16(wlnk->ulTableIndex);
+    region->wlnk = wlnk;
+}
+
+static void Parse_wsmp(DLS_Data *data, RIFF_Chunk *chunk, WSMPL **wsmp_ptr, WLOOP **wsmp_loop_ptr)
+{
+    Uint32 i;
+    WSMPL *wsmp = (WSMPL *)chunk->data;
+    WLOOP *loop;
+    wsmp->cbSize = SDL_SwapLE32(wsmp->cbSize);
+    wsmp->usUnityNote = SDL_SwapLE16(wsmp->usUnityNote);
+    wsmp->sFineTune = SDL_SwapLE16(wsmp->sFineTune);
+    wsmp->lAttenuation = SDL_SwapLE32(wsmp->lAttenuation);
+    wsmp->fulOptions = SDL_SwapLE32(wsmp->fulOptions);
+    wsmp->cSampleLoops = SDL_SwapLE32(wsmp->cSampleLoops);
+    loop = (WLOOP *)((Uint8 *)chunk->data + wsmp->cbSize);
+    *wsmp_ptr = wsmp;
+    *wsmp_loop_ptr = loop;
+    for ( i = 0; i < wsmp->cSampleLoops; ++i ) {
+        loop->cbSize = SDL_SwapLE32(loop->cbSize);
+        loop->ulType = SDL_SwapLE32(loop->ulType);
+        loop->ulStart = SDL_SwapLE32(loop->ulStart);
+        loop->ulLength = SDL_SwapLE32(loop->ulLength);
+        ++loop;
+    }
+}
+
+static void Parse_art(DLS_Data *data, RIFF_Chunk *chunk, CONNECTIONLIST **art_ptr, CONNECTION **artList_ptr)
+{
+    Uint32 i;
+    CONNECTIONLIST *art = (CONNECTIONLIST *)chunk->data;
+    CONNECTION *artList;
+    art->cbSize = SDL_SwapLE32(art->cbSize);
+    art->cConnections = SDL_SwapLE32(art->cConnections);
+    artList = (CONNECTION *)((Uint8 *)chunk->data + art->cbSize);
+    *art_ptr = art;
+    *artList_ptr = artList;
+    for ( i = 0; i < art->cConnections; ++i ) {
+        artList->usSource = SDL_SwapLE16(artList->usSource);
+        artList->usControl = SDL_SwapLE16(artList->usControl);
+        artList->usDestination = SDL_SwapLE16(artList->usDestination);
+        artList->usTransform = SDL_SwapLE16(artList->usTransform);
+        artList->lScale = SDL_SwapLE32(artList->lScale);
+        ++artList;
+    }
+}
+
+static void Parse_lart(DLS_Data *data, RIFF_Chunk *chunk, CONNECTIONLIST **conn_ptr, CONNECTION **connList_ptr)
+{
+    /* FIXME: This only supports one set of connections */
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_ART1:
+            case FOURCC_ART2:
+                Parse_art(data, chunk, conn_ptr, connList_ptr);
+                return;
+        }
+    }
+}
+
+static void Parse_rgn(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region)
+{
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_RGNH:
+                Parse_rgnh(data, chunk, region);
+                break;
+            case FOURCC_WLNK:
+                Parse_wlnk(data, chunk, region);
+                break;
+            case FOURCC_WSMP:
+                Parse_wsmp(data, chunk, &region->wsmp, &region->wsmp_loop);
+                break;
+            case FOURCC_LART:
+            case FOURCC_LAR2:
+                Parse_lart(data, chunk, &region->art, &region->artList);
+                break;
+        }
+    }
+}
+
+static void Parse_lrgn(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument)
+{
+    Uint32 region = 0;
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_RGN:
+            case FOURCC_RGN2:
+                if ( region < instrument->header->cRegions ) {
+                    Parse_rgn(data, chunk, &instrument->regions[region++]);
+                }
+                break;
+        }
+    }
+}
+
+static void Parse_INFO_INS(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument)
+{
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_INAM: /* Name */
+                instrument->name = chunk->data;
+                break;
+        }
+    }
+}
+
+static void Parse_ins(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument)
+{
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_INSH:
+                Parse_insh(data, chunk, instrument);
+                break;
+            case FOURCC_LRGN:
+                Parse_lrgn(data, chunk, instrument);
+                break;
+            case FOURCC_LART:
+            case FOURCC_LAR2:
+                Parse_lart(data, chunk, &instrument->art, &instrument->artList);
+                break;
+            case FOURCC_INFO:
+                Parse_INFO_INS(data, chunk, instrument);
+                break;
+        }
+    }
+}
+
+static void Parse_lins(DLS_Data *data, RIFF_Chunk *chunk)
+{
+    Uint32 instrument = 0;
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_INS:
+                if ( instrument < data->cInstruments ) {
+                    Parse_ins(data, chunk, &data->instruments[instrument++]);
+                }
+                break;
+        }
+    }
+}
+
+static void Parse_ptbl(DLS_Data *data, RIFF_Chunk *chunk)
+{
+    Uint32 i;
+    POOLTABLE *ptbl = (POOLTABLE *)chunk->data;
+    ptbl->cbSize = SDL_SwapLE32(ptbl->cbSize);
+    ptbl->cCues = SDL_SwapLE32(ptbl->cCues);
+    data->ptbl = ptbl;
+    data->ptblList = (POOLCUE *)((Uint8 *)chunk->data + ptbl->cbSize);
+    for ( i = 0; i < ptbl->cCues; ++i ) {
+        data->ptblList[i].ulOffset = SDL_SwapLE32(data->ptblList[i].ulOffset);
+    }
+    AllocWaveList(data);
+}
+
+static void Parse_fmt(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave)
+{
+    WaveFMT *fmt = (WaveFMT *)chunk->data;
+    fmt->wFormatTag = SDL_SwapLE16(fmt->wFormatTag);
+    fmt->wChannels = SDL_SwapLE16(fmt->wChannels);
+    fmt->dwSamplesPerSec = SDL_SwapLE32(fmt->dwSamplesPerSec);
+    fmt->dwAvgBytesPerSec = SDL_SwapLE32(fmt->dwAvgBytesPerSec);
+    fmt->wBlockAlign = SDL_SwapLE16(fmt->wBlockAlign);
+    fmt->wBitsPerSample = SDL_SwapLE16(fmt->wBitsPerSample);
+    wave->format = fmt;
+}
+
+static void Parse_data(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave)
+{
+    wave->data = chunk->data;
+    wave->length = chunk->length;
+}
+
+static void Parse_wave(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave)
+{
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_FMT:
+                Parse_fmt(data, chunk, wave);
+                break;
+            case FOURCC_DATA:
+                Parse_data(data, chunk, wave);
+                break;
+            case FOURCC_WSMP:
+                Parse_wsmp(data, chunk, &wave->wsmp, &wave->wsmp_loop);
+                break;
+        }
+    }
+}
+
+static void Parse_wvpl(DLS_Data *data, RIFF_Chunk *chunk)
+{
+    Uint32 wave = 0;
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_wave:
+                if ( wave < data->ptbl->cCues ) {
+                    Parse_wave(data, chunk, &data->waveList[wave++]);
+                }
+                break;
+        }
+    }
+}
+
+static void Parse_INFO_DLS(DLS_Data *data, RIFF_Chunk *chunk)
+{
+    for ( chunk = chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_IARL: /* Archival Location */
+                break;
+            case FOURCC_IART: /* Artist */
+                data->artist = chunk->data;
+                break;
+            case FOURCC_ICMS: /* Commisioned */
+                break;
+            case FOURCC_ICMT: /* Comments */
+                data->comments = chunk->data;
+                break;
+            case FOURCC_ICOP: /* Copyright */
+                data->copyright = chunk->data;
+                break;
+            case FOURCC_ICRD: /* Creation Date */
+                break;
+            case FOURCC_IENG: /* Engineer */
+                break;
+            case FOURCC_IGNR: /* Genre */
+                break;
+            case FOURCC_IKEY: /* Keywords */
+                break;
+            case FOURCC_IMED: /* Medium */
+                break;
+            case FOURCC_INAM: /* Name */
+                data->name = chunk->data;
+                break;
+            case FOURCC_IPRD: /* Product */
+                break;
+            case FOURCC_ISBJ: /* Subject */
+                break;
+            case FOURCC_ISFT: /* Software */
+                break;
+            case FOURCC_ISRC: /* Source */
+                break;
+            case FOURCC_ISRF: /* Source Form */
+                break;
+            case FOURCC_ITCH: /* Technician */
+                break;
+        }
+    }
+}
+
+DLS_Data *LoadDLS(SDL_RWops *src)
+{
+    RIFF_Chunk *chunk;
+    DLS_Data *data = (DLS_Data *)malloc(sizeof(*data));
+    if ( !data ) {
+        SDL_Error(SDL_ENOMEM);
+        return NULL;
+    }
+    memset(data, 0, sizeof(*data));
+
+    data->chunk = LoadRIFF(src);
+    if ( !data->chunk ) {
+        FreeDLS(data);
+        return NULL;
+    }
+
+    for ( chunk = data->chunk->child; chunk; chunk = chunk->next ) {
+        Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic;
+        switch(magic) {
+            case FOURCC_COLH:
+                Parse_colh(data, chunk);
+                break;
+            case FOURCC_LINS:
+                Parse_lins(data, chunk);
+                break;
+            case FOURCC_PTBL:
+                Parse_ptbl(data, chunk);
+                break;
+            case FOURCC_WVPL:
+                Parse_wvpl(data, chunk);
+                break;
+            case FOURCC_INFO:
+                Parse_INFO_DLS(data, chunk);
+                break;
+        }
+    }
+    return data;
+}
+
+void FreeDLS(DLS_Data *data)
+{
+    if ( data->chunk ) {
+        FreeRIFF(data->chunk);
+    }
+    FreeInstruments(data);
+    FreeWaveList(data);
+    free(data);
+}
+
+static const char *SourceToString(USHORT usSource)
+{
+    switch(usSource) {
+        case CONN_SRC_NONE:
+            return "NONE";
+        case CONN_SRC_LFO:
+            return "LFO";
+        case CONN_SRC_KEYONVELOCITY:
+            return "KEYONVELOCITY";
+        case CONN_SRC_KEYNUMBER:
+            return "KEYNUMBER";
+        case CONN_SRC_EG1:
+            return "EG1";
+        case CONN_SRC_EG2:
+            return "EG2";
+        case CONN_SRC_PITCHWHEEL:
+            return "PITCHWHEEL";
+        case CONN_SRC_CC1:
+            return "CC1";
+        case CONN_SRC_CC7:
+            return "CC7";
+        case CONN_SRC_CC10:
+            return "CC10";
+        case CONN_SRC_CC11:
+            return "CC11";
+        case CONN_SRC_POLYPRESSURE:
+            return "POLYPRESSURE";
+        case CONN_SRC_CHANNELPRESSURE:
+            return "CHANNELPRESSURE";
+        case CONN_SRC_VIBRATO:
+            return "VIBRATO";
+        case CONN_SRC_MONOPRESSURE:
+            return "MONOPRESSURE";
+        case CONN_SRC_CC91:
+            return "CC91";
+        case CONN_SRC_CC93:
+            return "CC93";
+        default:
+            return "UNKNOWN";
+    }
+}
+
+static const char *TransformToString(USHORT usTransform)
+{
+    switch (usTransform) {
+        case CONN_TRN_NONE:
+            return "NONE";
+        case CONN_TRN_CONCAVE:
+            return "CONCAVE";
+        case CONN_TRN_CONVEX:
+            return "CONVEX";
+        case CONN_TRN_SWITCH:
+            return "SWITCH";
+        default:
+            return "UNKNOWN";
+    }
+}
+
+static const char *DestinationToString(USHORT usDestination)
+{
+    switch (usDestination) {
+        case CONN_DST_NONE:
+            return "NONE";
+        case CONN_DST_ATTENUATION:
+            return "ATTENUATION";
+        case CONN_DST_PITCH:
+            return "PITCH";
+        case CONN_DST_PAN:
+            return "PAN";
+        case CONN_DST_LFO_FREQUENCY:
+            return "LFO_FREQUENCY";
+        case CONN_DST_LFO_STARTDELAY:
+            return "LFO_STARTDELAY";
+        case CONN_DST_EG1_ATTACKTIME:
+            return "EG1_ATTACKTIME";
+        case CONN_DST_EG1_DECAYTIME:
+            return "EG1_DECAYTIME";
+        case CONN_DST_EG1_RELEASETIME:
+            return "EG1_RELEASETIME";
+        case CONN_DST_EG1_SUSTAINLEVEL:
+            return "EG1_SUSTAINLEVEL";
+        case CONN_DST_EG2_ATTACKTIME:
+            return "EG2_ATTACKTIME";
+        case CONN_DST_EG2_DECAYTIME:
+            return "EG2_DECAYTIME";
+        case CONN_DST_EG2_RELEASETIME:
+            return "EG2_RELEASETIME";
+        case CONN_DST_EG2_SUSTAINLEVEL:
+            return "EG2_SUSTAINLEVEL";
+        case CONN_DST_KEYNUMBER:
+            return "KEYNUMBER";
+        case CONN_DST_LEFT:
+            return "LEFT";
+        case CONN_DST_RIGHT:
+            return "RIGHT";
+        case CONN_DST_CENTER:
+            return "CENTER";
+        case CONN_DST_LEFTREAR:
+            return "LEFTREAR";
+        case CONN_DST_RIGHTREAR:
+            return "RIGHTREAR";
+        case CONN_DST_LFE_CHANNEL:
+            return "LFE_CHANNEL";
+        case CONN_DST_CHORUS:
+            return "CHORUS";
+        case CONN_DST_REVERB:
+            return "REVERB";
+        case CONN_DST_VIB_FREQUENCY:
+            return "VIB_FREQUENCY";
+        case CONN_DST_VIB_STARTDELAY:
+            return "VIB_STARTDELAY";
+        case CONN_DST_EG1_DELAYTIME:
+            return "EG1_DELAYTIME";
+        case CONN_DST_EG1_HOLDTIME:
+            return "EG1_HOLDTIME";
+        case CONN_DST_EG1_SHUTDOWNTIME:
+            return "EG1_SHUTDOWNTIME";
+        case CONN_DST_EG2_DELAYTIME:
+            return "EG2_DELAYTIME";
+        case CONN_DST_EG2_HOLDTIME:
+            return "EG2_HOLDTIME";
+        case CONN_DST_FILTER_CUTOFF:
+            return "FILTER_CUTOFF";
+        case CONN_DST_FILTER_Q:
+            return "FILTER_Q";
+        default:
+            return "UNKOWN";
+    }
+}
+
+static void PrintArt(const char *type, CONNECTIONLIST *art, CONNECTION *artList)
+{
+    Uint32 i;
+    printf("%s Connections:\n", type);
+    for ( i = 0; i < art->cConnections; ++i ) {
+        printf("  Source: %s, Control: %s, Destination: %s, Transform: %s, Scale: %d\n",
+            SourceToString(artList[i].usSource),
+            SourceToString(artList[i].usControl),
+            DestinationToString(artList[i].usDestination),
+            TransformToString(artList[i].usTransform),
+            artList[i].lScale);
+    }
+}
+
+static void PrintWave(DLS_Wave *wave, Uint32 index)
+{
+    WaveFMT *format = wave->format;
+    if ( format ) {
+        printf("  Wave %u: Format: %hu, %hu channels, %u Hz, %hu bits (length = %u)\n", index, format->wFormatTag, format->wChannels, format->dwSamplesPerSec, format->wBitsPerSample, wave->length);
+    }
+    if ( wave->wsmp ) {
+        Uint32 i;
+        printf("    wsmp->usUnityNote = %hu\n", wave->wsmp->usUnityNote);
+        printf("    wsmp->sFineTune = %hd\n", wave->wsmp->sFineTune);
+        printf("    wsmp->lAttenuation = %d\n", wave->wsmp->lAttenuation);
+        printf("    wsmp->fulOptions = 0x%8.8x\n", wave->wsmp->fulOptions);
+        printf("    wsmp->cSampleLoops = %u\n", wave->wsmp->cSampleLoops);
+        for ( i = 0; i < wave->wsmp->cSampleLoops; ++i ) {
+            WLOOP *loop = &wave->wsmp_loop[i];
+            printf("    Loop %u:\n", i);
+            printf("      ulStart = %u\n", loop->ulStart);
+            printf("      ulLength = %u\n", loop->ulLength);
+        }
+    }
+}
+
+static void PrintRegion(DLS_Region *region, Uint32 index)
+{
+    printf("  Region %u:\n", index);
+    if ( region->header ) {
+        printf("    RangeKey = { %hu - %hu }\n", region->header->RangeKey.usLow, region->header->RangeKey.usHigh);
+        printf("    RangeVelocity = { %hu - %hu }\n", region->header->RangeVelocity.usLow, region->header->RangeVelocity.usHigh);
+        printf("    fusOptions = 0x%4.4hx\n", region->header->fusOptions);
+        printf("    usKeyGroup = %hu\n", region->header->usKeyGroup);
+    }
+    if ( region->wlnk ) {
+        printf("    wlnk->fusOptions = 0x%4.4hx\n", region->wlnk->fusOptions);
+        printf("    wlnk->usPhaseGroup = %hu\n", region->wlnk->usPhaseGroup);
+        printf("    wlnk->ulChannel = %u\n", region->wlnk->ulChannel);
+        printf("    wlnk->ulTableIndex = %u\n", region->wlnk->ulTableIndex);
+    }
+    if ( region->wsmp ) {
+        Uint32 i;
+        printf("    wsmp->usUnityNote = %hu\n", region->wsmp->usUnityNote);
+        printf("    wsmp->sFineTune = %hd\n", region->wsmp->sFineTune);
+        printf("    wsmp->lAttenuation = %d\n", region->wsmp->lAttenuation);
+        printf("    wsmp->fulOptions = 0x%8.8x\n", region->wsmp->fulOptions);
+        printf("    wsmp->cSampleLoops = %u\n", region->wsmp->cSampleLoops);
+        for ( i = 0; i < region->wsmp->cSampleLoops; ++i ) {
+            WLOOP *loop = &region->wsmp_loop[i];
+            printf("    Loop %u:\n", i);
+            printf("      ulStart = %u\n", loop->ulStart);
+            printf("      ulLength = %u\n", loop->ulLength);
+        }
+    }
+    if ( region->art && region->art->cConnections > 0 ) {
+        PrintArt("Region", region->art, region->artList);
+    }
+}
+
+static void PrintInstrument(DLS_Instrument *instrument, Uint32 index)
+{
+    printf("Instrument %u:\n", index);
+    if ( instrument->name ) {
+        printf("  Name: %s\n", instrument->name);
+    }
+    if ( instrument->header ) {
+        Uint32 i;
+        printf("  ulBank = 0x%8.8x\n", instrument->header->Locale.ulBank);
+        printf("  ulInstrument = %u\n", instrument->header->Locale.ulInstrument);
+        printf("  Regions: %u\n", instrument->header->cRegions);
+        for ( i = 0; i < instrument->header->cRegions; ++i ) {
+            PrintRegion(&instrument->regions[i], i);
+        }
+    }
+    if ( instrument->art && instrument->art->cConnections > 0 ) {
+        PrintArt("Instrument", instrument->art, instrument->artList);
+    }
+};
+
+void PrintDLS(DLS_Data *data)
+{
+    printf("DLS Data:\n");
+    printf("cInstruments = %u\n", data->cInstruments); 
+    if ( data->instruments ) {
+        Uint32 i;
+        for ( i = 0; i < data->cInstruments; ++i ) {
+            PrintInstrument(&data->instruments[i], i);
+        }
+    }
+    if ( data->ptbl && data->ptbl->cCues > 0 ) {
+        Uint32 i;
+        printf("Cues: ");
+        for ( i = 0; i < data->ptbl->cCues; ++i ) {
+            if ( i > 0 ) {
+                printf(", ");
+            }
+            printf("%u", data->ptblList[i].ulOffset);
+        }
+        printf("\n");
+    }
+    if ( data->waveList ) {
+        Uint32 i;
+        printf("Waves:\n");
+        for ( i = 0; i < data->ptbl->cCues; ++i ) {
+            PrintWave(&data->waveList[i], i);
+        }
+    }
+    if ( data->name ) {
+        printf("Name: %s\n", data->name);
+    }
+    if ( data->artist ) {
+        printf("Artist: %s\n", data->artist);
+    }
+    if ( data->copyright ) {
+        printf("Copyright: %s\n", data->copyright);
+    }
+    if ( data->comments ) {
+        printf("Comments: %s\n", data->comments);
+    }
+}
+
+#ifdef TEST_MAIN_DLS
+
+main(int argc, char *argv[])
+{
+    int i;
+    for ( i = 1; i < argc; ++i ) {
+        DLS_Data *data;
+        SDL_RWops *src = SDL_RWFromFile(argv[i], "rb");
+        if ( !src ) {
+            fprintf(stderr, "Couldn't open %s: %s", argv[i], SDL_GetError());
+            continue;
+        }
+        data = LoadDLS(src);
+        if ( data ) {
+            PrintRIFF(data->chunk, 0);
+            PrintDLS(data);
+            FreeDLS(data);
+        } else {
+            fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError());
+        }
+        SDL_RWclose(src);
+    }
+}
+
+#endif // TEST_MAIN
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------*/
+/* * * * * * * * * * * * * * * * * instrum_dls.c * * * * * * * * * * * * * */
+/*-------------------------------------------------------------------------*/
+
+DLS_Data *Timidity_LoadDLS(SDL_RWops *src)
+{
+  DLS_Data *patches = LoadDLS(src);
+  if (!patches) {
+    SNDDBG(("%s", SDL_GetError()));
+  }
+  return patches;
+}
+
+void Timidity_FreeDLS(DLS_Data *patches)
+{
+  FreeDLS(patches);
+}
+
+/* convert timecents to sec */
+static double to_msec(int timecent)
+{
+  if (timecent == 0x80000000 || timecent == 0)
+    return 0.0;
+  return 1000.0 * pow(2.0, (double)(timecent / 65536) / 1200.0);
+}
+
+/* convert decipercent to {0..1} */
+static double to_normalized_percent(int decipercent)
+{
+  return ((double)(decipercent / 65536)) / 1000.0;
+}
+
+/* convert from 8bit value to fractional offset (15.15) */
+static Sint32 to_offset(int offset)
+{
+	return (Sint32)offset << (7+15);
+}
+
+/* calculate ramp rate in fractional unit;
+ * diff = 8bit, time = msec
+ */
+static Sint32 calc_rate(MidiSong *song, int diff, int sample_rate, double msec)
+{
+    double rate;
+
+    if(msec < 6)
+      msec = 6;
+    if(diff == 0)
+      diff = 255;
+    diff <<= (7+15);
+    rate = ((double)diff / song->rate) * song->control_ratio * 1000.0 / msec;
+    return (Sint32)rate;
+}
+
+static int load_connection(ULONG cConnections, CONNECTION *artList, USHORT destination)
+{
+  ULONG i;
+  int value = 0;
+  for (i = 0; i < cConnections; ++i) {
+    CONNECTION *conn = &artList[i];
+    if(conn->usDestination == destination) {
+      // The formula for the destination is:
+      // usDestination = usDestination + usTransform(usSource * (usControl * lScale))
+      // Since we are only handling source/control of NONE and identity
+      // transform, this simplifies to: usDestination = usDestination + lScale
+      if (conn->usSource == CONN_SRC_NONE &&
+          conn->usControl == CONN_SRC_NONE &&
+          conn->usTransform == CONN_TRN_NONE)
+        value += conn->lScale;
+    }
+  }
+  return value;
+}
+
+static void load_region_dls(MidiSong *song, Sample *sample, DLS_Instrument *ins, Uint32 index)
+{
+  DLS_Region *rgn = &ins->regions[index];
+  DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
+
+  sample->low_freq = freq_table[rgn->header->RangeKey.usLow];
+  sample->high_freq = freq_table[rgn->header->RangeKey.usHigh];
+  sample->root_freq = freq_table[rgn->wsmp->usUnityNote];
+  sample->low_vel = rgn->header->RangeVelocity.usLow;
+  sample->high_vel = rgn->header->RangeVelocity.usHigh;
+
+  sample->modes = MODES_16BIT;
+  sample->sample_rate = wave->format->dwSamplesPerSec;
+  sample->data_length = wave->length / 2;
+  sample->data = (sample_t *)safe_malloc(wave->length);
+  memcpy(sample->data, wave->data, wave->length);
+  if (rgn->wsmp->cSampleLoops) {
+    sample->modes |= (MODES_LOOPING|MODES_SUSTAIN);
+    sample->loop_start = rgn->wsmp_loop->ulStart / 2;
+    sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
+  }
+  sample->volume = 1.0f;
+
+  if (sample->modes & MODES_SUSTAIN) {
+    int value;
+    double attack, hold, decay, release; int sustain;
+    CONNECTIONLIST *art = NULL;
+    CONNECTION *artList = NULL;
+
+    if (ins->art && ins->art->cConnections > 0 && ins->artList) {
+      art = ins->art;
+      artList = ins->artList;
+    } else {
+      art = rgn->art;
+      artList = rgn->artList;
+    }
+
+    value = load_connection(art->cConnections, artList, CONN_DST_EG1_ATTACKTIME);
+    attack = to_msec(value);
+    value = load_connection(art->cConnections, artList, CONN_DST_EG1_HOLDTIME);
+    hold = to_msec(value);
+    value = load_connection(art->cConnections, artList, CONN_DST_EG1_DECAYTIME);
+    decay = to_msec(value);
+    value = load_connection(art->cConnections, artList, CONN_DST_EG1_RELEASETIME);
+    release = to_msec(value);
+    value = load_connection(art->cConnections, artList, CONN_DST_EG1_SUSTAINLEVEL);
+    sustain = (int)((1.0 - to_normalized_percent(value)) * 250.0);
+    value = load_connection(art->cConnections, artList, CONN_DST_PAN);
+    sample->panning = (int)((0.5 + to_normalized_percent(value)) * 127.0);
+
+/*
+printf("%d, Rate=%d LV=%d HV=%d Low=%d Hi=%d Root=%d Pan=%d Attack=%f Hold=%f Sustain=%d Decay=%f Release=%f\n", index, sample->sample_rate, rgn->header->RangeVelocity.usLow, rgn->header->RangeVelocity.usHigh, sample->low_freq, sample->high_freq, sample->root_freq, sample->panning, attack, hold, sustain, decay, release);
+*/
+
+    sample->envelope_offset[0] = to_offset(255);
+    sample->envelope_rate[0] = calc_rate(song, 255, sample->sample_rate, attack);
+
+    sample->envelope_offset[1] = to_offset(250);
+    sample->envelope_rate[1] = calc_rate(song, 5, sample->sample_rate, hold);
+
+    sample->envelope_offset[2] = to_offset(sustain);
+    sample->envelope_rate[2] = calc_rate(song, 255 - sustain, sample->sample_rate, decay);
+
+    sample->envelope_offset[3] = to_offset(0);
+    sample->envelope_rate[3] = calc_rate(song, 5 + sustain, sample->sample_rate, release);
+
+    sample->envelope_offset[4] = to_offset(0);
+    sample->envelope_rate[4] = to_offset(1);
+
+    sample->envelope_offset[5] = to_offset(0);
+    sample->envelope_rate[5] = to_offset(1);
+
+    sample->modes |= MODES_ENVELOPE;
+  }
+
+  sample->data_length <<= FRACTION_BITS;
+  sample->loop_start <<= FRACTION_BITS;
+  sample->loop_end <<= FRACTION_BITS;
+}
+
+Instrument *load_instrument_dls(MidiSong *song, int drum, int bank, int instrument)
+{
+  Instrument *inst;
+  Uint32 i;
+  DLS_Instrument *dls_ins;
+
+  if (!song->patches)
+   return(NULL);
+
+  drum = drum ? 0x80000000 : 0;
+  for (i = 0; i < song->patches->cInstruments; ++i) {
+    dls_ins = &song->patches->instruments[i];
+    if ((dls_ins->header->Locale.ulBank & 0x80000000) == drum &&
+        ((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == bank &&
+        dls_ins->header->Locale.ulInstrument == instrument)
+      break;
+  }
+  if (i == song->patches->cInstruments && !bank) {
+    for (i = 0; i < song->patches->cInstruments; ++i) {
+      dls_ins = &song->patches->instruments[i];
+      if ((dls_ins->header->Locale.ulBank & 0x80000000) == drum &&
+          dls_ins->header->Locale.ulInstrument == instrument)
+        break;
+    }
+  }
+  if (i == song->patches->cInstruments) {
+    SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
+    return(NULL);
+  }
+
+  inst = (Instrument *)safe_malloc(sizeof(*inst));
+  inst->samples = dls_ins->header->cRegions;
+  inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(*inst->sample));
+  memset(inst->sample, 0, inst->samples * sizeof(*inst->sample));
+/*
+printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples);
+*/
+  for (i = 0; i < dls_ins->header->cRegions; ++i) {
+    load_region_dls(song, &inst->sample[i], dls_ins, i);
+  }
+  return(inst);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/timidity/instrum_dls.h	Fri Sep 26 20:51:58 2003 +0000
@@ -0,0 +1,24 @@
+/*
+
+    TiMidity -- Experimental MIDI to WAVE converter
+    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   instrum.h
+
+   */
+
+extern Instrument *load_instrument_dls(MidiSong *song, int drum, int bank, int instrument);
--- a/decoders/timidity/playmidi.c	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/playmidi.c	Fri Sep 26 20:51:58 2003 +0000
@@ -79,7 +79,7 @@
   reset_voices(song);
 }
 
-static void select_sample(MidiSong *song, int v, Instrument *ip)
+static void select_sample(MidiSong *song, int v, Instrument *ip, int vel)
 {
   Sint32 f, cdiff, diff;
   int s,i;
@@ -97,7 +97,8 @@
   f=song->voice[v].orig_frequency;
   for (i=0; i<s; i++)
     {
-      if (sp->low_freq <= f && sp->high_freq >= f)
+      if (sp->low_vel <= vel && sp->high_vel >= vel &&
+          sp->low_freq <= f && sp->high_freq >= f)
 	{
 	  song->voice[v].sample=sp;
 	  return;
@@ -282,7 +283,7 @@
 	song->voice[i].orig_frequency = freq_table[(int)(ip->sample->note_to_use)];
       else
 	song->voice[i].orig_frequency = freq_table[e->a & 0x7F];
-      select_sample(song, i, ip);
+      select_sample(song, i, ip, e->b);
     }
 
   song->voice[i].status = VOICE_ON;
--- a/decoders/timidity/timidity.c	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/timidity.c	Fri Sep 26 20:51:58 2003 +0000
@@ -398,6 +398,22 @@
   return 0;
 }
 
+int Timidity_Init_NoConfig()
+{
+  /* Allocate memory for the standard tonebank and drumset */
+  master_tonebank[0] = safe_malloc(sizeof(ToneBank));
+  memset(master_tonebank[0], 0, sizeof(ToneBank));
+  master_tonebank[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
+  memset(master_tonebank[0]->tone, 0, 128 * sizeof(ToneBankElement));
+
+  master_drumset[0] = safe_malloc(sizeof(ToneBank));
+  memset(master_drumset[0], 0, sizeof(ToneBank));
+  master_drumset[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
+  memset(master_drumset[0]->tone, 0, 128 * sizeof(ToneBankElement));
+
+  return 0;
+}
+
 int Timidity_Init()
 {
   /* !!! FIXME: This may be ugly, but slightly less so than requiring the
@@ -414,21 +430,12 @@
   add_to_pathlist("/etc");
 #endif
 
-  /* Allocate memory for the standard tonebank and drumset */
-  master_tonebank[0] = safe_malloc(sizeof(ToneBank));
-  memset(master_tonebank[0], 0, sizeof(ToneBank));
-  master_tonebank[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
-  memset(master_tonebank[0]->tone, 0, 128 * sizeof(ToneBankElement));
-
-  master_drumset[0] = safe_malloc(sizeof(ToneBank));
-  memset(master_drumset[0], 0, sizeof(ToneBank));
-  master_drumset[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
-  memset(master_drumset[0]->tone, 0, 128 * sizeof(ToneBankElement));
+  Timidity_Init_NoConfig();
 
   return read_config_file(CONFIG_FILE);
 }
 
-MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio)
+MidiSong *Timidity_LoadDLSSong(SDL_RWops *rw, DLS_Patches *patches, SDL_AudioSpec *audio)
 {
   MidiSong *song;
   Sint32 events;
@@ -440,6 +447,7 @@
   /* Allocate memory for the song */
   song = (MidiSong *)safe_malloc(sizeof(*song));
   memset(song, 0, sizeof(*song));
+  song->patches = patches;
 
   for (i = 0; i < 128; i++)
   {
@@ -529,6 +537,11 @@
   return(song);
 }
 
+MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio)
+{
+  return Timidity_LoadDLSSong(rw, NULL, audio);
+}
+
 void Timidity_FreeSong(MidiSong *song)
 {
   int i;
--- a/decoders/timidity/timidity.h	Sat Sep 13 20:46:09 2003 +0000
+++ b/decoders/timidity/timidity.h	Fri Sep 26 20:51:58 2003 +0000
@@ -19,6 +19,12 @@
 
 */
 
+#ifndef TIMIDITY_H
+#define TIMIDITY_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef Sint16 sample_t;
 typedef Sint32 final_volume_t;
 
@@ -30,7 +36,7 @@
 typedef struct {
   Sint32
     loop_start, loop_end, data_length,
-    sample_rate, low_freq, high_freq, root_freq;
+    sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
   Sint32
     envelope_rate[6], envelope_offset[6];
   float
@@ -107,6 +113,9 @@
     void *next;
 } MidiEventList;
 
+struct _DLS_Data;
+typedef struct _DLS_Data DLS_Patches;
+
 typedef struct {
     int playing;
     SDL_RWops *rw;
@@ -114,6 +123,7 @@
     Sint32 encoding;
     float master_volume;
     Sint32 amplification;
+    DLS_Patches *patches;
     ToneBank *tonebank[128];
     ToneBank *drumset[128];
     Instrument *default_instrument;
@@ -148,10 +158,19 @@
 /* Some of these are not defined in timidity.c but are here for convenience */
 
 extern int Timidity_Init(void);
+extern int Timidity_Init_NoConfig(void);
 extern void Timidity_SetVolume(MidiSong *song, int volume);
 extern int Timidity_PlaySome(MidiSong *song, void *stream, Sint32 len);
+extern DLS_Patches *Timidity_LoadDLS(SDL_RWops *rw);
+extern void Timidity_FreeDLS(DLS_Patches *patches);
+extern MidiSong *Timidity_LoadDLSSong(SDL_RWops *rw, DLS_Patches *patches, SDL_AudioSpec *audio);
 extern MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio);
 extern void Timidity_Start(MidiSong *song);
 extern void Timidity_Seek(MidiSong *song, Uint32 ms);
 extern void Timidity_FreeSong(MidiSong *song);
 extern void Timidity_Exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* TIMIDITY_H */