Added mikmod library, also added it to SDL_mixer
This commit is contained in:
@@ -1 +1 @@
|
||||
REminiscence
|
||||
pachi
|
||||
130
project/jni/mikmod/AUTHORS
Normal file
130
project/jni/mikmod/AUTHORS
Normal file
@@ -0,0 +1,130 @@
|
||||
libmikmod main authors
|
||||
----------------------
|
||||
|
||||
* Jean-Paul Mikkers (MikMak) <mikmak@via.nl>
|
||||
wrote MikMod and maintained it until version 3.
|
||||
* Jake Stine (Air Richter) <dracoirs@epix.net>
|
||||
[email doesn't work anymore...]
|
||||
made decisive contributions to the code (esp. IT support) and
|
||||
maintained MikMod version 3 until it was discontinued. He still works
|
||||
on the WinAmp module plugin, roughly based on MikMod.
|
||||
* Miod Vallat <miod@mikmod.org>
|
||||
maintainer MikMod'Unix (since version 3.0.4), made
|
||||
an audit of the code resulting in many bugs fixed.
|
||||
* Raphael Assenat <raph@raphnet.net>
|
||||
Revived the project after many years of inactivity, in 2004. Is
|
||||
the current maintainer.
|
||||
|
||||
Previous Unix maintainers
|
||||
-------------------------
|
||||
|
||||
* Steve McIntyre <steven@chiark.greenend.org.uk>
|
||||
maintained MikMod'Unix version 2. Used to maintain the Debian package
|
||||
for MikMod.
|
||||
* Peter Amstutz <tetron@student.umass.edu>
|
||||
maintained MikMod'Unix version 3 up to version 3.0.3.
|
||||
|
||||
General contributors
|
||||
--------------------
|
||||
|
||||
* Arne de Bruijn <arne@knoware.nl>
|
||||
wrote the compressed IT sample support.
|
||||
* Shlomi Fish <shlomif@vipe.technion.ac.il>
|
||||
wrote the Java port, bug fixes.
|
||||
* Juan Linietsky <coding@reduz.com.ar>
|
||||
overall bug fixes.
|
||||
* Claudio Matsuoka <claudio@helllabs.org>
|
||||
wrote the STX loader and submitted bug fixes.
|
||||
* Sebastiaan A. Megens <samegens@xs4all.nl>
|
||||
fixed various bugs (memory leaks, endianness issues, etc).
|
||||
* ``UFO'' <ufo303@poczta.onet.pl>
|
||||
wrote the OKT loader.
|
||||
* Kev Vance <kvance@zeux.org>
|
||||
wrote the GDM loader.
|
||||
|
||||
* Paul Fisher made decisive contributions and improvements.
|
||||
* Alexander Kerkhove fixed an ULT panning effect bug.
|
||||
* ``Kodiak'' helped on the interfaces of libmikmod.
|
||||
* Sylvain Marchand make MikMod more portable and GCC compilable.
|
||||
|
||||
|
||||
Contributors on the Unix side
|
||||
-----------------------------
|
||||
|
||||
* Axel "awe" Wefers <awe@fruitz-of-dojo.de>
|
||||
wrote the OSX CoreAudio driver, the AIFF driver and
|
||||
updated the Mac Audio Carbon driver
|
||||
* Douglas Carmichael <dcarmich@mcs.com>
|
||||
ported MikMod to FreeBSD.
|
||||
* Chris Conn <cconn@tohs.abacom.com>
|
||||
wrote the OSS driver.
|
||||
* Roine Gustaffson <e93_rog@e.kth.se>
|
||||
wrote the Digital AudioFile driver.
|
||||
* Stephan Kanthak <kanthak@informatik.rwth-aachen.de>
|
||||
wrote the SGI driver.
|
||||
* Lutz Vieweg <lkv@mania.robin.de>
|
||||
wrote the AIX and HP-UX drivers.
|
||||
* Valtteri Vuorikoski <vuori@sci.fi>
|
||||
wrote the Sun driver.
|
||||
* Andy Lo A Foe <andy@alsa-project.org>
|
||||
wrote the Ultra driver (for the Gravis Ultrasound sound card).
|
||||
* C Ray C <crayc@pyro.net>
|
||||
updated the Ultra driver to work with libmikmod 3.
|
||||
* ``MenTaLguY'' <mental@kludge.org>
|
||||
autoconfized the Unix libmikmod distribution.
|
||||
* Tobias Gloth <gloth@geomagic.com>
|
||||
created the new I/O interface, made the code MT-safe and submitted bug fixes.
|
||||
* Simon Hosie <gumboot@clear.net.nz>
|
||||
wrote the piped output driver, and submitted speed optimizations and bugfixes
|
||||
for the software mixer.
|
||||
* Gerd Rausch <gerd@alf.gun.de>
|
||||
wrote the sam9407 driver.
|
||||
* Joseph Carter <knghtbrd@debian.org>
|
||||
maintains the Debian package for MikMod and libmikmod, submitted
|
||||
bugfixes.
|
||||
|
||||
Contributors on the Windows side
|
||||
--------------------------------
|
||||
|
||||
* Brian McKinney <Brian.McKinney@colorado.edu>
|
||||
created the DirectSound driver.
|
||||
* Bjornar Henden <bhenden@online.no>
|
||||
created the Multimedia API windows driver.
|
||||
|
||||
Contributors on the Dos side
|
||||
----------------------------
|
||||
|
||||
Their code isn't there anymore, but they contributed to the success of
|
||||
libmikmod...
|
||||
|
||||
* Jean-Philippe Ajirent wrote the EMS memory routines.
|
||||
* Peter Breitling ported MikMod to DJGPP.
|
||||
* Arnout Cosman wrote the PAS driver.
|
||||
* Mario Koeppen wrote the WSS driver.
|
||||
* Mike Leibow wrote the GUS driver.
|
||||
* Jeremy McDonald wrote a fast assembly-language mixer.
|
||||
* Steffen Rusitschka and Vince Vu wrote the AWE driver.
|
||||
|
||||
Contributors on the Macintosh side
|
||||
----------------------------------
|
||||
|
||||
* Anders Bjoerklund <afb@algonet.se>
|
||||
ported libmikmod to the Macintosh.
|
||||
|
||||
Contributors on the OS/2 side
|
||||
-----------------------------
|
||||
|
||||
* Stefan Tibus <Stefan_Tibus@ThePentagon.com>
|
||||
ported libmikmod to OS/2.
|
||||
* Andrew Zabolotny <bit@eltech.ru>
|
||||
improved the existing OS/2 drivers.
|
||||
|
||||
Contributors on the BeOS side
|
||||
-----------------------------
|
||||
|
||||
* Thomas Neumann <tneumann@polycode.dk>
|
||||
integrated libmikmod into his BeOS APlayer, and contributed many bug fixes.
|
||||
|
||||
--
|
||||
If your name is missing, don't hesitate to remind me at
|
||||
<mikmod@mikmod.raphnet.net>
|
||||
24
project/jni/mikmod/Android.mk
Normal file
24
project/jni/mikmod/Android.mk
Normal file
@@ -0,0 +1,24 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := mikmod
|
||||
|
||||
APP_SUBDIRS := $(patsubst $(LOCAL_PATH)/%, %, $(shell find $(LOCAL_PATH) -type d))
|
||||
|
||||
LOCAL_CFLAGS := -O3 $(foreach D, $(APP_SUBDIRS), -I$(LOCAL_PATH)/$(D)) \
|
||||
-I$(LOCAL_PATH)/include -I$(LOCAL_PATH) -DHAVE_CONFIG_H
|
||||
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(foreach F, $(APP_SUBDIRS), $(addprefix $(F)/,$(notdir $(wildcard $(LOCAL_PATH)/$(F)/*.cpp))))
|
||||
LOCAL_SRC_FILES += $(foreach F, $(APP_SUBDIRS), $(addprefix $(F)/,$(notdir $(wildcard $(LOCAL_PATH)/$(F)/*.c))))
|
||||
|
||||
LOCAL_SHARED_LIBRARIES :=
|
||||
|
||||
LOCAL_STATIC_LIBRARIES :=
|
||||
|
||||
LOCAL_LDLIBS :=
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
504
project/jni/mikmod/COPYING.LESSER
Normal file
504
project/jni/mikmod/COPYING.LESSER
Normal file
@@ -0,0 +1,504 @@
|
||||
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 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 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.
|
||||
|
||||
Another 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 insure 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 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
|
||||
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!
|
||||
|
||||
|
||||
482
project/jni/mikmod/COPYING.LIB
Normal file
482
project/jni/mikmod/COPYING.LIB
Normal file
@@ -0,0 +1,482 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
183
project/jni/mikmod/INSTALL
Normal file
183
project/jni/mikmod/INSTALL
Normal file
@@ -0,0 +1,183 @@
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a time
|
||||
in the source code directory. After you have installed the package for
|
||||
one architecture, use `make distclean' before reconfiguring for another
|
||||
architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
|
||||
590
project/jni/mikmod/NEWS
Normal file
590
project/jni/mikmod/NEWS
Normal file
@@ -0,0 +1,590 @@
|
||||
Summary of changes between libmikmod 3.1.11 and libmikmod 3.2.0 ():
|
||||
==========================================================================
|
||||
|
||||
THANKS
|
||||
|
||||
- Axel "awe" Wefers <awe@fruitz-of-dojo.de>,
|
||||
for creating the CoreAudio driver, the new
|
||||
AIFF driver and updating the Carbon driver.
|
||||
- Frank Loemker, for sending me his collection of patches
|
||||
for libmikmod.
|
||||
- Anders F Björklund <afb@algonet.se>, for updates, fixes and tests on
|
||||
Mac Platforms.
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- MacOS X CoreAudio driver
|
||||
- Carbon support
|
||||
- Loader for ASYLUM Music Format v1.0 (.amf) modules,
|
||||
as used in crusader games.
|
||||
- New function 'Player_QueryVoices' added, which is used to return
|
||||
dynamic channel information about the module player. (Mikmod 3.2.2 uses
|
||||
it for it's dynamic panels).
|
||||
- Mixing with floating point output. The MacOSX CoreAudio driver uses it.
|
||||
Thanks goes to Anders F Björklund for implementing this.
|
||||
- AIFF disk writer driver.
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- The sun driver now compiles on solaris (Thanks to Nicolas Gros d'Aillon
|
||||
for sending me Jonathan Perkin's fix)
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.10 and libmikmod 3.1.11 (Thiers):
|
||||
==========================================================================
|
||||
|
||||
libmikmod 3.1.11 was released on 01/21/2004.
|
||||
|
||||
This is a small maintenance release. I know there are not many changes,
|
||||
but since it has been a very long time since the last one, and meanwhile
|
||||
libmikmod changed maintaner, I think it is justified.
|
||||
|
||||
THANKS
|
||||
|
||||
- Ingo Saitz, the maintainer of the mikmod packages for debian, for
|
||||
bugfixes.
|
||||
- Frank Loemker, for the lcc-win32 stuff and fixes for the direct sound
|
||||
driver.
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- Playback problems in MODs of length >128. This fixes the file beatwave.mod. Thanks
|
||||
to Emmanuel Coirier for pointing this out.
|
||||
- Applied debian patches:
|
||||
- Fix for broken volume fadeouts of IT instruments
|
||||
- Fixed configure test for pthread
|
||||
- devfs support for Linux OSS
|
||||
|
||||
- Makefile for lcc-win32. To compile libmikmod with lcc-win32 a rather new
|
||||
version is needed. I currently use version 3.7 compiled on Jan 20 2002.
|
||||
A version half a year old did not work.
|
||||
To compile
|
||||
- check that you have the lcc bin directory in the PATH
|
||||
(and no other compiler bin dirs),
|
||||
- change to libmikmod-3.1.11/win32,
|
||||
- check Makefile.lcc for any needed changes, and
|
||||
- use make -f Makefile.lcc.
|
||||
|
||||
- Different fixes for the direct sound driver:
|
||||
- Pausing did only work for half of the buffer.
|
||||
- Restarting the player did not work as the output thread was removed
|
||||
in DS_PlayStop().
|
||||
- Removed busy waiting for end of thread.
|
||||
- Sound output is started immediately on the first call to DS_Update()
|
||||
to be consistent with other non threaded drivers.
|
||||
- Different small clean ups.
|
||||
|
||||
- In MikMod_Reset() the raw output driver driver did not use the
|
||||
filename set via the cmdline.
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.9 and libmikmod 3.1.10 (Arlanc):
|
||||
=========================================================================
|
||||
|
||||
libmikmod 3.1.10 was released on 01/24/2002.
|
||||
|
||||
This version is yet another bugfix release. I have more contributions coming,
|
||||
especially a native MacOS X driver, that will not be present in 3.1.10 but
|
||||
will be in 3.1.11.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
- Most of the bugs mentioned below have been squished by ``UFO'',
|
||||
Holger Jakob, Thomas Neumann, Mark Page and Juan Linietsky.
|
||||
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- Systematic coredumps on library initialization and calls to
|
||||
MikMod_InfoDriver have been eliminated. Sorry, and thanks to Shlomi
|
||||
Fish for the best fix.
|
||||
|
||||
- The fix for spurious effect memory for portamentos in MOD files shouldn't
|
||||
have been applied to the ``porta to note'' (effect 3) effect. Fixed in this
|
||||
release. In the process, the aforementioned fix was perfected, as it
|
||||
broke a few modules by accident.
|
||||
|
||||
- IT Panbrello effect with random wave did not work.
|
||||
|
||||
- IT Tempo slide (T0x, T1x) was not updated accurately, and the effect memory
|
||||
was not implemented. The only tempo slide command which worked accurately
|
||||
was T10, which is a no-op (-:
|
||||
|
||||
- IT effect SC0 (cut note with no delay) is now correctly interpreted as SC1.
|
||||
|
||||
- XM effect 6 (porta + volume slide) didn't have memory.
|
||||
|
||||
- ProTracker effect F (change speed or bpm) should now be correctly handled
|
||||
when its value is 32, depending on the module type (some formats will use
|
||||
it as a speed value, others as a bpm value).
|
||||
|
||||
- XM playback stopped when reaching pattern 255 in the order list.
|
||||
|
||||
- Corrupted envelopes in XM instruments are detected and some repair is
|
||||
attempted.
|
||||
|
||||
- Some valid AMF, IMF and IT modules refused to load.
|
||||
|
||||
- Fine volume slide effects in volume column of IT modules, when using the
|
||||
effect memory (i.e. A0 and B0) were misinterpreted as AF and BF, thus
|
||||
causing unwanted large slides.
|
||||
|
||||
- Portamento to note effect in volume column of IT modules was not rendered
|
||||
correctly.
|
||||
|
||||
- S3M files marked as created by ScreamTracker will honour the limit of 64000
|
||||
bytes (not 64KB!) for sample length and sample offset effect position.
|
||||
|
||||
- Loops in instrument envelopes were processed one tick too fast.
|
||||
|
||||
- In-song message in FAR modules were not displayed correctly.
|
||||
|
||||
- ProTracker effect E9 (Retrig) was not played correctly.
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- Modules which are not panning-aware (not using any panning effects and
|
||||
with the tracker's default panning) use a recentered panning, so as to
|
||||
sound better with headphones. Suggested by Urpo Lankinen.
|
||||
|
||||
- Retrigger and panning effects are now recognized in FAR modules.
|
||||
|
||||
- All arpeggio effects are now played in OKT modules.
|
||||
|
||||
- FLT8 modules (8 channel StarTrekker) are now recognized and played.
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- The Windows DirectSound driver has been improved and will use less
|
||||
resources during playback.
|
||||
|
||||
- The native audio driver for NetBSD and OpenBSD should work better with
|
||||
recent versions of these systems, as well as with old sound cards such
|
||||
as the SoundBlaster Pro.
|
||||
|
||||
- Mac OS X is supported, although no native sound driver is available for
|
||||
it yet, thanks to Juha Kaunisto.
|
||||
|
||||
- Dynamically loading drivers is now supported on HP-PA systems running
|
||||
under HP-UX, as well on systems using the a.out binary file format.
|
||||
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.8 and libmikmod 3.1.9 (Vorey):
|
||||
=======================================================================
|
||||
|
||||
libmikmod 3.1.9 was released on 02/14/2000.
|
||||
|
||||
This version is a bugfix release, and was primarily considered as a public
|
||||
patch for 3.1.8 (namely, version 3.1.8-a). However, due to the very important
|
||||
bug fix in XM playback, among other things, it's worth being 3.1.9...
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
- Many thanks to ``UFO'', Thomas Neumann, James Kehl and Vito Caputo for their
|
||||
help, code and feedback.
|
||||
|
||||
- Special thanks to Gerd Rausch, for writing both the Linux sam9407 driver and
|
||||
the associated Mikmod driver. Nice work !
|
||||
|
||||
- Thanks to Bastien Nocera for letting me do some tests under Linux/PPC.
|
||||
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- Envelopes weren't loaded correctly for IMF and XM modules. In the average
|
||||
case, the first envelope point was correct, the remaining half points were
|
||||
bogus, and the other half completely random. This fix is definitely worth
|
||||
the upgrade.
|
||||
|
||||
- In MOD files, effect 0xc (set channel volume) with effect parameter 0xff was
|
||||
misplayed as a note cut.
|
||||
|
||||
- In MOD files too, effects 0x1, 0x2 and 0x3 (portamentos) with effect
|
||||
parameter 0x00 were using the command memory, but these commands do not have
|
||||
effect memory for MOD files.
|
||||
|
||||
- The Wuzamod check for STM modules wasn't present in 3.1.8, despite what the
|
||||
release notes said )-:
|
||||
|
||||
- Enabling the envelope (with an effect) for a sample with no associated
|
||||
envelope would cause immediate coredumps. Now fixed.
|
||||
|
||||
- Panning was ignored in GDM modules.
|
||||
|
||||
- Sample rate was incorrect for STM and STX modules.
|
||||
|
||||
- Arpeggio memory (for IT modules) was ignored.
|
||||
|
||||
- Tempo slide for IT modules was not processed correctly.
|
||||
|
||||
- Toggling surround sound didn't have effect until the driver was reset.
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- New loader for Amiga Oktalyzer (.OKT) modules.
|
||||
|
||||
- UNI loader recognizes recent APlayer modules (.APUN format level 0x104).
|
||||
|
||||
- Due to popular request, the function Player_LoadTitleFP() has been added to
|
||||
the library.
|
||||
|
||||
- Under Unix systems, make targets "check" and "uninstall" have been added.
|
||||
However, due to a bug in automake, "make uninstall" will only work correctly
|
||||
with the next release of automake (or the current CVS tree).
|
||||
|
||||
- New output driver for sam9407-based soundcards under Linux, featuring
|
||||
hardware playback.
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- Support for the latest Linux Ultra driver development versions (2.99) has
|
||||
been added. Also, a few bugs in this driver have been fixed.
|
||||
|
||||
- The DirectSound driver (win32) shipped with the previous release didn't
|
||||
compile. It should now - at least things are better !
|
||||
|
||||
- The OSS driver from 3.1.8 didn't work very well with some versions of the
|
||||
Linux kernel, as well as under Linux/PPC. The problems should be gone now.
|
||||
Also, the OSS driver now handles multi-soundcard configurations.
|
||||
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.7 and libmikmod 3.1.8 (Tence):
|
||||
=======================================================================
|
||||
|
||||
libmikmod 3.1.8 was released on 10/25/1999.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
- Many thanks (in no particular order) to Frank Loemker, Bjornar Henden, Joshua
|
||||
Shagam, Vito Caputo, Thomas Neumann, Zach Metzinger, and Kevin Langman for
|
||||
their help, code and feedback.
|
||||
|
||||
- Special thanks to Andrew Zabolotny for his huge work on the OS/2 drivers.
|
||||
The rest of your code is not lost, it will go into 3.2...
|
||||
|
||||
|
||||
BUGFIXES (more details can be found in file ``PROBLEMS'')
|
||||
|
||||
- IT global volume slide effect was played too fast.
|
||||
|
||||
- IT effect S6x (pattern delay for x ticks) was misunderstood as SEx (pattern
|
||||
delay for x rows).
|
||||
|
||||
- Finetune effect was not handled correctly for some XM modules.
|
||||
|
||||
- Software mixer incorrectly produced extra clicks in interpolated mode (fix by
|
||||
Frank Loemker).
|
||||
|
||||
- Under Unix systems, the piped output driver (drv_pipe), as well as the output
|
||||
to file drivers (drv_raw, drv_wav) had security issues if the libmikmod
|
||||
application is setuid root.
|
||||
|
||||
- Trying to read data from a file, with the data not located at offset 0,
|
||||
didn't work correctly since 3.1.5.
|
||||
|
||||
- Almost any text file beginning with "if" was considered as a valid module by
|
||||
Player_LoadTitle(), yet hopefully rejected when trying to load it.
|
||||
|
||||
- AMF effect 4 and variants lacked memory.
|
||||
|
||||
- IT modules featuring patterns with less than 32 rows could not be loaded.
|
||||
|
||||
- Some samples and effects in APlayer converted modules (.apun) were not played
|
||||
correctly.
|
||||
|
||||
- Linefeeds in the song message in IT modules weren't loaded correctly.
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- IMF effect XE (ignore envelope) implemented.
|
||||
|
||||
- Support for uLaw output with the OSS driver, for Linux/sparc.
|
||||
|
||||
- Started to modularize semaphore usage when possible. The Player_LoadTitle()
|
||||
function can be used while a module is playing without causing a short pause
|
||||
in playback.
|
||||
|
||||
- STM modules with the Wuzamod signature can now be loaded.
|
||||
|
||||
- More ``slightly corrupted'' XM modules can be loaded.
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- libmikmod 3.1.7 didn't compile out of the box under IRIX (sorry !)
|
||||
|
||||
- The EsounD driver didn't compile under Solaris
|
||||
|
||||
- Solaris driver forced playback to either headphone or speaker, instead of
|
||||
using the current output setting as default. This is now fixed.
|
||||
|
||||
- Under SunOS 4, libmikmod should compile with the non-ansi C compiler bundled
|
||||
by default.
|
||||
|
||||
- The ALSA driver now works with ALSA 0.4.
|
||||
|
||||
- The OSS driver should now work with Linux/ppc.
|
||||
|
||||
- Under OS/2, the MMPM/2 and DART driver have been almost rewritten by Andrew
|
||||
Zabolotny and work much better. And they are now somewhat configurable, too.
|
||||
|
||||
- libmikmod 3.1.8 should work as a DLL under win32 environments. And the
|
||||
non-directX driver is now registered in MikMod_RegisterAllDrivers().
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.6 and libmikmod 3.1.7 (Sauxillanges):
|
||||
==============================================================================
|
||||
|
||||
libmikmod 3.1.7 was released on 06/28/1999.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
- Anders Bjoerklund did a terrific job of creating a Macintosh driver !
|
||||
I'm proud to add the MacOS to the list of supported systems.
|
||||
|
||||
- Bjornar Henden provided a non-directX driver for Windows NT users. This
|
||||
makes libmikmod more portable than ever. Thanks a lot !
|
||||
|
||||
- Simon Hosie contributed speed optimizations and bug fixes to the software
|
||||
mixer. Thanks for your work !
|
||||
|
||||
- Timo Taipalus pointed out several severe problems and helped me to get rid
|
||||
of them. Thanks for your efforts !
|
||||
|
||||
|
||||
BUGFIXES (more details can be found in file ``PROBLEMS'')
|
||||
|
||||
- Very long samples were truncated when played with the normal software
|
||||
mixer.
|
||||
|
||||
- Invalid notes using non-existent instruments caused the current note to
|
||||
be retrigged instead of being ignored.
|
||||
|
||||
- Porta to note effects did not restart the sample envelopes.
|
||||
|
||||
- Note cut with non empty volume column on the same row resulted in the note
|
||||
cut being ignored.
|
||||
|
||||
- Disabling/enabling envelopes had no effect.
|
||||
|
||||
- 15 instrument modules embedding a ``Music Channel BBS'' ad were rejected.
|
||||
|
||||
- Huge (>64Kb) sample offsets were ignored with the hiqh quality mixer.
|
||||
|
||||
- Delay note effect was incorrectly converted to pattern jump, and porta to
|
||||
note was incorrectly converted to tremor, for GDM modules.
|
||||
|
||||
- Dual effect Lxx in S3M and IT was misconverted to L00 (this bug was
|
||||
introduced in 3.1.5-beta2, thanks to Timo Taipalus for noticing it)
|
||||
|
||||
- Pitch envelope was not played accurately (IT).
|
||||
|
||||
- XM modules in format 1.03 couldn't be loaded.
|
||||
|
||||
- XM modules with the tracker name empty made the library coredump on some
|
||||
platforms.
|
||||
|
||||
- Set finetune effect (E5x) wasn't handled correctly for XM modules.
|
||||
|
||||
- Fine slides (X1x,X2x) didn't play correctly for XM modules (thanks to Frank
|
||||
Loemker for reporting it).
|
||||
|
||||
- If the MikMod_InitThreads() function was called more than once, the library
|
||||
did not behave correctly.
|
||||
|
||||
- Sample loops were not computed correctly for Oktalyzer modules.
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- Modules can be played with a speed shift (suggested by Roope Anttinnen).
|
||||
|
||||
- MikMod_Init() and MikMod_Reset() have been extended to pass specific
|
||||
parameters to the drivers. This makes libmikmod 3.1.7 incompatible with the
|
||||
previous versions, but updated libmikmod-based players will be released soon.
|
||||
The shared library version has increased (now 2.0). This number scheme is
|
||||
going to be as crazy as ncurses' one...
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- It was not possible to create a multithreaded library on FreeBSD (fix by
|
||||
Roope Anttinnen).
|
||||
|
||||
- HP-UX driver used to reset mixer settings at initialization.
|
||||
|
||||
- Added MacOS support, thanks to Anders Bjoerklund.
|
||||
|
||||
- Solaris driver now works on Solaris/Intel edition.
|
||||
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.5 and libmikmod 3.1.6 (Romegier):
|
||||
==========================================================================
|
||||
|
||||
libmikmod 3.1.6 was released on 03/24/1999.
|
||||
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- When the library was built thread-safe, calls to Player_SetPosition
|
||||
resulted in a deadlock.
|
||||
|
||||
- The OSS driver was too strict and didn't allow OSS to select a different
|
||||
playback frequency.
|
||||
|
||||
- A volume bug has been removed from the module player (thanks to Thomas
|
||||
Neumann for the report).
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- Volume ramping has been ported from the high quality mixer to the regular
|
||||
mixer, and is enabled when interpolated mixing is requested. You should hear
|
||||
less clicks in interpolated mode from now ! (Suggested by Bjornar Henden)
|
||||
|
||||
- The UNI loader recognizes APlayer format 1.3 modules.
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- The NetBSD and OpenBSD driver should work with recent NetBSD and OpenBSD
|
||||
versions.
|
||||
|
||||
- Some Windows code has been merged. Feedback will be appreciated. Note that,
|
||||
as I don't have a windows development system (and no plan to have one in the
|
||||
near future), I can't test or debug the Windows part myself.
|
||||
|
||||
|
||||
|
||||
Summary of changes between libmikmod 3.1.2 and libmikmod 3.1.5 (Pradelles):
|
||||
===========================================================================
|
||||
|
||||
libmikmod 3.1.5 was released on 03/01/1999.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
- Many thanks to Lutz Roeder and Uwe Thoma, who send me the description of
|
||||
the Imago Orpheus file format (IMF), as well as some of Imago's code, which
|
||||
made the creation of the IMF loader a pure C exercise (-:
|
||||
|
||||
- Many thanks to Claudio Matsuoka, Tobias Gloth, C. Ray C. and Ben Collver for
|
||||
their contributions and bug reports.
|
||||
|
||||
- Also big thanks to Jan Havelka for his help in tracking and fixing bugs.
|
||||
|
||||
- I almost forgot to thank Cedric Hebert for pointing out the gcc 2.x
|
||||
optimization options bug !
|
||||
|
||||
- And as a last-minute add-on, Kev Vance submitted a GDM loader.
|
||||
|
||||
|
||||
BUGFIXES
|
||||
|
||||
- The OSS driver used much more memory than necessary without reason.
|
||||
|
||||
- Samples longer than 1 Mb were not played correctly. However, the fix now
|
||||
requires that your C compiler provides a 64 bit integer type. As a result,
|
||||
libmikmod will not compile anymore on AIX with old versions of xlC.
|
||||
|
||||
- Samples with ping pong loops could make the library segfault on some rare
|
||||
conditions. This bug was also present in MikIT and in the module plugin
|
||||
of winamp, which are also based on old MikMod 3 sources...
|
||||
|
||||
- The sample loaders will now load samples with extra information blocks in
|
||||
them, and has been made more robust.
|
||||
|
||||
- More checks to detect empty song messages.
|
||||
|
||||
- The song message loading routine was bugged and could make the library
|
||||
coredump.
|
||||
|
||||
- AMF modules in formats 1.0, 1.2 and 1.3 couldn't be loaded.
|
||||
|
||||
- MED loader now loads instrument names and song message if they exist.
|
||||
|
||||
- More check have been added to the 15 instrument MOD loader to prevent it
|
||||
from hanging on non-mod files ; let me know if you still experience
|
||||
problems with it.
|
||||
|
||||
- STM loader rejected STM created by MOD2STM ; the last pattern was never
|
||||
played ; also, in some STM modules the samples were not loaded correctly.
|
||||
|
||||
- XM modules in format 1.02 couldn't be loaded.
|
||||
|
||||
- Envelope sustain loops in XM modules were not processed correctly.
|
||||
|
||||
- Porta to note using the command memory used sometimes an incorrect value
|
||||
when playing AMF, IT, S3M and ULT modules.
|
||||
|
||||
- Volume slides for IT (Dxx) and XM (Axx) modules didn't continue in the
|
||||
background.
|
||||
|
||||
- Porta down effect in the volume column of IT modules was not played
|
||||
correctly.
|
||||
|
||||
- Problems occuring when compiling libmikmod when an older version of libmikmod
|
||||
is installed are now fixed.
|
||||
|
||||
|
||||
DOCUMENTATION FIXES
|
||||
|
||||
- The documentation incorrectly referred to PAN_MIDDLE instead of PAN_CENTER.
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
- On platforms that support POSIX.4 threads, the library is now thread-safe.
|
||||
|
||||
- Depending on your system's capabilities, ALSA and EsounD driver can now
|
||||
be dynamically loaded when a libmikmod application is run, so if you built
|
||||
your binary with the shared ALSA or EsounD libraries (which is the default),
|
||||
it will run on other systems lacking those libraries.
|
||||
|
||||
- New loaders for GDM (General Digital Music), IMF (Imago Orpheus) and STX
|
||||
(STMIK 0.2) modules.
|
||||
|
||||
- UNI loader is back, for those who need to play the ``Acid Tetris'' songs.
|
||||
|
||||
- S3M loader correctly identifies S3M modules created by Impulse Tracker
|
||||
an Imago Orpheus.
|
||||
|
||||
- IT effect T (slide tempo) is now implemented.
|
||||
|
||||
- The driver for the Linux Ultrasound project (the ancestor of ALSA) is back,
|
||||
too.
|
||||
|
||||
- The selection of the standard or high-quality software mixer is now made at
|
||||
runtime.
|
||||
|
||||
- New interfaces Voice_Get{Frequency,Panning,Volume} and
|
||||
Player_GetChannelPeriod (this one is for x11amp's MikMod plugin).
|
||||
|
||||
- Due to the addition of the new driver and loaders, library version has
|
||||
increased.
|
||||
|
||||
|
||||
PLATFORM SPECIFIC
|
||||
|
||||
- Compiling with gcc 2.x under Linux on x86 platforms performed aggressive
|
||||
optimizations which had nasty interferences with the channel volumes on
|
||||
some modules. Hopefully this is now fixed, so gcc users will get the same
|
||||
sound quality as egcs users.
|
||||
I apologize to everyone told me of this volume problem for the time it took
|
||||
me to figure out where it came from.
|
||||
|
||||
|
||||
Previous versions of libmikmod were bundled with the MikMod player ; refer to
|
||||
its ``NEWS'' file for older changes information.
|
||||
449
project/jni/mikmod/README
Normal file
449
project/jni/mikmod/README
Normal file
@@ -0,0 +1,449 @@
|
||||
Hello folks!
|
||||
|
||||
|
||||
This is libmikmod, version 3.2.0-beta1, a portable sound library for Unix
|
||||
and other systems. Check out the file 'NEWS' for more history information.
|
||||
|
||||
|
||||
>> BETA WARNING
|
||||
---------------
|
||||
|
||||
This is a *beta* version of libmikmod. Although it should work fine on
|
||||
almost all systems, there are likely a few last-minute errors or typos
|
||||
in the source, and some parts have not received enough hours of testing yet.
|
||||
|
||||
Also, please note that all features planned for the final 3.2.0 release are not
|
||||
available yet. Some structures or functions may change. This release is mainly
|
||||
intended to the libmikmod developers to share a common base for adding new
|
||||
features...
|
||||
|
||||
The library programming documentation (in docs/) is mostly up-to-date... It
|
||||
lacks the Player_QueryVoices documentation, though.
|
||||
|
||||
If you're not scared, then you can proceed and enjoy fewer bugs than in the
|
||||
previous version (-;
|
||||
|
||||
|
||||
>> BUILDING LIBMIKMOD
|
||||
---------------------
|
||||
|
||||
- If you're building libmikmod under MacOS, please refer to the 'README'
|
||||
file located in the 'macintosh' subdirectory.
|
||||
|
||||
- If you're building libmikmod under OS/2, please refer to the 'README'
|
||||
file located in the 'os2' subdirectory.
|
||||
|
||||
- If you're building libmikmod under Windows, please refer to the
|
||||
'README' file located in the 'win32' subdirectory.
|
||||
|
||||
- If you're building libmikmod under any other system which is not a
|
||||
Unix flavour, then be warned that this your platform is not supported
|
||||
and that libmikmod will probably not build out of the box; don't
|
||||
hesitate to drop me a note, and I'll see what I can do for this situation.
|
||||
|
||||
So you're on a good old Unix workstation, aren't you ?
|
||||
|
||||
You'll need an ANSI C compiler to build libmikmod. If your system does not
|
||||
come with an ANSI C compiler, you might want to try the GUN C compiler, gcc.
|
||||
If you're building on a 32 bit architecture, your compiler must provide a
|
||||
64 bit integer type (usually 'long long').
|
||||
|
||||
To prevent clobbering the sources, I recommend building libmikmod in an
|
||||
alternate directory, for example 'build':
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
In this directory, run libmikmod's configure script:
|
||||
|
||||
../configure
|
||||
|
||||
The configure script will attempt to guess correct values for various
|
||||
system-dependent variables used during the build process, and will
|
||||
create appropriate Makefiles for proper compilation.
|
||||
|
||||
If you're not familiar with configure scripts and their standard
|
||||
options, you can find more general information about them in the file
|
||||
INSTALL.
|
||||
|
||||
The default behaviour of the configure script is to create both a static
|
||||
and a shared library, with as many drivers as possible, which are
|
||||
dynamically loaded whenever possible. However, it can be given several
|
||||
options to tweak your configuration of libmikmod:
|
||||
|
||||
The --enable-af, --enable-alsa, --enable-esd, --enable-oss,
|
||||
--enable-sam9407 and --enable-ultra options will compile respectively
|
||||
the Digital AudioFile, Advanced Linux Sound Architecture (ALSA),
|
||||
Enlightened Sound Daemon, Open Sound System (OSS), sam9407 and Linux
|
||||
Ultrasound drivers.
|
||||
|
||||
Since the configure script will search for the appropriate include files
|
||||
and libraries, to compile as much drivers as possible, these options are
|
||||
mostly useful in their negative form:
|
||||
../configure --disable-esd
|
||||
will configure libmikmod without the Enlightened Sound Daemon driver,
|
||||
even if all the necessary files for compiling are present on the
|
||||
system.
|
||||
|
||||
The --enable-dl option enables the dynamic load of the alsa, esd and
|
||||
ultra drivers at runtime, if your systems support it. This option is
|
||||
enabled by default if the build system supports it, so it is more useful
|
||||
in its negative form:
|
||||
../configure --disable-dl
|
||||
will configure libmikmod without the dynamic loading facility.
|
||||
|
||||
The --enable-threads option enables the creation of a thread-safe
|
||||
libmikmod library, if your system provides POSIX threads. This option is
|
||||
enabled by default, so it is more useful in its negative form:
|
||||
../configure --disable-threads
|
||||
will configure for a non thread-safe version of libmikmod.
|
||||
|
||||
The --enable-shared and --enable-static options control whether a static
|
||||
library, a shared library or both should be built.
|
||||
|
||||
The --enable-debug option creates a debug version of libmikmod.
|
||||
|
||||
After you've successfully run configure, simply run
|
||||
|
||||
make
|
||||
|
||||
to get all things build. Then, run
|
||||
|
||||
make install
|
||||
|
||||
to have the library installed. Depending on where you choose to install
|
||||
it (using the --prefix= option to configure), you may need root
|
||||
privileges for this operation.
|
||||
|
||||
|
||||
>> DRIVER PARAMETERS
|
||||
--------------------
|
||||
|
||||
Until a good place to put this information is found, here is the list of
|
||||
parameters recognized by the drivers, as well as the driver alias list.
|
||||
When specifying multiple parameters, use a comma (,) to separate the
|
||||
different parameters, for example: somevalue=1,someothervalue=2
|
||||
|
||||
- AudioFile (alias "audiofile")
|
||||
machine= same syntax as the AUDIOFILE environment variable.
|
||||
|
||||
- AIX ("AIX") [AIX only]
|
||||
buffer= logarithmic size of the buffer, in the range 12-19. Default
|
||||
is 15.
|
||||
|
||||
- ALSA ("alsa") [Linux only]
|
||||
card= card number. Default is first pcm-capable card. Replaces the
|
||||
ALSA_CARD environment variable, which is now deprecated.
|
||||
pcm= pcm interface number. Default is first adequate interface.
|
||||
Replaces the ALSA_PCM environment variable, which is now
|
||||
deprecated.
|
||||
buffer= logarithmic fragment size, in the range 2-16. Default is 4.
|
||||
Replaces the MM_NUMFRAGS environment variable, which is now
|
||||
deprecated.
|
||||
|
||||
- DART ("dart") [OS/2 only]
|
||||
buffer= logarithmic fragment size, in the range 12-16. Default is
|
||||
computed to a bit more than 1/4" of playback.
|
||||
count= fragment count, in the range 2-8. Default is 2.
|
||||
device= waveaudio device number, in the range 0-8. Default is 0 (use
|
||||
default waveaudio device).
|
||||
|
||||
- DirectX ("ds") [Win32 only]
|
||||
buffer= logarithmic size of the buffer, in the range 12-19. Default
|
||||
is 16.
|
||||
globalfocus
|
||||
always play music, even if the application has not the
|
||||
focus. Required for full-screen applications.
|
||||
|
||||
- EsounD ("esd") [Unix only]
|
||||
machine= same syntax as the ESPEAKER environment variable.
|
||||
|
||||
- HP ("hp") [HP-UX only]
|
||||
buffer= logarithmic size of the buffer, in the range 12-19. Default
|
||||
is 15.
|
||||
headphone redirects the output to the headphone port.
|
||||
|
||||
- MacOS ("mac") [MacOS only]
|
||||
buffer= logarithmic size of the buffer, in the range 10-16. Default
|
||||
is 12.
|
||||
|
||||
- OS/2 MMPM ("os2") [OS/2 only]
|
||||
buffer= logarithmic size of the buffer, in the range 12-16. Default
|
||||
is computed to a bit more than 1/4" of playback.
|
||||
device= waveaudio device number, in the range 0-8. Default is 0 (use
|
||||
default waveaudio device).
|
||||
|
||||
- OSS ("oss") [Unix only]
|
||||
card= card number. Default is the card whose driver was loaded
|
||||
first.
|
||||
buffer= logarithmic fragment size, in the range 7-17. Default is 14.
|
||||
Replaces the MM_FRAGSIZE environment variable, which is now
|
||||
deprecated.
|
||||
count= fragment count, in the range 2-255. Default is 16.
|
||||
Replaces the MM_NUMFRAGS environment variable, which is now
|
||||
deprecated.
|
||||
|
||||
- Piped output ("pipe") [Unix only]
|
||||
pipe= Pipe command (mandatory).
|
||||
|
||||
- SGI audio library ("sgi") [IRIX only]
|
||||
fragsize= buffer size for libmikmod internal use.
|
||||
Replaces the MM_SGI_FRAGSIZE environment variable, which is
|
||||
now deprecated.
|
||||
bufsize= buffer size for the audio library.
|
||||
Replaces the MM_SGI_BUFSIZE environment variable, which is
|
||||
now deprecated.
|
||||
|
||||
- Disk writers in raw and wav formats ("raw" and "wav")
|
||||
file= Output file name. Default is music.raw for the raw driver
|
||||
and music.wav for the wav driver.
|
||||
|
||||
- Sun/Solaris/NetBSD/OpenBSD audio ("audio")
|
||||
[SunOS, Solaris, NetBSD, OpenBSD only]
|
||||
buffer= logarithmic fragment size, in the range 7-17. Default is 12.
|
||||
Replaces the MM_FRAGSIZE environment variable, which is now
|
||||
deprecated.
|
||||
headphone on SunOS/Solaris only, redirects the output to the headphone
|
||||
port.
|
||||
speaker on SunOS/Solaris only, redirects the output to the speaker.
|
||||
|
||||
- Linux sam9407-based soundcards ("sam9407") [Linux only]
|
||||
card= card number. Default is first card.
|
||||
|
||||
- NoSound ("nosound"), Standard output ("stdout"), Ultrasound ("ultra"),
|
||||
Windows Multimedia ("winmm")
|
||||
These driver have no options.
|
||||
|
||||
|
||||
>> ALSA DRIVER SPECIFIC INFORMATION (Linux specific)
|
||||
-----------------------------------
|
||||
|
||||
The Advanced Linux Sound Architecture (ALSA) project aims to provide
|
||||
better sound facilities than the current OSS drivers. Although it is
|
||||
still in beta, it appears to be very stable and very easy to program
|
||||
compared to the OSS.
|
||||
Besides, it works much better than OSS for Gravis-type soundcards.
|
||||
|
||||
You can find more information on ALSA, including an HOWTO, on the web:
|
||||
http://www.alsa-project.org
|
||||
|
||||
The Advanced Linux Sound Architecture (ALSA) is still in beta, but its
|
||||
API is stable, so this libmikmod version should work with future
|
||||
versions of ALSA.
|
||||
|
||||
This version of the libmikmod ALSA driver works with either ALSA
|
||||
versions 0.3.x (for Linux kernels 2.0.x) and 0.4.x (for Linux kernels
|
||||
2.2.x and later).
|
||||
The latest versions, 0.5.x and 0.9.x, are currently not supported natively,
|
||||
although you can use the OSS emulation without problems.
|
||||
|
||||
If the sound comes out jerky, you can pass the "buffer=xx" option to the
|
||||
driver, to tweak the ALSA settings. The default value (if this option is
|
||||
not used) is 4; the slower your machine is, the greater this value has
|
||||
to be, but the allowed range is 2 to 16. However, the ALSA generally
|
||||
finds good settings for your configuration, so I doubt you'll have to
|
||||
use this option.
|
||||
|
||||
|
||||
>> ENLIGHTENED SOUND DAEMON SPECIFIC INFORMATION (Unix specific)
|
||||
------------------------------------------------
|
||||
|
||||
The Enlightened Sound Daemon (EsounD) is still experimental and may
|
||||
change a lot until it reaches the 1.0 release. Thus, this libmikmod
|
||||
version might not work with future versions of EsounD.
|
||||
|
||||
You can find more information on EsounD on the web:
|
||||
http://www.tux.org/~ricdude/EsounD.html
|
||||
However, this page is getting very out of date. Recent EsounD work can
|
||||
be found on the GNOME project:
|
||||
http://www.gnome.org/applist/view.php3?name=esound
|
||||
which not kept up-to-date either...
|
||||
|
||||
The version of the libmikmod EsounD driver coincides with the latest
|
||||
EsounD release available when this version of libmikmod was released;
|
||||
for the 3.1.10 release, this is EsounD v0.2.23, but libmikmod should
|
||||
work with any version starting from 0.2.6, although the latest version
|
||||
is recommended.
|
||||
|
||||
Please note that between 0.2.8 and 0.2.12 the server port and the
|
||||
protocol have changed, thus clients compiled with libesd from 0.2.8 can
|
||||
not communicate with 0.2.12 (and later) esd, and vice versa.
|
||||
|
||||
If the esd daemon dies, libmikmod will try to reconnect every 5 seconds
|
||||
and every new module, if a module ends. So, you can safely restart esd
|
||||
and wait 5 seconds, and voila! Sound is back...
|
||||
|
||||
If you run esd and a libmikmod application on the same machine,
|
||||
everything should work fine. However, if there is a real network
|
||||
connection, synchronization problems can occur.
|
||||
|
||||
If sound clicks or gets chopped, then you've likely got a
|
||||
synchronization problem. Pausing the player for a second should cause
|
||||
the problem to disappear. If there's still problems, perhaps your
|
||||
network is not fast enough. Lowering the playback rate will hopefully
|
||||
solve the problem.
|
||||
|
||||
Also, the performance of the esd is really abominable if the esd
|
||||
playback frequency can't be divided by the libmikmod playback rate. For
|
||||
example, runinng a libmikmod application at 42000 Hz with esd at 44100
|
||||
Hz will sound horrible, and take a lot of CPU time due to resampling.
|
||||
|
||||
|
||||
>> SGI DRIVER SPECIFIC INFORMATION (IRIX specific)
|
||||
----------------------------------
|
||||
|
||||
The SGI audio driver was written by Stephan Kanthak in 1996 and its
|
||||
author grants to distribute it with the libmikmod package under the same
|
||||
restrictions as the library.
|
||||
|
||||
If you encounter any problems concerning crackles or short stops while
|
||||
playing, feel free to experiment with the values of the fragsize and
|
||||
bufsize options of the driver. The default values are 20000 for fragsize
|
||||
and 40000 for bufsize. Increasing bufsize might result in nonstop sound
|
||||
on slow machines, but increases latency of interactive applications. The
|
||||
value of fragsize should be set to about half of bufsize in most cases
|
||||
and needs to be increased only if you own a very slow SGI.
|
||||
|
||||
Common problems
|
||||
|
||||
- libmikmod does not compile on my SGI?
|
||||
First check out whether you have the SGI audio library (libaudio) or
|
||||
not. If the audio library is missing you should upgrade to IRIX 5.3 or
|
||||
newer and you will obtain the media development package automatically
|
||||
with it. If you have the audio library installed, check out if it is
|
||||
in the linker path.
|
||||
|
||||
Also, the audio API has been extended in recent IRIX releases (6.4 and
|
||||
later). The older API used by libmikmod is supposed to be still supported,
|
||||
please drop me a note if it is not on your IRIX release.
|
||||
|
||||
- Sound is _very_ noisy?
|
||||
Change sample size to 16 bits.
|
||||
|
||||
- Sound crackles or stops temporarily?
|
||||
Try to increase the value of the fragsize driver option (default value
|
||||
is 20000). Switch to mono mode if necessary.
|
||||
|
||||
- libmikmod applications only react very slowly?
|
||||
This is a typical effect on SGI machines because the audio library
|
||||
sets up an internal buffer that seems to be quite large on many
|
||||
installations. Try to decrease the bufsize driver option (default
|
||||
value is 40000).
|
||||
|
||||
How to contact the driver author:
|
||||
Stephan Kanthak <kanthak@i6.informatik.rwth-aachen.de>
|
||||
Please cc: me (miod), just in case.
|
||||
|
||||
|
||||
>> SUNOS, SOLARIS, NETBSD AND OPENBSD DRIVER SPECIFIC INFORMATION
|
||||
-----------------------------------------------------------------
|
||||
|
||||
The above mentioned systems use the same interface to the audio device.
|
||||
The libmikmod driver for this interface is the Sun driver. It was coded
|
||||
by Valtteri Vuorikoski <vuori@sci.fi> and updated to libmikmod 3 by Tor
|
||||
Norbye <tor@cs.stanford.edu>, and has been modified to work under NetBSD
|
||||
and OpenBSD by the current maintainer.
|
||||
|
||||
This driver works with old sound hardware using 8 KHz mono ulaw, and
|
||||
with modern hardware using pcm mono or stereo at any frequency. If your
|
||||
settings aren't supported by the audio device, sound initialization will
|
||||
fail. Refer to the audio(7) man page under SunOS/Solaris and the
|
||||
audio(4) man page under NetBSD/OpenBSD for more details on your audio
|
||||
hardware and its capabilities.
|
||||
|
||||
On Sun workstations, you might be interested in passing the "headphone"
|
||||
option to the driver to force output on the headphones, since plugging
|
||||
the headphones is not enough.
|
||||
|
||||
If you run NetBSD or OpenBSD, the driver does not support the headphone
|
||||
and speaker parameters, but you can achieve the same effect with
|
||||
audioctl(1), for example:
|
||||
audioctl -w play.port=1
|
||||
will select the speaker, while a value of 2 would have selected the
|
||||
headphone.
|
||||
|
||||
If sound is jerky, you can pass the "buffer=xx" option to the driver to
|
||||
increase its internal buffer size. The default value (when this option
|
||||
is not used) is 12; the slower your machine, the greater this value has
|
||||
to be, in the range 7-17.
|
||||
|
||||
If you can't get libmikmod to work with your hardware, you can use its
|
||||
raw disk writer driver, in 8 bit mono 8 kHz, and send the music.raw file
|
||||
to /dev/audio with sox, using the following command line:
|
||||
sox -t raw -c 1 -r 8000 -u -b music.raw -t raw -U -r 8000 \
|
||||
-c 1 -b /dev/audio
|
||||
(or use the piped output driver with this command line)
|
||||
|
||||
Or if you played in 16 bit stereo, you can convert the file to a .au
|
||||
file:
|
||||
audioconvert -o music.au -f sun \
|
||||
-i rate=44.1k,channels=stereo,encoding=linear16 music.raw
|
||||
and play the file:
|
||||
audioplay -p headphone -v 10 music.au
|
||||
|
||||
|
||||
>> SAM9407 DRIVER SPECIFIC INFORMATION (Linux specific)
|
||||
--------------------------------------
|
||||
|
||||
The SAM9407 driver provides an OSS-compatible driver for the soundcards
|
||||
based on the sam9407 audio chip (MaxiSound 64 and Terratec EWS, among
|
||||
others), and provides advanced features such as hardware module
|
||||
playback.
|
||||
|
||||
You can find more information on this driver on the web:
|
||||
http://www.anime.net/~sam9407
|
||||
|
||||
The version of the libmikmod sam9407 driver coincides with the latest sam9407
|
||||
driver release available when this version of libmikmod was released; for the
|
||||
3.1.10 release, this is sam9407 driver v1.0.0.
|
||||
|
||||
|
||||
>> THANKS
|
||||
---------
|
||||
|
||||
I would like to thank everyone who contributed to libmikmod. Their names
|
||||
are in the AUTHORS file for the significative contributions, but some
|
||||
other names can be found in the NEWS file. Thanks a lot! Keeping
|
||||
libmikmod alive wouldn't be much fun without you.
|
||||
|
||||
|
||||
>> LICENSE
|
||||
----------
|
||||
|
||||
The libmikmod sound library is covered by the GNU Library General Public
|
||||
License as published by the Free Software Fundation (you'll find it in
|
||||
the file COPYING.LIB); either version 2 of the licence, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU Lesser General Public License, version 2.1, in file
|
||||
COPYING.LESSER, can be considered as a later version of the LGPL, and is
|
||||
strongly recommended for people who will embed libmikmod in their
|
||||
application as a shared library.
|
||||
|
||||
Parts of the library (in playercode/mdulaw.c) are derived from the files
|
||||
libst.h and raw.c from an old version of the sox (SOund eXchange)
|
||||
package written by Lance Norskog and Jef Poskanzer. The following
|
||||
copyright notice applies to these parts:
|
||||
|
||||
Copyright (C) 1989 by Jef Poskanzer.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation. This software is provided "as is" without express or
|
||||
implied warranty.
|
||||
|
||||
|
||||
>> CONTACT AND DOWNLOAD INFO
|
||||
----------------------------
|
||||
|
||||
* email:
|
||||
Please send all your libmikmod related e-mail to me, at:
|
||||
mikmod@raphnet.net
|
||||
|
||||
* web:
|
||||
libmikmod home page is located at:
|
||||
http://mikmod.raphnet.net
|
||||
|
||||
|
||||
45
project/jni/mikmod/TODO
Normal file
45
project/jni/mikmod/TODO
Normal file
@@ -0,0 +1,45 @@
|
||||
TODO list for future versions (or ROADMAP if you prefer)
|
||||
=============================
|
||||
|
||||
**** for the next major release, libmikmod 3.2:
|
||||
|
||||
- bugfixes
|
||||
- ability to have several modules in memory (it doesn't work in all cases in
|
||||
the current version)
|
||||
- integration of the LINA (LINA Is Not A3D) companion library written by
|
||||
David Banz.
|
||||
- total module length computation
|
||||
- ability to seek in modules in smaller chunks than patterns
|
||||
|
||||
**** during 3.2.x maintenance releases:
|
||||
|
||||
- a NAS (Network Audio System) driver
|
||||
- DMF and PSM loaders
|
||||
- loading of stereo and ADPCM wave files
|
||||
|
||||
**** hopefully in 3.x.x releases:
|
||||
|
||||
- bugfixes
|
||||
- use of glib or Pth for better thread support (i.e. more portability)
|
||||
- LIQ loader (see with Claudio Matsuoka)
|
||||
- MED improvements (at least I hope so)
|
||||
- software mixer improvements
|
||||
- an OSS sequencer driver
|
||||
- an ALSA sequencer driver
|
||||
|
||||
**** Will hopefully occur in 4.x
|
||||
|
||||
- bugfixes
|
||||
- a TFMX loader (see with Claudio, too)
|
||||
|
||||
**** Plans for the 4.x series and later:
|
||||
|
||||
- bugfixes
|
||||
- a well-defined module loader interface, allowing both libmikmod and xmp to
|
||||
share the same loader code (in cooperation with Claudio, of course)
|
||||
- extending the feature list, at the request of the users: midi support ?
|
||||
mp3 support ? cdda support ? suggestions welcome.
|
||||
|
||||
|
||||
Want something else ? Drop me a note at <miod@mikmod.org> and I'll
|
||||
see what I can do for you...
|
||||
159
project/jni/mikmod/config.h
Normal file
159
project/jni/mikmod/config.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* config.h. Generated automatically by configure. */
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */
|
||||
|
||||
/* Define if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
We just want to avoid a redefinition error message. */
|
||||
#ifndef _ALL_SOURCE
|
||||
/* #undef _ALL_SOURCE */
|
||||
#endif
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS
|
||||
|
||||
/* Define if your system supports binary pipes (i.e. Unix) */
|
||||
#define DRV_PIPE 1
|
||||
|
||||
/* Define if you want a .aiff file writer driver */
|
||||
#define DRV_AIFF 1
|
||||
|
||||
/* Define if the AudioFile driver is compiled */
|
||||
/* #undef DRV_AF */
|
||||
/* Define if the AIX audio driver is compiled */
|
||||
/* #undef DRV_AIX */
|
||||
/* Define if the Linux ALSA driver is compiled */
|
||||
/* #undef DRV_ALSA */
|
||||
/* Define if the Enlightened Sound Daemon driver is compiled */
|
||||
/* #undef DRV_ESD */
|
||||
/* Define if the HP-UX audio driver is compiled */
|
||||
/* #undef DRV_HP */
|
||||
/* Define if the Open Sound System driver is compiled */
|
||||
/* #undef DRV_OSS */
|
||||
/* Define if the Linux SAM9407 driver is compiled */
|
||||
/* #undef DRV_SAM9407 */
|
||||
/* Define if the SGI audio driver is compiled */
|
||||
/* #undef DRV_SGI */
|
||||
/* Define if the Sun audio driver or compatible (NetBSD, OpenBSD)
|
||||
is compiled */
|
||||
/* #undef DRV_SUN */
|
||||
/* Define if the Linux Ultra driver is compiled */
|
||||
/* #undef DRV_ULTRA */
|
||||
/* Define this if you want the MacOS X CoreAudio driver */
|
||||
/* #undef DRV_OSX */
|
||||
/* Define this if you want the Carbon Mac Audio driver */
|
||||
/* #undef DRV_MAC */
|
||||
|
||||
/* Define if you want a debug version of the library */
|
||||
/* #undef MIKMOD_DEBUG */
|
||||
/* Define if you want runtime dynamic linking of ALSA and EsounD drivers */
|
||||
/* #undef MIKMOD_DYNAMIC */
|
||||
/* Define if your system provides POSIX.4 threads */
|
||||
#define HAVE_PTHREAD 1
|
||||
|
||||
/* Define if your system is SunOS 4.* */
|
||||
/* #undef SUNOS */
|
||||
/* Define if your system is AIX 3.* - might be needed for 4.* too */
|
||||
/* #undef AIX */
|
||||
/* Define if your system defines random(3) and srandom(3) in math.h instead
|
||||
of stdlib.h */
|
||||
/* #undef SRANDOM_IN_MATH_H */
|
||||
/* Define if EsounD driver depends on ALSA */
|
||||
/* #undef MIKMOD_DYNAMIC_ESD_NEEDS_ALSA */
|
||||
/* Define if your system has RTLD_GLOBAL defined in <dlfcn.h> */
|
||||
/* #undef HAVE_RTLD_GLOBAL */
|
||||
/* Define if your system needs leading underscore to function names in dlsym() calls */
|
||||
/* #undef DLSYM_NEEDS_UNDERSCORE */
|
||||
|
||||
/* Define if you have the setenv function. */
|
||||
#define HAVE_SETENV 1
|
||||
|
||||
/* Define if you have the snprintf function. */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
/* Define if you have the srandom function. */
|
||||
/* #undef HAVE_SRANDOM */
|
||||
|
||||
/* Define if you have the strcasecmp function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define if you have the strdup function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define if you have the strstr function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define if you have the <AF/AFlib.h> header file. */
|
||||
/* #undef HAVE_AF_AFLIB_H */
|
||||
|
||||
/* Define if you have the <dl.h> header file. */
|
||||
/* #undef HAVE_DL_H */
|
||||
|
||||
/* Define if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Define if you have the <dmedia/audio.h> header file. */
|
||||
/* #undef HAVE_DMEDIA_AUDIO_H */
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define if you have the <libgus.h> header file. */
|
||||
/* #undef HAVE_LIBGUS_H */
|
||||
|
||||
/* Define if you have the <machine/soundcard.h> header file. */
|
||||
/* #undef HAVE_MACHINE_SOUNDCARD_H */
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
/* Define if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define if you have the <sun/audioio.h> header file. */
|
||||
/* #undef HAVE_SUN_AUDIOIO_H */
|
||||
|
||||
/* Define if you have the <sys/acpa.h> header file. */
|
||||
/* #undef HAVE_SYS_ACPA_H */
|
||||
|
||||
/* Define if you have the <sys/asoundlib.h> header file. */
|
||||
/* #undef HAVE_SYS_ASOUNDLIB_H */
|
||||
|
||||
/* Define if you have the <sys/audio.h> header file. */
|
||||
/* #undef HAVE_SYS_AUDIO_H */
|
||||
|
||||
/* Define if you have the <sys/audioio.h> header file. */
|
||||
/* #undef HAVE_SYS_AUDIOIO_H */
|
||||
|
||||
/* Define if you have the <sys/ioctl.h> header file. */
|
||||
/* #undef HAVE_SYS_IOCTL_H */
|
||||
|
||||
/* Define if you have the <sys/sam9407.h> header file. */
|
||||
/* #undef HAVE_SYS_SAM9407_H */
|
||||
|
||||
/* Define if you have the <sys/soundcard.h> header file. */
|
||||
/* #undef HAVE_SYS_SOUNDCARD_H */
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libmikmod"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "3.2.0b2"
|
||||
|
||||
379
project/jni/mikmod/drivers/drv_aiff.c
Normal file
379
project/jni/mikmod/drivers/drv_aiff.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/* MikMod sound library
|
||||
(c) 2004, Raphael Assenat
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: drv_aiff.c,v 1.4 2004/02/20 22:08:33 raph Exp $
|
||||
|
||||
Driver for output to a file called MUSIC.AIFF [or .AIF on Windows].
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Written by Axel "awe" Wefers <awe@fruitz-of-dojo.de>
|
||||
|
||||
|
||||
Raphael Assenat: 19 Feb 2004: Command line options documented in the MDRIVER structure,
|
||||
and I added #if 0 's around pragmas, since gcc complaines about them.
|
||||
Hopefully, the IDE which uses them wont care about that?
|
||||
*/
|
||||
|
||||
/*_______________________________________________________________________________________________iNCLUDES
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark INCLUDES
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef DRV_AIFF
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h> /* required for IEEE extended conversion */
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
/*________________________________________________________________________________________________dEFINES
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark DEFINES
|
||||
#endif
|
||||
|
||||
#define AIFF_BUFFERSIZE 32768
|
||||
#if defined(WIN32) || defined(DJGPP)
|
||||
#define AIFF_FILENAME "music.aif"
|
||||
#else
|
||||
#define AIFF_FILENAME "music.aiff"
|
||||
#endif /* WIN32 */
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
/*_________________________________________________________________________________________________mACROS
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark MACROS
|
||||
#endif
|
||||
|
||||
#define AIFF_FLOAT_TO_UNSIGNED(f) ((unsigned long)(((long)(f - 2147483648.0)) + 2147483647L + 1))
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
/*___________________________________________________________________________________________________vARS
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark VARIABLES
|
||||
#endif
|
||||
static MWRITER *gAiffOut = NULL;
|
||||
static FILE *gAiffFile = NULL;
|
||||
static SBYTE *gAiffAudioBuffer = NULL;
|
||||
static CHAR *gAiffFileName = NULL;
|
||||
static ULONG gAiffDumpSize = 0;
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
/*____________________________________________________________________________________fUNCTION_pROTOTYPES
|
||||
*/
|
||||
#if 0
|
||||
#pragma mark FUNCTION PROTOTYPES
|
||||
#endif
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fclose(FILE *);
|
||||
#endif
|
||||
|
||||
static void AIFF_ConvertToIeeeExtended (double theValue, char *theBytes);
|
||||
static void AIFF_PutHeader (void);
|
||||
static void AIFF_CommandLine (CHAR *theCmdLine);
|
||||
static BOOL AIFF_IsThere (void);
|
||||
static BOOL AIFF_Init (void);
|
||||
static void AIFF_Exit (void);
|
||||
static void AIFF_Update (void);
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
/*___________________________________________________________________________AIFF_ConvertToIeeeExtended()
|
||||
*/
|
||||
|
||||
void AIFF_ConvertToIeeeExtended (double theValue, char *theBytes)
|
||||
{
|
||||
int mySign;
|
||||
int myExponent;
|
||||
double myFMant, myFsMant;
|
||||
unsigned long myHiMant, myLoMant;
|
||||
|
||||
if (theValue < 0)
|
||||
{
|
||||
mySign = 0x8000;
|
||||
theValue *= -1;
|
||||
} else
|
||||
{
|
||||
mySign = 0;
|
||||
}
|
||||
|
||||
if (theValue == 0)
|
||||
{
|
||||
myExponent = 0;
|
||||
myHiMant = 0;
|
||||
myLoMant = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
myFMant = frexp (theValue, &myExponent);
|
||||
if ((myExponent > 16384) || !(myFMant < 1))
|
||||
{
|
||||
myExponent = mySign | 0x7FFF;
|
||||
myHiMant = 0;
|
||||
myLoMant = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
myExponent += 16382;
|
||||
if (myExponent < 0)
|
||||
{
|
||||
myFMant = ldexp (myFMant, myExponent);
|
||||
myExponent = 0;
|
||||
}
|
||||
myExponent |= mySign;
|
||||
myFMant = ldexp (myFMant, 32);
|
||||
myFsMant = floor (myFMant);
|
||||
myHiMant = AIFF_FLOAT_TO_UNSIGNED (myFsMant);
|
||||
myFMant = ldexp (myFMant - myFsMant, 32);
|
||||
myFsMant = floor (myFMant);
|
||||
myLoMant = AIFF_FLOAT_TO_UNSIGNED (myFsMant);
|
||||
}
|
||||
}
|
||||
|
||||
theBytes[0] = myExponent >> 8;
|
||||
theBytes[1] = myExponent;
|
||||
theBytes[2] = myHiMant >> 24;
|
||||
theBytes[3] = myHiMant >> 16;
|
||||
theBytes[4] = myHiMant >> 8;
|
||||
theBytes[5] = myHiMant;
|
||||
theBytes[6] = myLoMant >> 24;
|
||||
theBytes[7] = myLoMant >> 16;
|
||||
theBytes[8] = myLoMant >> 8;
|
||||
theBytes[9] = myLoMant;
|
||||
}
|
||||
|
||||
/*_______________________________________________________________________________________AIFF_PutHeader()
|
||||
*/
|
||||
|
||||
static void AIFF_PutHeader(void)
|
||||
{
|
||||
ULONG myFrames;
|
||||
UBYTE myIEEE[10];
|
||||
|
||||
myFrames = gAiffDumpSize / (((md_mode&DMODE_STEREO) ? 2 : 1) * ((md_mode & DMODE_16BITS) ? 2 : 1));
|
||||
AIFF_ConvertToIeeeExtended ((double) md_mixfreq, myIEEE);
|
||||
|
||||
_mm_fseek (gAiffOut, 0, SEEK_SET);
|
||||
_mm_write_string ("FORM", gAiffOut); /* chunk 'FORM' */
|
||||
_mm_write_M_ULONG (gAiffDumpSize + 36, gAiffOut); /* length of the file */
|
||||
_mm_write_string ("AIFFCOMM", gAiffOut); /* chunk 'AIFF', 'COMM' */
|
||||
_mm_write_M_ULONG (18, gAiffOut); /* length of this AIFF block */
|
||||
_mm_write_M_UWORD ((md_mode & DMODE_STEREO) ? 2 : 1, gAiffOut); /* channels */
|
||||
_mm_write_M_ULONG (myFrames, gAiffOut); /* frames = freq * secs */
|
||||
_mm_write_M_UWORD ((md_mode & DMODE_16BITS) ? 16 : 8, gAiffOut); /* bits per sample */
|
||||
_mm_write_UBYTES (myIEEE, 10, gAiffOut); /* frequency [IEEE extended] */
|
||||
_mm_write_string ("SSND", gAiffOut); /* data chunk 'SSND' */
|
||||
_mm_write_M_ULONG (gAiffDumpSize, gAiffOut); /* data length */
|
||||
_mm_write_M_ULONG (0, gAiffOut); /* data offset, always zero */
|
||||
_mm_write_M_ULONG (0, gAiffOut); /* data blocksize, always zero */
|
||||
}
|
||||
|
||||
/*_____________________________________________________________________________________AIFF_CommandLine()
|
||||
*/
|
||||
|
||||
static void AIFF_CommandLine (CHAR *theCmdLine)
|
||||
{
|
||||
CHAR *myFileName = MD_GetAtom ("file", theCmdLine,0);
|
||||
|
||||
if (myFileName != NULL)
|
||||
{
|
||||
_mm_free (gAiffFileName);
|
||||
gAiffFileName = myFileName;
|
||||
}
|
||||
}
|
||||
|
||||
/*_________________________________________________________________________________________AIFF_isThere()
|
||||
*/
|
||||
|
||||
static BOOL AIFF_IsThere (void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*____________________________________________________________________________________________AIFF_Init()
|
||||
*/
|
||||
|
||||
static BOOL AIFF_Init (void)
|
||||
{
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
if (!MD_Access (gAiffFileName ? gAiffFileName : AIFF_FILENAME))
|
||||
{
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(gAiffFile = fopen (gAiffFileName ? gAiffFileName : AIFF_FILENAME, "wb")))
|
||||
{
|
||||
_mm_errno = MMERR_OPENING_FILE;
|
||||
return (1);
|
||||
}
|
||||
if (!(gAiffOut =_mm_new_file_writer (gAiffFile)))
|
||||
{
|
||||
fclose (gAiffFile);
|
||||
unlink(gAiffFileName ? gAiffFileName : AIFF_FILENAME);
|
||||
gAiffFile = NULL;
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (!(gAiffAudioBuffer = (SBYTE*) _mm_malloc (AIFF_BUFFERSIZE)))
|
||||
{
|
||||
_mm_delete_file_writer (gAiffOut);
|
||||
fclose (gAiffFile);
|
||||
unlink (gAiffFileName ? gAiffFileName : AIFF_FILENAME);
|
||||
gAiffFile = NULL;
|
||||
gAiffOut = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
md_mode|=DMODE_SOFT_MUSIC|DMODE_SOFT_SNDFX;
|
||||
|
||||
if (VC_Init ())
|
||||
{
|
||||
_mm_delete_file_writer (gAiffOut);
|
||||
fclose (gAiffFile);
|
||||
unlink (gAiffFileName ? gAiffFileName : AIFF_FILENAME);
|
||||
gAiffFile = NULL;
|
||||
gAiffOut = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
gAiffDumpSize = 0;
|
||||
AIFF_PutHeader ();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*____________________________________________________________________________________________AIFF_Exit()
|
||||
*/
|
||||
|
||||
static void AIFF_Exit (void)
|
||||
{
|
||||
VC_Exit ();
|
||||
|
||||
/* write in the actual sizes now */
|
||||
if (gAiffOut != NULL)
|
||||
{
|
||||
AIFF_PutHeader ();
|
||||
_mm_delete_file_writer (gAiffOut);
|
||||
fclose (gAiffFile);
|
||||
gAiffFile = NULL;
|
||||
gAiffOut = NULL;
|
||||
}
|
||||
if (gAiffAudioBuffer != NULL)
|
||||
{
|
||||
free (gAiffAudioBuffer);
|
||||
gAiffAudioBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*__________________________________________________________________________________________AIFF_Update()
|
||||
*/
|
||||
|
||||
static void AIFF_Update (void)
|
||||
{
|
||||
ULONG myByteCount;
|
||||
|
||||
myByteCount = VC_WriteBytes (gAiffAudioBuffer, AIFF_BUFFERSIZE);
|
||||
if (md_mode & DMODE_16BITS)
|
||||
{
|
||||
_mm_write_M_UWORDS ((UWORD *) gAiffAudioBuffer, myByteCount >> 1, gAiffOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < myByteCount; i++)
|
||||
{
|
||||
gAiffAudioBuffer[i] -= 0x80; /* convert to signed PCM */
|
||||
}
|
||||
_mm_write_UBYTES (gAiffAudioBuffer, myByteCount, gAiffOut);
|
||||
}
|
||||
gAiffDumpSize += myByteCount;
|
||||
}
|
||||
|
||||
/*________________________________________________________________________________________________drv_osx
|
||||
*/
|
||||
|
||||
MIKMODAPI MDRIVER drv_aiff = {
|
||||
NULL,
|
||||
"Disk writer (aiff)",
|
||||
"AIFF disk writer (music.aiff) v1.1",
|
||||
0,255,
|
||||
"aif",
|
||||
"file:t:music.aiff:Output file name\n",
|
||||
AIFF_CommandLine,
|
||||
AIFF_IsThere,
|
||||
VC_SampleLoad,
|
||||
VC_SampleUnload,
|
||||
VC_SampleSpace,
|
||||
VC_SampleLength,
|
||||
AIFF_Init,
|
||||
AIFF_Exit,
|
||||
NULL,
|
||||
VC_SetNumVoices,
|
||||
VC_PlayStart,
|
||||
VC_PlayStop,
|
||||
AIFF_Update,
|
||||
NULL,
|
||||
VC_VoiceSetVolume,
|
||||
VC_VoiceGetVolume,
|
||||
VC_VoiceSetFrequency,
|
||||
VC_VoiceGetFrequency,
|
||||
VC_VoiceSetPanning,
|
||||
VC_VoiceGetPanning,
|
||||
VC_VoicePlay,
|
||||
VC_VoiceStop,
|
||||
VC_VoiceStopped,
|
||||
VC_VoiceGetPosition,
|
||||
VC_VoiceRealVolume
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
MISSING(drv_aiff);
|
||||
|
||||
#endif
|
||||
|
||||
/*____________________________________________________________________________________________________eOF
|
||||
*/
|
||||
107
project/jni/mikmod/drivers/drv_nos.c
Normal file
107
project/jni/mikmod/drivers/drv_nos.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: drv_nos.c,v 1.3 2004/01/31 22:39:40 raph Exp $
|
||||
|
||||
Driver for no output
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Written by Jean-Paul Mikkers <mikmak@via.nl>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#define ZEROLEN 32768
|
||||
|
||||
static SBYTE *zerobuf=NULL;
|
||||
|
||||
static BOOL NS_IsThere(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL NS_Init(void)
|
||||
{
|
||||
zerobuf=(SBYTE*)_mm_malloc(ZEROLEN);
|
||||
return VC_Init();
|
||||
}
|
||||
|
||||
static void NS_Exit(void)
|
||||
{
|
||||
VC_Exit();
|
||||
_mm_free(zerobuf);
|
||||
}
|
||||
|
||||
static void NS_Update(void)
|
||||
{
|
||||
if (zerobuf)
|
||||
VC_WriteBytes(zerobuf,ZEROLEN);
|
||||
}
|
||||
|
||||
MIKMODAPI MDRIVER drv_nos={
|
||||
NULL,
|
||||
"No Sound",
|
||||
"Nosound Driver v3.0",
|
||||
255,255,
|
||||
"nosound",
|
||||
NULL,
|
||||
NULL,
|
||||
NS_IsThere,
|
||||
VC_SampleLoad,
|
||||
VC_SampleUnload,
|
||||
VC_SampleSpace,
|
||||
VC_SampleLength,
|
||||
NS_Init,
|
||||
NS_Exit,
|
||||
NULL,
|
||||
VC_SetNumVoices,
|
||||
VC_PlayStart,
|
||||
VC_PlayStop,
|
||||
NS_Update,
|
||||
NULL,
|
||||
VC_VoiceSetVolume,
|
||||
VC_VoiceGetVolume,
|
||||
VC_VoiceSetFrequency,
|
||||
VC_VoiceGetFrequency,
|
||||
VC_VoiceSetPanning,
|
||||
VC_VoiceGetPanning,
|
||||
VC_VoicePlay,
|
||||
VC_VoiceStop,
|
||||
VC_VoiceStopped,
|
||||
VC_VoiceGetPosition,
|
||||
VC_VoiceRealVolume
|
||||
};
|
||||
|
||||
|
||||
/* ex:set ts=4: */
|
||||
220
project/jni/mikmod/drivers/drv_pipe.c
Normal file
220
project/jni/mikmod/drivers/drv_pipe.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: drv_pipe.c,v 1.3 2004/01/31 22:39:40 raph Exp $
|
||||
|
||||
Driver for output via a pipe to another command
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Written by Simon Hosie <gumboot@clear.net.nz>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef DRV_PIPE
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fclose(FILE *);
|
||||
#endif
|
||||
|
||||
#define BUFFERSIZE 32768
|
||||
|
||||
static MWRITER *pipeout=NULL;
|
||||
static FILE *pipefile=NULL;
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
static int pipefd[2]={-1,-1};
|
||||
static pid_t pid;
|
||||
#endif
|
||||
static SBYTE *audiobuffer=NULL;
|
||||
|
||||
static CHAR *target=NULL;
|
||||
|
||||
static void pipe_CommandLine(CHAR *cmdline)
|
||||
{
|
||||
CHAR *ptr=MD_GetAtom("pipe",cmdline,0);
|
||||
|
||||
if(ptr) {
|
||||
_mm_free(target);
|
||||
target=ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL pipe_IsThere(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL pipe_Init(void)
|
||||
{
|
||||
if(!target) {
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
#if !defined unix && (!defined __APPLE__ || !defined __MACH__)
|
||||
#ifdef __EMX__
|
||||
_fsetmode(stdout, "b");
|
||||
#endif
|
||||
#ifdef __WATCOMC__
|
||||
pipefile = _popen(target, "wb");
|
||||
#else
|
||||
pipefile = popen(target, "wb");
|
||||
#endif
|
||||
if (!pipefile) {
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
/* poor man's popen() */
|
||||
if (pipe(pipefd)) {
|
||||
_mm_errno = MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
switch (pid=fork()) {
|
||||
case -1:
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
pipefd[0]=pipefd[1]=-1;
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
case 0:
|
||||
if (pipefd[0]) {
|
||||
dup2(pipefd[0],0);
|
||||
close(pipefd[0]);
|
||||
}
|
||||
close(pipefd[1]);
|
||||
if (!MD_DropPrivileges())
|
||||
execl("/bin/sh","sh","-c",target,NULL);
|
||||
exit(127);
|
||||
}
|
||||
close(pipefd[0]);
|
||||
if (!(pipefile=fdopen(pipefd[1],"wb"))) {
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if(!(pipeout=_mm_new_file_writer(pipefile)))
|
||||
return 1;
|
||||
if(!(audiobuffer=(SBYTE*)_mm_malloc(BUFFERSIZE)))
|
||||
return 1;
|
||||
|
||||
md_mode|=DMODE_SOFT_MUSIC|DMODE_SOFT_SNDFX;
|
||||
|
||||
return VC_Init();
|
||||
}
|
||||
|
||||
static void pipe_Exit(void)
|
||||
{
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
int pstat;
|
||||
pid_t pid2;
|
||||
#endif
|
||||
|
||||
VC_Exit();
|
||||
_mm_free(audiobuffer);
|
||||
if(pipeout) {
|
||||
_mm_delete_file_writer(pipeout);
|
||||
pipeout=NULL;
|
||||
}
|
||||
if(pipefile) {
|
||||
#if !defined unix && (!defined __APPLE__ || !defined __MACH__)
|
||||
#ifdef __WATCOMC__
|
||||
_pclose(pipefile);
|
||||
#else
|
||||
pclose(pipefile);
|
||||
#endif
|
||||
#ifdef __EMX__
|
||||
_fsetmode(stdout,"t");
|
||||
#endif
|
||||
#else
|
||||
fclose(pipefile);
|
||||
do {
|
||||
pid2=waitpid(pid,&pstat,0);
|
||||
} while (pid2==-1 && errno==EINTR);
|
||||
#endif
|
||||
pipefile=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void pipe_Update(void)
|
||||
{
|
||||
_mm_write_UBYTES(audiobuffer,VC_WriteBytes(audiobuffer,BUFFERSIZE),pipeout);
|
||||
}
|
||||
|
||||
MIKMODAPI MDRIVER drv_pipe={
|
||||
NULL,
|
||||
"Piped writer",
|
||||
"Piped Output driver v0.2",
|
||||
0,255,
|
||||
"pipe",
|
||||
"pipe:t::Pipe command\n",
|
||||
pipe_CommandLine,
|
||||
pipe_IsThere,
|
||||
VC_SampleLoad,
|
||||
VC_SampleUnload,
|
||||
VC_SampleSpace,
|
||||
VC_SampleLength,
|
||||
pipe_Init,
|
||||
pipe_Exit,
|
||||
NULL,
|
||||
VC_SetNumVoices,
|
||||
VC_PlayStart,
|
||||
VC_PlayStop,
|
||||
pipe_Update,
|
||||
NULL,
|
||||
VC_VoiceSetVolume,
|
||||
VC_VoiceGetVolume,
|
||||
VC_VoiceSetFrequency,
|
||||
VC_VoiceGetFrequency,
|
||||
VC_VoiceSetPanning,
|
||||
VC_VoiceGetPanning,
|
||||
VC_VoicePlay,
|
||||
VC_VoiceStop,
|
||||
VC_VoiceStopped,
|
||||
VC_VoiceGetPosition,
|
||||
VC_VoiceRealVolume
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
MISSING(drv_pipe);
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
121
project/jni/mikmod/drivers/drv_stdout.c
Normal file
121
project/jni/mikmod/drivers/drv_stdout.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: drv_stdout.c,v 1.3 2004/01/31 22:39:40 raph Exp $
|
||||
|
||||
Output data to stdout
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#define BUFFERSIZE 32768
|
||||
|
||||
static SBYTE *audiobuffer=NULL;
|
||||
|
||||
static BOOL stdout_IsThere(void)
|
||||
{
|
||||
/* only allow this driver on pipes */
|
||||
return 1-isatty(1);
|
||||
}
|
||||
|
||||
static BOOL stdout_Init(void)
|
||||
{
|
||||
if(!(audiobuffer=(SBYTE*)_mm_malloc(BUFFERSIZE))) return 1;
|
||||
#ifdef __EMX__
|
||||
_fsetmode(stdout,"b");
|
||||
#endif
|
||||
return VC_Init();
|
||||
}
|
||||
|
||||
static void stdout_Exit(void)
|
||||
{
|
||||
VC_Exit();
|
||||
#ifdef __EMX__
|
||||
_fsetmode(stdout,"t");
|
||||
#endif
|
||||
if (audiobuffer) {
|
||||
free(audiobuffer);
|
||||
audiobuffer=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void stdout_Update(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
_write
|
||||
#else
|
||||
write
|
||||
#endif
|
||||
(1,audiobuffer,VC_WriteBytes((SBYTE*)audiobuffer,BUFFERSIZE));
|
||||
}
|
||||
|
||||
static BOOL stdout_Reset(void)
|
||||
{
|
||||
VC_Exit();
|
||||
return VC_Init();
|
||||
}
|
||||
|
||||
MIKMODAPI MDRIVER drv_stdout={
|
||||
NULL,
|
||||
"stdout",
|
||||
"Standard output driver v1.1",
|
||||
0,255,
|
||||
"stdout",
|
||||
NULL,
|
||||
NULL,
|
||||
stdout_IsThere,
|
||||
VC_SampleLoad,
|
||||
VC_SampleUnload,
|
||||
VC_SampleSpace,
|
||||
VC_SampleLength,
|
||||
stdout_Init,
|
||||
stdout_Exit,
|
||||
stdout_Reset,
|
||||
VC_SetNumVoices,
|
||||
VC_PlayStart,
|
||||
VC_PlayStop,
|
||||
stdout_Update,
|
||||
NULL,
|
||||
VC_VoiceSetVolume,
|
||||
VC_VoiceGetVolume,
|
||||
VC_VoiceSetFrequency,
|
||||
VC_VoiceGetFrequency,
|
||||
VC_VoiceSetPanning,
|
||||
VC_VoiceGetPanning,
|
||||
VC_VoicePlay,
|
||||
VC_VoiceStop,
|
||||
VC_VoiceStopped,
|
||||
VC_VoiceGetPosition,
|
||||
VC_VoiceRealVolume
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
189
project/jni/mikmod/drivers/drv_wav.c
Normal file
189
project/jni/mikmod/drivers/drv_wav.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: drv_wav.c,v 1.3 2004/01/31 22:39:40 raph Exp $
|
||||
|
||||
Driver for output to a file called MUSIC.WAV
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fclose(FILE *);
|
||||
#endif
|
||||
|
||||
#define BUFFERSIZE 32768
|
||||
#define FILENAME "music.wav"
|
||||
|
||||
static MWRITER *wavout=NULL;
|
||||
static FILE *wavfile=NULL;
|
||||
static SBYTE *audiobuffer=NULL;
|
||||
static ULONG dumpsize;
|
||||
static CHAR *filename=NULL;
|
||||
|
||||
static void putheader(void)
|
||||
{
|
||||
_mm_fseek(wavout,0,SEEK_SET);
|
||||
_mm_write_string("RIFF",wavout);
|
||||
_mm_write_I_ULONG(dumpsize+44,wavout);
|
||||
_mm_write_string("WAVEfmt ",wavout);
|
||||
_mm_write_I_ULONG(16,wavout); /* length of this RIFF block crap */
|
||||
|
||||
_mm_write_I_UWORD(1, wavout); /* microsoft format type */
|
||||
_mm_write_I_UWORD((md_mode&DMODE_STEREO)?2:1,wavout);
|
||||
_mm_write_I_ULONG(md_mixfreq,wavout);
|
||||
_mm_write_I_ULONG(md_mixfreq*((md_mode&DMODE_STEREO)?2:1)*
|
||||
((md_mode&DMODE_16BITS)?2:1),wavout);
|
||||
/* block alignment (8/16 bit) */
|
||||
_mm_write_I_UWORD(((md_mode&DMODE_16BITS)?2:1)*
|
||||
((md_mode&DMODE_STEREO)?2:1),wavout);
|
||||
_mm_write_I_UWORD((md_mode&DMODE_16BITS)?16:8,wavout);
|
||||
_mm_write_string("data",wavout);
|
||||
_mm_write_I_ULONG(dumpsize,wavout);
|
||||
}
|
||||
|
||||
static void WAV_CommandLine(CHAR *cmdline)
|
||||
{
|
||||
CHAR *ptr=MD_GetAtom("file",cmdline,0);
|
||||
|
||||
if(ptr) {
|
||||
_mm_free(filename);
|
||||
filename=ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WAV_IsThere(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL WAV_Init(void)
|
||||
{
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
if (!MD_Access(filename?filename:FILENAME)) {
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!(wavfile=fopen(filename?filename:FILENAME,"wb"))) {
|
||||
_mm_errno=MMERR_OPENING_FILE;
|
||||
return 1;
|
||||
}
|
||||
if(!(wavout=_mm_new_file_writer (wavfile))) {
|
||||
fclose(wavfile);unlink(filename?filename:FILENAME);
|
||||
wavfile=NULL;
|
||||
return 1;
|
||||
}
|
||||
if(!(audiobuffer=(SBYTE*)_mm_malloc(BUFFERSIZE))) {
|
||||
_mm_delete_file_writer(wavout);
|
||||
fclose(wavfile);unlink(filename?filename:FILENAME);
|
||||
wavfile=NULL;wavout=NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
md_mode|=DMODE_SOFT_MUSIC|DMODE_SOFT_SNDFX;
|
||||
|
||||
if (VC_Init()) {
|
||||
_mm_delete_file_writer(wavout);
|
||||
fclose(wavfile);unlink(filename?filename:FILENAME);
|
||||
wavfile=NULL;wavout=NULL;
|
||||
return 1;
|
||||
}
|
||||
dumpsize=0;
|
||||
putheader();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WAV_Exit(void)
|
||||
{
|
||||
VC_Exit();
|
||||
|
||||
/* write in the actual sizes now */
|
||||
if(wavout) {
|
||||
putheader();
|
||||
_mm_delete_file_writer(wavout);
|
||||
fclose(wavfile);
|
||||
wavfile=NULL;wavout=NULL;
|
||||
}
|
||||
if(audiobuffer) {
|
||||
free(audiobuffer);
|
||||
audiobuffer=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void WAV_Update(void)
|
||||
{
|
||||
ULONG done;
|
||||
|
||||
done=VC_WriteBytes(audiobuffer,BUFFERSIZE);
|
||||
_mm_write_UBYTES(audiobuffer,done,wavout);
|
||||
dumpsize+=done;
|
||||
}
|
||||
|
||||
MIKMODAPI MDRIVER drv_wav={
|
||||
NULL,
|
||||
"Disk writer (wav)",
|
||||
"Wav disk writer (music.wav) v1.2",
|
||||
0,255,
|
||||
"wav",
|
||||
"file:t:music.wav:Output file name\n",
|
||||
WAV_CommandLine,
|
||||
WAV_IsThere,
|
||||
VC_SampleLoad,
|
||||
VC_SampleUnload,
|
||||
VC_SampleSpace,
|
||||
VC_SampleLength,
|
||||
WAV_Init,
|
||||
WAV_Exit,
|
||||
NULL,
|
||||
VC_SetNumVoices,
|
||||
VC_PlayStart,
|
||||
VC_PlayStop,
|
||||
WAV_Update,
|
||||
NULL,
|
||||
VC_VoiceSetVolume,
|
||||
VC_VoiceGetVolume,
|
||||
VC_VoiceSetFrequency,
|
||||
VC_VoiceGetFrequency,
|
||||
VC_VoiceSetPanning,
|
||||
VC_VoiceGetPanning,
|
||||
VC_VoicePlay,
|
||||
VC_VoiceStop,
|
||||
VC_VoiceStopped,
|
||||
VC_VoiceGetPosition,
|
||||
VC_VoiceRealVolume
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
747
project/jni/mikmod/include/mikmod.h
Normal file
747
project/jni/mikmod/include/mikmod.h
Normal file
@@ -0,0 +1,747 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mikmod.h.in,v 1.11 2004/02/18 14:10:39 raph Exp $
|
||||
|
||||
MikMod sound library include file
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef _MIKMOD_H_
|
||||
#define _MIKMOD_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Compiler magic for shared libraries
|
||||
*/
|
||||
|
||||
#if defined WIN32 && defined _DLL
|
||||
#ifdef DLL_EXPORTS
|
||||
#define MIKMODAPI __declspec(dllexport)
|
||||
#else
|
||||
#define MIKMODAPI __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define MIKMODAPI
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Library version
|
||||
*/
|
||||
|
||||
#define LIBMIKMOD_VERSION_MAJOR 3L
|
||||
#define LIBMIKMOD_VERSION_MINOR 2L
|
||||
#define LIBMIKMOD_REVISION 0L
|
||||
|
||||
#define LIBMIKMOD_VERSION \
|
||||
((LIBMIKMOD_VERSION_MAJOR<<16)| \
|
||||
(LIBMIKMOD_VERSION_MINOR<< 8)| \
|
||||
(LIBMIKMOD_REVISION))
|
||||
|
||||
MIKMODAPI extern long MikMod_GetVersion(void);
|
||||
|
||||
/*
|
||||
* ========== Platform independent-type definitions
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OS2__)||defined(__EMX__)
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#include <os2.h>
|
||||
#else
|
||||
typedef char CHAR;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(__arch64__) || defined(__alpha)
|
||||
/* 64 bit architectures */
|
||||
|
||||
typedef signed char SBYTE; /* 1 byte, signed */
|
||||
typedef unsigned char UBYTE; /* 1 byte, unsigned */
|
||||
typedef signed short SWORD; /* 2 bytes, signed */
|
||||
typedef unsigned short UWORD; /* 2 bytes, unsigned */
|
||||
typedef signed int SLONG; /* 4 bytes, signed */
|
||||
typedef unsigned int ULONG; /* 4 bytes, unsigned */
|
||||
typedef int BOOL; /* 0=false, <>0 true */
|
||||
|
||||
#else
|
||||
/* 32 bit architectures */
|
||||
|
||||
typedef signed char SBYTE; /* 1 byte, signed */
|
||||
typedef unsigned char UBYTE; /* 1 byte, unsigned */
|
||||
typedef signed short SWORD; /* 2 bytes, signed */
|
||||
typedef unsigned short UWORD; /* 2 bytes, unsigned */
|
||||
typedef signed long SLONG; /* 4 bytes, signed */
|
||||
#if !defined(__OS2__)&&!defined(__EMX__)&&!defined(WIN32)
|
||||
typedef unsigned long ULONG; /* 4 bytes, unsigned */
|
||||
typedef int BOOL; /* 0=false, <>0 true */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Error codes
|
||||
*/
|
||||
|
||||
enum {
|
||||
MMERR_OPENING_FILE = 1,
|
||||
MMERR_OUT_OF_MEMORY,
|
||||
MMERR_DYNAMIC_LINKING,
|
||||
|
||||
MMERR_SAMPLE_TOO_BIG,
|
||||
MMERR_OUT_OF_HANDLES,
|
||||
MMERR_UNKNOWN_WAVE_TYPE,
|
||||
|
||||
MMERR_LOADING_PATTERN,
|
||||
MMERR_LOADING_TRACK,
|
||||
MMERR_LOADING_HEADER,
|
||||
MMERR_LOADING_SAMPLEINFO,
|
||||
MMERR_NOT_A_MODULE,
|
||||
MMERR_NOT_A_STREAM,
|
||||
MMERR_MED_SYNTHSAMPLES,
|
||||
MMERR_ITPACK_INVALID_DATA,
|
||||
|
||||
MMERR_DETECTING_DEVICE,
|
||||
MMERR_INVALID_DEVICE,
|
||||
MMERR_INITIALIZING_MIXER,
|
||||
MMERR_OPENING_AUDIO,
|
||||
MMERR_8BIT_ONLY,
|
||||
MMERR_16BIT_ONLY,
|
||||
MMERR_STEREO_ONLY,
|
||||
MMERR_ULAW,
|
||||
MMERR_NON_BLOCK,
|
||||
|
||||
MMERR_AF_AUDIO_PORT,
|
||||
|
||||
MMERR_AIX_CONFIG_INIT,
|
||||
MMERR_AIX_CONFIG_CONTROL,
|
||||
MMERR_AIX_CONFIG_START,
|
||||
|
||||
MMERR_GUS_SETTINGS,
|
||||
MMERR_GUS_RESET,
|
||||
MMERR_GUS_TIMER,
|
||||
|
||||
MMERR_HP_SETSAMPLESIZE,
|
||||
MMERR_HP_SETSPEED,
|
||||
MMERR_HP_CHANNELS,
|
||||
MMERR_HP_AUDIO_OUTPUT,
|
||||
MMERR_HP_AUDIO_DESC,
|
||||
MMERR_HP_BUFFERSIZE,
|
||||
|
||||
MMERR_OSS_SETFRAGMENT,
|
||||
MMERR_OSS_SETSAMPLESIZE,
|
||||
MMERR_OSS_SETSTEREO,
|
||||
MMERR_OSS_SETSPEED,
|
||||
|
||||
MMERR_SGI_SPEED,
|
||||
MMERR_SGI_16BIT,
|
||||
MMERR_SGI_8BIT,
|
||||
MMERR_SGI_STEREO,
|
||||
MMERR_SGI_MONO,
|
||||
|
||||
MMERR_SUN_INIT,
|
||||
|
||||
MMERR_OS2_MIXSETUP,
|
||||
MMERR_OS2_SEMAPHORE,
|
||||
MMERR_OS2_TIMER,
|
||||
MMERR_OS2_THREAD,
|
||||
|
||||
MMERR_DS_PRIORITY,
|
||||
MMERR_DS_BUFFER,
|
||||
MMERR_DS_FORMAT,
|
||||
MMERR_DS_NOTIFY,
|
||||
MMERR_DS_EVENT,
|
||||
MMERR_DS_THREAD,
|
||||
MMERR_DS_UPDATE,
|
||||
|
||||
MMERR_WINMM_HANDLE,
|
||||
MMERR_WINMM_ALLOCATED,
|
||||
MMERR_WINMM_DEVICEID,
|
||||
MMERR_WINMM_FORMAT,
|
||||
MMERR_WINMM_UNKNOWN,
|
||||
|
||||
MMERR_MAC_SPEED,
|
||||
MMERR_MAC_START,
|
||||
|
||||
MMERR_OSX_UNKNOWN_DEVICE,
|
||||
MMERR_OSX_BAD_PROPERTY,
|
||||
MMERR_OSX_UNSUPPORTED_FORMAT,
|
||||
MMERR_OSX_SET_STEREO,
|
||||
MMERR_OSX_BUFFER_ALLOC,
|
||||
MMERR_OSX_ADD_IO_PROC,
|
||||
MMERR_OSX_DEVICE_START,
|
||||
MMERR_OSX_PTHREAD,
|
||||
|
||||
MMERR_DOSWSS_STARTDMA,
|
||||
MMERR_DOSSB_STARTDMA,
|
||||
|
||||
MMERR_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* ========== Error handling
|
||||
*/
|
||||
|
||||
typedef void (MikMod_handler)(void);
|
||||
typedef MikMod_handler *MikMod_handler_t;
|
||||
|
||||
MIKMODAPI extern int MikMod_errno;
|
||||
MIKMODAPI extern BOOL MikMod_critical;
|
||||
MIKMODAPI extern char *MikMod_strerror(int);
|
||||
|
||||
MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t);
|
||||
|
||||
/*
|
||||
* ========== Library initialization and core functions
|
||||
*/
|
||||
|
||||
struct MDRIVER;
|
||||
|
||||
MIKMODAPI extern void MikMod_RegisterAllDrivers(void);
|
||||
|
||||
MIKMODAPI extern CHAR* MikMod_InfoDriver(void);
|
||||
MIKMODAPI extern void MikMod_RegisterDriver(struct MDRIVER*);
|
||||
MIKMODAPI extern int MikMod_DriverFromAlias(CHAR*);
|
||||
MIKMODAPI extern struct MDRIVER *MikMod_DriverByOrdinal(int);
|
||||
|
||||
MIKMODAPI extern BOOL MikMod_Init(CHAR*);
|
||||
MIKMODAPI extern void MikMod_Exit(void);
|
||||
MIKMODAPI extern BOOL MikMod_Reset(CHAR*);
|
||||
MIKMODAPI extern BOOL MikMod_SetNumVoices(int,int);
|
||||
MIKMODAPI extern BOOL MikMod_Active(void);
|
||||
MIKMODAPI extern BOOL MikMod_EnableOutput(void);
|
||||
MIKMODAPI extern void MikMod_DisableOutput(void);
|
||||
MIKMODAPI extern void MikMod_Update(void);
|
||||
|
||||
MIKMODAPI extern BOOL MikMod_InitThreads(void);
|
||||
MIKMODAPI extern void MikMod_Lock(void);
|
||||
MIKMODAPI extern void MikMod_Unlock(void);
|
||||
|
||||
/*
|
||||
* ========== Reader, Writer
|
||||
*/
|
||||
|
||||
typedef struct MREADER {
|
||||
BOOL (*Seek)(struct MREADER*,long,int);
|
||||
long (*Tell)(struct MREADER*);
|
||||
BOOL (*Read)(struct MREADER*,void*,size_t);
|
||||
int (*Get)(struct MREADER*);
|
||||
BOOL (*Eof)(struct MREADER*);
|
||||
} MREADER;
|
||||
|
||||
typedef struct MWRITER {
|
||||
BOOL (*Seek)(struct MWRITER*,long,int);
|
||||
long (*Tell)(struct MWRITER*);
|
||||
BOOL (*Write)(struct MWRITER*,void*,size_t);
|
||||
BOOL (*Put)(struct MWRITER*,int);
|
||||
} MWRITER;
|
||||
|
||||
/*
|
||||
* ========== Samples
|
||||
*/
|
||||
|
||||
/* Sample playback should not be interrupted */
|
||||
#define SFX_CRITICAL 1
|
||||
|
||||
/* Sample format [loading and in-memory] flags: */
|
||||
#define SF_16BITS 0x0001
|
||||
#define SF_STEREO 0x0002
|
||||
#define SF_SIGNED 0x0004
|
||||
#define SF_BIG_ENDIAN 0x0008
|
||||
#define SF_DELTA 0x0010
|
||||
#define SF_ITPACKED 0x0020
|
||||
|
||||
#define SF_FORMATMASK 0x003F
|
||||
|
||||
/* General Playback flags */
|
||||
|
||||
#define SF_LOOP 0x0100
|
||||
#define SF_BIDI 0x0200
|
||||
#define SF_REVERSE 0x0400
|
||||
#define SF_SUSTAIN 0x0800
|
||||
|
||||
#define SF_PLAYBACKMASK 0x0C00
|
||||
|
||||
/* Module-only Playback Flags */
|
||||
|
||||
#define SF_OWNPAN 0x1000
|
||||
#define SF_UST_LOOP 0x2000
|
||||
|
||||
#define SF_EXTRAPLAYBACKMASK 0x3000
|
||||
|
||||
/* Panning constants */
|
||||
#define PAN_LEFT 0
|
||||
#define PAN_HALFLEFT 64
|
||||
#define PAN_CENTER 128
|
||||
#define PAN_HALFRIGHT 192
|
||||
#define PAN_RIGHT 255
|
||||
#define PAN_SURROUND 512 /* panning value for Dolby Surround */
|
||||
|
||||
typedef struct SAMPLE {
|
||||
SWORD panning; /* panning (0-255 or PAN_SURROUND) */
|
||||
ULONG speed; /* Base playing speed/frequency of note */
|
||||
UBYTE volume; /* volume 0-64 */
|
||||
UWORD inflags; /* sample format on disk */
|
||||
UWORD flags; /* sample format in memory */
|
||||
ULONG length; /* length of sample (in samples!) */
|
||||
ULONG loopstart; /* repeat position (relative to start, in samples) */
|
||||
ULONG loopend; /* repeat end */
|
||||
ULONG susbegin; /* sustain loop begin (in samples) \ Not Supported */
|
||||
ULONG susend; /* sustain loop end / Yet! */
|
||||
|
||||
/* Variables used by the module player only! (ignored for sound effects) */
|
||||
UBYTE globvol; /* global volume */
|
||||
UBYTE vibflags; /* autovibrato flag stuffs */
|
||||
UBYTE vibtype; /* Vibratos moved from INSTRUMENT to SAMPLE */
|
||||
UBYTE vibsweep;
|
||||
UBYTE vibdepth;
|
||||
UBYTE vibrate;
|
||||
CHAR* samplename; /* name of the sample */
|
||||
|
||||
/* Values used internally only */
|
||||
UWORD avibpos; /* autovibrato pos [player use] */
|
||||
UBYTE divfactor; /* for sample scaling, maintains proper period slides */
|
||||
ULONG seekpos; /* seek position in file */
|
||||
SWORD handle; /* sample handle used by individual drivers */
|
||||
} SAMPLE;
|
||||
|
||||
/* Sample functions */
|
||||
|
||||
MIKMODAPI extern SAMPLE *Sample_Load(CHAR*);
|
||||
MIKMODAPI extern SAMPLE *Sample_LoadFP(FILE*);
|
||||
MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*);
|
||||
MIKMODAPI extern void Sample_Free(SAMPLE*);
|
||||
MIKMODAPI extern SBYTE Sample_Play(SAMPLE*,ULONG,UBYTE);
|
||||
|
||||
MIKMODAPI extern void Voice_SetVolume(SBYTE,UWORD);
|
||||
MIKMODAPI extern UWORD Voice_GetVolume(SBYTE);
|
||||
MIKMODAPI extern void Voice_SetFrequency(SBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG Voice_GetFrequency(SBYTE);
|
||||
MIKMODAPI extern void Voice_SetPanning(SBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG Voice_GetPanning(SBYTE);
|
||||
MIKMODAPI extern void Voice_Play(SBYTE,SAMPLE*,ULONG);
|
||||
MIKMODAPI extern void Voice_Stop(SBYTE);
|
||||
MIKMODAPI extern BOOL Voice_Stopped(SBYTE);
|
||||
MIKMODAPI extern SLONG Voice_GetPosition(SBYTE);
|
||||
MIKMODAPI extern ULONG Voice_RealVolume(SBYTE);
|
||||
|
||||
/*
|
||||
* ========== Internal module representation (UniMod)
|
||||
*/
|
||||
|
||||
/*
|
||||
Instrument definition - for information only, the only field which may be
|
||||
of use in user programs is the name field
|
||||
*/
|
||||
|
||||
/* Instrument note count */
|
||||
#define INSTNOTES 120
|
||||
|
||||
/* Envelope point */
|
||||
typedef struct ENVPT {
|
||||
SWORD pos;
|
||||
SWORD val;
|
||||
} ENVPT;
|
||||
|
||||
/* Envelope point count */
|
||||
#define ENVPOINTS 32
|
||||
|
||||
/* Instrument structure */
|
||||
typedef struct INSTRUMENT {
|
||||
CHAR* insname;
|
||||
|
||||
UBYTE flags;
|
||||
UWORD samplenumber[INSTNOTES];
|
||||
UBYTE samplenote[INSTNOTES];
|
||||
|
||||
UBYTE nnatype;
|
||||
UBYTE dca; /* duplicate check action */
|
||||
UBYTE dct; /* duplicate check type */
|
||||
UBYTE globvol;
|
||||
UWORD volfade;
|
||||
SWORD panning; /* instrument-based panning var */
|
||||
|
||||
UBYTE pitpansep; /* pitch pan separation (0 to 255) */
|
||||
UBYTE pitpancenter; /* pitch pan center (0 to 119) */
|
||||
UBYTE rvolvar; /* random volume varations (0 - 100%) */
|
||||
UBYTE rpanvar; /* random panning varations (0 - 100%) */
|
||||
|
||||
/* volume envelope */
|
||||
UBYTE volflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE volpts;
|
||||
UBYTE volsusbeg;
|
||||
UBYTE volsusend;
|
||||
UBYTE volbeg;
|
||||
UBYTE volend;
|
||||
ENVPT volenv[ENVPOINTS];
|
||||
/* panning envelope */
|
||||
UBYTE panflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE panpts;
|
||||
UBYTE pansusbeg;
|
||||
UBYTE pansusend;
|
||||
UBYTE panbeg;
|
||||
UBYTE panend;
|
||||
ENVPT panenv[ENVPOINTS];
|
||||
/* pitch envelope */
|
||||
UBYTE pitflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE pitpts;
|
||||
UBYTE pitsusbeg;
|
||||
UBYTE pitsusend;
|
||||
UBYTE pitbeg;
|
||||
UBYTE pitend;
|
||||
ENVPT pitenv[ENVPOINTS];
|
||||
} INSTRUMENT;
|
||||
|
||||
struct MP_CONTROL;
|
||||
struct MP_VOICE;
|
||||
|
||||
/*
|
||||
Module definition
|
||||
*/
|
||||
|
||||
/* maximum master channels supported */
|
||||
#define UF_MAXCHAN 64
|
||||
|
||||
/* Module flags */
|
||||
#define UF_XMPERIODS 0x0001 /* XM periods / finetuning */
|
||||
#define UF_LINEAR 0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */
|
||||
#define UF_INST 0x0004 /* Instruments are used */
|
||||
#define UF_NNA 0x0008 /* IT: NNA used, set numvoices rather
|
||||
than numchn */
|
||||
#define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */
|
||||
#define UF_BGSLIDES 0x0020 /* continue volume slides in the background */
|
||||
#define UF_HIGHBPM 0x0040 /* MED: can use >255 bpm */
|
||||
#define UF_NOWRAP 0x0080 /* XM-type (i.e. illogical) pattern break
|
||||
semantics */
|
||||
#define UF_ARPMEM 0x0100 /* IT: need arpeggio memory */
|
||||
#define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */
|
||||
#define UF_PANNING 0x0400 /* module uses panning effects or have
|
||||
non-tracker default initial panning */
|
||||
|
||||
typedef struct MODULE {
|
||||
/* general module information */
|
||||
CHAR* songname; /* name of the song */
|
||||
CHAR* modtype; /* string type of module loaded */
|
||||
CHAR* comment; /* module comments */
|
||||
|
||||
UWORD flags; /* See module flags above */
|
||||
UBYTE numchn; /* number of module channels */
|
||||
UBYTE numvoices; /* max # voices used for full NNA playback */
|
||||
UWORD numpos; /* number of positions in this song */
|
||||
UWORD numpat; /* number of patterns in this song */
|
||||
UWORD numins; /* number of instruments */
|
||||
UWORD numsmp; /* number of samples */
|
||||
struct INSTRUMENT* instruments; /* all instruments */
|
||||
struct SAMPLE* samples; /* all samples */
|
||||
UBYTE realchn; /* real number of channels used */
|
||||
UBYTE totalchn; /* total number of channels used (incl NNAs) */
|
||||
|
||||
/* playback settings */
|
||||
UWORD reppos; /* restart position */
|
||||
UBYTE initspeed; /* initial song speed */
|
||||
UWORD inittempo; /* initial song tempo */
|
||||
UBYTE initvolume; /* initial global volume (0 - 128) */
|
||||
UWORD panning[UF_MAXCHAN]; /* panning positions */
|
||||
UBYTE chanvol[UF_MAXCHAN]; /* channel positions */
|
||||
UWORD bpm; /* current beats-per-minute speed */
|
||||
UWORD sngspd; /* current song speed */
|
||||
SWORD volume; /* song volume (0-128) (or user volume) */
|
||||
|
||||
BOOL extspd; /* extended speed flag (default enabled) */
|
||||
BOOL panflag; /* panning flag (default enabled) */
|
||||
BOOL wrap; /* wrap module ? (default disabled) */
|
||||
BOOL loop; /* allow module to loop ? (default enabled) */
|
||||
BOOL fadeout; /* volume fade out during last pattern */
|
||||
|
||||
UWORD patpos; /* current row number */
|
||||
SWORD sngpos; /* current song position */
|
||||
ULONG sngtime; /* current song time in 2^-10 seconds */
|
||||
|
||||
SWORD relspd; /* relative speed factor */
|
||||
|
||||
/* internal module representation */
|
||||
UWORD numtrk; /* number of tracks */
|
||||
UBYTE** tracks; /* array of numtrk pointers to tracks */
|
||||
UWORD* patterns; /* array of Patterns */
|
||||
UWORD* pattrows; /* array of number of rows for each pattern */
|
||||
UWORD* positions; /* all positions */
|
||||
|
||||
BOOL forbid; /* if true, no player update! */
|
||||
UWORD numrow; /* number of rows on current pattern */
|
||||
UWORD vbtick; /* tick counter (counts from 0 to sngspd) */
|
||||
UWORD sngremainder;/* used for song time computation */
|
||||
|
||||
struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */
|
||||
struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */
|
||||
|
||||
UBYTE globalslide; /* global volume slide rate */
|
||||
UBYTE pat_repcrazy;/* module has just looped to position -1 */
|
||||
UWORD patbrk; /* position where to start a new pattern */
|
||||
UBYTE patdly; /* patterndelay counter (command memory) */
|
||||
UBYTE patdly2; /* patterndelay counter (real one) */
|
||||
SWORD posjmp; /* flag to indicate a jump is needed... */
|
||||
UWORD bpmlimit; /* threshold to detect bpm or speed values */
|
||||
} MODULE;
|
||||
|
||||
|
||||
/* This structure is used to query current playing voices status */
|
||||
typedef struct VOICEINFO {
|
||||
INSTRUMENT* i; /* Current channel instrument */
|
||||
SAMPLE* s; /* Current channel sample */
|
||||
SWORD panning; /* panning position */
|
||||
SBYTE volume; /* channel's "global" volume (0..64) */
|
||||
UWORD period; /* period to play the sample at */
|
||||
UBYTE kick; /* if true = sample has been restarted */
|
||||
} VOICEINFO;
|
||||
|
||||
/*
|
||||
* ========== Module loaders
|
||||
*/
|
||||
|
||||
struct MLOADER;
|
||||
|
||||
MIKMODAPI extern CHAR* MikMod_InfoLoader(void);
|
||||
MIKMODAPI extern void MikMod_RegisterAllLoaders(void);
|
||||
MIKMODAPI extern void MikMod_RegisterLoader(struct MLOADER*);
|
||||
|
||||
MIKMODAPI extern struct MLOADER load_669; /* 669 and Extended-669 (by Tran/Renaissance) */
|
||||
MIKMODAPI extern struct MLOADER load_amf; /* DMP Advanced Module Format (by Otto Chrons) */
|
||||
MIKMODAPI extern struct MLOADER load_asy; /* ASYLUM Music Format 1.0 */
|
||||
MIKMODAPI extern struct MLOADER load_dsm; /* DSIK internal module format */
|
||||
MIKMODAPI extern struct MLOADER load_far; /* Farandole Composer (by Daniel Potter) */
|
||||
MIKMODAPI extern struct MLOADER load_gdm; /* General DigiMusic (by Edward Schlunder) */
|
||||
MIKMODAPI extern struct MLOADER load_it; /* Impulse Tracker (by Jeffrey Lim) */
|
||||
MIKMODAPI extern struct MLOADER load_imf; /* Imago Orpheus (by Lutz Roeder) */
|
||||
MIKMODAPI extern struct MLOADER load_med; /* Amiga MED modules (by Teijo Kinnunen) */
|
||||
MIKMODAPI extern struct MLOADER load_m15; /* Soundtracker 15-instrument */
|
||||
MIKMODAPI extern struct MLOADER load_mod; /* Standard 31-instrument Module loader */
|
||||
MIKMODAPI extern struct MLOADER load_mtm; /* Multi-Tracker Module (by Renaissance) */
|
||||
MIKMODAPI extern struct MLOADER load_okt; /* Amiga Oktalyzer */
|
||||
MIKMODAPI extern struct MLOADER load_stm; /* ScreamTracker 2 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker (by MAS) */
|
||||
MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */
|
||||
MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */
|
||||
|
||||
/*
|
||||
* ========== Module player
|
||||
*/
|
||||
|
||||
MIKMODAPI extern MODULE* Player_Load(CHAR*,int,BOOL);
|
||||
MIKMODAPI extern MODULE* Player_LoadFP(FILE*,int,BOOL);
|
||||
MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,BOOL);
|
||||
MIKMODAPI extern CHAR* Player_LoadTitle(CHAR*);
|
||||
MIKMODAPI extern CHAR* Player_LoadTitleFP(FILE*);
|
||||
MIKMODAPI extern void Player_Free(MODULE*);
|
||||
MIKMODAPI extern void Player_Start(MODULE*);
|
||||
MIKMODAPI extern BOOL Player_Active(void);
|
||||
MIKMODAPI extern void Player_Stop(void);
|
||||
MIKMODAPI extern void Player_TogglePause(void);
|
||||
MIKMODAPI extern BOOL Player_Paused(void);
|
||||
MIKMODAPI extern void Player_NextPosition(void);
|
||||
MIKMODAPI extern void Player_PrevPosition(void);
|
||||
MIKMODAPI extern void Player_SetPosition(UWORD);
|
||||
MIKMODAPI extern BOOL Player_Muted(UBYTE);
|
||||
MIKMODAPI extern void Player_SetVolume(SWORD);
|
||||
MIKMODAPI extern MODULE* Player_GetModule(void);
|
||||
MIKMODAPI extern void Player_SetSpeed(UWORD);
|
||||
MIKMODAPI extern void Player_SetTempo(UWORD);
|
||||
MIKMODAPI extern void Player_Unmute(SLONG,...);
|
||||
MIKMODAPI extern void Player_Mute(SLONG,...);
|
||||
MIKMODAPI extern void Player_ToggleMute(SLONG,...);
|
||||
MIKMODAPI extern int Player_GetChannelVoice(UBYTE);
|
||||
MIKMODAPI extern UWORD Player_GetChannelPeriod(UBYTE);
|
||||
MIKMODAPI extern int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo);
|
||||
|
||||
typedef void (MikMod_player)(void);
|
||||
typedef MikMod_player *MikMod_player_t;
|
||||
|
||||
MIKMODAPI extern MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t);
|
||||
|
||||
#define MUTE_EXCLUSIVE 32000
|
||||
#define MUTE_INCLUSIVE 32001
|
||||
|
||||
/*
|
||||
* ========== Drivers
|
||||
*/
|
||||
|
||||
enum {
|
||||
MD_MUSIC = 0,
|
||||
MD_SNDFX
|
||||
};
|
||||
|
||||
enum {
|
||||
MD_HARDWARE = 0,
|
||||
MD_SOFTWARE
|
||||
};
|
||||
|
||||
/* Mixing flags */
|
||||
|
||||
/* These ones take effect only after MikMod_Init or MikMod_Reset */
|
||||
#define DMODE_16BITS 0x0001 /* enable 16 bit output */
|
||||
#define DMODE_STEREO 0x0002 /* enable stereo output */
|
||||
#define DMODE_SOFT_SNDFX 0x0004 /* Process sound effects via software mixer */
|
||||
#define DMODE_SOFT_MUSIC 0x0008 /* Process music via software mixer */
|
||||
#define DMODE_HQMIXER 0x0010 /* Use high-quality (slower) software mixer */
|
||||
#define DMODE_FLOAT 0x0020 /* enable float output */
|
||||
/* These take effect immediately. */
|
||||
#define DMODE_SURROUND 0x0100 /* enable surround sound */
|
||||
#define DMODE_INTERP 0x0200 /* enable interpolation */
|
||||
#define DMODE_REVERSE 0x0400 /* reverse stereo */
|
||||
|
||||
struct SAMPLOAD;
|
||||
typedef struct MDRIVER {
|
||||
struct MDRIVER* next;
|
||||
CHAR* Name;
|
||||
CHAR* Version;
|
||||
|
||||
UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */
|
||||
UBYTE SoftVoiceLimit; /* Limit of software mixer voices */
|
||||
|
||||
CHAR *Alias;
|
||||
CHAR *CmdLineHelp;
|
||||
|
||||
void (*CommandLine) (CHAR*);
|
||||
BOOL (*IsPresent) (void);
|
||||
SWORD (*SampleLoad) (struct SAMPLOAD*,int);
|
||||
void (*SampleUnload) (SWORD);
|
||||
ULONG (*FreeSampleSpace) (int);
|
||||
ULONG (*RealSampleLength) (int,struct SAMPLE*);
|
||||
BOOL (*Init) (void);
|
||||
void (*Exit) (void);
|
||||
BOOL (*Reset) (void);
|
||||
BOOL (*SetNumVoices) (void);
|
||||
BOOL (*PlayStart) (void);
|
||||
void (*PlayStop) (void);
|
||||
void (*Update) (void);
|
||||
void (*Pause) (void);
|
||||
void (*VoiceSetVolume) (UBYTE,UWORD);
|
||||
UWORD (*VoiceGetVolume) (UBYTE);
|
||||
void (*VoiceSetFrequency)(UBYTE,ULONG);
|
||||
ULONG (*VoiceGetFrequency)(UBYTE);
|
||||
void (*VoiceSetPanning) (UBYTE,ULONG);
|
||||
ULONG (*VoiceGetPanning) (UBYTE);
|
||||
void (*VoicePlay) (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
void (*VoiceStop) (UBYTE);
|
||||
BOOL (*VoiceStopped) (UBYTE);
|
||||
SLONG (*VoiceGetPosition) (UBYTE);
|
||||
ULONG (*VoiceRealVolume) (UBYTE);
|
||||
} MDRIVER;
|
||||
|
||||
/* These variables can be changed at ANY time and results will be immediate */
|
||||
MIKMODAPI extern UBYTE md_volume; /* global sound volume (0-128) */
|
||||
MIKMODAPI extern UBYTE md_musicvolume; /* volume of song */
|
||||
MIKMODAPI extern UBYTE md_sndfxvolume; /* volume of sound effects */
|
||||
MIKMODAPI extern UBYTE md_reverb; /* 0 = none; 15 = chaos */
|
||||
MIKMODAPI extern UBYTE md_pansep; /* 0 = mono; 128 == 100% (full left/right) */
|
||||
|
||||
/* The variables below can be changed at any time, but changes will not be
|
||||
implemented until MikMod_Reset is called. A call to MikMod_Reset may result
|
||||
in a skip or pop in audio (depending on the soundcard driver and the settings
|
||||
changed). */
|
||||
MIKMODAPI extern UWORD md_device; /* device */
|
||||
MIKMODAPI extern UWORD md_mixfreq; /* mixing frequency */
|
||||
MIKMODAPI extern UWORD md_mode; /* mode. See DMODE_? flags above */
|
||||
|
||||
/* The following variable should not be changed! */
|
||||
MIKMODAPI extern MDRIVER* md_driver; /* Current driver in use. */
|
||||
|
||||
/* Known drivers list */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */
|
||||
MIKMODAPI extern struct MDRIVER drv_pipe; /* piped output */
|
||||
MIKMODAPI extern struct MDRIVER drv_raw; /* raw file disk writer [music.raw] */
|
||||
MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */
|
||||
MIKMODAPI extern struct MDRIVER drv_wav; /* RIFF WAVE file disk writer [music.wav] */
|
||||
MIKMODAPI extern struct MDRIVER drv_aiff; /* AIFF file disk writer [music.aiff] */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_ultra; /* Linux Ultrasound driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_sam9407; /* Linux sam9407 driver */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_AF; /* Dec Alpha AudioFile */
|
||||
MIKMODAPI extern struct MDRIVER drv_aix; /* AIX audio device */
|
||||
MIKMODAPI extern struct MDRIVER drv_alsa; /* Advanced Linux Sound Architecture (ALSA) */
|
||||
MIKMODAPI extern struct MDRIVER drv_esd; /* Enlightened sound daemon (EsounD) */
|
||||
MIKMODAPI extern struct MDRIVER drv_hp; /* HP-UX audio device */
|
||||
MIKMODAPI extern struct MDRIVER drv_oss; /* OpenSound System (Linux,FreeBSD...) */
|
||||
MIKMODAPI extern struct MDRIVER drv_sgi; /* SGI audio library */
|
||||
MIKMODAPI extern struct MDRIVER drv_sun; /* Sun/NetBSD/OpenBSD audio device */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_dart; /* OS/2 Direct Audio RealTime */
|
||||
MIKMODAPI extern struct MDRIVER drv_os2; /* OS/2 MMPM/2 */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_ds; /* Win32 DirectSound driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_win; /* Win32 multimedia API driver */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_mac; /* Macintosh Sound Manager driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_osx; /* MacOS X CoreAudio Driver */
|
||||
|
||||
/*========== Virtual channel mixer interface (for user-supplied drivers only) */
|
||||
|
||||
MIKMODAPI extern BOOL VC_Init(void);
|
||||
MIKMODAPI extern void VC_Exit(void);
|
||||
MIKMODAPI extern BOOL VC_SetNumVoices(void);
|
||||
MIKMODAPI extern ULONG VC_SampleSpace(int);
|
||||
MIKMODAPI extern ULONG VC_SampleLength(int,SAMPLE*);
|
||||
|
||||
MIKMODAPI extern BOOL VC_PlayStart(void);
|
||||
MIKMODAPI extern void VC_PlayStop(void);
|
||||
|
||||
MIKMODAPI extern SWORD VC_SampleLoad(struct SAMPLOAD*,int);
|
||||
MIKMODAPI extern void VC_SampleUnload(SWORD);
|
||||
|
||||
MIKMODAPI extern ULONG VC_WriteBytes(SBYTE*,ULONG);
|
||||
MIKMODAPI extern ULONG VC_SilenceBytes(SBYTE*,ULONG);
|
||||
|
||||
MIKMODAPI extern void VC_VoiceSetVolume(UBYTE,UWORD);
|
||||
MIKMODAPI extern UWORD VC_VoiceGetVolume(UBYTE);
|
||||
MIKMODAPI extern void VC_VoiceSetFrequency(UBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG VC_VoiceGetFrequency(UBYTE);
|
||||
MIKMODAPI extern void VC_VoiceSetPanning(UBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG VC_VoiceGetPanning(UBYTE);
|
||||
MIKMODAPI extern void VC_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
|
||||
MIKMODAPI extern void VC_VoiceStop(UBYTE);
|
||||
MIKMODAPI extern BOOL VC_VoiceStopped(UBYTE);
|
||||
MIKMODAPI extern SLONG VC_VoiceGetPosition(UBYTE);
|
||||
MIKMODAPI extern ULONG VC_VoiceRealVolume(UBYTE);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
747
project/jni/mikmod/include/mikmod_build.h
Normal file
747
project/jni/mikmod/include/mikmod_build.h
Normal file
@@ -0,0 +1,747 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mikmod.h.in,v 1.11 2004/02/18 14:10:39 raph Exp $
|
||||
|
||||
MikMod sound library include file
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef _MIKMOD_H_
|
||||
#define _MIKMOD_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Compiler magic for shared libraries
|
||||
*/
|
||||
|
||||
#if defined WIN32 && defined _DLL
|
||||
#ifdef DLL_EXPORTS
|
||||
#define MIKMODAPI __declspec(dllexport)
|
||||
#else
|
||||
#define MIKMODAPI __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define MIKMODAPI
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Library version
|
||||
*/
|
||||
|
||||
#define LIBMIKMOD_VERSION_MAJOR 3L
|
||||
#define LIBMIKMOD_VERSION_MINOR 2L
|
||||
#define LIBMIKMOD_REVISION 0L
|
||||
|
||||
#define LIBMIKMOD_VERSION \
|
||||
((LIBMIKMOD_VERSION_MAJOR<<16)| \
|
||||
(LIBMIKMOD_VERSION_MINOR<< 8)| \
|
||||
(LIBMIKMOD_REVISION))
|
||||
|
||||
MIKMODAPI extern long MikMod_GetVersion(void);
|
||||
|
||||
/*
|
||||
* ========== Platform independent-type definitions
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OS2__)||defined(__EMX__)
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#include <os2.h>
|
||||
#else
|
||||
typedef char CHAR;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(__arch64__) || defined(__alpha)
|
||||
/* 64 bit architectures */
|
||||
|
||||
typedef signed char SBYTE; /* 1 byte, signed */
|
||||
typedef unsigned char UBYTE; /* 1 byte, unsigned */
|
||||
typedef signed short SWORD; /* 2 bytes, signed */
|
||||
typedef unsigned short UWORD; /* 2 bytes, unsigned */
|
||||
typedef signed int SLONG; /* 4 bytes, signed */
|
||||
typedef unsigned int ULONG; /* 4 bytes, unsigned */
|
||||
typedef int BOOL; /* 0=false, <>0 true */
|
||||
|
||||
#else
|
||||
/* 32 bit architectures */
|
||||
|
||||
typedef signed char SBYTE; /* 1 byte, signed */
|
||||
typedef unsigned char UBYTE; /* 1 byte, unsigned */
|
||||
typedef signed short SWORD; /* 2 bytes, signed */
|
||||
typedef unsigned short UWORD; /* 2 bytes, unsigned */
|
||||
typedef signed long SLONG; /* 4 bytes, signed */
|
||||
#if !defined(__OS2__)&&!defined(__EMX__)&&!defined(WIN32)
|
||||
typedef unsigned long ULONG; /* 4 bytes, unsigned */
|
||||
typedef int BOOL; /* 0=false, <>0 true */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ========== Error codes
|
||||
*/
|
||||
|
||||
enum {
|
||||
MMERR_OPENING_FILE = 1,
|
||||
MMERR_OUT_OF_MEMORY,
|
||||
MMERR_DYNAMIC_LINKING,
|
||||
|
||||
MMERR_SAMPLE_TOO_BIG,
|
||||
MMERR_OUT_OF_HANDLES,
|
||||
MMERR_UNKNOWN_WAVE_TYPE,
|
||||
|
||||
MMERR_LOADING_PATTERN,
|
||||
MMERR_LOADING_TRACK,
|
||||
MMERR_LOADING_HEADER,
|
||||
MMERR_LOADING_SAMPLEINFO,
|
||||
MMERR_NOT_A_MODULE,
|
||||
MMERR_NOT_A_STREAM,
|
||||
MMERR_MED_SYNTHSAMPLES,
|
||||
MMERR_ITPACK_INVALID_DATA,
|
||||
|
||||
MMERR_DETECTING_DEVICE,
|
||||
MMERR_INVALID_DEVICE,
|
||||
MMERR_INITIALIZING_MIXER,
|
||||
MMERR_OPENING_AUDIO,
|
||||
MMERR_8BIT_ONLY,
|
||||
MMERR_16BIT_ONLY,
|
||||
MMERR_STEREO_ONLY,
|
||||
MMERR_ULAW,
|
||||
MMERR_NON_BLOCK,
|
||||
|
||||
MMERR_AF_AUDIO_PORT,
|
||||
|
||||
MMERR_AIX_CONFIG_INIT,
|
||||
MMERR_AIX_CONFIG_CONTROL,
|
||||
MMERR_AIX_CONFIG_START,
|
||||
|
||||
MMERR_GUS_SETTINGS,
|
||||
MMERR_GUS_RESET,
|
||||
MMERR_GUS_TIMER,
|
||||
|
||||
MMERR_HP_SETSAMPLESIZE,
|
||||
MMERR_HP_SETSPEED,
|
||||
MMERR_HP_CHANNELS,
|
||||
MMERR_HP_AUDIO_OUTPUT,
|
||||
MMERR_HP_AUDIO_DESC,
|
||||
MMERR_HP_BUFFERSIZE,
|
||||
|
||||
MMERR_OSS_SETFRAGMENT,
|
||||
MMERR_OSS_SETSAMPLESIZE,
|
||||
MMERR_OSS_SETSTEREO,
|
||||
MMERR_OSS_SETSPEED,
|
||||
|
||||
MMERR_SGI_SPEED,
|
||||
MMERR_SGI_16BIT,
|
||||
MMERR_SGI_8BIT,
|
||||
MMERR_SGI_STEREO,
|
||||
MMERR_SGI_MONO,
|
||||
|
||||
MMERR_SUN_INIT,
|
||||
|
||||
MMERR_OS2_MIXSETUP,
|
||||
MMERR_OS2_SEMAPHORE,
|
||||
MMERR_OS2_TIMER,
|
||||
MMERR_OS2_THREAD,
|
||||
|
||||
MMERR_DS_PRIORITY,
|
||||
MMERR_DS_BUFFER,
|
||||
MMERR_DS_FORMAT,
|
||||
MMERR_DS_NOTIFY,
|
||||
MMERR_DS_EVENT,
|
||||
MMERR_DS_THREAD,
|
||||
MMERR_DS_UPDATE,
|
||||
|
||||
MMERR_WINMM_HANDLE,
|
||||
MMERR_WINMM_ALLOCATED,
|
||||
MMERR_WINMM_DEVICEID,
|
||||
MMERR_WINMM_FORMAT,
|
||||
MMERR_WINMM_UNKNOWN,
|
||||
|
||||
MMERR_MAC_SPEED,
|
||||
MMERR_MAC_START,
|
||||
|
||||
MMERR_OSX_UNKNOWN_DEVICE,
|
||||
MMERR_OSX_BAD_PROPERTY,
|
||||
MMERR_OSX_UNSUPPORTED_FORMAT,
|
||||
MMERR_OSX_SET_STEREO,
|
||||
MMERR_OSX_BUFFER_ALLOC,
|
||||
MMERR_OSX_ADD_IO_PROC,
|
||||
MMERR_OSX_DEVICE_START,
|
||||
MMERR_OSX_PTHREAD,
|
||||
|
||||
MMERR_DOSWSS_STARTDMA,
|
||||
MMERR_DOSSB_STARTDMA,
|
||||
|
||||
MMERR_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* ========== Error handling
|
||||
*/
|
||||
|
||||
typedef void (MikMod_handler)(void);
|
||||
typedef MikMod_handler *MikMod_handler_t;
|
||||
|
||||
MIKMODAPI extern int MikMod_errno;
|
||||
MIKMODAPI extern BOOL MikMod_critical;
|
||||
MIKMODAPI extern char *MikMod_strerror(int);
|
||||
|
||||
MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t);
|
||||
|
||||
/*
|
||||
* ========== Library initialization and core functions
|
||||
*/
|
||||
|
||||
struct MDRIVER;
|
||||
|
||||
MIKMODAPI extern void MikMod_RegisterAllDrivers(void);
|
||||
|
||||
MIKMODAPI extern CHAR* MikMod_InfoDriver(void);
|
||||
MIKMODAPI extern void MikMod_RegisterDriver(struct MDRIVER*);
|
||||
MIKMODAPI extern int MikMod_DriverFromAlias(CHAR*);
|
||||
MIKMODAPI extern struct MDRIVER *MikMod_DriverByOrdinal(int);
|
||||
|
||||
MIKMODAPI extern BOOL MikMod_Init(CHAR*);
|
||||
MIKMODAPI extern void MikMod_Exit(void);
|
||||
MIKMODAPI extern BOOL MikMod_Reset(CHAR*);
|
||||
MIKMODAPI extern BOOL MikMod_SetNumVoices(int,int);
|
||||
MIKMODAPI extern BOOL MikMod_Active(void);
|
||||
MIKMODAPI extern BOOL MikMod_EnableOutput(void);
|
||||
MIKMODAPI extern void MikMod_DisableOutput(void);
|
||||
MIKMODAPI extern void MikMod_Update(void);
|
||||
|
||||
MIKMODAPI extern BOOL MikMod_InitThreads(void);
|
||||
MIKMODAPI extern void MikMod_Lock(void);
|
||||
MIKMODAPI extern void MikMod_Unlock(void);
|
||||
|
||||
/*
|
||||
* ========== Reader, Writer
|
||||
*/
|
||||
|
||||
typedef struct MREADER {
|
||||
BOOL (*Seek)(struct MREADER*,long,int);
|
||||
long (*Tell)(struct MREADER*);
|
||||
BOOL (*Read)(struct MREADER*,void*,size_t);
|
||||
int (*Get)(struct MREADER*);
|
||||
BOOL (*Eof)(struct MREADER*);
|
||||
} MREADER;
|
||||
|
||||
typedef struct MWRITER {
|
||||
BOOL (*Seek)(struct MWRITER*,long,int);
|
||||
long (*Tell)(struct MWRITER*);
|
||||
BOOL (*Write)(struct MWRITER*,void*,size_t);
|
||||
BOOL (*Put)(struct MWRITER*,int);
|
||||
} MWRITER;
|
||||
|
||||
/*
|
||||
* ========== Samples
|
||||
*/
|
||||
|
||||
/* Sample playback should not be interrupted */
|
||||
#define SFX_CRITICAL 1
|
||||
|
||||
/* Sample format [loading and in-memory] flags: */
|
||||
#define SF_16BITS 0x0001
|
||||
#define SF_STEREO 0x0002
|
||||
#define SF_SIGNED 0x0004
|
||||
#define SF_BIG_ENDIAN 0x0008
|
||||
#define SF_DELTA 0x0010
|
||||
#define SF_ITPACKED 0x0020
|
||||
|
||||
#define SF_FORMATMASK 0x003F
|
||||
|
||||
/* General Playback flags */
|
||||
|
||||
#define SF_LOOP 0x0100
|
||||
#define SF_BIDI 0x0200
|
||||
#define SF_REVERSE 0x0400
|
||||
#define SF_SUSTAIN 0x0800
|
||||
|
||||
#define SF_PLAYBACKMASK 0x0C00
|
||||
|
||||
/* Module-only Playback Flags */
|
||||
|
||||
#define SF_OWNPAN 0x1000
|
||||
#define SF_UST_LOOP 0x2000
|
||||
|
||||
#define SF_EXTRAPLAYBACKMASK 0x3000
|
||||
|
||||
/* Panning constants */
|
||||
#define PAN_LEFT 0
|
||||
#define PAN_HALFLEFT 64
|
||||
#define PAN_CENTER 128
|
||||
#define PAN_HALFRIGHT 192
|
||||
#define PAN_RIGHT 255
|
||||
#define PAN_SURROUND 512 /* panning value for Dolby Surround */
|
||||
|
||||
typedef struct SAMPLE {
|
||||
SWORD panning; /* panning (0-255 or PAN_SURROUND) */
|
||||
ULONG speed; /* Base playing speed/frequency of note */
|
||||
UBYTE volume; /* volume 0-64 */
|
||||
UWORD inflags; /* sample format on disk */
|
||||
UWORD flags; /* sample format in memory */
|
||||
ULONG length; /* length of sample (in samples!) */
|
||||
ULONG loopstart; /* repeat position (relative to start, in samples) */
|
||||
ULONG loopend; /* repeat end */
|
||||
ULONG susbegin; /* sustain loop begin (in samples) \ Not Supported */
|
||||
ULONG susend; /* sustain loop end / Yet! */
|
||||
|
||||
/* Variables used by the module player only! (ignored for sound effects) */
|
||||
UBYTE globvol; /* global volume */
|
||||
UBYTE vibflags; /* autovibrato flag stuffs */
|
||||
UBYTE vibtype; /* Vibratos moved from INSTRUMENT to SAMPLE */
|
||||
UBYTE vibsweep;
|
||||
UBYTE vibdepth;
|
||||
UBYTE vibrate;
|
||||
CHAR* samplename; /* name of the sample */
|
||||
|
||||
/* Values used internally only */
|
||||
UWORD avibpos; /* autovibrato pos [player use] */
|
||||
UBYTE divfactor; /* for sample scaling, maintains proper period slides */
|
||||
ULONG seekpos; /* seek position in file */
|
||||
SWORD handle; /* sample handle used by individual drivers */
|
||||
} SAMPLE;
|
||||
|
||||
/* Sample functions */
|
||||
|
||||
MIKMODAPI extern SAMPLE *Sample_Load(CHAR*);
|
||||
MIKMODAPI extern SAMPLE *Sample_LoadFP(FILE*);
|
||||
MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*);
|
||||
MIKMODAPI extern void Sample_Free(SAMPLE*);
|
||||
MIKMODAPI extern SBYTE Sample_Play(SAMPLE*,ULONG,UBYTE);
|
||||
|
||||
MIKMODAPI extern void Voice_SetVolume(SBYTE,UWORD);
|
||||
MIKMODAPI extern UWORD Voice_GetVolume(SBYTE);
|
||||
MIKMODAPI extern void Voice_SetFrequency(SBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG Voice_GetFrequency(SBYTE);
|
||||
MIKMODAPI extern void Voice_SetPanning(SBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG Voice_GetPanning(SBYTE);
|
||||
MIKMODAPI extern void Voice_Play(SBYTE,SAMPLE*,ULONG);
|
||||
MIKMODAPI extern void Voice_Stop(SBYTE);
|
||||
MIKMODAPI extern BOOL Voice_Stopped(SBYTE);
|
||||
MIKMODAPI extern SLONG Voice_GetPosition(SBYTE);
|
||||
MIKMODAPI extern ULONG Voice_RealVolume(SBYTE);
|
||||
|
||||
/*
|
||||
* ========== Internal module representation (UniMod)
|
||||
*/
|
||||
|
||||
/*
|
||||
Instrument definition - for information only, the only field which may be
|
||||
of use in user programs is the name field
|
||||
*/
|
||||
|
||||
/* Instrument note count */
|
||||
#define INSTNOTES 120
|
||||
|
||||
/* Envelope point */
|
||||
typedef struct ENVPT {
|
||||
SWORD pos;
|
||||
SWORD val;
|
||||
} ENVPT;
|
||||
|
||||
/* Envelope point count */
|
||||
#define ENVPOINTS 32
|
||||
|
||||
/* Instrument structure */
|
||||
typedef struct INSTRUMENT {
|
||||
CHAR* insname;
|
||||
|
||||
UBYTE flags;
|
||||
UWORD samplenumber[INSTNOTES];
|
||||
UBYTE samplenote[INSTNOTES];
|
||||
|
||||
UBYTE nnatype;
|
||||
UBYTE dca; /* duplicate check action */
|
||||
UBYTE dct; /* duplicate check type */
|
||||
UBYTE globvol;
|
||||
UWORD volfade;
|
||||
SWORD panning; /* instrument-based panning var */
|
||||
|
||||
UBYTE pitpansep; /* pitch pan separation (0 to 255) */
|
||||
UBYTE pitpancenter; /* pitch pan center (0 to 119) */
|
||||
UBYTE rvolvar; /* random volume varations (0 - 100%) */
|
||||
UBYTE rpanvar; /* random panning varations (0 - 100%) */
|
||||
|
||||
/* volume envelope */
|
||||
UBYTE volflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE volpts;
|
||||
UBYTE volsusbeg;
|
||||
UBYTE volsusend;
|
||||
UBYTE volbeg;
|
||||
UBYTE volend;
|
||||
ENVPT volenv[ENVPOINTS];
|
||||
/* panning envelope */
|
||||
UBYTE panflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE panpts;
|
||||
UBYTE pansusbeg;
|
||||
UBYTE pansusend;
|
||||
UBYTE panbeg;
|
||||
UBYTE panend;
|
||||
ENVPT panenv[ENVPOINTS];
|
||||
/* pitch envelope */
|
||||
UBYTE pitflg; /* bit 0: on 1: sustain 2: loop */
|
||||
UBYTE pitpts;
|
||||
UBYTE pitsusbeg;
|
||||
UBYTE pitsusend;
|
||||
UBYTE pitbeg;
|
||||
UBYTE pitend;
|
||||
ENVPT pitenv[ENVPOINTS];
|
||||
} INSTRUMENT;
|
||||
|
||||
struct MP_CONTROL;
|
||||
struct MP_VOICE;
|
||||
|
||||
/*
|
||||
Module definition
|
||||
*/
|
||||
|
||||
/* maximum master channels supported */
|
||||
#define UF_MAXCHAN 64
|
||||
|
||||
/* Module flags */
|
||||
#define UF_XMPERIODS 0x0001 /* XM periods / finetuning */
|
||||
#define UF_LINEAR 0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */
|
||||
#define UF_INST 0x0004 /* Instruments are used */
|
||||
#define UF_NNA 0x0008 /* IT: NNA used, set numvoices rather
|
||||
than numchn */
|
||||
#define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */
|
||||
#define UF_BGSLIDES 0x0020 /* continue volume slides in the background */
|
||||
#define UF_HIGHBPM 0x0040 /* MED: can use >255 bpm */
|
||||
#define UF_NOWRAP 0x0080 /* XM-type (i.e. illogical) pattern break
|
||||
semantics */
|
||||
#define UF_ARPMEM 0x0100 /* IT: need arpeggio memory */
|
||||
#define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */
|
||||
#define UF_PANNING 0x0400 /* module uses panning effects or have
|
||||
non-tracker default initial panning */
|
||||
|
||||
typedef struct MODULE {
|
||||
/* general module information */
|
||||
CHAR* songname; /* name of the song */
|
||||
CHAR* modtype; /* string type of module loaded */
|
||||
CHAR* comment; /* module comments */
|
||||
|
||||
UWORD flags; /* See module flags above */
|
||||
UBYTE numchn; /* number of module channels */
|
||||
UBYTE numvoices; /* max # voices used for full NNA playback */
|
||||
UWORD numpos; /* number of positions in this song */
|
||||
UWORD numpat; /* number of patterns in this song */
|
||||
UWORD numins; /* number of instruments */
|
||||
UWORD numsmp; /* number of samples */
|
||||
struct INSTRUMENT* instruments; /* all instruments */
|
||||
struct SAMPLE* samples; /* all samples */
|
||||
UBYTE realchn; /* real number of channels used */
|
||||
UBYTE totalchn; /* total number of channels used (incl NNAs) */
|
||||
|
||||
/* playback settings */
|
||||
UWORD reppos; /* restart position */
|
||||
UBYTE initspeed; /* initial song speed */
|
||||
UWORD inittempo; /* initial song tempo */
|
||||
UBYTE initvolume; /* initial global volume (0 - 128) */
|
||||
UWORD panning[UF_MAXCHAN]; /* panning positions */
|
||||
UBYTE chanvol[UF_MAXCHAN]; /* channel positions */
|
||||
UWORD bpm; /* current beats-per-minute speed */
|
||||
UWORD sngspd; /* current song speed */
|
||||
SWORD volume; /* song volume (0-128) (or user volume) */
|
||||
|
||||
BOOL extspd; /* extended speed flag (default enabled) */
|
||||
BOOL panflag; /* panning flag (default enabled) */
|
||||
BOOL wrap; /* wrap module ? (default disabled) */
|
||||
BOOL loop; /* allow module to loop ? (default enabled) */
|
||||
BOOL fadeout; /* volume fade out during last pattern */
|
||||
|
||||
UWORD patpos; /* current row number */
|
||||
SWORD sngpos; /* current song position */
|
||||
ULONG sngtime; /* current song time in 2^-10 seconds */
|
||||
|
||||
SWORD relspd; /* relative speed factor */
|
||||
|
||||
/* internal module representation */
|
||||
UWORD numtrk; /* number of tracks */
|
||||
UBYTE** tracks; /* array of numtrk pointers to tracks */
|
||||
UWORD* patterns; /* array of Patterns */
|
||||
UWORD* pattrows; /* array of number of rows for each pattern */
|
||||
UWORD* positions; /* all positions */
|
||||
|
||||
BOOL forbid; /* if true, no player update! */
|
||||
UWORD numrow; /* number of rows on current pattern */
|
||||
UWORD vbtick; /* tick counter (counts from 0 to sngspd) */
|
||||
UWORD sngremainder;/* used for song time computation */
|
||||
|
||||
struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */
|
||||
struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */
|
||||
|
||||
UBYTE globalslide; /* global volume slide rate */
|
||||
UBYTE pat_repcrazy;/* module has just looped to position -1 */
|
||||
UWORD patbrk; /* position where to start a new pattern */
|
||||
UBYTE patdly; /* patterndelay counter (command memory) */
|
||||
UBYTE patdly2; /* patterndelay counter (real one) */
|
||||
SWORD posjmp; /* flag to indicate a jump is needed... */
|
||||
UWORD bpmlimit; /* threshold to detect bpm or speed values */
|
||||
} MODULE;
|
||||
|
||||
|
||||
/* This structure is used to query current playing voices status */
|
||||
typedef struct VOICEINFO {
|
||||
INSTRUMENT* i; /* Current channel instrument */
|
||||
SAMPLE* s; /* Current channel sample */
|
||||
SWORD panning; /* panning position */
|
||||
SBYTE volume; /* channel's "global" volume (0..64) */
|
||||
UWORD period; /* period to play the sample at */
|
||||
UBYTE kick; /* if true = sample has been restarted */
|
||||
} VOICEINFO;
|
||||
|
||||
/*
|
||||
* ========== Module loaders
|
||||
*/
|
||||
|
||||
struct MLOADER;
|
||||
|
||||
MIKMODAPI extern CHAR* MikMod_InfoLoader(void);
|
||||
MIKMODAPI extern void MikMod_RegisterAllLoaders(void);
|
||||
MIKMODAPI extern void MikMod_RegisterLoader(struct MLOADER*);
|
||||
|
||||
MIKMODAPI extern struct MLOADER load_669; /* 669 and Extended-669 (by Tran/Renaissance) */
|
||||
MIKMODAPI extern struct MLOADER load_amf; /* DMP Advanced Module Format (by Otto Chrons) */
|
||||
MIKMODAPI extern struct MLOADER load_asy; /* ASYLUM Music Format 1.0 */
|
||||
MIKMODAPI extern struct MLOADER load_dsm; /* DSIK internal module format */
|
||||
MIKMODAPI extern struct MLOADER load_far; /* Farandole Composer (by Daniel Potter) */
|
||||
MIKMODAPI extern struct MLOADER load_gdm; /* General DigiMusic (by Edward Schlunder) */
|
||||
MIKMODAPI extern struct MLOADER load_it; /* Impulse Tracker (by Jeffrey Lim) */
|
||||
MIKMODAPI extern struct MLOADER load_imf; /* Imago Orpheus (by Lutz Roeder) */
|
||||
MIKMODAPI extern struct MLOADER load_med; /* Amiga MED modules (by Teijo Kinnunen) */
|
||||
MIKMODAPI extern struct MLOADER load_m15; /* Soundtracker 15-instrument */
|
||||
MIKMODAPI extern struct MLOADER load_mod; /* Standard 31-instrument Module loader */
|
||||
MIKMODAPI extern struct MLOADER load_mtm; /* Multi-Tracker Module (by Renaissance) */
|
||||
MIKMODAPI extern struct MLOADER load_okt; /* Amiga Oktalyzer */
|
||||
MIKMODAPI extern struct MLOADER load_stm; /* ScreamTracker 2 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */
|
||||
MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker (by MAS) */
|
||||
MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */
|
||||
MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */
|
||||
|
||||
/*
|
||||
* ========== Module player
|
||||
*/
|
||||
|
||||
MIKMODAPI extern MODULE* Player_Load(CHAR*,int,BOOL);
|
||||
MIKMODAPI extern MODULE* Player_LoadFP(FILE*,int,BOOL);
|
||||
MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,BOOL);
|
||||
MIKMODAPI extern CHAR* Player_LoadTitle(CHAR*);
|
||||
MIKMODAPI extern CHAR* Player_LoadTitleFP(FILE*);
|
||||
MIKMODAPI extern void Player_Free(MODULE*);
|
||||
MIKMODAPI extern void Player_Start(MODULE*);
|
||||
MIKMODAPI extern BOOL Player_Active(void);
|
||||
MIKMODAPI extern void Player_Stop(void);
|
||||
MIKMODAPI extern void Player_TogglePause(void);
|
||||
MIKMODAPI extern BOOL Player_Paused(void);
|
||||
MIKMODAPI extern void Player_NextPosition(void);
|
||||
MIKMODAPI extern void Player_PrevPosition(void);
|
||||
MIKMODAPI extern void Player_SetPosition(UWORD);
|
||||
MIKMODAPI extern BOOL Player_Muted(UBYTE);
|
||||
MIKMODAPI extern void Player_SetVolume(SWORD);
|
||||
MIKMODAPI extern MODULE* Player_GetModule(void);
|
||||
MIKMODAPI extern void Player_SetSpeed(UWORD);
|
||||
MIKMODAPI extern void Player_SetTempo(UWORD);
|
||||
MIKMODAPI extern void Player_Unmute(SLONG,...);
|
||||
MIKMODAPI extern void Player_Mute(SLONG,...);
|
||||
MIKMODAPI extern void Player_ToggleMute(SLONG,...);
|
||||
MIKMODAPI extern int Player_GetChannelVoice(UBYTE);
|
||||
MIKMODAPI extern UWORD Player_GetChannelPeriod(UBYTE);
|
||||
MIKMODAPI extern int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo);
|
||||
|
||||
typedef void (MikMod_player)(void);
|
||||
typedef MikMod_player *MikMod_player_t;
|
||||
|
||||
MIKMODAPI extern MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t);
|
||||
|
||||
#define MUTE_EXCLUSIVE 32000
|
||||
#define MUTE_INCLUSIVE 32001
|
||||
|
||||
/*
|
||||
* ========== Drivers
|
||||
*/
|
||||
|
||||
enum {
|
||||
MD_MUSIC = 0,
|
||||
MD_SNDFX
|
||||
};
|
||||
|
||||
enum {
|
||||
MD_HARDWARE = 0,
|
||||
MD_SOFTWARE
|
||||
};
|
||||
|
||||
/* Mixing flags */
|
||||
|
||||
/* These ones take effect only after MikMod_Init or MikMod_Reset */
|
||||
#define DMODE_16BITS 0x0001 /* enable 16 bit output */
|
||||
#define DMODE_STEREO 0x0002 /* enable stereo output */
|
||||
#define DMODE_SOFT_SNDFX 0x0004 /* Process sound effects via software mixer */
|
||||
#define DMODE_SOFT_MUSIC 0x0008 /* Process music via software mixer */
|
||||
#define DMODE_HQMIXER 0x0010 /* Use high-quality (slower) software mixer */
|
||||
#define DMODE_FLOAT 0x0020 /* enable float output */
|
||||
/* These take effect immediately. */
|
||||
#define DMODE_SURROUND 0x0100 /* enable surround sound */
|
||||
#define DMODE_INTERP 0x0200 /* enable interpolation */
|
||||
#define DMODE_REVERSE 0x0400 /* reverse stereo */
|
||||
|
||||
struct SAMPLOAD;
|
||||
typedef struct MDRIVER {
|
||||
struct MDRIVER* next;
|
||||
CHAR* Name;
|
||||
CHAR* Version;
|
||||
|
||||
UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */
|
||||
UBYTE SoftVoiceLimit; /* Limit of software mixer voices */
|
||||
|
||||
CHAR *Alias;
|
||||
CHAR *CmdLineHelp;
|
||||
|
||||
void (*CommandLine) (CHAR*);
|
||||
BOOL (*IsPresent) (void);
|
||||
SWORD (*SampleLoad) (struct SAMPLOAD*,int);
|
||||
void (*SampleUnload) (SWORD);
|
||||
ULONG (*FreeSampleSpace) (int);
|
||||
ULONG (*RealSampleLength) (int,struct SAMPLE*);
|
||||
BOOL (*Init) (void);
|
||||
void (*Exit) (void);
|
||||
BOOL (*Reset) (void);
|
||||
BOOL (*SetNumVoices) (void);
|
||||
BOOL (*PlayStart) (void);
|
||||
void (*PlayStop) (void);
|
||||
void (*Update) (void);
|
||||
void (*Pause) (void);
|
||||
void (*VoiceSetVolume) (UBYTE,UWORD);
|
||||
UWORD (*VoiceGetVolume) (UBYTE);
|
||||
void (*VoiceSetFrequency)(UBYTE,ULONG);
|
||||
ULONG (*VoiceGetFrequency)(UBYTE);
|
||||
void (*VoiceSetPanning) (UBYTE,ULONG);
|
||||
ULONG (*VoiceGetPanning) (UBYTE);
|
||||
void (*VoicePlay) (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
void (*VoiceStop) (UBYTE);
|
||||
BOOL (*VoiceStopped) (UBYTE);
|
||||
SLONG (*VoiceGetPosition) (UBYTE);
|
||||
ULONG (*VoiceRealVolume) (UBYTE);
|
||||
} MDRIVER;
|
||||
|
||||
/* These variables can be changed at ANY time and results will be immediate */
|
||||
MIKMODAPI extern UBYTE md_volume; /* global sound volume (0-128) */
|
||||
MIKMODAPI extern UBYTE md_musicvolume; /* volume of song */
|
||||
MIKMODAPI extern UBYTE md_sndfxvolume; /* volume of sound effects */
|
||||
MIKMODAPI extern UBYTE md_reverb; /* 0 = none; 15 = chaos */
|
||||
MIKMODAPI extern UBYTE md_pansep; /* 0 = mono; 128 == 100% (full left/right) */
|
||||
|
||||
/* The variables below can be changed at any time, but changes will not be
|
||||
implemented until MikMod_Reset is called. A call to MikMod_Reset may result
|
||||
in a skip or pop in audio (depending on the soundcard driver and the settings
|
||||
changed). */
|
||||
MIKMODAPI extern UWORD md_device; /* device */
|
||||
MIKMODAPI extern UWORD md_mixfreq; /* mixing frequency */
|
||||
MIKMODAPI extern UWORD md_mode; /* mode. See DMODE_? flags above */
|
||||
|
||||
/* The following variable should not be changed! */
|
||||
MIKMODAPI extern MDRIVER* md_driver; /* Current driver in use. */
|
||||
|
||||
/* Known drivers list */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */
|
||||
MIKMODAPI extern struct MDRIVER drv_pipe; /* piped output */
|
||||
MIKMODAPI extern struct MDRIVER drv_raw; /* raw file disk writer [music.raw] */
|
||||
MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */
|
||||
MIKMODAPI extern struct MDRIVER drv_wav; /* RIFF WAVE file disk writer [music.wav] */
|
||||
MIKMODAPI extern struct MDRIVER drv_aiff; /* AIFF file disk writer [music.aiff] */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_ultra; /* Linux Ultrasound driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_sam9407; /* Linux sam9407 driver */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_AF; /* Dec Alpha AudioFile */
|
||||
MIKMODAPI extern struct MDRIVER drv_aix; /* AIX audio device */
|
||||
MIKMODAPI extern struct MDRIVER drv_alsa; /* Advanced Linux Sound Architecture (ALSA) */
|
||||
MIKMODAPI extern struct MDRIVER drv_esd; /* Enlightened sound daemon (EsounD) */
|
||||
MIKMODAPI extern struct MDRIVER drv_hp; /* HP-UX audio device */
|
||||
MIKMODAPI extern struct MDRIVER drv_oss; /* OpenSound System (Linux,FreeBSD...) */
|
||||
MIKMODAPI extern struct MDRIVER drv_sgi; /* SGI audio library */
|
||||
MIKMODAPI extern struct MDRIVER drv_sun; /* Sun/NetBSD/OpenBSD audio device */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_dart; /* OS/2 Direct Audio RealTime */
|
||||
MIKMODAPI extern struct MDRIVER drv_os2; /* OS/2 MMPM/2 */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_ds; /* Win32 DirectSound driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_win; /* Win32 multimedia API driver */
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_mac; /* Macintosh Sound Manager driver */
|
||||
MIKMODAPI extern struct MDRIVER drv_osx; /* MacOS X CoreAudio Driver */
|
||||
|
||||
/*========== Virtual channel mixer interface (for user-supplied drivers only) */
|
||||
|
||||
MIKMODAPI extern BOOL VC_Init(void);
|
||||
MIKMODAPI extern void VC_Exit(void);
|
||||
MIKMODAPI extern BOOL VC_SetNumVoices(void);
|
||||
MIKMODAPI extern ULONG VC_SampleSpace(int);
|
||||
MIKMODAPI extern ULONG VC_SampleLength(int,SAMPLE*);
|
||||
|
||||
MIKMODAPI extern BOOL VC_PlayStart(void);
|
||||
MIKMODAPI extern void VC_PlayStop(void);
|
||||
|
||||
MIKMODAPI extern SWORD VC_SampleLoad(struct SAMPLOAD*,int);
|
||||
MIKMODAPI extern void VC_SampleUnload(SWORD);
|
||||
|
||||
MIKMODAPI extern ULONG VC_WriteBytes(SBYTE*,ULONG);
|
||||
MIKMODAPI extern ULONG VC_SilenceBytes(SBYTE*,ULONG);
|
||||
|
||||
MIKMODAPI extern void VC_VoiceSetVolume(UBYTE,UWORD);
|
||||
MIKMODAPI extern UWORD VC_VoiceGetVolume(UBYTE);
|
||||
MIKMODAPI extern void VC_VoiceSetFrequency(UBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG VC_VoiceGetFrequency(UBYTE);
|
||||
MIKMODAPI extern void VC_VoiceSetPanning(UBYTE,ULONG);
|
||||
MIKMODAPI extern ULONG VC_VoiceGetPanning(UBYTE);
|
||||
MIKMODAPI extern void VC_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
|
||||
MIKMODAPI extern void VC_VoiceStop(UBYTE);
|
||||
MIKMODAPI extern BOOL VC_VoiceStopped(UBYTE);
|
||||
MIKMODAPI extern SLONG VC_VoiceGetPosition(UBYTE);
|
||||
MIKMODAPI extern ULONG VC_VoiceRealVolume(UBYTE);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
685
project/jni/mikmod/include/mikmod_internals.h
Normal file
685
project/jni/mikmod/include/mikmod_internals.h
Normal file
@@ -0,0 +1,685 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mikmod_internals.h,v 1.4 2004/02/18 13:29:17 raph Exp $
|
||||
|
||||
MikMod sound library internal definitions
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef _MIKMOD_INTERNALS_H
|
||||
#define _MIKMOD_INTERNALS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#if defined(__OS2__)||defined(__EMX__)||defined(WIN32)
|
||||
#define strcasecmp(s,t) stricmp(s,t)
|
||||
#endif
|
||||
|
||||
#include <mikmod_build.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4761)
|
||||
#endif
|
||||
|
||||
/*========== More type definitions */
|
||||
|
||||
/* SLONGLONG: 64bit, signed */
|
||||
#if defined (__arch64__) || defined(__alpha)
|
||||
typedef long SLONGLONG;
|
||||
#define NATIVE_64BIT_INT
|
||||
#elif defined(__WATCOMC__)
|
||||
typedef __int64 SLONGLONG;
|
||||
#elif defined(WIN32) && !defined(__MWERKS__)
|
||||
typedef LONGLONG SLONGLONG;
|
||||
#elif macintosh && !TYPE_LONGLONG
|
||||
#include <Types.h>
|
||||
typedef SInt64 SLONGLONG;
|
||||
#else
|
||||
typedef long long SLONGLONG;
|
||||
#endif
|
||||
|
||||
/*========== Error handling */
|
||||
|
||||
#define _mm_errno MikMod_errno
|
||||
#define _mm_critical MikMod_critical
|
||||
extern MikMod_handler_t _mm_errorhandler;
|
||||
|
||||
/*========== Memory allocation */
|
||||
|
||||
extern void* _mm_malloc(size_t);
|
||||
extern void* _mm_calloc(size_t,size_t);
|
||||
#define _mm_free(p) do { if (p) free(p); p = NULL; } while(0)
|
||||
|
||||
/*========== MT stuff */
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#define DECLARE_MUTEX(name) \
|
||||
extern pthread_mutex_t _mm_mutex_##name
|
||||
#define MUTEX_LOCK(name) \
|
||||
pthread_mutex_lock(&_mm_mutex_##name)
|
||||
#define MUTEX_UNLOCK(name) \
|
||||
pthread_mutex_unlock(&_mm_mutex_##name)
|
||||
#elif defined(__OS2__)||defined(__EMX__)
|
||||
#define DECLARE_MUTEX(name) \
|
||||
extern HMTX _mm_mutex_##name
|
||||
#define MUTEX_LOCK(name) \
|
||||
if(_mm_mutex_##name) \
|
||||
DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT)
|
||||
#define MUTEX_UNLOCK(name) \
|
||||
if(_mm_mutex_##name) \
|
||||
DosReleaseMutexSem(_mm_mutex_##name)
|
||||
#elif defined(WIN32)
|
||||
#include <windows.h>
|
||||
#define DECLARE_MUTEX(name) \
|
||||
extern HANDLE _mm_mutex_##name
|
||||
#define MUTEX_LOCK(name) \
|
||||
if(_mm_mutex_##name) \
|
||||
WaitForSingleObject(_mm_mutex_##name,INFINITE)
|
||||
#define MUTEX_UNLOCK(name) \
|
||||
if(_mm_mutex_##name) \
|
||||
ReleaseMutex(_mm_mutex_##name)
|
||||
#else
|
||||
#define DECLARE_MUTEX(name) \
|
||||
extern void *_mm_mutex_##name
|
||||
#define MUTEX_LOCK(name)
|
||||
#define MUTEX_UNLOCK(name)
|
||||
#endif
|
||||
|
||||
DECLARE_MUTEX(lists);
|
||||
DECLARE_MUTEX(vars);
|
||||
|
||||
/*========== Portable file I/O */
|
||||
|
||||
extern MREADER* _mm_new_file_reader(FILE* fp);
|
||||
extern void _mm_delete_file_reader(MREADER*);
|
||||
|
||||
extern MWRITER* _mm_new_file_writer(FILE *fp);
|
||||
extern void _mm_delete_file_writer(MWRITER*);
|
||||
|
||||
extern BOOL _mm_FileExists(CHAR *fname);
|
||||
|
||||
#define _mm_write_SBYTE(x,y) y->Put(y,(int)x)
|
||||
#define _mm_write_UBYTE(x,y) y->Put(y,(int)x)
|
||||
|
||||
#define _mm_read_SBYTE(x) (SBYTE)x->Get(x)
|
||||
#define _mm_read_UBYTE(x) (UBYTE)x->Get(x)
|
||||
|
||||
#define _mm_write_SBYTES(x,y,z) z->Write(z,(void *)x,y)
|
||||
#define _mm_write_UBYTES(x,y,z) z->Write(z,(void *)x,y)
|
||||
#define _mm_read_SBYTES(x,y,z) z->Read(z,(void *)x,y)
|
||||
#define _mm_read_UBYTES(x,y,z) z->Read(z,(void *)x,y)
|
||||
|
||||
#define _mm_fseek(x,y,z) x->Seek(x,y,z)
|
||||
#define _mm_ftell(x) x->Tell(x)
|
||||
#define _mm_rewind(x) _mm_fseek(x,0,SEEK_SET)
|
||||
|
||||
#define _mm_eof(x) x->Eof(x)
|
||||
|
||||
extern void _mm_iobase_setcur(MREADER*);
|
||||
extern void _mm_iobase_revert(void);
|
||||
extern FILE *_mm_fopen(CHAR*,CHAR*);
|
||||
extern int _mm_fclose(FILE *);
|
||||
extern void _mm_write_string(CHAR*,MWRITER*);
|
||||
extern int _mm_read_string (CHAR*,int,MREADER*);
|
||||
|
||||
extern SWORD _mm_read_M_SWORD(MREADER*);
|
||||
extern SWORD _mm_read_I_SWORD(MREADER*);
|
||||
extern UWORD _mm_read_M_UWORD(MREADER*);
|
||||
extern UWORD _mm_read_I_UWORD(MREADER*);
|
||||
|
||||
extern SLONG _mm_read_M_SLONG(MREADER*);
|
||||
extern SLONG _mm_read_I_SLONG(MREADER*);
|
||||
extern ULONG _mm_read_M_ULONG(MREADER*);
|
||||
extern ULONG _mm_read_I_ULONG(MREADER*);
|
||||
|
||||
extern int _mm_read_M_SWORDS(SWORD*,int,MREADER*);
|
||||
extern int _mm_read_I_SWORDS(SWORD*,int,MREADER*);
|
||||
extern int _mm_read_M_UWORDS(UWORD*,int,MREADER*);
|
||||
extern int _mm_read_I_UWORDS(UWORD*,int,MREADER*);
|
||||
|
||||
extern int _mm_read_M_SLONGS(SLONG*,int,MREADER*);
|
||||
extern int _mm_read_I_SLONGS(SLONG*,int,MREADER*);
|
||||
extern int _mm_read_M_ULONGS(ULONG*,int,MREADER*);
|
||||
extern int _mm_read_I_ULONGS(ULONG*,int,MREADER*);
|
||||
|
||||
extern void _mm_write_M_SWORD(SWORD,MWRITER*);
|
||||
extern void _mm_write_I_SWORD(SWORD,MWRITER*);
|
||||
extern void _mm_write_M_UWORD(UWORD,MWRITER*);
|
||||
extern void _mm_write_I_UWORD(UWORD,MWRITER*);
|
||||
|
||||
extern void _mm_write_M_SLONG(SLONG,MWRITER*);
|
||||
extern void _mm_write_I_SLONG(SLONG,MWRITER*);
|
||||
extern void _mm_write_M_ULONG(ULONG,MWRITER*);
|
||||
extern void _mm_write_I_ULONG(ULONG,MWRITER*);
|
||||
|
||||
extern void _mm_write_M_SWORDS(SWORD*,int,MWRITER*);
|
||||
extern void _mm_write_I_SWORDS(SWORD*,int,MWRITER*);
|
||||
extern void _mm_write_M_UWORDS(UWORD*,int,MWRITER*);
|
||||
extern void _mm_write_I_UWORDS(UWORD*,int,MWRITER*);
|
||||
|
||||
extern void _mm_write_M_SLONGS(SLONG*,int,MWRITER*);
|
||||
extern void _mm_write_I_SLONGS(SLONG*,int,MWRITER*);
|
||||
extern void _mm_write_M_ULONGS(ULONG*,int,MWRITER*);
|
||||
extern void _mm_write_I_ULONGS(ULONG*,int,MWRITER*);
|
||||
|
||||
/*========== Samples */
|
||||
|
||||
/* This is a handle of sorts attached to any sample registered with
|
||||
SL_RegisterSample. Generally, this only need be used or changed by the
|
||||
loaders and drivers of mikmod. */
|
||||
typedef struct SAMPLOAD {
|
||||
struct SAMPLOAD *next;
|
||||
|
||||
ULONG length; /* length of sample (in samples!) */
|
||||
ULONG loopstart; /* repeat position (relative to start, in samples) */
|
||||
ULONG loopend; /* repeat end */
|
||||
UWORD infmt,outfmt;
|
||||
int scalefactor;
|
||||
SAMPLE* sample;
|
||||
MREADER* reader;
|
||||
} SAMPLOAD;
|
||||
|
||||
/*========== Sample and waves loading interface */
|
||||
|
||||
extern void SL_HalveSample(SAMPLOAD*,int);
|
||||
extern void SL_Sample8to16(SAMPLOAD*);
|
||||
extern void SL_Sample16to8(SAMPLOAD*);
|
||||
extern void SL_SampleSigned(SAMPLOAD*);
|
||||
extern void SL_SampleUnsigned(SAMPLOAD*);
|
||||
extern BOOL SL_LoadSamples(void);
|
||||
extern SAMPLOAD* SL_RegisterSample(SAMPLE*,int,MREADER*);
|
||||
extern BOOL SL_Load(void*,SAMPLOAD*,ULONG);
|
||||
extern BOOL SL_Init(SAMPLOAD*);
|
||||
extern void SL_Exit(SAMPLOAD*);
|
||||
|
||||
/*========== Internal module representation (UniMod) interface */
|
||||
|
||||
/* number of notes in an octave */
|
||||
#define OCTAVE 12
|
||||
|
||||
extern void UniSetRow(UBYTE*);
|
||||
extern UBYTE UniGetByte(void);
|
||||
extern UWORD UniGetWord(void);
|
||||
extern UBYTE* UniFindRow(UBYTE*,UWORD);
|
||||
extern void UniSkipOpcode(void);
|
||||
extern void UniReset(void);
|
||||
extern void UniWriteByte(UBYTE);
|
||||
extern void UniWriteWord(UWORD);
|
||||
extern void UniNewline(void);
|
||||
extern UBYTE* UniDup(void);
|
||||
extern BOOL UniInit(void);
|
||||
extern void UniCleanup(void);
|
||||
extern void UniEffect(UWORD,UWORD);
|
||||
#define UniInstrument(x) UniEffect(UNI_INSTRUMENT,x)
|
||||
#define UniNote(x) UniEffect(UNI_NOTE,x)
|
||||
extern void UniPTEffect(UBYTE,UBYTE);
|
||||
extern void UniVolEffect(UWORD,UBYTE);
|
||||
|
||||
/*========== Module Commands */
|
||||
|
||||
enum {
|
||||
/* Simple note */
|
||||
UNI_NOTE = 1,
|
||||
/* Instrument change */
|
||||
UNI_INSTRUMENT,
|
||||
/* Protracker effects */
|
||||
UNI_PTEFFECT0, /* arpeggio */
|
||||
UNI_PTEFFECT1, /* porta up */
|
||||
UNI_PTEFFECT2, /* porta down */
|
||||
UNI_PTEFFECT3, /* porta to note */
|
||||
UNI_PTEFFECT4, /* vibrato */
|
||||
UNI_PTEFFECT5, /* dual effect 3+A */
|
||||
UNI_PTEFFECT6, /* dual effect 4+A */
|
||||
UNI_PTEFFECT7, /* tremolo */
|
||||
UNI_PTEFFECT8, /* pan */
|
||||
UNI_PTEFFECT9, /* sample offset */
|
||||
UNI_PTEFFECTA, /* volume slide */
|
||||
UNI_PTEFFECTB, /* pattern jump */
|
||||
UNI_PTEFFECTC, /* set volume */
|
||||
UNI_PTEFFECTD, /* pattern break */
|
||||
UNI_PTEFFECTE, /* extended effects */
|
||||
UNI_PTEFFECTF, /* set speed */
|
||||
/* Scream Tracker effects */
|
||||
UNI_S3MEFFECTA, /* set speed */
|
||||
UNI_S3MEFFECTD, /* volume slide */
|
||||
UNI_S3MEFFECTE, /* porta down */
|
||||
UNI_S3MEFFECTF, /* porta up */
|
||||
UNI_S3MEFFECTI, /* tremor */
|
||||
UNI_S3MEFFECTQ, /* retrig */
|
||||
UNI_S3MEFFECTR, /* tremolo */
|
||||
UNI_S3MEFFECTT, /* set tempo */
|
||||
UNI_S3MEFFECTU, /* fine vibrato */
|
||||
UNI_KEYOFF, /* note off */
|
||||
/* Fast Tracker effects */
|
||||
UNI_KEYFADE, /* note fade */
|
||||
UNI_VOLEFFECTS, /* volume column effects */
|
||||
UNI_XMEFFECT4, /* vibrato */
|
||||
UNI_XMEFFECT6, /* dual effect 4+A */
|
||||
UNI_XMEFFECTA, /* volume slide */
|
||||
UNI_XMEFFECTE1, /* fine porta up */
|
||||
UNI_XMEFFECTE2, /* fine porta down */
|
||||
UNI_XMEFFECTEA, /* fine volume slide up */
|
||||
UNI_XMEFFECTEB, /* fine volume slide down */
|
||||
UNI_XMEFFECTG, /* set global volume */
|
||||
UNI_XMEFFECTH, /* global volume slide */
|
||||
UNI_XMEFFECTL, /* set envelope position */
|
||||
UNI_XMEFFECTP, /* pan slide */
|
||||
UNI_XMEFFECTX1, /* extra fine porta up */
|
||||
UNI_XMEFFECTX2, /* extra fine porta down */
|
||||
/* Impulse Tracker effects */
|
||||
UNI_ITEFFECTG, /* porta to note */
|
||||
UNI_ITEFFECTH, /* vibrato */
|
||||
UNI_ITEFFECTI, /* tremor (xy not incremented) */
|
||||
UNI_ITEFFECTM, /* set channel volume */
|
||||
UNI_ITEFFECTN, /* slide / fineslide channel volume */
|
||||
UNI_ITEFFECTP, /* slide / fineslide channel panning */
|
||||
UNI_ITEFFECTT, /* slide tempo */
|
||||
UNI_ITEFFECTU, /* fine vibrato */
|
||||
UNI_ITEFFECTW, /* slide / fineslide global volume */
|
||||
UNI_ITEFFECTY, /* panbrello */
|
||||
UNI_ITEFFECTZ, /* resonant filters */
|
||||
UNI_ITEFFECTS0,
|
||||
/* UltraTracker effects */
|
||||
UNI_ULTEFFECT9, /* Sample fine offset */
|
||||
/* OctaMED effects */
|
||||
UNI_MEDSPEED,
|
||||
UNI_MEDEFFECTF1, /* play note twice */
|
||||
UNI_MEDEFFECTF2, /* delay note */
|
||||
UNI_MEDEFFECTF3, /* play note three times */
|
||||
/* Oktalyzer effects */
|
||||
UNI_OKTARP, /* arpeggio */
|
||||
|
||||
UNI_LAST
|
||||
};
|
||||
|
||||
extern UWORD unioperands[UNI_LAST];
|
||||
|
||||
/* IT / S3M Extended SS effects: */
|
||||
enum {
|
||||
SS_GLISSANDO = 1,
|
||||
SS_FINETUNE,
|
||||
SS_VIBWAVE,
|
||||
SS_TREMWAVE,
|
||||
SS_PANWAVE,
|
||||
SS_FRAMEDELAY,
|
||||
SS_S7EFFECTS,
|
||||
SS_PANNING,
|
||||
SS_SURROUND,
|
||||
SS_HIOFFSET,
|
||||
SS_PATLOOP,
|
||||
SS_NOTECUT,
|
||||
SS_NOTEDELAY,
|
||||
SS_PATDELAY
|
||||
};
|
||||
|
||||
/* IT Volume column effects */
|
||||
enum {
|
||||
VOL_VOLUME = 1,
|
||||
VOL_PANNING,
|
||||
VOL_VOLSLIDE,
|
||||
VOL_PITCHSLIDEDN,
|
||||
VOL_PITCHSLIDEUP,
|
||||
VOL_PORTAMENTO,
|
||||
VOL_VIBRATO
|
||||
};
|
||||
|
||||
/* IT resonant filter information */
|
||||
|
||||
#define UF_MAXMACRO 0x10
|
||||
#define UF_MAXFILTER 0x100
|
||||
|
||||
#define FILT_CUT 0x80
|
||||
#define FILT_RESONANT 0x81
|
||||
|
||||
typedef struct FILTER {
|
||||
UBYTE filter,inf;
|
||||
} FILTER;
|
||||
|
||||
/*========== Instruments */
|
||||
|
||||
/* Instrument format flags */
|
||||
#define IF_OWNPAN 1
|
||||
#define IF_PITCHPAN 2
|
||||
|
||||
/* Envelope flags: */
|
||||
#define EF_ON 1
|
||||
#define EF_SUSTAIN 2
|
||||
#define EF_LOOP 4
|
||||
#define EF_VOLENV 8
|
||||
|
||||
/* New Note Action Flags */
|
||||
#define NNA_CUT 0
|
||||
#define NNA_CONTINUE 1
|
||||
#define NNA_OFF 2
|
||||
#define NNA_FADE 3
|
||||
|
||||
#define NNA_MASK 3
|
||||
|
||||
#define DCT_OFF 0
|
||||
#define DCT_NOTE 1
|
||||
#define DCT_SAMPLE 2
|
||||
#define DCT_INST 3
|
||||
|
||||
#define DCA_CUT 0
|
||||
#define DCA_OFF 1
|
||||
#define DCA_FADE 2
|
||||
|
||||
#define KEY_KICK 0
|
||||
#define KEY_OFF 1
|
||||
#define KEY_FADE 2
|
||||
#define KEY_KILL (KEY_OFF|KEY_FADE)
|
||||
|
||||
#define KICK_ABSENT 0
|
||||
#define KICK_NOTE 1
|
||||
#define KICK_KEYOFF 2
|
||||
#define KICK_ENV 4
|
||||
|
||||
#define AV_IT 1 /* IT vs. XM vibrato info */
|
||||
|
||||
/*========== Playing */
|
||||
|
||||
#define POS_NONE (-2) /* no loop position defined */
|
||||
|
||||
#define LAST_PATTERN (UWORD)(-1) /* special ``end of song'' pattern */
|
||||
|
||||
typedef struct ENVPR {
|
||||
UBYTE flg; /* envelope flag */
|
||||
UBYTE pts; /* number of envelope points */
|
||||
UBYTE susbeg; /* envelope sustain index begin */
|
||||
UBYTE susend; /* envelope sustain index end */
|
||||
UBYTE beg; /* envelope loop begin */
|
||||
UBYTE end; /* envelope loop end */
|
||||
SWORD p; /* current envelope counter */
|
||||
UWORD a; /* envelope index a */
|
||||
UWORD b; /* envelope index b */
|
||||
ENVPT* env; /* envelope points */
|
||||
} ENVPR;
|
||||
|
||||
typedef struct MP_CHANNEL {
|
||||
INSTRUMENT* i;
|
||||
SAMPLE* s;
|
||||
UBYTE sample; /* which sample number */
|
||||
UBYTE note; /* the audible note as heard, direct rep of period */
|
||||
SWORD outvolume; /* output volume (vol + sampcol + instvol) */
|
||||
SBYTE chanvol; /* channel's "global" volume */
|
||||
UWORD fadevol; /* fading volume rate */
|
||||
SWORD panning; /* panning position */
|
||||
UBYTE kick; /* if true = sample has to be restarted */
|
||||
UBYTE kick_flag; /* kick has been true */
|
||||
UWORD period; /* period to play the sample at */
|
||||
UBYTE nna; /* New note action type + master/slave flags */
|
||||
|
||||
UBYTE volflg; /* volume envelope settings */
|
||||
UBYTE panflg; /* panning envelope settings */
|
||||
UBYTE pitflg; /* pitch envelope settings */
|
||||
|
||||
UBYTE keyoff; /* if true = fade out and stuff */
|
||||
SWORD handle; /* which sample-handle */
|
||||
UBYTE notedelay; /* (used for note delay) */
|
||||
SLONG start; /* The starting byte index in the sample */
|
||||
} MP_CHANNEL;
|
||||
|
||||
typedef struct MP_CONTROL {
|
||||
struct MP_CHANNEL main;
|
||||
|
||||
struct MP_VOICE *slave; /* Audio Slave of current effects control channel */
|
||||
|
||||
UBYTE slavechn; /* Audio Slave of current effects control channel */
|
||||
UBYTE muted; /* if set, channel not played */
|
||||
UWORD ultoffset; /* fine sample offset memory */
|
||||
UBYTE anote; /* the note that indexes the audible */
|
||||
UBYTE oldnote;
|
||||
SWORD ownper;
|
||||
SWORD ownvol;
|
||||
UBYTE dca; /* duplicate check action */
|
||||
UBYTE dct; /* duplicate check type */
|
||||
UBYTE* row; /* row currently playing on this channel */
|
||||
SBYTE retrig; /* retrig value (0 means don't retrig) */
|
||||
ULONG speed; /* what finetune to use */
|
||||
SWORD volume; /* amiga volume (0 t/m 64) to play the sample at */
|
||||
|
||||
SWORD tmpvolume; /* tmp volume */
|
||||
UWORD tmpperiod; /* tmp period */
|
||||
UWORD wantedperiod; /* period to slide to (with effect 3 or 5) */
|
||||
|
||||
UBYTE arpmem; /* arpeggio command memory */
|
||||
UBYTE pansspd; /* panslide speed */
|
||||
UWORD slidespeed;
|
||||
UWORD portspeed; /* noteslide speed (toneportamento) */
|
||||
|
||||
UBYTE s3mtremor; /* s3m tremor (effect I) counter */
|
||||
UBYTE s3mtronof; /* s3m tremor ontime/offtime */
|
||||
UBYTE s3mvolslide; /* last used volslide */
|
||||
SBYTE sliding;
|
||||
UBYTE s3mrtgspeed; /* last used retrig speed */
|
||||
UBYTE s3mrtgslide; /* last used retrig slide */
|
||||
|
||||
UBYTE glissando; /* glissando (0 means off) */
|
||||
UBYTE wavecontrol;
|
||||
|
||||
SBYTE vibpos; /* current vibrato position */
|
||||
UBYTE vibspd; /* "" speed */
|
||||
UBYTE vibdepth; /* "" depth */
|
||||
|
||||
SBYTE trmpos; /* current tremolo position */
|
||||
UBYTE trmspd; /* "" speed */
|
||||
UBYTE trmdepth; /* "" depth */
|
||||
|
||||
UBYTE fslideupspd;
|
||||
UBYTE fslidednspd;
|
||||
UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */
|
||||
UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */
|
||||
UBYTE ffportupspd; /* fx X1 (extra fine portamento up) data */
|
||||
UBYTE ffportdnspd; /* fx X2 (extra fine portamento dn) data */
|
||||
|
||||
ULONG hioffset; /* last used high order of sample offset */
|
||||
UWORD soffset; /* last used low order of sample-offset (effect 9) */
|
||||
|
||||
UBYTE sseffect; /* last used Sxx effect */
|
||||
UBYTE ssdata; /* last used Sxx data info */
|
||||
UBYTE chanvolslide; /* last used channel volume slide */
|
||||
|
||||
UBYTE panbwave; /* current panbrello waveform */
|
||||
UBYTE panbpos; /* current panbrello position */
|
||||
SBYTE panbspd; /* "" speed */
|
||||
UBYTE panbdepth; /* "" depth */
|
||||
|
||||
UWORD newsamp; /* set to 1 upon a sample / inst change */
|
||||
UBYTE voleffect; /* Volume Column Effect Memory as used by IT */
|
||||
UBYTE voldata; /* Volume Column Data Memory */
|
||||
|
||||
SWORD pat_reppos; /* patternloop position */
|
||||
UWORD pat_repcnt; /* times to loop */
|
||||
} MP_CONTROL;
|
||||
|
||||
/* Used by NNA only player (audio control. AUDTMP is used for full effects
|
||||
control). */
|
||||
typedef struct MP_VOICE {
|
||||
struct MP_CHANNEL main;
|
||||
|
||||
ENVPR venv;
|
||||
ENVPR penv;
|
||||
ENVPR cenv;
|
||||
|
||||
UWORD avibpos; /* autovibrato pos */
|
||||
UWORD aswppos; /* autovibrato sweep pos */
|
||||
|
||||
ULONG totalvol; /* total volume of channel (before global mixings) */
|
||||
|
||||
BOOL mflag;
|
||||
SWORD masterchn;
|
||||
UWORD masterperiod;
|
||||
|
||||
MP_CONTROL* master; /* index of "master" effects channel */
|
||||
} MP_VOICE;
|
||||
|
||||
/*========== Loaders */
|
||||
|
||||
typedef struct MLOADER {
|
||||
struct MLOADER* next;
|
||||
CHAR* type;
|
||||
CHAR* version;
|
||||
BOOL (*Init)(void);
|
||||
BOOL (*Test)(void);
|
||||
BOOL (*Load)(BOOL);
|
||||
void (*Cleanup)(void);
|
||||
CHAR* (*LoadTitle)(void);
|
||||
} MLOADER;
|
||||
|
||||
/* internal loader variables */
|
||||
extern MREADER* modreader;
|
||||
extern UWORD finetune[16];
|
||||
extern MODULE of; /* static unimod loading space */
|
||||
extern UWORD npertab[7*OCTAVE]; /* used by the original MOD loaders */
|
||||
|
||||
extern SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */
|
||||
extern UBYTE* poslookup; /* lookup table for pattern jumps after
|
||||
blank pattern removal */
|
||||
extern UBYTE poslookupcnt;
|
||||
extern UWORD* origpositions;
|
||||
|
||||
extern BOOL filters; /* resonant filters in use */
|
||||
extern UBYTE activemacro; /* active midi macro number for Sxx */
|
||||
extern UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */
|
||||
extern FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */
|
||||
|
||||
extern int* noteindex;
|
||||
|
||||
/*========== Internal loader interface */
|
||||
|
||||
extern BOOL ReadComment(UWORD);
|
||||
extern BOOL ReadLinedComment(UWORD,UWORD);
|
||||
extern BOOL AllocPositions(int);
|
||||
extern BOOL AllocPatterns(void);
|
||||
extern BOOL AllocTracks(void);
|
||||
extern BOOL AllocInstruments(void);
|
||||
extern BOOL AllocSamples(void);
|
||||
extern CHAR* DupStr(CHAR*,UWORD,BOOL);
|
||||
|
||||
/* loader utility functions */
|
||||
extern int* AllocLinear(void);
|
||||
extern void FreeLinear(void);
|
||||
extern int speed_to_finetune(ULONG,int);
|
||||
extern void S3MIT_ProcessCmd(UBYTE,UBYTE,unsigned int);
|
||||
extern void S3MIT_CreateOrders(BOOL);
|
||||
|
||||
/* flags for S3MIT_ProcessCmd */
|
||||
#define S3MIT_OLDSTYLE 1 /* behave as old scream tracker */
|
||||
#define S3MIT_IT 2 /* behave as impulse tracker */
|
||||
#define S3MIT_SCREAM 4 /* enforce scream tracker specific limits */
|
||||
|
||||
/* used to convert c4spd to linear XM periods (IT and IMF loaders). */
|
||||
extern UWORD getlinearperiod(UWORD,ULONG);
|
||||
extern ULONG getfrequency(UWORD,ULONG);
|
||||
|
||||
/* loader shared data */
|
||||
#define STM_NTRACKERS 3
|
||||
extern CHAR *STM_Signatures[STM_NTRACKERS];
|
||||
|
||||
/*========== Player interface */
|
||||
|
||||
extern BOOL Player_Init(MODULE*);
|
||||
extern void Player_Exit(MODULE*);
|
||||
extern void Player_HandleTick(void);
|
||||
|
||||
/*========== Drivers */
|
||||
|
||||
/* max. number of handles a driver has to provide. (not strict) */
|
||||
#define MAXSAMPLEHANDLES 384
|
||||
|
||||
/* These variables can be changed at ANY time and results will be immediate */
|
||||
extern UWORD md_bpm; /* current song / hardware BPM rate */
|
||||
|
||||
/* Variables below can be changed via MD_SetNumVoices at any time. However, a
|
||||
call to MD_SetNumVoicess while the driver is active will cause the sound to
|
||||
skip slightly. */
|
||||
extern UBYTE md_numchn; /* number of song + sound effects voices */
|
||||
extern UBYTE md_sngchn; /* number of song voices */
|
||||
extern UBYTE md_sfxchn; /* number of sound effects voices */
|
||||
extern UBYTE md_hardchn; /* number of hardware mixed voices */
|
||||
extern UBYTE md_softchn; /* number of software mixed voices */
|
||||
|
||||
/* This is for use by the hardware drivers only. It points to the registered
|
||||
tickhandler function. */
|
||||
extern void (*md_player)(void);
|
||||
|
||||
extern SWORD MD_SampleLoad(SAMPLOAD*,int);
|
||||
extern void MD_SampleUnload(SWORD);
|
||||
extern ULONG MD_SampleSpace(int);
|
||||
extern ULONG MD_SampleLength(int,SAMPLE*);
|
||||
|
||||
/* uLaw conversion */
|
||||
extern void unsignedtoulaw(char *,int);
|
||||
|
||||
/* Parameter extraction helper */
|
||||
extern CHAR *MD_GetAtom(CHAR*,CHAR*,BOOL);
|
||||
|
||||
/* Internal software mixer stuff */
|
||||
extern void VC_SetupPointers(void);
|
||||
extern BOOL VC1_Init(void);
|
||||
extern BOOL VC2_Init(void);
|
||||
|
||||
#if defined(unix) || defined(__APPLE__) && defined(__MACH__)
|
||||
/* POSIX helper functions */
|
||||
extern BOOL MD_Access(CHAR *);
|
||||
extern BOOL MD_DropPrivileges(void);
|
||||
#endif
|
||||
|
||||
/* Macro to define a missing driver, yet allowing binaries to dynamically link
|
||||
with the library without missing symbol errors */
|
||||
#define MISSING(a) MDRIVER a = { NULL, NULL, NULL, 0, 0 }
|
||||
|
||||
/*========== Prototypes for non-MT safe versions of some public functions */
|
||||
|
||||
extern void _mm_registerdriver(struct MDRIVER*);
|
||||
extern void _mm_registerloader(struct MLOADER*);
|
||||
extern BOOL MikMod_Active_internal(void);
|
||||
extern void MikMod_DisableOutput_internal(void);
|
||||
extern BOOL MikMod_EnableOutput_internal(void);
|
||||
extern void MikMod_Exit_internal(void);
|
||||
extern BOOL MikMod_SetNumVoices_internal(int,int);
|
||||
extern void Player_Exit_internal(MODULE*);
|
||||
extern void Player_Stop_internal(void);
|
||||
extern BOOL Player_Paused_internal(void);
|
||||
extern void Sample_Free_internal(SAMPLE*);
|
||||
extern void Voice_Play_internal(SBYTE,SAMPLE*,ULONG);
|
||||
extern void Voice_SetFrequency_internal(SBYTE,ULONG);
|
||||
extern void Voice_SetPanning_internal(SBYTE,ULONG);
|
||||
extern void Voice_SetVolume_internal(SBYTE,UWORD);
|
||||
extern void Voice_Stop_internal(SBYTE);
|
||||
extern BOOL Voice_Stopped_internal(SBYTE);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
368
project/jni/mikmod/loaders/load_669.c
Normal file
368
project/jni/mikmod/loaders/load_669.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_669.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Composer 669 module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* header */
|
||||
typedef struct S69HEADER {
|
||||
UBYTE marker[2];
|
||||
CHAR message[108];
|
||||
UBYTE nos;
|
||||
UBYTE nop;
|
||||
UBYTE looporder;
|
||||
UBYTE orders[0x80];
|
||||
UBYTE tempos[0x80];
|
||||
UBYTE breaks[0x80];
|
||||
} S69HEADER;
|
||||
|
||||
/* sample information */
|
||||
typedef struct S69SAMPLE {
|
||||
CHAR filename[13];
|
||||
SLONG length;
|
||||
SLONG loopbeg;
|
||||
SLONG loopend;
|
||||
} S69SAMPLE;
|
||||
|
||||
/* encoded note */
|
||||
typedef struct S69NOTE {
|
||||
UBYTE a,b,c;
|
||||
} S69NOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
/* current pattern */
|
||||
static S69NOTE* s69pat=NULL;
|
||||
/* Module header */
|
||||
static S69HEADER* mh=NULL;
|
||||
|
||||
/* file type identification */
|
||||
static CHAR* S69_Version[]={
|
||||
"Composer 669",
|
||||
"Extended 669"
|
||||
};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL S69_Test(void)
|
||||
{
|
||||
UBYTE buf[0x80];
|
||||
|
||||
if(!_mm_read_UBYTES(buf,2,modreader))
|
||||
return 0;
|
||||
/* look for id */
|
||||
if(!memcmp(buf,"if",2) || !memcmp(buf,"JN",2)) {
|
||||
int i;
|
||||
|
||||
/* skip song message */
|
||||
_mm_fseek(modreader,108,SEEK_CUR);
|
||||
/* sanity checks */
|
||||
if(_mm_read_UBYTE(modreader) > 64) return 0;
|
||||
if(_mm_read_UBYTE(modreader) > 128) return 0;
|
||||
if(_mm_read_UBYTE(modreader) > 127) return 0;
|
||||
/* check order table */
|
||||
if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
|
||||
for(i=0;i<0x80;i++)
|
||||
if((buf[i]>=0x80)&&(buf[i]!=0xff)) return 0;
|
||||
/* check tempos table */
|
||||
if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
|
||||
for(i=0;i<0x80;i++)
|
||||
if((!buf[i])||(buf[i]>32)) return 0;
|
||||
/* check pattern length table */
|
||||
if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
|
||||
for(i=0;i<0x80;i++)
|
||||
if(buf[i]>0x3f) return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL S69_Init(void)
|
||||
{
|
||||
if(!(s69pat=(S69NOTE *)_mm_malloc(64*8*sizeof(S69NOTE)))) return 0;
|
||||
if(!(mh=(S69HEADER *)_mm_malloc(sizeof(S69HEADER)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void S69_Cleanup(void)
|
||||
{
|
||||
_mm_free(s69pat);
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static BOOL S69_LoadPatterns(void)
|
||||
{
|
||||
int track,row,channel;
|
||||
UBYTE note,inst,vol,effect,lastfx,lastval;
|
||||
S69NOTE *cur;
|
||||
int tracks=0;
|
||||
|
||||
if(!AllocPatterns()) return 0;
|
||||
if(!AllocTracks()) return 0;
|
||||
|
||||
for(track=0;track<of.numpat;track++) {
|
||||
/* set pattern break locations */
|
||||
of.pattrows[track]=mh->breaks[track]+1;
|
||||
|
||||
/* load the 669 pattern */
|
||||
cur=s69pat;
|
||||
for(row=0;row<64;row++) {
|
||||
for(channel=0;channel<8;channel++,cur++) {
|
||||
cur->a = _mm_read_UBYTE(modreader);
|
||||
cur->b = _mm_read_UBYTE(modreader);
|
||||
cur->c = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* translate the pattern */
|
||||
for(channel=0;channel<8;channel++) {
|
||||
UniReset();
|
||||
/* set pattern tempo */
|
||||
UniPTEffect(0xf,78);
|
||||
UniPTEffect(0xf,mh->tempos[track]);
|
||||
|
||||
lastfx=0xff,lastval=0;
|
||||
|
||||
for(row=0;row<=mh->breaks[track];row++) {
|
||||
int a,b,c;
|
||||
|
||||
/* fetch the encoded note */
|
||||
a=s69pat[(row*8)+channel].a;
|
||||
b=s69pat[(row*8)+channel].b;
|
||||
c=s69pat[(row*8)+channel].c;
|
||||
|
||||
/* decode it */
|
||||
note=a>>2;
|
||||
inst=((a&0x3)<<4)|((b&0xf0)>>4);
|
||||
vol=b&0xf;
|
||||
|
||||
if (a<0xff) {
|
||||
if (a<0xfe) {
|
||||
UniInstrument(inst);
|
||||
UniNote(note+2*OCTAVE);
|
||||
lastfx=0xff; /* reset background effect memory */
|
||||
}
|
||||
UniPTEffect(0xc,vol<<2);
|
||||
}
|
||||
|
||||
if ((c!=0xff)||(lastfx!=0xff)) {
|
||||
if(c==0xff)
|
||||
c=lastfx,effect=lastval;
|
||||
else
|
||||
effect=c&0xf;
|
||||
|
||||
switch(c>>4) {
|
||||
case 0: /* porta up */
|
||||
UniPTEffect(0x1,effect);
|
||||
lastfx=c,lastval=effect;
|
||||
break;
|
||||
case 1: /* porta down */
|
||||
UniPTEffect(0x2,effect);
|
||||
lastfx=c,lastval=effect;
|
||||
break;
|
||||
case 2: /* porta to note */
|
||||
UniPTEffect(0x3,effect);
|
||||
lastfx=c,lastval=effect;
|
||||
break;
|
||||
case 3: /* frequency adjust */
|
||||
/* DMP converts this effect to S3M FF1. Why not ? */
|
||||
UniEffect(UNI_S3MEFFECTF,0xf0|effect);
|
||||
break;
|
||||
case 4: /* vibrato */
|
||||
UniPTEffect(0x4,effect);
|
||||
lastfx=c,lastval=effect;
|
||||
break;
|
||||
case 5: /* set speed */
|
||||
if (effect)
|
||||
UniPTEffect(0xf,effect);
|
||||
else
|
||||
if(mh->marker[0]!=0x69) {
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr,"\r669: unsupported super fast tempo at pat=%d row=%d chan=%d\n",
|
||||
track,row,channel);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
UniNewline();
|
||||
}
|
||||
if(!(of.tracks[tracks++]=UniDup())) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL S69_Load(BOOL curious)
|
||||
{
|
||||
int i;
|
||||
SAMPLE *current;
|
||||
S69SAMPLE sample;
|
||||
|
||||
/* module header */
|
||||
_mm_read_UBYTES(mh->marker,2,modreader);
|
||||
_mm_read_UBYTES(mh->message,108,modreader);
|
||||
mh->nos=_mm_read_UBYTE(modreader);
|
||||
mh->nop=_mm_read_UBYTE(modreader);
|
||||
mh->looporder=_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->orders,0x80,modreader);
|
||||
for(i=0;i<0x80;i++)
|
||||
if ((mh->orders[i]>=0x80)&&(mh->orders[i]!=0xff)) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 1;
|
||||
}
|
||||
_mm_read_UBYTES(mh->tempos,0x80,modreader);
|
||||
for(i=0;i<0x80;i++)
|
||||
if ((!mh->tempos[i])||(mh->tempos[i]>32)) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 1;
|
||||
}
|
||||
_mm_read_UBYTES(mh->breaks,0x80,modreader);
|
||||
for(i=0;i<0x80;i++)
|
||||
if (mh->breaks[i]>0x3f) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed=4;
|
||||
of.inittempo=78;
|
||||
of.songname=DupStr(mh->message,36,1);
|
||||
of.modtype=strdup(S69_Version[memcmp(mh->marker,"JN",2)==0]);
|
||||
of.numchn=8;
|
||||
of.numpat=mh->nop;
|
||||
of.numins=of.numsmp=mh->nos;
|
||||
of.numtrk=of.numchn*of.numpat;
|
||||
of.flags=UF_XMPERIODS|UF_LINEAR;
|
||||
|
||||
for(i= 35;(i>= 0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
|
||||
for(i=36+35;(i>=36+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
|
||||
for(i=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
|
||||
if((mh->message[0])||(mh->message[36])||(mh->message[72]))
|
||||
if((of.comment=(CHAR*)_mm_malloc(3*(36+1)+1))) {
|
||||
strncpy(of.comment,mh->message,36);
|
||||
strcat(of.comment,"\r");
|
||||
if (mh->message[36]) strncat(of.comment,mh->message+36,36);
|
||||
strcat(of.comment,"\r");
|
||||
if (mh->message[72]) strncat(of.comment,mh->message+72,36);
|
||||
strcat(of.comment,"\r");
|
||||
of.comment[3*(36+1)]=0;
|
||||
}
|
||||
|
||||
if(!AllocPositions(0x80)) return 0;
|
||||
for(i=0;i<0x80;i++) {
|
||||
if(mh->orders[i]>=mh->nop) break;
|
||||
of.positions[i]=mh->orders[i];
|
||||
}
|
||||
of.numpos=i;
|
||||
of.reppos=mh->looporder<of.numpos?mh->looporder:0;
|
||||
|
||||
if(!AllocSamples()) return 0;
|
||||
current=of.samples;
|
||||
|
||||
for(i=0;i<of.numins;i++) {
|
||||
/* sample information */
|
||||
_mm_read_UBYTES((UBYTE*)sample.filename,13,modreader);
|
||||
sample.length=_mm_read_I_SLONG(modreader);
|
||||
sample.loopbeg=_mm_read_I_SLONG(modreader);
|
||||
sample.loopend=_mm_read_I_SLONG(modreader);
|
||||
if (sample.loopend==0xfffff) sample.loopend=0;
|
||||
|
||||
if((sample.length<0)||(sample.loopbeg<-1)||(sample.loopend<-1)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
current->samplename=DupStr(sample.filename,13,1);
|
||||
current->seekpos=0;
|
||||
current->speed=0;
|
||||
current->length=sample.length;
|
||||
current->loopstart=sample.loopbeg;
|
||||
current->loopend=sample.loopend;
|
||||
current->flags=(sample.loopbeg<sample.loopend)?SF_LOOP:0;
|
||||
current->volume=64;
|
||||
|
||||
current++;
|
||||
}
|
||||
|
||||
if(!S69_LoadPatterns()) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *S69_LoadTitle(void)
|
||||
{
|
||||
CHAR s[36];
|
||||
|
||||
_mm_fseek(modreader,2,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,36,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,36,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_669={
|
||||
NULL,
|
||||
"669",
|
||||
"669 (Composer 669, Unis 669)",
|
||||
S69_Init,
|
||||
S69_Test,
|
||||
S69_Load,
|
||||
S69_Cleanup,
|
||||
S69_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
569
project/jni/mikmod/loaders/load_amf.c
Normal file
569
project/jni/mikmod/loaders/load_amf.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_amf.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
DMP Advanced Module Format loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct AMFHEADER {
|
||||
UBYTE id[3]; /* AMF file marker */
|
||||
UBYTE version; /* upper major, lower nibble minor version number */
|
||||
CHAR songname[32]; /* ASCIIZ songname */
|
||||
UBYTE numsamples; /* number of samples saved */
|
||||
UBYTE numorders;
|
||||
UWORD numtracks; /* number of tracks saved */
|
||||
UBYTE numchannels; /* number of channels used */
|
||||
SBYTE panpos[32]; /* voice pan positions */
|
||||
UBYTE songbpm;
|
||||
UBYTE songspd;
|
||||
} AMFHEADER;
|
||||
|
||||
typedef struct AMFSAMPLE {
|
||||
UBYTE type;
|
||||
CHAR samplename[32];
|
||||
CHAR filename[13];
|
||||
ULONG offset;
|
||||
ULONG length;
|
||||
UWORD c2spd;
|
||||
UBYTE volume;
|
||||
ULONG reppos;
|
||||
ULONG repend;
|
||||
} AMFSAMPLE;
|
||||
|
||||
typedef struct AMFNOTE {
|
||||
UBYTE note,instr,volume,fxcnt;
|
||||
UBYTE effect[3];
|
||||
SBYTE parameter[3];
|
||||
} AMFNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static AMFHEADER *mh = NULL;
|
||||
#define AMFTEXTLEN 22
|
||||
static CHAR AMF_Version[AMFTEXTLEN+1] = "DSMI Module Format 0.0";
|
||||
static AMFNOTE *track = NULL;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL AMF_Test(void)
|
||||
{
|
||||
UBYTE id[3],ver;
|
||||
|
||||
if(!_mm_read_UBYTES(id,3,modreader)) return 0;
|
||||
if(memcmp(id,"AMF",3)) return 0;
|
||||
|
||||
ver=_mm_read_UBYTE(modreader);
|
||||
if((ver>=10)&&(ver<=14)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL AMF_Init(void)
|
||||
{
|
||||
if(!(mh=(AMFHEADER*)_mm_malloc(sizeof(AMFHEADER)))) return 0;
|
||||
if(!(track=(AMFNOTE*)_mm_calloc(64,sizeof(AMFNOTE)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AMF_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(track);
|
||||
}
|
||||
|
||||
static BOOL AMF_UnpackTrack(MREADER* modreader)
|
||||
{
|
||||
ULONG tracksize;
|
||||
UBYTE row,cmd;
|
||||
SBYTE arg;
|
||||
|
||||
/* empty track */
|
||||
memset(track,0,64*sizeof(AMFNOTE));
|
||||
|
||||
/* read packed track */
|
||||
if (modreader) {
|
||||
tracksize=_mm_read_I_UWORD(modreader);
|
||||
tracksize+=((ULONG)_mm_read_UBYTE(modreader))<<16;
|
||||
if (tracksize)
|
||||
while(tracksize--) {
|
||||
row=_mm_read_UBYTE(modreader);
|
||||
cmd=_mm_read_UBYTE(modreader);
|
||||
arg=_mm_read_SBYTE(modreader);
|
||||
/* unexpected end of track */
|
||||
if(!tracksize) {
|
||||
if((row==0xff)&&(cmd==0xff)&&(arg==-1))
|
||||
break;
|
||||
/* the last triplet should be FF FF FF, but this is not
|
||||
always the case... maybe a bug in m2amf ?
|
||||
else
|
||||
return 0;
|
||||
*/
|
||||
|
||||
}
|
||||
/* invalid row (probably unexpected end of row) */
|
||||
if (row>=64)
|
||||
return 0;
|
||||
if (cmd<0x7f) {
|
||||
/* note, vol */
|
||||
track[row].note=cmd;
|
||||
track[row].volume=(UBYTE)arg+1;
|
||||
} else
|
||||
if (cmd==0x7f) {
|
||||
/* duplicate row */
|
||||
if ((arg<0)&&(row+arg>=0)) {
|
||||
memcpy(track+row,track+(row+arg),sizeof(AMFNOTE));
|
||||
}
|
||||
} else
|
||||
if (cmd==0x80) {
|
||||
/* instr */
|
||||
track[row].instr=arg+1;
|
||||
} else
|
||||
if (cmd==0x83) {
|
||||
/* volume without note */
|
||||
track[row].volume=(UBYTE)arg+1;
|
||||
} else
|
||||
if (cmd==0xff) {
|
||||
/* apparently, some M2AMF version fail to estimate the
|
||||
size of the compressed patterns correctly, and end
|
||||
up with blanks, i.e. dead triplets. Those are marked
|
||||
with cmd == 0xff. Let's ignore them. */
|
||||
} else
|
||||
if(track[row].fxcnt<3) {
|
||||
/* effect, param */
|
||||
if(cmd>0x97)
|
||||
return 0;
|
||||
track[row].effect[track[row].fxcnt]=cmd&0x7f;
|
||||
track[row].parameter[track[row].fxcnt]=arg;
|
||||
track[row].fxcnt++;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UBYTE* AMF_ConvertTrack(void)
|
||||
{
|
||||
int row,fx4memory=0;
|
||||
|
||||
/* convert track */
|
||||
UniReset();
|
||||
for (row=0;row<64;row++) {
|
||||
if (track[row].instr) UniInstrument(track[row].instr-1);
|
||||
if (track[row].note>OCTAVE) UniNote(track[row].note-OCTAVE);
|
||||
|
||||
/* AMF effects */
|
||||
while(track[row].fxcnt--) {
|
||||
SBYTE inf=track[row].parameter[track[row].fxcnt];
|
||||
|
||||
switch(track[row].effect[track[row].fxcnt]) {
|
||||
case 1: /* Set speed */
|
||||
UniEffect(UNI_S3MEFFECTA,inf);
|
||||
break;
|
||||
case 2: /* Volume slide */
|
||||
if(inf) {
|
||||
UniWriteByte(UNI_S3MEFFECTD);
|
||||
if (inf>=0)
|
||||
UniWriteByte((inf&0xf)<<4);
|
||||
else
|
||||
UniWriteByte((-inf)&0xf);
|
||||
}
|
||||
break;
|
||||
/* effect 3, set channel volume, done in UnpackTrack */
|
||||
case 4: /* Porta up/down */
|
||||
if(inf) {
|
||||
if(inf>0) {
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
fx4memory=UNI_S3MEFFECTE;
|
||||
} else {
|
||||
UniEffect(UNI_S3MEFFECTF,-inf);
|
||||
fx4memory=UNI_S3MEFFECTF;
|
||||
}
|
||||
} else if(fx4memory)
|
||||
UniEffect(fx4memory,0);
|
||||
break;
|
||||
/* effect 5, "Porta abs", not supported */
|
||||
case 6: /* Porta to note */
|
||||
UniEffect(UNI_ITEFFECTG,inf);
|
||||
break;
|
||||
case 7: /* Tremor */
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
break;
|
||||
case 8: /* Arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 9: /* Vibrato */
|
||||
UniPTEffect(0x4,inf);
|
||||
break;
|
||||
case 0xa: /* Porta + Volume slide */
|
||||
UniPTEffect(0x3,0);
|
||||
if(inf) {
|
||||
UniWriteByte(UNI_S3MEFFECTD);
|
||||
if (inf>=0)
|
||||
UniWriteByte((inf&0xf)<<4);
|
||||
else
|
||||
UniWriteByte((-inf)&0xf);
|
||||
}
|
||||
break;
|
||||
case 0xb: /* Vibrato + Volume slide */
|
||||
UniPTEffect(0x4,0);
|
||||
if(inf) {
|
||||
UniWriteByte(UNI_S3MEFFECTD);
|
||||
if (inf>=0)
|
||||
UniWriteByte((inf&0xf)<<4);
|
||||
else
|
||||
UniWriteByte((-inf)&0xf);
|
||||
}
|
||||
break;
|
||||
case 0xc: /* Pattern break (in hex) */
|
||||
UniPTEffect(0xd,inf);
|
||||
break;
|
||||
case 0xd: /* Pattern jump */
|
||||
UniPTEffect(0xb,inf);
|
||||
break;
|
||||
/* effect 0xe, "Sync", not supported */
|
||||
case 0xf: /* Retrig */
|
||||
UniEffect(UNI_S3MEFFECTQ,inf&0xf);
|
||||
break;
|
||||
case 0x10: /* Sample offset */
|
||||
UniPTEffect(0x9,inf);
|
||||
break;
|
||||
case 0x11: /* Fine volume slide */
|
||||
if(inf) {
|
||||
UniWriteByte(UNI_S3MEFFECTD);
|
||||
if (inf>=0)
|
||||
UniWriteByte((inf&0xf)<<4|0xf);
|
||||
else
|
||||
UniWriteByte(0xf0|((-inf)&0xf));
|
||||
}
|
||||
break;
|
||||
case 0x12: /* Fine portamento */
|
||||
if(inf) {
|
||||
if(inf>0) {
|
||||
UniEffect(UNI_S3MEFFECTE,0xf0|(inf&0xf));
|
||||
fx4memory=UNI_S3MEFFECTE;
|
||||
} else {
|
||||
UniEffect(UNI_S3MEFFECTF,0xf0|((-inf)&0xf));
|
||||
fx4memory=UNI_S3MEFFECTF;
|
||||
}
|
||||
} else if(fx4memory)
|
||||
UniEffect(fx4memory,0);
|
||||
break;
|
||||
case 0x13: /* Delay note */
|
||||
UniPTEffect(0xe,0xd0|(inf&0xf));
|
||||
break;
|
||||
case 0x14: /* Note cut */
|
||||
UniPTEffect(0xc,0);
|
||||
track[row].volume=0;
|
||||
break;
|
||||
case 0x15: /* Set tempo */
|
||||
UniEffect(UNI_S3MEFFECTT,inf);
|
||||
break;
|
||||
case 0x16: /* Extra fine portamento */
|
||||
if(inf) {
|
||||
if(inf>0) {
|
||||
UniEffect(UNI_S3MEFFECTE,0xe0|((inf>>2)&0xf));
|
||||
fx4memory=UNI_S3MEFFECTE;
|
||||
} else {
|
||||
UniEffect(UNI_S3MEFFECTF,0xe0|(((-inf)>>2)&0xf));
|
||||
fx4memory=UNI_S3MEFFECTF;
|
||||
}
|
||||
} else if(fx4memory)
|
||||
UniEffect(fx4memory,0);
|
||||
break;
|
||||
case 0x17: /* Panning */
|
||||
if (inf>64)
|
||||
UniEffect(UNI_ITEFFECTS0,0x91); /* surround */
|
||||
else
|
||||
UniPTEffect(0x8,(inf==64)?255:(inf+64)<<1);
|
||||
of.flags |= UF_PANNING;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (track[row].volume) UniVolEffect(VOL_VOLUME,track[row].volume-1);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL AMF_Load(BOOL curious)
|
||||
{
|
||||
int t,u,realtrackcnt,realsmpcnt,defaultpanning;
|
||||
AMFSAMPLE s;
|
||||
SAMPLE *q;
|
||||
UWORD *track_remap;
|
||||
ULONG samplepos;
|
||||
int channel_remap[16];
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_UBYTES(mh->id,3,modreader);
|
||||
mh->version =_mm_read_UBYTE(modreader);
|
||||
_mm_read_string(mh->songname,32,modreader);
|
||||
mh->numsamples =_mm_read_UBYTE(modreader);
|
||||
mh->numorders =_mm_read_UBYTE(modreader);
|
||||
mh->numtracks =_mm_read_I_UWORD(modreader);
|
||||
mh->numchannels =_mm_read_UBYTE(modreader);
|
||||
if((!mh->numchannels)||(mh->numchannels>(mh->version>=12?32:16))) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mh->version>=11) {
|
||||
memset(mh->panpos,0,32);
|
||||
_mm_read_SBYTES(mh->panpos,(mh->version>=13)?32:16,modreader);
|
||||
} else
|
||||
_mm_read_UBYTES(channel_remap,16,modreader);
|
||||
|
||||
if (mh->version>=13) {
|
||||
mh->songbpm=_mm_read_UBYTE(modreader);
|
||||
if(mh->songbpm<32) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
mh->songspd=_mm_read_UBYTE(modreader);
|
||||
if(mh->songspd>32) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
mh->songbpm=125;
|
||||
mh->songspd=6;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = mh->songspd;
|
||||
of.inittempo = mh->songbpm;
|
||||
AMF_Version[AMFTEXTLEN-3]='0'+(mh->version/10);
|
||||
AMF_Version[AMFTEXTLEN-1]='0'+(mh->version%10);
|
||||
of.modtype = strdup(AMF_Version);
|
||||
of.numchn = mh->numchannels;
|
||||
of.numtrk = mh->numorders*mh->numchannels;
|
||||
if (mh->numtracks>of.numtrk)
|
||||
of.numtrk=mh->numtracks;
|
||||
of.numtrk++; /* add room for extra, empty track */
|
||||
of.songname = DupStr(mh->songname,32,1);
|
||||
of.numpos = mh->numorders;
|
||||
of.numpat = mh->numorders;
|
||||
of.reppos = 0;
|
||||
of.flags |= UF_S3MSLIDES;
|
||||
/* XXX whenever possible, we should try to determine the original format.
|
||||
Here we assume it was S3M-style wrt bpmlimit... */
|
||||
of.bpmlimit = 32;
|
||||
|
||||
/*
|
||||
* Play with the panning table. Although the AMF format embeds a
|
||||
* panning table, if the module was a MOD or an S3M with default
|
||||
* panning and didn't use any panning commands, don't flag
|
||||
* UF_PANNING, to use our preferred panning table for this case.
|
||||
*/
|
||||
defaultpanning = 1;
|
||||
for (t = 0; t < 32; t++) {
|
||||
if (mh->panpos[t] > 64) {
|
||||
of.panning[t] = PAN_SURROUND;
|
||||
defaultpanning = 0;
|
||||
} else
|
||||
if (mh->panpos[t] == 64)
|
||||
of.panning[t] = PAN_RIGHT;
|
||||
else
|
||||
of.panning[t] = (mh->panpos[t] + 64) << 1;
|
||||
}
|
||||
if (defaultpanning) {
|
||||
for (t = 0; t < of.numchn; t++)
|
||||
if (of.panning[t] == (((t + 1) & 2) ? PAN_RIGHT : PAN_LEFT)) {
|
||||
defaultpanning = 0; /* not MOD canonical panning */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (defaultpanning)
|
||||
of.flags |= UF_PANNING;
|
||||
|
||||
of.numins=of.numsmp=mh->numsamples;
|
||||
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
for(t=0;t<of.numpos;t++)
|
||||
of.positions[t]=t;
|
||||
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
/* read AMF order table */
|
||||
for (t=0;t<of.numpat;t++) {
|
||||
if (mh->version>=14)
|
||||
/* track size */
|
||||
of.pattrows[t]=_mm_read_I_UWORD(modreader);
|
||||
if (mh->version>=10)
|
||||
_mm_read_I_UWORDS(of.patterns+(t*of.numchn),of.numchn,modreader);
|
||||
else
|
||||
for(u=0;u<of.numchn;u++)
|
||||
of.patterns[t*of.numchn+channel_remap[u]]=_mm_read_I_UWORD(modreader);
|
||||
}
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read sample information */
|
||||
if(!AllocSamples()) return 0;
|
||||
q=of.samples;
|
||||
for(t=0;t<of.numins;t++) {
|
||||
/* try to read sample info */
|
||||
s.type=_mm_read_UBYTE(modreader);
|
||||
_mm_read_string(s.samplename,32,modreader);
|
||||
_mm_read_string(s.filename,13,modreader);
|
||||
s.offset =_mm_read_I_ULONG(modreader);
|
||||
s.length =_mm_read_I_ULONG(modreader);
|
||||
s.c2spd =_mm_read_I_UWORD(modreader);
|
||||
if(s.c2spd==8368) s.c2spd=8363;
|
||||
s.volume =_mm_read_UBYTE(modreader);
|
||||
if(mh->version>=11) {
|
||||
s.reppos =_mm_read_I_ULONG(modreader);
|
||||
s.repend =_mm_read_I_ULONG(modreader);
|
||||
} else {
|
||||
s.reppos =_mm_read_I_UWORD(modreader);
|
||||
s.repend =s.length;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->samplename = DupStr(s.samplename,32,1);
|
||||
q->speed = s.c2spd;
|
||||
q->volume = s.volume;
|
||||
if (s.type) {
|
||||
q->seekpos = s.offset;
|
||||
q->length = s.length;
|
||||
q->loopstart = s.reppos;
|
||||
q->loopend = s.repend;
|
||||
if((s.repend-s.reppos)>2) q->flags |= SF_LOOP;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
|
||||
/* read track table */
|
||||
if(!(track_remap=_mm_calloc(mh->numtracks+1,sizeof(UWORD))))
|
||||
return 0;
|
||||
_mm_read_I_UWORDS(track_remap+1,mh->numtracks,modreader);
|
||||
if(_mm_eof(modreader)) {
|
||||
free(track_remap);
|
||||
_mm_errno=MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(realtrackcnt=t=0;t<=mh->numtracks;t++)
|
||||
if (realtrackcnt<track_remap[t])
|
||||
realtrackcnt=track_remap[t];
|
||||
for(t=0;t<of.numpat*of.numchn;t++)
|
||||
of.patterns[t]=(of.patterns[t]<=mh->numtracks)?
|
||||
track_remap[of.patterns[t]]-1:realtrackcnt;
|
||||
|
||||
free(track_remap);
|
||||
|
||||
/* unpack tracks */
|
||||
for(t=0;t<realtrackcnt;t++) {
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
if (!AMF_UnpackTrack(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
if(!(of.tracks[t]=AMF_ConvertTrack()))
|
||||
return 0;
|
||||
}
|
||||
/* add an extra void track */
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) UniNewline();
|
||||
of.tracks[realtrackcnt++]=UniDup();
|
||||
for(t=realtrackcnt;t<of.numtrk;t++) of.tracks[t]=NULL;
|
||||
|
||||
/* compute sample offsets */
|
||||
samplepos=_mm_ftell(modreader);
|
||||
for(realsmpcnt=t=0;t<of.numsmp;t++)
|
||||
if(realsmpcnt<of.samples[t].seekpos)
|
||||
realsmpcnt=of.samples[t].seekpos;
|
||||
for(t=1;t<=realsmpcnt;t++) {
|
||||
q=of.samples;
|
||||
while(q->seekpos!=t) q++;
|
||||
q->seekpos=samplepos;
|
||||
samplepos+=q->length;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *AMF_LoadTitle(void)
|
||||
{
|
||||
CHAR s[32];
|
||||
|
||||
_mm_fseek(modreader,4,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,32,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,32,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_amf={
|
||||
NULL,
|
||||
"AMF",
|
||||
"AMF (DSMI Advanced Module Format)",
|
||||
AMF_Init,
|
||||
AMF_Test,
|
||||
AMF_Load,
|
||||
AMF_Cleanup,
|
||||
AMF_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
398
project/jni/mikmod/loaders/load_asy.c
Normal file
398
project/jni/mikmod/loaders/load_asy.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/* MikMod sound library
|
||||
(c) 2004, Raphael Assenat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_asy.c,v 1.3 2004/01/28 01:18:22 raph Exp $
|
||||
|
||||
ASYLUM Music Format v1.0 (.amf) loader
|
||||
adapted from load_mod.c by Raphael Assenat <raph@raphnet.net>,
|
||||
with the help of the AMF2MOD utility sourcecode,
|
||||
written to convert crusader's amf files into 8
|
||||
channels mod file in 1995 by Mr. P / Powersource
|
||||
mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca
|
||||
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct MSAMPINFO {
|
||||
CHAR samplename[24];
|
||||
UBYTE finetune;
|
||||
UBYTE volume;
|
||||
ULONG length;
|
||||
ULONG reppos;
|
||||
ULONG replen;
|
||||
} MSAMPINFO;
|
||||
|
||||
typedef struct MODULEHEADER {
|
||||
CHAR songname[21];
|
||||
UBYTE num_patterns; /* number of patterns used */
|
||||
UBYTE num_orders;
|
||||
UBYTE positions[256]; /* which pattern to play at pos */
|
||||
MSAMPINFO samples[64]; /* all sampleinfo */
|
||||
} MODULEHEADER;
|
||||
|
||||
typedef struct MODTYPE {
|
||||
CHAR id[5];
|
||||
UBYTE channels;
|
||||
CHAR *name;
|
||||
} MODTYPE;
|
||||
|
||||
typedef struct MODNOTE {
|
||||
UBYTE a, b, c, d;
|
||||
} MODNOTE;
|
||||
|
||||
/* This table is taken from AMF2MOD.C
|
||||
* written in 1995 by Mr. P / Powersource
|
||||
* mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */
|
||||
UWORD periodtable[]={6848,6464,6096,5760,5424,5120,4832,4560,4304,
|
||||
4064,3840,3628,3424,3232,3048,2880,2712,2560,
|
||||
2416,2280,2152,2032,1920,1814,1712,1616,1524,
|
||||
1440,1356,1280,1208,1140,1076,1016, 960, 907,
|
||||
856, 808, 762, 720, 678, 640, 604, 570, 538,
|
||||
508, 480, 453, 428, 404, 381, 360, 339, 320,
|
||||
302, 285, 269, 254, 240, 226, 214, 202, 190,
|
||||
180, 170, 160, 151, 143, 135, 127, 120, 113,
|
||||
107, 101, 95, 90, 85, 80, 75, 71, 67,
|
||||
63, 60, 56, 53, 50, 47, 45, 42, 40,
|
||||
37, 35, 33, 31, 30, 28};
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static CHAR asylum[] = "Asylum 1.0";
|
||||
|
||||
static MODULEHEADER *mh = NULL;
|
||||
static MODNOTE *patbuf = NULL;
|
||||
static int modtype = 0;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
static BOOL ASY_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
|
||||
{
|
||||
if (!memcmp(id, "ASYLUM Music Format V1.0", 24))
|
||||
{
|
||||
*descr = asylum;
|
||||
*numchn = 8;
|
||||
modtype = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL ASY_Test(void)
|
||||
{
|
||||
UBYTE namestring[24], numchn;
|
||||
CHAR *descr;
|
||||
|
||||
/* Read the magic string */
|
||||
_mm_fseek(modreader, 0, SEEK_SET);
|
||||
if (!_mm_read_UBYTES(namestring, 24, modreader))
|
||||
return 0;
|
||||
|
||||
/* Test if the string is what we expect */
|
||||
if (ASY_CheckType(namestring, &numchn, &descr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL ASY_Init(void)
|
||||
{
|
||||
if (!(mh = (MODULEHEADER *)_mm_malloc(sizeof(MODULEHEADER))))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ASY_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(patbuf);
|
||||
}
|
||||
|
||||
static void ConvertNote(MODNOTE *n)
|
||||
{
|
||||
UBYTE instrument, effect, effdat, note;
|
||||
UWORD period;
|
||||
UBYTE lastnote = 0;
|
||||
|
||||
instrument = n->b&0x1f;
|
||||
effect = n->c;
|
||||
effdat = n->d;
|
||||
|
||||
/* convert amf note to mod period */
|
||||
if (n->a) {
|
||||
period = periodtable[n->a];
|
||||
} else {
|
||||
period = 0;
|
||||
}
|
||||
|
||||
/* Convert the period to a note number */
|
||||
note = 0;
|
||||
if (period)
|
||||
{
|
||||
for (note = 0; note < 7 * OCTAVE; note++)
|
||||
if (period >= npertab[note])
|
||||
break;
|
||||
if (note == 7 * OCTAVE)
|
||||
note = 0;
|
||||
else
|
||||
note++;
|
||||
}
|
||||
|
||||
if (instrument) {
|
||||
/* if instrument does not exist, note cut */
|
||||
if ((instrument > 31) || (!mh->samples[instrument - 1].length)) {
|
||||
UniPTEffect(0xc, 0);
|
||||
if (effect == 0xc)
|
||||
effect = effdat = 0;
|
||||
} else {
|
||||
/* Protracker handling */
|
||||
if (!modtype) {
|
||||
/* if we had a note, then change instrument...*/
|
||||
if (note)
|
||||
UniInstrument(instrument - 1);
|
||||
/* ...otherwise, only adjust volume... */
|
||||
else {
|
||||
/* ...unless an effect was specified,
|
||||
* which forces a new note to be
|
||||
* played */
|
||||
if (effect || effdat) {
|
||||
UniInstrument(instrument - 1);
|
||||
note = lastnote;
|
||||
} else
|
||||
UniPTEffect(0xc,
|
||||
mh->samples[instrument -
|
||||
1].volume & 0x7f);
|
||||
}
|
||||
} else {
|
||||
/* Fasttracker handling */
|
||||
UniInstrument(instrument - 1);
|
||||
if (!note)
|
||||
note = lastnote;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (note) {
|
||||
UniNote(note + 2 * OCTAVE - 1);
|
||||
lastnote = note;
|
||||
}
|
||||
|
||||
/* Convert pattern jump from Dec to Hex */
|
||||
if (effect == 0xd)
|
||||
effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf);
|
||||
|
||||
/* Volume slide, up has priority */
|
||||
if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
|
||||
effdat &= 0xf0;
|
||||
|
||||
UniPTEffect(effect, effdat);
|
||||
}
|
||||
|
||||
static UBYTE *ConvertTrack(MODNOTE *n)
|
||||
{
|
||||
int t;
|
||||
|
||||
UniReset();
|
||||
for (t = 0; t < 64; t++) {
|
||||
ConvertNote(n);
|
||||
UniNewline();
|
||||
n += of.numchn;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
/* Loads all patterns of a modfile and converts them into the 3 byte format. */
|
||||
static BOOL ML_LoadPatterns(void)
|
||||
{
|
||||
int t, s, tracks = 0;
|
||||
|
||||
if (!AllocPatterns()) {
|
||||
return 0;
|
||||
}
|
||||
if (!AllocTracks()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate temporary buffer for loading and converting the patterns */
|
||||
if (!(patbuf = (MODNOTE *)_mm_calloc(64U * of.numchn, sizeof(MODNOTE))))
|
||||
return 0;
|
||||
|
||||
|
||||
/* patterns start here */
|
||||
_mm_fseek(modreader, 0xA66, SEEK_SET);
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
/* Load the pattern into the temp buffer and convert it */
|
||||
for (s = 0; s < (64U * of.numchn); s++) {
|
||||
patbuf[s].a = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].b = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].c = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].d = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
for (s = 0; s < of.numchn; s++) {
|
||||
if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL ASY_Load(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
SAMPLE *q;
|
||||
MSAMPINFO *s;
|
||||
CHAR *descr=asylum;
|
||||
ULONG seekpos;
|
||||
|
||||
// no title in asylum amf files :(
|
||||
strcpy(mh->songname, "");
|
||||
|
||||
_mm_fseek(modreader, 0x23, SEEK_SET);
|
||||
mh->num_patterns = _mm_read_UBYTE(modreader);
|
||||
mh->num_orders = _mm_read_UBYTE(modreader);
|
||||
|
||||
// skip unknown byte
|
||||
_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->positions, 256, modreader);
|
||||
|
||||
/* read samples headers*/
|
||||
for (t = 0; t < 64; t++) {
|
||||
s = &mh->samples[t];
|
||||
|
||||
_mm_fseek(modreader, 0x126 + (t*37), SEEK_SET);
|
||||
|
||||
_mm_read_string(s->samplename, 22, modreader);
|
||||
s->samplename[21] = 0; /* just in case */
|
||||
|
||||
s->finetune = _mm_read_UBYTE(modreader);
|
||||
s->volume = _mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTE(modreader); // skip unknown byte
|
||||
s->length = _mm_read_I_ULONG(modreader);
|
||||
s->reppos = _mm_read_I_ULONG(modreader);
|
||||
s->replen = _mm_read_I_ULONG(modreader);
|
||||
}
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
of.numchn = 8;
|
||||
modtype = 0;
|
||||
of.songname = DupStr(mh->songname, 21, 1);
|
||||
of.numpos = mh->num_orders;
|
||||
of.reppos = 0;
|
||||
of.numpat = mh->num_patterns;
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
|
||||
|
||||
/* Copy positions (orders) */
|
||||
if (!AllocPositions(of.numpos))
|
||||
return 0;
|
||||
for (t = 0; t < of.numpos; t++) {
|
||||
of.positions[t] = mh->positions[t];
|
||||
}
|
||||
|
||||
/* Finally, init the sampleinfo structures */
|
||||
of.numins = 31;
|
||||
of.numsmp = 31;
|
||||
if (!AllocSamples())
|
||||
return 0;
|
||||
s = mh->samples;
|
||||
q = of.samples;
|
||||
seekpos = 2662+(2048*(of.numpat));
|
||||
for (t = 0; t < of.numins; t++) {
|
||||
/* convert the samplename */
|
||||
q->samplename = DupStr(s->samplename, 23, 1);
|
||||
|
||||
/* init the sampleinfo variables */
|
||||
q->speed = finetune[s->finetune & 0xf];
|
||||
q->volume = s->volume & 0x7f;
|
||||
|
||||
q->loopstart = (ULONG)s->reppos;
|
||||
q->loopend = (ULONG)q->loopstart + (s->replen);
|
||||
q->length = (ULONG)s->length;
|
||||
|
||||
q->flags = SF_SIGNED;
|
||||
|
||||
q->seekpos = seekpos;
|
||||
seekpos += q->length;
|
||||
|
||||
if ((s->replen) > 2) {
|
||||
q->flags |= SF_LOOP;
|
||||
}
|
||||
|
||||
/* fix replen if repend > length */
|
||||
if (q->loopend > q->length)
|
||||
q->loopend = q->length;
|
||||
|
||||
s++;
|
||||
q++;
|
||||
}
|
||||
|
||||
of.modtype = strdup(descr);
|
||||
|
||||
if (!ML_LoadPatterns())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CHAR *ASY_LoadTitle(void)
|
||||
{
|
||||
CHAR *s = ""; // no titles
|
||||
|
||||
return (DupStr(s, 21, 1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MLOADER load_asy = {
|
||||
NULL,
|
||||
"AMF",
|
||||
"AMF (ASYLUM Music Format V1.0)",
|
||||
ASY_Init,
|
||||
ASY_Test,
|
||||
ASY_Load,
|
||||
ASY_Cleanup,
|
||||
ASY_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
364
project/jni/mikmod/loaders/load_dsm.c
Normal file
364
project/jni/mikmod/loaders/load_dsm.c
Normal file
@@ -0,0 +1,364 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_dsm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
DSIK internal format (DSM) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
#define DSM_MAXCHAN (16)
|
||||
#define DSM_MAXORDERS (128)
|
||||
|
||||
typedef struct DSMSONG {
|
||||
CHAR songname[28];
|
||||
UWORD version;
|
||||
UWORD flags;
|
||||
ULONG reserved2;
|
||||
UWORD numord;
|
||||
UWORD numsmp;
|
||||
UWORD numpat;
|
||||
UWORD numtrk;
|
||||
UBYTE globalvol;
|
||||
UBYTE mastervol;
|
||||
UBYTE speed;
|
||||
UBYTE bpm;
|
||||
UBYTE panpos[DSM_MAXCHAN];
|
||||
UBYTE orders[DSM_MAXORDERS];
|
||||
} DSMSONG;
|
||||
|
||||
typedef struct DSMINST {
|
||||
CHAR filename[13];
|
||||
UWORD flags;
|
||||
UBYTE volume;
|
||||
ULONG length;
|
||||
ULONG loopstart;
|
||||
ULONG loopend;
|
||||
ULONG reserved1;
|
||||
UWORD c2spd;
|
||||
UWORD period;
|
||||
CHAR samplename[28];
|
||||
} DSMINST;
|
||||
|
||||
typedef struct DSMNOTE {
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
} DSMNOTE;
|
||||
|
||||
#define DSM_SURROUND (0xa4)
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static CHAR* SONGID="SONG";
|
||||
static CHAR* INSTID="INST";
|
||||
static CHAR* PATTID="PATT";
|
||||
|
||||
static UBYTE blockid[4];
|
||||
static ULONG blockln;
|
||||
static ULONG blocklp;
|
||||
static DSMSONG* mh=NULL;
|
||||
static DSMNOTE* dsmbuf=NULL;
|
||||
|
||||
static CHAR DSM_Version[]="DSIK DSM-format";
|
||||
|
||||
static unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL DSM_Test(void)
|
||||
{
|
||||
UBYTE id[12];
|
||||
|
||||
if(!_mm_read_UBYTES(id,12,modreader)) return 0;
|
||||
if(!memcmp(id,DSMSIG,4) && !memcmp(id+8,DSMSIG+4,4)) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL DSM_Init(void)
|
||||
{
|
||||
if(!(dsmbuf=(DSMNOTE *)_mm_malloc(DSM_MAXCHAN*64*sizeof(DSMNOTE)))) return 0;
|
||||
if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DSM_Cleanup(void)
|
||||
{
|
||||
_mm_free(dsmbuf);
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static BOOL GetBlockHeader(void)
|
||||
{
|
||||
/* make sure we're at the right position for reading the
|
||||
next riff block, no matter how many bytes read */
|
||||
_mm_fseek(modreader, blocklp+blockln, SEEK_SET);
|
||||
|
||||
while(1) {
|
||||
_mm_read_UBYTES(blockid,4,modreader);
|
||||
blockln=_mm_read_I_ULONG(modreader);
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) &&
|
||||
memcmp(blockid,PATTID,4)) {
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr,"\rDSM: Skipping unknown block type %4.4s\n",blockid);
|
||||
#endif
|
||||
_mm_fseek(modreader, blockln, SEEK_CUR);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
blocklp = _mm_ftell(modreader);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL DSM_ReadPattern(void)
|
||||
{
|
||||
int flag,row=0;
|
||||
SWORD length;
|
||||
DSMNOTE *n;
|
||||
|
||||
/* clear pattern data */
|
||||
memset(dsmbuf,255,DSM_MAXCHAN*64*sizeof(DSMNOTE));
|
||||
length=_mm_read_I_SWORD(modreader);
|
||||
|
||||
while(row<64) {
|
||||
flag=_mm_read_UBYTE(modreader);
|
||||
if((_mm_eof(modreader))||(--length<0)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
n=&dsmbuf[((flag&0xf)*64)+row];
|
||||
if(flag&0x80) n->note=_mm_read_UBYTE(modreader);
|
||||
if(flag&0x40) n->ins=_mm_read_UBYTE(modreader);
|
||||
if(flag&0x20) n->vol=_mm_read_UBYTE(modreader);
|
||||
if(flag&0x10) {
|
||||
n->cmd=_mm_read_UBYTE(modreader);
|
||||
n->inf=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
} else
|
||||
row++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UBYTE *DSM_ConvertTrack(DSMNOTE *tr)
|
||||
{
|
||||
int t;
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
note=tr[t].note;
|
||||
ins=tr[t].ins;
|
||||
vol=tr[t].vol;
|
||||
cmd=tr[t].cmd;
|
||||
inf=tr[t].inf;
|
||||
|
||||
if(ins!=0 && ins!=255) UniInstrument(ins-1);
|
||||
if(note!=255) UniNote(note-1); /* normal note */
|
||||
if(vol<65) UniPTEffect(0xc,vol);
|
||||
|
||||
if(cmd!=255) {
|
||||
if(cmd==0x8) {
|
||||
if(inf==DSM_SURROUND)
|
||||
UniEffect(UNI_ITEFFECTS0,0x91);
|
||||
else
|
||||
if(inf<=0x80) {
|
||||
inf=(inf<0x80)?inf<<1:255;
|
||||
UniPTEffect(cmd,inf);
|
||||
}
|
||||
} else
|
||||
if(cmd==0xb) {
|
||||
if(inf<=0x7f) UniPTEffect(cmd,inf);
|
||||
} else {
|
||||
/* Convert pattern jump from Dec to Hex */
|
||||
if(cmd == 0xd)
|
||||
inf = (((inf&0xf0)>>4)*10)+(inf&0xf);
|
||||
UniPTEffect(cmd,inf);
|
||||
}
|
||||
}
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL DSM_Load(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
DSMINST s;
|
||||
SAMPLE *q;
|
||||
int cursmp=0,curpat=0,track=0;
|
||||
|
||||
blocklp=0;
|
||||
blockln=12;
|
||||
|
||||
if(!GetBlockHeader()) return 0;
|
||||
if(memcmp(blockid,SONGID,4)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_mm_read_UBYTES(mh->songname,28,modreader);
|
||||
mh->version=_mm_read_I_UWORD(modreader);
|
||||
mh->flags=_mm_read_I_UWORD(modreader);
|
||||
mh->reserved2=_mm_read_I_ULONG(modreader);
|
||||
mh->numord=_mm_read_I_UWORD(modreader);
|
||||
mh->numsmp=_mm_read_I_UWORD(modreader);
|
||||
mh->numpat=_mm_read_I_UWORD(modreader);
|
||||
mh->numtrk=_mm_read_I_UWORD(modreader);
|
||||
mh->globalvol=_mm_read_UBYTE(modreader);
|
||||
mh->mastervol=_mm_read_UBYTE(modreader);
|
||||
mh->speed=_mm_read_UBYTE(modreader);
|
||||
mh->bpm=_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->panpos,DSM_MAXCHAN,modreader);
|
||||
_mm_read_UBYTES(mh->orders,DSM_MAXORDERS,modreader);
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed=mh->speed;
|
||||
of.inittempo=mh->bpm;
|
||||
of.modtype=strdup(DSM_Version);
|
||||
of.numchn=mh->numtrk;
|
||||
of.numpat=mh->numpat;
|
||||
of.numtrk=of.numchn*of.numpat;
|
||||
of.songname=DupStr(mh->songname,28,1); /* make a cstr of songname */
|
||||
of.reppos=0;
|
||||
of.flags |= UF_PANNING;
|
||||
/* XXX whenever possible, we should try to determine the original format.
|
||||
Here we assume it was S3M-style wrt bpmlimit... */
|
||||
of.bpmlimit = 32;
|
||||
|
||||
for(t=0;t<DSM_MAXCHAN;t++)
|
||||
of.panning[t]=mh->panpos[t]==DSM_SURROUND?PAN_SURROUND:
|
||||
mh->panpos[t]<0x80?(mh->panpos[t]<<1):255;
|
||||
|
||||
if(!AllocPositions(mh->numord)) return 0;
|
||||
of.numpos=0;
|
||||
for(t=0;t<mh->numord;t++) {
|
||||
int order=mh->orders[t];
|
||||
if(order==255) order=LAST_PATTERN;
|
||||
of.positions[of.numpos]=order;
|
||||
if(mh->orders[t]<254) of.numpos++;
|
||||
}
|
||||
|
||||
of.numins=of.numsmp=mh->numsmp;
|
||||
|
||||
if(!AllocSamples()) return 0;
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
while(cursmp<of.numins||curpat<of.numpat) {
|
||||
if(!GetBlockHeader()) return 0;
|
||||
if(!memcmp(blockid,INSTID,4) && cursmp<of.numins) {
|
||||
q=&of.samples[cursmp];
|
||||
|
||||
/* try to read sample info */
|
||||
_mm_read_UBYTES(s.filename,13,modreader);
|
||||
s.flags=_mm_read_I_UWORD(modreader);
|
||||
s.volume=_mm_read_UBYTE(modreader);
|
||||
s.length=_mm_read_I_ULONG(modreader);
|
||||
s.loopstart=_mm_read_I_ULONG(modreader);
|
||||
s.loopend=_mm_read_I_ULONG(modreader);
|
||||
s.reserved1=_mm_read_I_ULONG(modreader);
|
||||
s.c2spd=_mm_read_I_UWORD(modreader);
|
||||
s.period=_mm_read_I_UWORD(modreader);
|
||||
_mm_read_UBYTES(s.samplename,28,modreader);
|
||||
|
||||
q->samplename=DupStr(s.samplename,28,1);
|
||||
q->seekpos=_mm_ftell(modreader);
|
||||
q->speed=s.c2spd;
|
||||
q->length=s.length;
|
||||
q->loopstart=s.loopstart;
|
||||
q->loopend=s.loopend;
|
||||
q->volume=s.volume;
|
||||
|
||||
if(s.flags&1) q->flags|=SF_LOOP;
|
||||
if(s.flags&2) q->flags|=SF_SIGNED;
|
||||
/* (s.flags&4) means packed sample,
|
||||
but did they really exist in dsm ?*/
|
||||
cursmp++;
|
||||
} else
|
||||
if(!memcmp(blockid,PATTID,4) && curpat<of.numpat) {
|
||||
DSM_ReadPattern();
|
||||
for(t=0;t<of.numchn;t++)
|
||||
if(!(of.tracks[track++]=DSM_ConvertTrack(&dsmbuf[t*64]))) return 0;
|
||||
curpat++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *DSM_LoadTitle(void)
|
||||
{
|
||||
CHAR s[28];
|
||||
|
||||
_mm_fseek(modreader,12,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,28,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_dsm={
|
||||
NULL,
|
||||
"DSM",
|
||||
"DSM (DSIK internal format)",
|
||||
DSM_Init,
|
||||
DSM_Test,
|
||||
DSM_Load,
|
||||
DSM_Cleanup,
|
||||
DSM_LoadTitle
|
||||
};
|
||||
|
||||
|
||||
/* ex:set ts=4: */
|
||||
346
project/jni/mikmod/loaders/load_far.c
Normal file
346
project/jni/mikmod/loaders/load_far.c
Normal file
@@ -0,0 +1,346 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_far.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Farandole (FAR) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct FARHEADER1 {
|
||||
UBYTE id[4]; /* file magic */
|
||||
CHAR songname[40]; /* songname */
|
||||
CHAR blah[3]; /* 13,10,26 */
|
||||
UWORD headerlen; /* remaining length of header in bytes */
|
||||
UBYTE version;
|
||||
UBYTE onoff[16];
|
||||
UBYTE edit1[9];
|
||||
UBYTE speed;
|
||||
UBYTE panning[16];
|
||||
UBYTE edit2[4];
|
||||
UWORD stlen;
|
||||
} FARHEADER1;
|
||||
|
||||
typedef struct FARHEADER2 {
|
||||
UBYTE orders[256];
|
||||
UBYTE numpat;
|
||||
UBYTE snglen;
|
||||
UBYTE loopto;
|
||||
UWORD patsiz[256];
|
||||
} FARHEADER2;
|
||||
|
||||
typedef struct FARSAMPLE {
|
||||
CHAR samplename[32];
|
||||
ULONG length;
|
||||
UBYTE finetune;
|
||||
UBYTE volume;
|
||||
ULONG reppos;
|
||||
ULONG repend;
|
||||
UBYTE type;
|
||||
UBYTE loop;
|
||||
} FARSAMPLE;
|
||||
|
||||
typedef struct FARNOTE {
|
||||
UBYTE note,ins,vol,eff;
|
||||
} FARNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static CHAR FAR_Version[] = "Farandole";
|
||||
static FARHEADER1 *mh1 = NULL;
|
||||
static FARHEADER2 *mh2 = NULL;
|
||||
static FARNOTE *pat = NULL;
|
||||
|
||||
static unsigned char FARSIG[4+3]={'F','A','R',0xfe,13,10,26};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL FAR_Test(void)
|
||||
{
|
||||
UBYTE id[47];
|
||||
|
||||
if(!_mm_read_UBYTES(id,47,modreader)) return 0;
|
||||
if((memcmp(id,FARSIG,4))||(memcmp(id+44,FARSIG+4,3))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL FAR_Init(void)
|
||||
{
|
||||
if(!(mh1 = (FARHEADER1*)_mm_malloc(sizeof(FARHEADER1)))) return 0;
|
||||
if(!(mh2 = (FARHEADER2*)_mm_malloc(sizeof(FARHEADER2)))) return 0;
|
||||
if(!(pat = (FARNOTE*)_mm_malloc(256*16*4*sizeof(FARNOTE)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FAR_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh1);
|
||||
_mm_free(mh2);
|
||||
_mm_free(pat);
|
||||
}
|
||||
|
||||
static UBYTE *FAR_ConvertTrack(FARNOTE* n,int rows)
|
||||
{
|
||||
int t,vibdepth=1;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<rows;t++) {
|
||||
if(n->note) {
|
||||
UniInstrument(n->ins);
|
||||
UniNote(n->note+3*OCTAVE-1);
|
||||
}
|
||||
if (n->vol&0xf) UniPTEffect(0xc,(n->vol&0xf)<<2);
|
||||
if (n->eff)
|
||||
switch(n->eff>>4) {
|
||||
case 0x3: /* porta to note */
|
||||
UniPTEffect(0x3,(n->eff&0xf)<<4);
|
||||
break;
|
||||
case 0x4: /* retrigger */
|
||||
UniPTEffect(0x0e, 0x90 | (n->eff & 0x0f));
|
||||
break;
|
||||
case 0x5: /* set vibrato depth */
|
||||
vibdepth=n->eff&0xf;
|
||||
break;
|
||||
case 0x6: /* vibrato */
|
||||
UniPTEffect(0x4,((n->eff&0xf)<<4)|vibdepth);
|
||||
break;
|
||||
case 0x7: /* volume slide up */
|
||||
UniPTEffect(0xa,(n->eff&0xf)<<4);
|
||||
break;
|
||||
case 0x8: /* volume slide down */
|
||||
UniPTEffect(0xa,n->eff&0xf);
|
||||
break;
|
||||
case 0xb: /* panning */
|
||||
UniPTEffect(0xe,0x80|(n->eff&0xf));
|
||||
break;
|
||||
case 0xf: /* set speed */
|
||||
UniPTEffect(0xf,n->eff&0xf);
|
||||
break;
|
||||
|
||||
/* others not yet implemented */
|
||||
default:
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr,"\rFAR: unsupported effect %02X\n",n->eff);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
UniNewline();
|
||||
n+=16;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL FAR_Load(BOOL curious)
|
||||
{
|
||||
int t,u,tracks=0;
|
||||
SAMPLE *q;
|
||||
FARSAMPLE s;
|
||||
FARNOTE *crow;
|
||||
UBYTE smap[8];
|
||||
|
||||
/* try to read module header (first part) */
|
||||
_mm_read_UBYTES(mh1->id,4,modreader);
|
||||
_mm_read_SBYTES(mh1->songname,40,modreader);
|
||||
_mm_read_SBYTES(mh1->blah,3,modreader);
|
||||
mh1->headerlen = _mm_read_I_UWORD (modreader);
|
||||
mh1->version = _mm_read_UBYTE (modreader);
|
||||
_mm_read_UBYTES(mh1->onoff,16,modreader);
|
||||
_mm_read_UBYTES(mh1->edit1,9,modreader);
|
||||
mh1->speed = _mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh1->panning,16,modreader);
|
||||
_mm_read_UBYTES(mh1->edit2,4,modreader);
|
||||
mh1->stlen = _mm_read_I_UWORD (modreader);
|
||||
|
||||
/* init modfile data */
|
||||
of.modtype = strdup(FAR_Version);
|
||||
of.songname = DupStr(mh1->songname,40,1);
|
||||
of.numchn = 16;
|
||||
of.initspeed = mh1->speed;
|
||||
of.inittempo = 80;
|
||||
of.reppos = 0;
|
||||
of.flags |= UF_PANNING;
|
||||
for(t=0;t<16;t++) of.panning[t]=mh1->panning[t]<<4;
|
||||
|
||||
/* read songtext into comment field */
|
||||
if(mh1->stlen)
|
||||
if (!ReadLinedComment(mh1->stlen, 66)) return 0;
|
||||
|
||||
/* try to read module header (second part) */
|
||||
_mm_read_UBYTES(mh2->orders,256,modreader);
|
||||
mh2->numpat = _mm_read_UBYTE(modreader);
|
||||
mh2->snglen = _mm_read_UBYTE(modreader);
|
||||
mh2->loopto = _mm_read_UBYTE(modreader);
|
||||
_mm_read_I_UWORDS(mh2->patsiz,256,modreader);
|
||||
|
||||
of.numpos = mh2->snglen;
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
for(t=0;t<of.numpos;t++) {
|
||||
if(mh2->orders[t]==0xff) break;
|
||||
of.positions[t] = mh2->orders[t];
|
||||
}
|
||||
|
||||
/* count number of patterns stored in file */
|
||||
of.numpat = 0;
|
||||
for(t=0;t<256;t++)
|
||||
if(mh2->patsiz[t])
|
||||
if((t+1)>of.numpat) of.numpat=t+1;
|
||||
of.numtrk = of.numpat*of.numchn;
|
||||
|
||||
/* seek across eventual new data */
|
||||
_mm_fseek(modreader,mh1->headerlen-(869+mh1->stlen),SEEK_CUR);
|
||||
|
||||
/* alloc track and pattern structures */
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
UBYTE rows=0,tempo;
|
||||
|
||||
memset(pat,0,256*16*4*sizeof(FARNOTE));
|
||||
if(mh2->patsiz[t]) {
|
||||
rows = _mm_read_UBYTE(modreader);
|
||||
tempo = _mm_read_UBYTE(modreader);
|
||||
|
||||
crow = pat;
|
||||
/* file often allocates 64 rows even if there are less in pattern */
|
||||
if (mh2->patsiz[t]<2+(rows*16*4)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
for(u=(mh2->patsiz[t]-2)/4;u;u--,crow++) {
|
||||
crow->note = _mm_read_UBYTE(modreader);
|
||||
crow->ins = _mm_read_UBYTE(modreader);
|
||||
crow->vol = _mm_read_UBYTE(modreader);
|
||||
crow->eff = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
crow=pat;
|
||||
of.pattrows[t] = rows;
|
||||
for(u=16;u;u--,crow++)
|
||||
if(!(of.tracks[tracks++]=FAR_ConvertTrack(crow,rows))) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
tracks+=16;
|
||||
}
|
||||
|
||||
/* read sample map */
|
||||
if(!_mm_read_UBYTES(smap,8,modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* count number of samples used */
|
||||
of.numins = 0;
|
||||
for(t=0;t<64;t++)
|
||||
if(smap[t>>3]&(1<<(t&7))) of.numins=t+1;
|
||||
of.numsmp = of.numins;
|
||||
|
||||
/* alloc sample structs */
|
||||
if(!AllocSamples()) return 0;
|
||||
|
||||
q = of.samples;
|
||||
for(t=0;t<of.numsmp;t++) {
|
||||
q->speed = 8363;
|
||||
q->flags = SF_SIGNED;
|
||||
if(smap[t>>3]&(1<<(t&7))) {
|
||||
_mm_read_SBYTES(s.samplename,32,modreader);
|
||||
s.length = _mm_read_I_ULONG(modreader);
|
||||
s.finetune = _mm_read_UBYTE(modreader);
|
||||
s.volume = _mm_read_UBYTE(modreader);
|
||||
s.reppos = _mm_read_I_ULONG(modreader);
|
||||
s.repend = _mm_read_I_ULONG(modreader);
|
||||
s.type = _mm_read_UBYTE(modreader);
|
||||
s.loop = _mm_read_UBYTE(modreader);
|
||||
|
||||
q->samplename = DupStr(s.samplename,32,1);
|
||||
q->length = s.length;
|
||||
q->loopstart = s.reppos;
|
||||
q->loopend = s.repend;
|
||||
q->volume = s.volume<<2;
|
||||
|
||||
if(s.type&1) q->flags|=SF_16BITS;
|
||||
if(s.loop&8) q->flags|=SF_LOOP;
|
||||
|
||||
q->seekpos = _mm_ftell(modreader);
|
||||
_mm_fseek(modreader,q->length,SEEK_CUR);
|
||||
} else
|
||||
q->samplename = DupStr(NULL,0,0);
|
||||
q++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *FAR_LoadTitle(void)
|
||||
{
|
||||
CHAR s[40];
|
||||
|
||||
_mm_fseek(modreader,4,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,40,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,40,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_far={
|
||||
NULL,
|
||||
"FAR",
|
||||
"FAR (Farandole Composer)",
|
||||
FAR_Init,
|
||||
FAR_Test,
|
||||
FAR_Load,
|
||||
FAR_Cleanup,
|
||||
FAR_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
558
project/jni/mikmod/loaders/load_gdm.c
Normal file
558
project/jni/mikmod/loaders/load_gdm.c
Normal file
@@ -0,0 +1,558 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software;you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation;either version 2 of
|
||||
the License,or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library;if not,write to the Free Software
|
||||
Foundation,Inc.,59 Temple Place - Suite 330,Boston,MA
|
||||
02111-1307,USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_gdm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
General DigiMusic (GDM) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Written by Kev Vance<kvance@zeux.org>
|
||||
based on the file format description written by 'MenTaLguY'
|
||||
<mental@kludge.org>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
typedef struct GDMNOTE {
|
||||
UBYTE note;
|
||||
UBYTE samp;
|
||||
struct {
|
||||
UBYTE effect;
|
||||
UBYTE param;
|
||||
} effect[4];
|
||||
} GDMNOTE;
|
||||
|
||||
typedef GDMNOTE GDMTRACK[64];
|
||||
|
||||
typedef struct GDMHEADER {
|
||||
CHAR id1[4];
|
||||
CHAR songname[32];
|
||||
CHAR author[32];
|
||||
CHAR eofmarker[3];
|
||||
CHAR id2[4];
|
||||
|
||||
UBYTE majorver;
|
||||
UBYTE minorver;
|
||||
UWORD trackerid;
|
||||
UBYTE t_majorver;
|
||||
UBYTE t_minorver;
|
||||
UBYTE pantable[32];
|
||||
UBYTE mastervol;
|
||||
UBYTE mastertempo;
|
||||
UBYTE masterbpm;
|
||||
UWORD flags;
|
||||
|
||||
ULONG orderloc;
|
||||
UBYTE ordernum;
|
||||
ULONG patternloc;
|
||||
UBYTE patternnum;
|
||||
ULONG samhead;
|
||||
ULONG samdata;
|
||||
UBYTE samnum;
|
||||
ULONG messageloc;
|
||||
ULONG messagelen;
|
||||
ULONG scrollyloc;
|
||||
UWORD scrollylen;
|
||||
ULONG graphicloc;
|
||||
UWORD graphiclen;
|
||||
} GDMHEADER;
|
||||
|
||||
typedef struct GDMSAMPLE {
|
||||
CHAR sampname[32];
|
||||
CHAR filename[13];
|
||||
UBYTE ems;
|
||||
ULONG length;
|
||||
ULONG loopbeg;
|
||||
ULONG loopend;
|
||||
UBYTE flags;
|
||||
UWORD c4spd;
|
||||
UBYTE vol;
|
||||
UBYTE pan;
|
||||
} GDMSAMPLE;
|
||||
|
||||
static GDMHEADER *mh=NULL; /* pointer to GDM header */
|
||||
static GDMNOTE *gdmbuf=NULL; /* pointer to a complete GDM pattern */
|
||||
|
||||
CHAR GDM_Version[]="General DigiMusic 1.xx";
|
||||
|
||||
BOOL GDM_Test(void)
|
||||
{
|
||||
/* test for gdm magic numbers */
|
||||
UBYTE id[4];
|
||||
|
||||
_mm_fseek(modreader,0x00,SEEK_SET);
|
||||
if (!_mm_read_UBYTES(id,4,modreader))
|
||||
return 0;
|
||||
if (!memcmp(id,"GDM\xfe",4)) {
|
||||
_mm_fseek(modreader,71,SEEK_SET);
|
||||
if (!_mm_read_UBYTES(id,4,modreader))
|
||||
return 0;
|
||||
if (!memcmp(id,"GMFS",4))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL GDM_Init(void)
|
||||
{
|
||||
if (!(gdmbuf=(GDMNOTE*)_mm_malloc(32*64*sizeof(GDMNOTE)))) return 0;
|
||||
if (!(mh=(GDMHEADER*)_mm_malloc(sizeof(GDMHEADER)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GDM_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(gdmbuf);
|
||||
}
|
||||
|
||||
BOOL GDM_ReadPattern(void)
|
||||
{
|
||||
int pos,flag,ch,i,maxch;
|
||||
GDMNOTE n;
|
||||
UWORD length,x=0;
|
||||
|
||||
/* get pattern length */
|
||||
length=_mm_read_I_UWORD(modreader)-2;
|
||||
|
||||
/* clear pattern data */
|
||||
memset(gdmbuf,255,32*64*sizeof(GDMNOTE));
|
||||
pos=0;
|
||||
maxch=0;
|
||||
|
||||
while (x<length) {
|
||||
memset(&n,255,sizeof(GDMNOTE));
|
||||
flag=_mm_read_UBYTE(modreader);
|
||||
x++;
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ch=flag&31;
|
||||
if (ch>maxch) maxch=ch;
|
||||
if (!flag) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (flag&0x60) {
|
||||
if (flag&0x20) {
|
||||
/* new note */
|
||||
n.note=_mm_read_UBYTE(modreader)&127;
|
||||
n.samp=_mm_read_UBYTE(modreader);
|
||||
x +=2;
|
||||
}
|
||||
if (flag&0x40) {
|
||||
do {
|
||||
/* effect channel set */
|
||||
i=_mm_read_UBYTE(modreader);
|
||||
n.effect[i>>6].effect=i&31;
|
||||
n.effect[i>>6].param=_mm_read_UBYTE(modreader);
|
||||
x +=2;
|
||||
} while (i&32);
|
||||
}
|
||||
memcpy(gdmbuf+(64U*ch)+pos,&n,sizeof(GDMNOTE));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
UBYTE *GDM_ConvertTrack(GDMNOTE*tr)
|
||||
{
|
||||
int t,i=0;
|
||||
UBYTE note,ins,inf;
|
||||
|
||||
UniReset();
|
||||
for (t=0;t<64;t++) {
|
||||
note=tr[t].note;
|
||||
ins=tr[t].samp;
|
||||
|
||||
if ((ins)&&(ins!=255))
|
||||
UniInstrument(ins-1);
|
||||
if (note!=255) {
|
||||
UniNote(((note>>4)*OCTAVE)+(note&0xf)-1);
|
||||
}
|
||||
for (i=0;i<4;i++) {
|
||||
inf = tr[t].effect[i].param;
|
||||
switch (tr[t].effect[i].effect) {
|
||||
case 1: /* toneslide up */
|
||||
UniEffect(UNI_S3MEFFECTF,inf);
|
||||
break;
|
||||
case 2: /* toneslide down */
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
break;
|
||||
case 3: /* glissando to note */
|
||||
UniEffect(UNI_ITEFFECTG,inf);
|
||||
break;
|
||||
case 4: /* vibrato */
|
||||
UniEffect(UNI_ITEFFECTH,inf);
|
||||
break;
|
||||
case 5: /* portamento+volslide */
|
||||
UniEffect(UNI_ITEFFECTG,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 6: /* vibrato+volslide */
|
||||
UniEffect(UNI_ITEFFECTH,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 7: /* tremolo */
|
||||
UniEffect(UNI_S3MEFFECTR,inf);
|
||||
break;
|
||||
case 8: /* tremor */
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
break;
|
||||
case 9: /* offset */
|
||||
UniPTEffect(0x09,inf);
|
||||
break;
|
||||
case 0x0a: /* volslide */
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0x0b: /* jump to order */
|
||||
UniPTEffect(0x0b,inf);
|
||||
break;
|
||||
case 0x0c: /* volume set */
|
||||
UniPTEffect(0x0c,inf);
|
||||
break;
|
||||
case 0x0d: /* pattern break */
|
||||
UniPTEffect(0x0d,inf);
|
||||
break;
|
||||
case 0x0e: /* extended */
|
||||
switch (inf&0xf0) {
|
||||
case 0x10: /* fine portamento up */
|
||||
UniEffect(UNI_S3MEFFECTF, 0x0f|((inf<<4)&0x0f));
|
||||
break;
|
||||
case 0x20: /* fine portamento down */
|
||||
UniEffect(UNI_S3MEFFECTE, 0xf0|(inf&0x0f));
|
||||
break;
|
||||
case 0x30: /* glissando control */
|
||||
UniEffect(SS_GLISSANDO, inf&0x0f);
|
||||
break;
|
||||
case 0x40: /* vibrato waveform */
|
||||
UniEffect(SS_VIBWAVE, inf&0x0f);
|
||||
break;
|
||||
case 0x50: /* set c4spd */
|
||||
UniEffect(SS_FINETUNE, inf&0x0f);
|
||||
break;
|
||||
case 0x60: /* loop fun */
|
||||
UniEffect(UNI_ITEFFECTS0, (inf&0x0f)|0xb0);
|
||||
break;
|
||||
case 0x70: /* tremolo waveform */
|
||||
UniEffect(SS_TREMWAVE, inf&0x0f);
|
||||
break;
|
||||
case 0x80: /* extra fine porta up */
|
||||
UniEffect(UNI_S3MEFFECTF, 0x0e|((inf<<4)&0x0f));
|
||||
break;
|
||||
case 0x90: /* extra fine porta down */
|
||||
UniEffect(UNI_S3MEFFECTE, 0xe0|(inf&0x0f));
|
||||
break;
|
||||
case 0xa0: /* fine volslide up */
|
||||
UniEffect(UNI_S3MEFFECTD, 0x0f|((inf<<4)&0x0f));
|
||||
break;
|
||||
case 0xb0: /* fine volslide down */
|
||||
UniEffect(UNI_S3MEFFECTE, 0xf0|(inf&0x0f));
|
||||
break;
|
||||
case 0xc0: /* note cut */
|
||||
case 0xd0: /* note delay */
|
||||
case 0xe0: /* extend row */
|
||||
UniPTEffect(0xe,inf);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0f: /* set tempo */
|
||||
UniEffect(UNI_S3MEFFECTA,inf);
|
||||
break;
|
||||
case 0x10: /* arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 0x12: /* retrigger */
|
||||
UniEffect(UNI_S3MEFFECTQ,inf);
|
||||
break;
|
||||
case 0x13: /* set global volume */
|
||||
UniEffect(UNI_XMEFFECTG,inf<<1);
|
||||
break;
|
||||
case 0x14: /* fine vibrato */
|
||||
UniEffect(UNI_ITEFFECTU,inf);
|
||||
break;
|
||||
case 0x1e: /* special */
|
||||
switch (inf&0xf0) {
|
||||
case 8: /* set pan position */
|
||||
if (inf >=128)
|
||||
UniPTEffect(0x08,255);
|
||||
else
|
||||
UniPTEffect(0x08,inf<<1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1f: /* set bpm */
|
||||
if (inf >=0x20)
|
||||
UniEffect(UNI_S3MEFFECTT,inf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL GDM_Load(BOOL curious)
|
||||
{
|
||||
int i,x,u,track;
|
||||
SAMPLE *q;
|
||||
GDMSAMPLE s;
|
||||
ULONG position;
|
||||
|
||||
/* read header */
|
||||
_mm_read_string(mh->id1,4,modreader);
|
||||
_mm_read_string(mh->songname,32,modreader);
|
||||
_mm_read_string(mh->author,32,modreader);
|
||||
_mm_read_string(mh->eofmarker,3,modreader);
|
||||
_mm_read_string(mh->id2,4,modreader);
|
||||
|
||||
mh->majorver=_mm_read_UBYTE(modreader);
|
||||
mh->minorver=_mm_read_UBYTE(modreader);
|
||||
mh->trackerid=_mm_read_I_UWORD(modreader);
|
||||
mh->t_majorver=_mm_read_UBYTE(modreader);
|
||||
mh->t_minorver=_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->pantable,32,modreader);
|
||||
mh->mastervol=_mm_read_UBYTE(modreader);
|
||||
mh->mastertempo=_mm_read_UBYTE(modreader);
|
||||
mh->masterbpm=_mm_read_UBYTE(modreader);
|
||||
mh->flags=_mm_read_I_UWORD(modreader);
|
||||
|
||||
mh->orderloc=_mm_read_I_ULONG(modreader);
|
||||
mh->ordernum=_mm_read_UBYTE(modreader);
|
||||
mh->patternloc=_mm_read_I_ULONG(modreader);
|
||||
mh->patternnum=_mm_read_UBYTE(modreader);
|
||||
mh->samhead=_mm_read_I_ULONG(modreader);
|
||||
mh->samdata=_mm_read_I_ULONG(modreader);
|
||||
mh->samnum=_mm_read_UBYTE(modreader);
|
||||
mh->messageloc=_mm_read_I_ULONG(modreader);
|
||||
mh->messagelen=_mm_read_I_ULONG(modreader);
|
||||
mh->scrollyloc=_mm_read_I_ULONG(modreader);
|
||||
mh->scrollylen=_mm_read_I_UWORD(modreader);
|
||||
mh->graphicloc=_mm_read_I_ULONG(modreader);
|
||||
mh->graphiclen=_mm_read_I_UWORD(modreader);
|
||||
|
||||
/* have we ended abruptly? */
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* any orders? */
|
||||
if(mh->ordernum==255) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now we fill */
|
||||
of.modtype=strdup(GDM_Version);
|
||||
of.modtype[18]=mh->majorver+'0';
|
||||
of.modtype[20]=mh->minorver/10+'0';
|
||||
of.modtype[21]=mh->minorver%10+'0';
|
||||
of.songname=DupStr(mh->songname,32,0);
|
||||
of.numpat=mh->patternnum+1;
|
||||
of.reppos=0;
|
||||
of.numins=of.numsmp=mh->samnum+1;
|
||||
of.initspeed=mh->mastertempo;
|
||||
of.inittempo=mh->masterbpm;
|
||||
of.initvolume=mh->mastervol<<1;
|
||||
of.flags|=UF_S3MSLIDES | UF_PANNING;
|
||||
/* XXX whenever possible, we should try to determine the original format.
|
||||
Here we assume it was S3M-style wrt bpmlimit... */
|
||||
of.bpmlimit = 32;
|
||||
|
||||
/* read the order data */
|
||||
if (!AllocPositions(mh->ordernum+1)) {
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_mm_fseek(modreader,mh->orderloc,SEEK_SET);
|
||||
for (i=0;i<mh->ordernum+1;i++)
|
||||
of.positions[i]=_mm_read_UBYTE(modreader);
|
||||
|
||||
of.numpos=0;
|
||||
for (i=0;i<mh->ordernum+1;i++) {
|
||||
int order=of.positions[i];
|
||||
if(order==255) order=LAST_PATTERN;
|
||||
of.positions[of.numpos]=order;
|
||||
if (of.positions[i]<254) of.numpos++;
|
||||
}
|
||||
|
||||
/* have we ended abruptly yet? */
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* time to load the samples */
|
||||
if (!AllocSamples()) {
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q=of.samples;
|
||||
position=mh->samdata;
|
||||
|
||||
/* seek to instrument position */
|
||||
_mm_fseek(modreader,mh->samhead,SEEK_SET);
|
||||
|
||||
for (i=0;i<of.numins;i++) {
|
||||
/* load sample info */
|
||||
_mm_read_UBYTES(s.sampname,32,modreader);
|
||||
_mm_read_UBYTES(s.filename,12,modreader);
|
||||
s.ems=_mm_read_UBYTE(modreader);
|
||||
s.length=_mm_read_I_ULONG(modreader);
|
||||
s.loopbeg=_mm_read_I_ULONG(modreader);
|
||||
s.loopend=_mm_read_I_ULONG(modreader);
|
||||
s.flags=_mm_read_UBYTE(modreader);
|
||||
s.c4spd=_mm_read_I_UWORD(modreader);
|
||||
s.vol=_mm_read_UBYTE(modreader);
|
||||
s.pan=_mm_read_UBYTE(modreader);
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
q->samplename=DupStr(s.sampname,32,0);
|
||||
q->speed=s.c4spd;
|
||||
q->length=s.length;
|
||||
q->loopstart=s.loopbeg;
|
||||
q->loopend=s.loopend;
|
||||
q->volume=s.vol;
|
||||
q->panning=s.pan;
|
||||
q->seekpos=position;
|
||||
|
||||
position +=s.length;
|
||||
|
||||
if (s.flags&1)
|
||||
q->flags |=SF_LOOP;
|
||||
if (s.flags&2)
|
||||
q->flags |=SF_16BITS;
|
||||
if (s.flags&16)
|
||||
q->flags |=SF_STEREO;
|
||||
q++;
|
||||
}
|
||||
|
||||
/* set the panning */
|
||||
for (i=x=0;i<32;i++) {
|
||||
of.panning[i]=mh->pantable[i];
|
||||
if (!of.panning[i])
|
||||
of.panning[i]=PAN_LEFT;
|
||||
else if (of.panning[i]==8)
|
||||
of.panning[i]=PAN_CENTER;
|
||||
else if (of.panning[i]==15)
|
||||
of.panning[i]=PAN_RIGHT;
|
||||
else if (of.panning[i]==16)
|
||||
of.panning[i]=PAN_SURROUND;
|
||||
else if (of.panning[i]==255)
|
||||
of.panning[i]=128;
|
||||
else
|
||||
of.panning[i]<<=3;
|
||||
if (mh->pantable[i]!=255)
|
||||
x=i;
|
||||
}
|
||||
|
||||
of.numchn=x+1;
|
||||
if (of.numchn<1)
|
||||
of.numchn=1; /* for broken counts */
|
||||
|
||||
/* load the pattern info */
|
||||
of.numtrk=of.numpat*of.numchn;
|
||||
|
||||
/* jump to patterns */
|
||||
_mm_fseek(modreader,mh->patternloc,SEEK_SET);
|
||||
|
||||
if (!AllocTracks()) {
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!AllocPatterns()) {
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=track=0;i<of.numpat;i++) {
|
||||
if (!GDM_ReadPattern()) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
for (u=0;u<of.numchn;u++,track++) {
|
||||
of.tracks[track]=GDM_ConvertTrack(&gdmbuf[u<<6]);
|
||||
if (!of.tracks[track]) {
|
||||
_mm_errno=MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *GDM_LoadTitle(void)
|
||||
{
|
||||
CHAR s[32];
|
||||
|
||||
_mm_fseek(modreader,4,SEEK_SET);
|
||||
if (!_mm_read_UBYTES(s,32,modreader)) return NULL;
|
||||
|
||||
return DupStr(s,28,0);
|
||||
}
|
||||
|
||||
MIKMODAPI MLOADER load_gdm=
|
||||
{
|
||||
NULL,
|
||||
"GDM",
|
||||
"GDM (General DigiMusic)",
|
||||
GDM_Init,
|
||||
GDM_Test,
|
||||
GDM_Load,
|
||||
GDM_Cleanup,
|
||||
GDM_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
738
project/jni/mikmod/loaders/load_imf.c
Normal file
738
project/jni/mikmod/loaders/load_imf.c
Normal file
@@ -0,0 +1,738 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_imf.c,v 1.2 2004/02/06 19:29:03 raph Exp $
|
||||
|
||||
Imago Orpheus (IMF) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* module header */
|
||||
typedef struct IMFHEADER {
|
||||
CHAR songname[32];
|
||||
UWORD ordnum;
|
||||
UWORD patnum;
|
||||
UWORD insnum;
|
||||
UWORD flags;
|
||||
UBYTE initspeed;
|
||||
UBYTE inittempo;
|
||||
UBYTE mastervol;
|
||||
UBYTE mastermult;
|
||||
UBYTE orders[256];
|
||||
} IMFHEADER;
|
||||
|
||||
/* channel settings */
|
||||
typedef struct IMFCHANNEL {
|
||||
CHAR name[12];
|
||||
UBYTE chorus;
|
||||
UBYTE reverb;
|
||||
UBYTE pan;
|
||||
UBYTE status;
|
||||
} IMFCHANNEL;
|
||||
|
||||
/* instrument header */
|
||||
#define IMFNOTECNT (10*OCTAVE)
|
||||
#define IMFENVCNT (16*2)
|
||||
typedef struct IMFINSTHEADER {
|
||||
CHAR name[32];
|
||||
UBYTE what[IMFNOTECNT];
|
||||
UWORD volenv[IMFENVCNT];
|
||||
UWORD panenv[IMFENVCNT];
|
||||
UWORD pitenv[IMFENVCNT];
|
||||
UBYTE volpts;
|
||||
UBYTE volsus;
|
||||
UBYTE volbeg;
|
||||
UBYTE volend;
|
||||
UBYTE volflg;
|
||||
UBYTE panpts;
|
||||
UBYTE pansus;
|
||||
UBYTE panbeg;
|
||||
UBYTE panend;
|
||||
UBYTE panflg;
|
||||
UBYTE pitpts;
|
||||
UBYTE pitsus;
|
||||
UBYTE pitbeg;
|
||||
UBYTE pitend;
|
||||
UBYTE pitflg;
|
||||
UWORD volfade;
|
||||
UWORD numsmp;
|
||||
ULONG signature;
|
||||
} IMFINSTHEADER;
|
||||
|
||||
/* sample header */
|
||||
typedef struct IMFWAVHEADER {
|
||||
CHAR samplename[13];
|
||||
ULONG length;
|
||||
ULONG loopstart;
|
||||
ULONG loopend;
|
||||
ULONG samplerate;
|
||||
UBYTE volume;
|
||||
UBYTE pan;
|
||||
UBYTE flags;
|
||||
} IMFWAVHEADER;
|
||||
|
||||
typedef struct IMFNOTE {
|
||||
UBYTE note,ins,eff1,dat1,eff2,dat2;
|
||||
} IMFNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static CHAR IMF_Version[]="Imago Orpheus";
|
||||
|
||||
static IMFNOTE *imfpat=NULL;
|
||||
static IMFHEADER *mh=NULL;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL IMF_Test(void)
|
||||
{
|
||||
UBYTE id[4];
|
||||
|
||||
_mm_fseek(modreader,0x3c,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(id,4,modreader)) return 0;
|
||||
if(!memcmp(id,"IM10",4)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IMF_Init(void)
|
||||
{
|
||||
if(!(imfpat=(IMFNOTE*)_mm_malloc(32*256*sizeof(IMFNOTE)))) return 0;
|
||||
if(!(mh=(IMFHEADER*)_mm_malloc(sizeof(IMFHEADER)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void IMF_Cleanup(void)
|
||||
{
|
||||
FreeLinear();
|
||||
|
||||
_mm_free(imfpat);
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static BOOL IMF_ReadPattern(SLONG size,UWORD rows)
|
||||
{
|
||||
int row=0,flag,ch;
|
||||
IMFNOTE *n,dummy;
|
||||
|
||||
/* clear pattern data */
|
||||
memset(imfpat,255,32*256*sizeof(IMFNOTE));
|
||||
|
||||
while((size>0)&&(row<rows)) {
|
||||
flag=_mm_read_UBYTE(modreader);size--;
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
ch=remap[flag&31];
|
||||
|
||||
if(ch!=-1)
|
||||
n=&imfpat[256*ch+row];
|
||||
else
|
||||
n=&dummy;
|
||||
|
||||
if(flag&32) {
|
||||
n->note=_mm_read_UBYTE(modreader);
|
||||
if(n->note>=0xa0) n->note=0xa0; /* note off */
|
||||
n->ins =_mm_read_UBYTE(modreader);
|
||||
size-=2;
|
||||
}
|
||||
if(flag&64) {
|
||||
size-=2;
|
||||
n->eff2=_mm_read_UBYTE(modreader);
|
||||
n->dat2=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
if(flag&128) {
|
||||
n->eff1=_mm_read_UBYTE(modreader);
|
||||
n->dat1=_mm_read_UBYTE(modreader);
|
||||
size-=2;
|
||||
}
|
||||
} else row++;
|
||||
}
|
||||
if((size)||(row!=rows)) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void IMF_ProcessCmd(UBYTE eff,UBYTE inf)
|
||||
{
|
||||
if((eff)&&(eff!=255))
|
||||
switch (eff) {
|
||||
case 0x01: /* set tempo */
|
||||
UniEffect(UNI_S3MEFFECTA,inf);
|
||||
break;
|
||||
case 0x02: /* set BPM */
|
||||
if(inf>=0x20) UniEffect(UNI_S3MEFFECTT,inf);
|
||||
break;
|
||||
case 0x03: /* tone portamento */
|
||||
UniEffect(UNI_ITEFFECTG,inf);
|
||||
break;
|
||||
case 0x04: /* porta + volslide */
|
||||
UniEffect(UNI_ITEFFECTG,inf);
|
||||
UniEffect(UNI_S3MEFFECTD,0);
|
||||
break;
|
||||
case 0x05: /* vibrato */
|
||||
UniEffect(UNI_XMEFFECT4,inf);
|
||||
break;
|
||||
case 0x06: /* vibrato + volslide */
|
||||
UniEffect(UNI_XMEFFECT6,inf);
|
||||
break;
|
||||
case 0x07: /* fine vibrato */
|
||||
UniEffect(UNI_ITEFFECTU,inf);
|
||||
break;
|
||||
case 0x08: /* tremolo */
|
||||
UniEffect(UNI_S3MEFFECTR,inf);
|
||||
break;
|
||||
case 0x09: /* arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 0x0a: /* panning */
|
||||
UniPTEffect(0x8,(inf>=128)?255:(inf<<1));
|
||||
break;
|
||||
case 0x0b: /* pan slide */
|
||||
UniEffect(UNI_XMEFFECTP,inf);
|
||||
break;
|
||||
case 0x0c: /* set channel volume */
|
||||
if(inf<=64) UniPTEffect(0xc,inf);
|
||||
break;
|
||||
case 0x0d: /* volume slide */
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0x0e: /* fine volume slide */
|
||||
if(inf) {
|
||||
if(inf>>4)
|
||||
UniEffect(UNI_S3MEFFECTD,0x0f|inf);
|
||||
else
|
||||
UniEffect(UNI_S3MEFFECTD,0xf0|inf);
|
||||
} else
|
||||
UniEffect(UNI_S3MEFFECTD,0);
|
||||
break;
|
||||
case 0x0f: /* set finetune */
|
||||
UniPTEffect(0xe,0x50|(inf>>4));
|
||||
break;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
case 0x10: /* note slide up */
|
||||
case 0x11: /* not slide down */
|
||||
fprintf(stderr,"\rIMF effect 0x10/0x11 (note slide)"
|
||||
" not implemented (eff=%2X inf=%2X)\n",eff,inf);
|
||||
break;
|
||||
#endif
|
||||
case 0x12: /* slide up */
|
||||
UniEffect(UNI_S3MEFFECTF,inf);
|
||||
break;
|
||||
case 0x13: /* slide down */
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
break;
|
||||
case 0x14: /* fine slide up */
|
||||
if (inf) {
|
||||
if (inf<0x40)
|
||||
UniEffect(UNI_S3MEFFECTF,0xe0|(inf>>2));
|
||||
else
|
||||
UniEffect(UNI_S3MEFFECTF,0xf0|(inf>>4));
|
||||
} else
|
||||
UniEffect(UNI_S3MEFFECTF,0);
|
||||
break;
|
||||
case 0x15: /* fine slide down */
|
||||
if (inf) {
|
||||
if (inf<0x40)
|
||||
UniEffect(UNI_S3MEFFECTE,0xe0|(inf>>2));
|
||||
else
|
||||
UniEffect(UNI_S3MEFFECTE,0xf0|(inf>>4));
|
||||
} else
|
||||
UniEffect(UNI_S3MEFFECTE,0);
|
||||
break;
|
||||
/* 0x16 set filter cutoff (awe32) */
|
||||
/* 0x17 filter side + resonance (awe32) */
|
||||
case 0x18: /* sample offset */
|
||||
UniPTEffect(0x9,inf);
|
||||
break;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
case 0x19: /* set fine sample offset */
|
||||
fprintf(stderr,"\rIMF effect 0x19 (fine sample offset)"
|
||||
" not implemented (inf=%2X)\n",inf);
|
||||
break;
|
||||
#endif
|
||||
case 0x1a: /* keyoff */
|
||||
UniWriteByte(UNI_KEYOFF);
|
||||
break;
|
||||
case 0x1b: /* retrig */
|
||||
UniEffect(UNI_S3MEFFECTQ,inf);
|
||||
break;
|
||||
case 0x1c: /* tremor */
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
break;
|
||||
case 0x1d: /* position jump */
|
||||
UniPTEffect(0xb,inf);
|
||||
break;
|
||||
case 0x1e: /* pattern break */
|
||||
UniPTEffect(0xd,(inf>>4)*10+(inf&0xf));
|
||||
break;
|
||||
case 0x1f: /* set master volume */
|
||||
if(inf<=64) UniEffect(UNI_XMEFFECTG,inf<<1);
|
||||
break;
|
||||
case 0x20: /* master volume slide */
|
||||
UniEffect(UNI_XMEFFECTH,inf);
|
||||
break;
|
||||
case 0x21: /* extended effects */
|
||||
switch(inf>>4) {
|
||||
case 0x1: /* set filter */
|
||||
case 0x5: /* vibrato waveform */
|
||||
case 0x8: /* tremolo waveform */
|
||||
UniPTEffect(0xe,inf-0x10);
|
||||
break;
|
||||
case 0xa: /* pattern loop */
|
||||
UniPTEffect(0xe,0x60|(inf&0xf));
|
||||
break;
|
||||
case 0xb: /* pattern delay */
|
||||
UniPTEffect(0xe,0xe0|(inf&0xf));
|
||||
break;
|
||||
case 0x3: /* glissando */
|
||||
case 0xc: /* note cut */
|
||||
case 0xd: /* note delay */
|
||||
case 0xf: /* invert loop */
|
||||
UniPTEffect(0xe,inf);
|
||||
break;
|
||||
case 0xe: /* ignore envelope */
|
||||
UniEffect(UNI_ITEFFECTS0, 0x77); /* vol */
|
||||
UniEffect(UNI_ITEFFECTS0, 0x79); /* pan */
|
||||
UniEffect(UNI_ITEFFECTS0, 0x7b); /* pit */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* 0x22 chorus (awe32) */
|
||||
/* 0x23 reverb (awe32) */
|
||||
}
|
||||
}
|
||||
|
||||
static UBYTE* IMF_ConvertTrack(IMFNOTE* tr,UWORD rows)
|
||||
{
|
||||
int t;
|
||||
UBYTE note,ins;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<rows;t++) {
|
||||
note=tr[t].note;
|
||||
ins=tr[t].ins;
|
||||
|
||||
if((ins)&&(ins!=255)) UniInstrument(ins-1);
|
||||
if(note!=255) {
|
||||
if(note==0xa0) {
|
||||
UniPTEffect(0xc,0); /* Note cut */
|
||||
if(tr[t].eff1==0x0c) tr[t].eff1=0;
|
||||
if(tr[t].eff2==0x0c) tr[t].eff2=0;
|
||||
} else
|
||||
UniNote(((note>>4)*OCTAVE)+(note&0xf));
|
||||
}
|
||||
|
||||
IMF_ProcessCmd(tr[t].eff1,tr[t].dat1);
|
||||
IMF_ProcessCmd(tr[t].eff2,tr[t].dat2);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL IMF_Load(BOOL curious)
|
||||
{
|
||||
#define IMF_SMPINCR 64
|
||||
int t,u,track=0,oldnumsmp;
|
||||
IMFCHANNEL channels[32];
|
||||
INSTRUMENT *d;
|
||||
SAMPLE *q;
|
||||
IMFWAVHEADER *wh=NULL,*s=NULL;
|
||||
ULONG *nextwav=NULL;
|
||||
UWORD wavcnt=0;
|
||||
UBYTE id[4];
|
||||
|
||||
/* try to read the module header */
|
||||
_mm_read_string(mh->songname,32,modreader);
|
||||
mh->ordnum=_mm_read_I_UWORD(modreader);
|
||||
mh->patnum=_mm_read_I_UWORD(modreader);
|
||||
mh->insnum=_mm_read_I_UWORD(modreader);
|
||||
mh->flags =_mm_read_I_UWORD(modreader);
|
||||
_mm_fseek(modreader,8,SEEK_CUR);
|
||||
mh->initspeed =_mm_read_UBYTE(modreader);
|
||||
mh->inittempo =_mm_read_UBYTE(modreader);
|
||||
mh->mastervol =_mm_read_UBYTE(modreader);
|
||||
mh->mastermult=_mm_read_UBYTE(modreader);
|
||||
_mm_fseek(modreader,64,SEEK_SET);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.songname=DupStr(mh->songname,31,1);
|
||||
of.modtype=strdup(IMF_Version);
|
||||
of.numpat=mh->patnum;
|
||||
of.numins=mh->insnum;
|
||||
of.reppos=0;
|
||||
of.initspeed=mh->initspeed;
|
||||
of.inittempo=mh->inittempo;
|
||||
of.initvolume=mh->mastervol<<1;
|
||||
of.flags |= UF_INST | UF_ARPMEM | UF_PANNING;
|
||||
if(mh->flags&1) of.flags |= UF_LINEAR;
|
||||
of.bpmlimit=32;
|
||||
|
||||
/* read channel information */
|
||||
of.numchn=0;
|
||||
memset(remap,-1,32*sizeof(UBYTE));
|
||||
for(t=0;t<32;t++) {
|
||||
_mm_read_string(channels[t].name,12,modreader);
|
||||
channels[t].chorus=_mm_read_UBYTE(modreader);
|
||||
channels[t].reverb=_mm_read_UBYTE(modreader);
|
||||
channels[t].pan =_mm_read_UBYTE(modreader);
|
||||
channels[t].status=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
/* bug in Imago Orpheus ? If only channel 1 is enabled, in fact we have to
|
||||
enable 16 channels */
|
||||
if(!channels[0].status) {
|
||||
for(t=1;t<16;t++) if(channels[t].status!=1) break;
|
||||
if(t==16) for(t=1;t<16;t++) channels[t].status=0;
|
||||
}
|
||||
for(t=0;t<32;t++) {
|
||||
if(channels[t].status!=2)
|
||||
remap[t]=of.numchn++;
|
||||
else
|
||||
remap[t]=-1;
|
||||
}
|
||||
for(t=0;t<32;t++)
|
||||
if(remap[t]!=-1) {
|
||||
of.panning[remap[t]]=channels[t].pan;
|
||||
of.chanvol[remap[t]]=channels[t].status?0:64;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read order list */
|
||||
_mm_read_UBYTES(mh->orders,256,modreader);
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
of.numpos=0;
|
||||
for(t=0;t<mh->ordnum;t++)
|
||||
if(mh->orders[t]!=0xff) of.numpos++;
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
for(t=u=0;t<mh->ordnum;t++)
|
||||
if(mh->orders[t]!=0xff) of.positions[u++]=mh->orders[t];
|
||||
|
||||
/* load pattern info */
|
||||
of.numtrk=of.numpat*of.numchn;
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
SLONG size;
|
||||
UWORD rows;
|
||||
|
||||
size=(SLONG)_mm_read_I_UWORD(modreader);
|
||||
rows=_mm_read_I_UWORD(modreader);
|
||||
if((rows>256)||(size<4)) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
of.pattrows[t]=rows;
|
||||
if(!IMF_ReadPattern(size-4,rows)) return 0;
|
||||
for(u=0;u<of.numchn;u++)
|
||||
if(!(of.tracks[track++]=IMF_ConvertTrack(&imfpat[u*256],rows)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load instruments */
|
||||
if(!AllocInstruments()) return 0;
|
||||
d=of.instruments;
|
||||
|
||||
for(oldnumsmp=t=0;t<of.numins;t++) {
|
||||
IMFINSTHEADER ih;
|
||||
|
||||
memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
|
||||
|
||||
/* read instrument header */
|
||||
_mm_read_string(ih.name,32,modreader);
|
||||
d->insname=DupStr(ih.name,31,1);
|
||||
_mm_read_UBYTES(ih.what,IMFNOTECNT,modreader);
|
||||
_mm_fseek(modreader,8,SEEK_CUR);
|
||||
_mm_read_I_UWORDS(ih.volenv,IMFENVCNT,modreader);
|
||||
_mm_read_I_UWORDS(ih.panenv,IMFENVCNT,modreader);
|
||||
_mm_read_I_UWORDS(ih.pitenv,IMFENVCNT,modreader);
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define IMF_FinishLoadingEnvelope(name) \
|
||||
ih. name##pts=_mm_read_UBYTE(modreader); \
|
||||
ih. name##sus=_mm_read_UBYTE(modreader); \
|
||||
ih. name##beg=_mm_read_UBYTE(modreader); \
|
||||
ih. name##end=_mm_read_UBYTE(modreader); \
|
||||
ih. name##flg=_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader)
|
||||
#else
|
||||
#define IMF_FinishLoadingEnvelope(name) \
|
||||
ih. name/**/pts=_mm_read_UBYTE(modreader); \
|
||||
ih. name/**/sus=_mm_read_UBYTE(modreader); \
|
||||
ih. name/**/beg=_mm_read_UBYTE(modreader); \
|
||||
ih. name/**/end=_mm_read_UBYTE(modreader); \
|
||||
ih. name/**/flg=_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader); \
|
||||
_mm_read_UBYTE(modreader)
|
||||
#endif
|
||||
|
||||
IMF_FinishLoadingEnvelope(vol);
|
||||
IMF_FinishLoadingEnvelope(pan);
|
||||
IMF_FinishLoadingEnvelope(pit);
|
||||
|
||||
ih.volfade=_mm_read_I_UWORD(modreader);
|
||||
ih.numsmp =_mm_read_I_UWORD(modreader);
|
||||
|
||||
_mm_read_UBYTES(id,4,modreader);
|
||||
/* Looks like Imago Orpheus forgets the signature for empty
|
||||
instruments following a multi-sample instrument... */
|
||||
if(memcmp(id,"II10",4) &&
|
||||
(oldnumsmp && memcmp(id,"\x0\x0\x0\x0",4))) {
|
||||
if(nextwav) free(nextwav);
|
||||
if(wh) free(wh);
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
oldnumsmp=ih.numsmp;
|
||||
|
||||
if((ih.numsmp>16)||(ih.volpts>IMFENVCNT/2)||(ih.panpts>IMFENVCNT/2)||
|
||||
(ih.pitpts>IMFENVCNT/2)||(_mm_eof(modreader))) {
|
||||
if(nextwav) free(nextwav);
|
||||
if(wh) free(wh);
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(u=0;u<IMFNOTECNT;u++)
|
||||
d->samplenumber[u]=ih.what[u]>ih.numsmp?0xffff:ih.what[u]+of.numsmp;
|
||||
d->volfade=ih.volfade;
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define IMF_ProcessEnvelope(name) \
|
||||
for (u = 0; u < (IMFENVCNT >> 1); u++) { \
|
||||
d-> name##env[u].pos = ih. name##env[u << 1]; \
|
||||
d-> name##env[u].val = ih. name##env[(u << 1)+ 1]; \
|
||||
} \
|
||||
if (ih. name##flg&1) d-> name##flg|=EF_ON; \
|
||||
if (ih. name##flg&2) d-> name##flg|=EF_SUSTAIN; \
|
||||
if (ih. name##flg&4) d-> name##flg|=EF_LOOP; \
|
||||
d-> name##susbeg=d-> name##susend=ih. name##sus; \
|
||||
d-> name##beg=ih. name##beg; \
|
||||
d-> name##end=ih. name##end; \
|
||||
d-> name##pts=ih. name##pts; \
|
||||
\
|
||||
if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \
|
||||
d-> name##flg&=~EF_ON
|
||||
#else
|
||||
#define IMF_ProcessEnvelope(name) \
|
||||
for (u = 0; u < (IMFENVCNT >> 1); u++) { \
|
||||
d-> name/**/env[u].pos = ih. name/**/env[u << 1]; \
|
||||
d-> name/**/env[u].val = ih. name/**/env[(u << 1)+ 1]; \
|
||||
} \
|
||||
if (ih. name/**/flg&1) d-> name/**/flg|=EF_ON; \
|
||||
if (ih. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \
|
||||
if (ih. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \
|
||||
d-> name/**/susbeg=d-> name/**/susend=ih. name/**/sus; \
|
||||
d-> name/**/beg=ih. name/**/beg; \
|
||||
d-> name/**/end=ih. name/**/end; \
|
||||
d-> name/**/pts=ih. name/**/pts; \
|
||||
\
|
||||
if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
|
||||
d-> name/**/flg&=~EF_ON
|
||||
#endif
|
||||
|
||||
IMF_ProcessEnvelope(vol);
|
||||
IMF_ProcessEnvelope(pan);
|
||||
IMF_ProcessEnvelope(pit);
|
||||
#undef IMF_ProcessEnvelope
|
||||
|
||||
if(ih.pitflg&1) {
|
||||
d->pitflg&=~EF_ON;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr, "\rFilter envelopes not supported yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* gather sample information */
|
||||
for(u=0;u<ih.numsmp;u++,s++) {
|
||||
/* allocate more room for sample information if necessary */
|
||||
if(of.numsmp+u==wavcnt) {
|
||||
wavcnt+=IMF_SMPINCR;
|
||||
if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))) {
|
||||
if(wh) free(wh);
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
if(!(wh=realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) {
|
||||
free(nextwav);
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
s=wh+(wavcnt-IMF_SMPINCR);
|
||||
}
|
||||
|
||||
_mm_read_string(s->samplename,13,modreader);
|
||||
_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);
|
||||
s->length =_mm_read_I_ULONG(modreader);
|
||||
s->loopstart =_mm_read_I_ULONG(modreader);
|
||||
s->loopend =_mm_read_I_ULONG(modreader);
|
||||
s->samplerate=_mm_read_I_ULONG(modreader);
|
||||
s->volume =_mm_read_UBYTE(modreader)&0x7f;
|
||||
s->pan =_mm_read_UBYTE(modreader);
|
||||
_mm_fseek(modreader,14,SEEK_CUR);
|
||||
s->flags =_mm_read_UBYTE(modreader);
|
||||
_mm_fseek(modreader,11,SEEK_CUR);
|
||||
_mm_read_UBYTES(id,4,modreader);
|
||||
if(((memcmp(id,"IS10",4))&&(memcmp(id,"IW10",4)))||
|
||||
(_mm_eof(modreader))) {
|
||||
free(nextwav);free(wh);
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
nextwav[of.numsmp+u]=_mm_ftell(modreader);
|
||||
_mm_fseek(modreader,s->length,SEEK_CUR);
|
||||
}
|
||||
|
||||
of.numsmp+=ih.numsmp;
|
||||
d++;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if(!of.numsmp) {
|
||||
if(nextwav) free(nextwav);
|
||||
if(wh) free(wh);
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load samples */
|
||||
if(!AllocSamples()) {
|
||||
free(nextwav);free(wh);
|
||||
return 0;
|
||||
}
|
||||
if(!AllocLinear()) {
|
||||
free(nextwav);free(wh);
|
||||
return 0;
|
||||
}
|
||||
q=of.samples;
|
||||
s=wh;
|
||||
for(u=0;u<of.numsmp;u++,s++,q++) {
|
||||
q->samplename=DupStr(s->samplename,12,1);
|
||||
q->length =s->length;
|
||||
q->loopstart=s->loopstart;
|
||||
q->loopend =s->loopend;
|
||||
q->volume =s->volume;
|
||||
q->speed =s->samplerate;
|
||||
if(of.flags&UF_LINEAR)
|
||||
q->speed=speed_to_finetune(s->samplerate<<1,u);
|
||||
q->panning =s->pan;
|
||||
q->seekpos =nextwav[u];
|
||||
|
||||
q->flags|=SF_SIGNED;
|
||||
if(s->flags&0x1) q->flags|=SF_LOOP;
|
||||
if(s->flags&0x2) q->flags|=SF_BIDI;
|
||||
if(s->flags&0x8) q->flags|=SF_OWNPAN;
|
||||
if(s->flags&0x4) {
|
||||
q->flags|=SF_16BITS;
|
||||
q->length >>=1;
|
||||
q->loopstart>>=1;
|
||||
q->loopend >>=1;
|
||||
}
|
||||
}
|
||||
|
||||
d=of.instruments;
|
||||
s=wh;
|
||||
for(u=0;u<of.numins;u++,d++) {
|
||||
for(t=0;t<IMFNOTECNT;t++) {
|
||||
if(d->samplenumber[t]>=of.numsmp)
|
||||
d->samplenote[t]=255;
|
||||
else if (of.flags&UF_LINEAR) {
|
||||
int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];
|
||||
d->samplenote[u]=(note<0)?0:(note>255?255:note);
|
||||
} else
|
||||
d->samplenote[t]=t;
|
||||
}
|
||||
}
|
||||
|
||||
free(wh);free(nextwav);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *IMF_LoadTitle(void)
|
||||
{
|
||||
CHAR s[31];
|
||||
|
||||
_mm_fseek(modreader,0,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,31,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,31,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_imf={
|
||||
NULL,
|
||||
"IMF",
|
||||
"IMF (Imago Orpheus)",
|
||||
IMF_Init,
|
||||
IMF_Test,
|
||||
IMF_Load,
|
||||
IMF_Cleanup,
|
||||
IMF_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
1008
project/jni/mikmod/loaders/load_it.c
Normal file
1008
project/jni/mikmod/loaders/load_it.c
Normal file
File diff suppressed because it is too large
Load Diff
505
project/jni/mikmod/loaders/load_m15.c
Normal file
505
project/jni/mikmod/loaders/load_m15.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_m15.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
15 instrument MOD loader
|
||||
Also supports Ultimate Sound Tracker (old M15 format)
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module Structure */
|
||||
|
||||
typedef struct MSAMPINFO {
|
||||
CHAR samplename[23]; /* 22 in module, 23 in memory */
|
||||
UWORD length;
|
||||
UBYTE finetune;
|
||||
UBYTE volume;
|
||||
UWORD reppos;
|
||||
UWORD replen;
|
||||
} MSAMPINFO;
|
||||
|
||||
typedef struct MODULEHEADER {
|
||||
CHAR songname[21]; /* the songname.., 20 in module, 21 in memory */
|
||||
MSAMPINFO samples[15]; /* all sampleinfo */
|
||||
UBYTE songlength; /* number of patterns used */
|
||||
UBYTE magic1; /* should be 127 */
|
||||
UBYTE positions[128]; /* which pattern to play at pos */
|
||||
} MODULEHEADER;
|
||||
|
||||
typedef struct MODNOTE {
|
||||
UBYTE a,b,c,d;
|
||||
} MODNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static MODULEHEADER *mh = NULL;
|
||||
static MODNOTE *patbuf = NULL;
|
||||
static BOOL ust_loader = 0; /* if TRUE, load as an ust module. */
|
||||
|
||||
/* known file formats which can confuse the loader */
|
||||
#define REJECT 2
|
||||
static char *signatures[REJECT]={
|
||||
"CAKEWALK", /* cakewalk midi files */
|
||||
"SZDD" /* Microsoft compressed files */
|
||||
};
|
||||
static int siglen[REJECT]={8,4};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
static BOOL LoadModuleHeader(MODULEHEADER *mh)
|
||||
{
|
||||
int t,u;
|
||||
|
||||
_mm_read_string(mh->songname,20,modreader);
|
||||
mh->songname[20]=0; /* just in case */
|
||||
|
||||
/* sanity check : title should contain printable characters and a bunch
|
||||
of null chars */
|
||||
for(t=0;t<20;t++)
|
||||
if((mh->songname[t])&&(mh->songname[t]<32)) return 0;
|
||||
for(t=0;(mh->songname[t])&&(t<20);t++);
|
||||
if(t<20) for(;t<20;t++) if(mh->songname[t]) return 0;
|
||||
|
||||
for(t=0;t<15;t++) {
|
||||
MSAMPINFO *s=&mh->samples[t];
|
||||
|
||||
_mm_read_string(s->samplename,22,modreader);
|
||||
s->samplename[22]=0; /* just in case */
|
||||
s->length =_mm_read_M_UWORD(modreader);
|
||||
s->finetune =_mm_read_UBYTE(modreader);
|
||||
s->volume =_mm_read_UBYTE(modreader);
|
||||
s->reppos =_mm_read_M_UWORD(modreader);
|
||||
s->replen =_mm_read_M_UWORD(modreader);
|
||||
|
||||
/* sanity check : sample title should contain printable characters and
|
||||
a bunch of null chars */
|
||||
for(u=0;u<20;u++)
|
||||
if((s->samplename[u])&&(s->samplename[u]</*32*/14)) return 0;
|
||||
for(u=0;(s->samplename[u])&&(u<20);u++);
|
||||
if(u<20) for(;u<20;u++) if(s->samplename[u]) return 0;
|
||||
|
||||
/* sanity check : finetune values */
|
||||
if(s->finetune>>4) return 0;
|
||||
}
|
||||
|
||||
mh->songlength =_mm_read_UBYTE(modreader);
|
||||
mh->magic1 =_mm_read_UBYTE(modreader); /* should be 127 */
|
||||
|
||||
/* sanity check : no more than 128 positions, restart position in range */
|
||||
if((!mh->songlength)||(mh->songlength>128)) return 0;
|
||||
/* values encountered so far are 0x6a and 0x78 */
|
||||
if(((mh->magic1&0xf8)!=0x78)&&(mh->magic1!=0x6a)&&(mh->magic1>mh->songlength)) return 0;
|
||||
|
||||
_mm_read_UBYTES(mh->positions,128,modreader);
|
||||
|
||||
/* sanity check : pattern range is 0..63 */
|
||||
for(t=0;t<128;t++)
|
||||
if(mh->positions[t]>63) return 0;
|
||||
|
||||
return(!_mm_eof(modreader));
|
||||
}
|
||||
|
||||
/* Checks the patterns in the modfile for UST / 15-inst indications.
|
||||
For example, if an effect 3xx is found, it is assumed that the song
|
||||
is 15-inst. If a 1xx effect has dat greater than 0x20, it is UST.
|
||||
|
||||
Returns: 0 indecisive; 1 = UST; 2 = 15-inst */
|
||||
static int CheckPatternType(int numpat)
|
||||
{
|
||||
int t;
|
||||
UBYTE eff, dat;
|
||||
|
||||
for(t=0;t<numpat*(64U*4);t++) {
|
||||
/* Load the pattern into the temp buffer and scan it */
|
||||
_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);
|
||||
eff = _mm_read_UBYTE(modreader);
|
||||
dat = _mm_read_UBYTE(modreader);
|
||||
|
||||
switch(eff) {
|
||||
case 1:
|
||||
if(dat>0x1f) return 1;
|
||||
if(dat<0x3) return 2;
|
||||
break;
|
||||
case 2:
|
||||
if(dat>0x1f) return 1;
|
||||
return 2;
|
||||
case 3:
|
||||
if (dat) return 2;
|
||||
break;
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL M15_Test(void)
|
||||
{
|
||||
int t, numpat;
|
||||
MODULEHEADER mh;
|
||||
|
||||
ust_loader = 0;
|
||||
if(!LoadModuleHeader(&mh)) return 0;
|
||||
|
||||
/* reject other file types */
|
||||
for(t=0;t<REJECT;t++)
|
||||
if(!memcmp(mh.songname,signatures[t],siglen[t])) return 0;
|
||||
|
||||
if(mh.magic1>127) return 0;
|
||||
if((!mh.songlength)||(mh.songlength>mh.magic1)) return 0;
|
||||
|
||||
for(t=0;t<15;t++) {
|
||||
/* all finetunes should be zero */
|
||||
if(mh.samples[t].finetune) return 0;
|
||||
|
||||
/* all volumes should be <= 64 */
|
||||
if(mh.samples[t].volume>64) return 0;
|
||||
|
||||
/* all instrument names should begin with s, st-, or a number */
|
||||
if((mh.samples[t].samplename[0]=='s')||
|
||||
(mh.samples[t].samplename[0]=='S')) {
|
||||
if((memcmp(mh.samples[t].samplename,"st-",3)) &&
|
||||
(memcmp(mh.samples[t].samplename,"ST-",3)) &&
|
||||
(*mh.samples[t].samplename))
|
||||
ust_loader = 1;
|
||||
} else
|
||||
if(!isdigit((int)mh.samples[t].samplename[0]))
|
||||
ust_loader = 1;
|
||||
|
||||
if(mh.samples[t].length>4999||mh.samples[t].reppos>9999) {
|
||||
ust_loader = 0;
|
||||
if(mh.samples[t].length>32768) return 0;
|
||||
}
|
||||
|
||||
/* if loop information is incorrect as words, but correct as bytes,
|
||||
this is likely to be an ust-style module */
|
||||
if((mh.samples[t].reppos+mh.samples[t].replen>mh.samples[t].length)&&
|
||||
(mh.samples[t].reppos+mh.samples[t].replen<(mh.samples[t].length<<1))){
|
||||
ust_loader = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!ust_loader) return 1;
|
||||
}
|
||||
|
||||
for(numpat=0,t=0;t<mh.songlength;t++)
|
||||
if(mh.positions[t]>numpat)
|
||||
numpat = mh.positions[t];
|
||||
numpat++;
|
||||
switch(CheckPatternType(numpat)) {
|
||||
case 0: /* indecisive, so check more clues... */
|
||||
break;
|
||||
case 1:
|
||||
ust_loader = 1;
|
||||
break;
|
||||
case 2:
|
||||
ust_loader = 0;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL M15_Init(void)
|
||||
{
|
||||
if(!(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void M15_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(patbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
Old (amiga) noteinfo:
|
||||
|
||||
_____byte 1_____ byte2_ _____byte 3_____ byte4_
|
||||
/ \ / \ / \ / \
|
||||
0000 0000-00000000 0000 0000-00000000
|
||||
|
||||
Upper four 12 bits for Lower four Effect command.
|
||||
bits of sam- note period. bits of sam-
|
||||
ple number. ple number.
|
||||
*/
|
||||
|
||||
static UBYTE M15_ConvertNote(MODNOTE* n, UBYTE lasteffect)
|
||||
{
|
||||
UBYTE instrument,effect,effdat,note;
|
||||
UWORD period;
|
||||
UBYTE lastnote=0;
|
||||
|
||||
/* decode the 4 bytes that make up a single note */
|
||||
instrument = n->c>>4;
|
||||
period = (((UWORD)n->a&0xf)<<8)+n->b;
|
||||
effect = n->c&0xf;
|
||||
effdat = n->d;
|
||||
|
||||
/* Convert the period to a note number */
|
||||
note=0;
|
||||
if(period) {
|
||||
for(note=0;note<7*OCTAVE;note++)
|
||||
if(period>=npertab[note]) break;
|
||||
if(note==7*OCTAVE) note=0;
|
||||
else note++;
|
||||
}
|
||||
|
||||
if(instrument) {
|
||||
/* if instrument does not exist, note cut */
|
||||
if((instrument>15)||(!mh->samples[instrument-1].length)) {
|
||||
UniPTEffect(0xc,0);
|
||||
if(effect==0xc) effect=effdat=0;
|
||||
} else {
|
||||
/* if we had a note, then change instrument... */
|
||||
if(note)
|
||||
UniInstrument(instrument-1);
|
||||
/* ...otherwise, only adjust volume... */
|
||||
else {
|
||||
/* ...unless an effect was specified, which forces a new note
|
||||
to be played */
|
||||
if(effect||effdat) {
|
||||
UniInstrument(instrument-1);
|
||||
note=lastnote;
|
||||
} else
|
||||
UniPTEffect(0xc,mh->samples[instrument-1].volume&0x7f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(note) {
|
||||
UniNote(note+2*OCTAVE-1);
|
||||
lastnote=note;
|
||||
}
|
||||
|
||||
/* Convert pattern jump from Dec to Hex */
|
||||
if(effect == 0xd)
|
||||
effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
|
||||
|
||||
/* Volume slide, up has priority */
|
||||
if((effect==0xa)&&(effdat&0xf)&&(effdat&0xf0))
|
||||
effdat&=0xf0;
|
||||
|
||||
/* Handle ``heavy'' volumes correctly */
|
||||
if ((effect == 0xc) && (effdat > 0x40))
|
||||
effdat = 0x40;
|
||||
|
||||
if(ust_loader) {
|
||||
switch(effect) {
|
||||
case 0:
|
||||
case 3:
|
||||
break;
|
||||
case 1:
|
||||
UniPTEffect(0,effdat);
|
||||
break;
|
||||
case 2:
|
||||
if(effdat&0xf) UniPTEffect(1,effdat&0xf);
|
||||
else if(effdat>>2) UniPTEffect(2,effdat>>2);
|
||||
break;
|
||||
default:
|
||||
UniPTEffect(effect,effdat);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* An isolated 100, 200 or 300 effect should be ignored (no
|
||||
"standalone" porta memory in mod files). However, a sequence
|
||||
such as 1XX, 100, 100, 100 is fine. */
|
||||
if ((!effdat) && ((effect == 1)||(effect == 2)||(effect ==3)) &&
|
||||
(lasteffect < 0x10) && (effect != lasteffect))
|
||||
effect = 0;
|
||||
|
||||
UniPTEffect(effect,effdat);
|
||||
}
|
||||
if (effect == 8)
|
||||
of.flags |= UF_PANNING;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static UBYTE *M15_ConvertTrack(MODNOTE* n)
|
||||
{
|
||||
int t;
|
||||
UBYTE lasteffect = 0x10; /* non existant effect */
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
lasteffect = M15_ConvertNote(n,lasteffect);
|
||||
UniNewline();
|
||||
n+=4;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
/* Loads all patterns of a modfile and converts them into the 3 byte format. */
|
||||
static BOOL M15_LoadPatterns(void)
|
||||
{
|
||||
int t,s,tracks=0;
|
||||
|
||||
if(!AllocPatterns()) return 0;
|
||||
if(!AllocTracks()) return 0;
|
||||
|
||||
/* Allocate temporary buffer for loading and converting the patterns */
|
||||
if(!(patbuf=(MODNOTE*)_mm_calloc(64U*4,sizeof(MODNOTE)))) return 0;
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
/* Load the pattern into the temp buffer and convert it */
|
||||
for(s=0;s<(64U*4);s++) {
|
||||
patbuf[s].a=_mm_read_UBYTE(modreader);
|
||||
patbuf[s].b=_mm_read_UBYTE(modreader);
|
||||
patbuf[s].c=_mm_read_UBYTE(modreader);
|
||||
patbuf[s].d=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
|
||||
for(s=0;s<4;s++)
|
||||
if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL M15_Load(BOOL curious)
|
||||
{
|
||||
int t,scan;
|
||||
SAMPLE *q;
|
||||
MSAMPINFO *s;
|
||||
|
||||
/* try to read module header */
|
||||
if(!LoadModuleHeader(mh)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(ust_loader)
|
||||
of.modtype = strdup("Ultimate Soundtracker");
|
||||
else
|
||||
of.modtype = strdup("Soundtracker");
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
of.numchn = 4;
|
||||
of.songname = DupStr(mh->songname,21,1);
|
||||
of.numpos = mh->songlength;
|
||||
of.reppos = 0;
|
||||
|
||||
/* Count the number of patterns */
|
||||
of.numpat = 0;
|
||||
for(t=0;t<of.numpos;t++)
|
||||
if(mh->positions[t]>of.numpat)
|
||||
of.numpat=mh->positions[t];
|
||||
/* since some old modules embed extra patterns, we have to check the
|
||||
whole list to get the samples' file offsets right - however we can find
|
||||
garbage here, so check carefully */
|
||||
scan=1;
|
||||
for(t=of.numpos;t<128;t++)
|
||||
if(mh->positions[t]>=0x80) scan=0;
|
||||
if (scan)
|
||||
for(t=of.numpos;t<128;t++) {
|
||||
if(mh->positions[t]>of.numpat)
|
||||
of.numpat=mh->positions[t];
|
||||
if((curious)&&(mh->positions[t])) of.numpos=t+1;
|
||||
}
|
||||
of.numpat++;
|
||||
of.numtrk = of.numpat*of.numchn;
|
||||
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
for(t=0;t<of.numpos;t++)
|
||||
of.positions[t]=mh->positions[t];
|
||||
|
||||
/* Finally, init the sampleinfo structures */
|
||||
of.numins=of.numsmp=15;
|
||||
if(!AllocSamples()) return 0;
|
||||
|
||||
s = mh->samples;
|
||||
q = of.samples;
|
||||
|
||||
for(t=0;t<of.numins;t++) {
|
||||
/* convert the samplename */
|
||||
q->samplename = DupStr(s->samplename,23,1);
|
||||
|
||||
/* init the sampleinfo variables and convert the size pointers */
|
||||
q->speed = finetune[s->finetune&0xf];
|
||||
q->volume = s->volume;
|
||||
if(ust_loader)
|
||||
q->loopstart = s->reppos;
|
||||
else
|
||||
q->loopstart = s->reppos<<1;
|
||||
q->loopend = q->loopstart+(s->replen<<1);
|
||||
q->length = s->length<<1;
|
||||
|
||||
q->flags = SF_SIGNED;
|
||||
if(ust_loader) q->flags |= SF_UST_LOOP;
|
||||
if(s->replen>2) q->flags |= SF_LOOP;
|
||||
|
||||
s++;
|
||||
q++;
|
||||
}
|
||||
|
||||
if(!M15_LoadPatterns()) return 0;
|
||||
ust_loader = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CHAR *M15_LoadTitle(void)
|
||||
{
|
||||
CHAR s[21];
|
||||
|
||||
_mm_fseek(modreader,0,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
|
||||
s[20]=0; /* just in case */
|
||||
return(DupStr(s,21,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_m15={
|
||||
NULL,
|
||||
"15-instrument module",
|
||||
"MOD (15 instrument)",
|
||||
M15_Init,
|
||||
M15_Test,
|
||||
M15_Load,
|
||||
M15_Cleanup,
|
||||
M15_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
719
project/jni/mikmod/loaders/load_med.c
Normal file
719
project/jni/mikmod/loaders/load_med.c
Normal file
@@ -0,0 +1,719 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_med.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Amiga MED module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module information */
|
||||
|
||||
typedef struct MEDHEADER {
|
||||
ULONG id;
|
||||
ULONG modlen;
|
||||
ULONG MEDSONGP; /* struct MEDSONG *song; */
|
||||
UWORD psecnum; /* for the player routine, MMD2 only */
|
||||
UWORD pseq; /* " " " " */
|
||||
ULONG MEDBlockPP; /* struct MEDBlock **blockarr; */
|
||||
ULONG reserved1;
|
||||
ULONG MEDINSTHEADERPP; /* struct MEDINSTHEADER **smplarr; */
|
||||
ULONG reserved2;
|
||||
ULONG MEDEXPP; /* struct MEDEXP *expdata; */
|
||||
ULONG reserved3;
|
||||
UWORD pstate; /* some data for the player routine */
|
||||
UWORD pblock;
|
||||
UWORD pline;
|
||||
UWORD pseqnum;
|
||||
SWORD actplayline;
|
||||
UBYTE counter;
|
||||
UBYTE extra_songs; /* number of songs - 1 */
|
||||
} MEDHEADER;
|
||||
|
||||
typedef struct MEDSAMPLE {
|
||||
UWORD rep, replen; /* offs: 0(s), 2(s) */
|
||||
UBYTE midich; /* offs: 4(s) */
|
||||
UBYTE midipreset; /* offs: 5(s) */
|
||||
UBYTE svol; /* offs: 6(s) */
|
||||
SBYTE strans; /* offs: 7(s) */
|
||||
} MEDSAMPLE;
|
||||
|
||||
typedef struct MEDSONG {
|
||||
MEDSAMPLE sample[63]; /* 63 * 8 bytes = 504 bytes */
|
||||
UWORD numblocks; /* offs: 504 */
|
||||
UWORD songlen; /* offs: 506 */
|
||||
UBYTE playseq[256]; /* offs: 508 */
|
||||
UWORD deftempo; /* offs: 764 */
|
||||
SBYTE playtransp; /* offs: 766 */
|
||||
UBYTE flags; /* offs: 767 */
|
||||
UBYTE flags2; /* offs: 768 */
|
||||
UBYTE tempo2; /* offs: 769 */
|
||||
UBYTE trkvol[16]; /* offs: 770 */
|
||||
UBYTE mastervol; /* offs: 786 */
|
||||
UBYTE numsamples; /* offs: 787 */
|
||||
} MEDSONG;
|
||||
|
||||
typedef struct MEDEXP {
|
||||
ULONG nextmod; /* pointer to next module */
|
||||
ULONG exp_smp; /* pointer to MEDINSTEXT array */
|
||||
UWORD s_ext_entries;
|
||||
UWORD s_ext_entrsz;
|
||||
ULONG annotxt; /* pointer to annotation text */
|
||||
ULONG annolen;
|
||||
ULONG iinfo; /* pointer to MEDINSTINFO array */
|
||||
UWORD i_ext_entries;
|
||||
UWORD i_ext_entrsz;
|
||||
ULONG jumpmask;
|
||||
ULONG rgbtable;
|
||||
ULONG channelsplit;
|
||||
ULONG n_info;
|
||||
ULONG songname; /* pointer to songname */
|
||||
ULONG songnamelen;
|
||||
ULONG dumps;
|
||||
ULONG reserved2[7];
|
||||
} MEDEXP;
|
||||
|
||||
typedef struct MMD0NOTE {
|
||||
UBYTE a, b, c;
|
||||
} MMD0NOTE;
|
||||
|
||||
typedef struct MMD1NOTE {
|
||||
UBYTE a, b, c, d;
|
||||
} MMD1NOTE;
|
||||
|
||||
typedef struct MEDINSTHEADER {
|
||||
ULONG length;
|
||||
SWORD type;
|
||||
/* Followed by actual data */
|
||||
} MEDINSTHEADER;
|
||||
|
||||
typedef struct MEDINSTEXT {
|
||||
UBYTE hold;
|
||||
UBYTE decay;
|
||||
UBYTE suppress_midi_off;
|
||||
SBYTE finetune;
|
||||
} MEDINSTEXT;
|
||||
|
||||
typedef struct MEDINSTINFO {
|
||||
UBYTE name[40];
|
||||
} MEDINSTINFO;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
#define MMD0_string 0x4D4D4430
|
||||
#define MMD1_string 0x4D4D4431
|
||||
|
||||
static MEDHEADER *mh = NULL;
|
||||
static MEDSONG *ms = NULL;
|
||||
static MEDEXP *me = NULL;
|
||||
static ULONG *ba = NULL;
|
||||
static MMD0NOTE *mmd0pat = NULL;
|
||||
static MMD1NOTE *mmd1pat = NULL;
|
||||
|
||||
static BOOL decimalvolumes;
|
||||
static BOOL bpmtempos;
|
||||
|
||||
#define d0note(row,col) mmd0pat[((row)*(UWORD)of.numchn)+(col)]
|
||||
#define d1note(row,col) mmd1pat[((row)*(UWORD)of.numchn)+(col)]
|
||||
|
||||
static CHAR MED_Version[] = "OctaMED (MMDx)";
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL MED_Test(void)
|
||||
{
|
||||
UBYTE id[4];
|
||||
|
||||
if (!_mm_read_UBYTES(id, 4, modreader))
|
||||
return 0;
|
||||
if ((!memcmp(id, "MMD0", 4)) || (!memcmp(id, "MMD1", 4)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL MED_Init(void)
|
||||
{
|
||||
if (!(me = (MEDEXP *)_mm_malloc(sizeof(MEDEXP))))
|
||||
return 0;
|
||||
if (!(mh = (MEDHEADER *)_mm_malloc(sizeof(MEDHEADER))))
|
||||
return 0;
|
||||
if (!(ms = (MEDSONG *)_mm_malloc(sizeof(MEDSONG))))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MED_Cleanup(void)
|
||||
{
|
||||
_mm_free(me);
|
||||
_mm_free(mh);
|
||||
_mm_free(ms);
|
||||
_mm_free(ba);
|
||||
_mm_free(mmd0pat);
|
||||
_mm_free(mmd1pat);
|
||||
}
|
||||
|
||||
static void EffectCvt(UBYTE eff, UBYTE dat)
|
||||
{
|
||||
switch (eff) {
|
||||
/* 0x0 0x1 0x2 0x3 0x4 PT effects */
|
||||
case 0x5: /* PT vibrato with speed/depth nibbles swapped */
|
||||
UniPTEffect(0x4, (dat >> 4) | ((dat & 0xf) << 4));
|
||||
break;
|
||||
/* 0x6 0x7 not used */
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
break;
|
||||
case 0x8: /* midi hold/decay */
|
||||
break;
|
||||
case 0x9:
|
||||
if (bpmtempos) {
|
||||
if (!dat)
|
||||
dat = of.initspeed;
|
||||
UniEffect(UNI_S3MEFFECTA, dat);
|
||||
} else {
|
||||
if (dat <= 0x20) {
|
||||
if (!dat)
|
||||
dat = of.initspeed;
|
||||
else
|
||||
dat /= 4;
|
||||
UniPTEffect(0xf, dat);
|
||||
} else
|
||||
UniEffect(UNI_MEDSPEED, ((UWORD)dat * 125) / (33 * 4));
|
||||
}
|
||||
break;
|
||||
/* 0xa 0xb PT effects */
|
||||
case 0xc:
|
||||
if (decimalvolumes)
|
||||
dat = (dat >> 4) * 10 + (dat & 0xf);
|
||||
UniPTEffect(0xc, dat);
|
||||
break;
|
||||
case 0xd: /* same as PT volslide */
|
||||
UniPTEffect(0xa, dat);
|
||||
break;
|
||||
case 0xe: /* synth jmp - midi */
|
||||
break;
|
||||
case 0xf:
|
||||
switch (dat) {
|
||||
case 0: /* patternbreak */
|
||||
UniPTEffect(0xd, 0);
|
||||
break;
|
||||
case 0xf1: /* play note twice */
|
||||
UniWriteByte(UNI_MEDEFFECTF1);
|
||||
break;
|
||||
case 0xf2: /* delay note */
|
||||
UniWriteByte(UNI_MEDEFFECTF2);
|
||||
break;
|
||||
case 0xf3: /* play note three times */
|
||||
UniWriteByte(UNI_MEDEFFECTF3);
|
||||
break;
|
||||
case 0xfe: /* stop playing */
|
||||
UniPTEffect(0xb, of.numpat);
|
||||
break;
|
||||
case 0xff: /* note cut */
|
||||
UniPTEffect(0xc, 0);
|
||||
break;
|
||||
default:
|
||||
if (dat <= 10)
|
||||
UniPTEffect(0xf, dat);
|
||||
else if (dat <= 240) {
|
||||
if (bpmtempos)
|
||||
UniPTEffect(0xf, (dat < 32) ? 32 : dat);
|
||||
else
|
||||
UniEffect(UNI_MEDSPEED, ((UWORD)dat * 125) / 33);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: /* all normal PT effects are handled here */
|
||||
UniPTEffect(eff, dat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static UBYTE *MED_Convert1(int count, int col)
|
||||
{
|
||||
int t;
|
||||
UBYTE inst, note, eff, dat;
|
||||
MMD1NOTE *n;
|
||||
|
||||
UniReset();
|
||||
for (t = 0; t < count; t++) {
|
||||
n = &d1note(t, col);
|
||||
|
||||
note = n->a & 0x7f;
|
||||
inst = n->b & 0x3f;
|
||||
eff = n->c & 0xf;
|
||||
dat = n->d;
|
||||
|
||||
if (inst)
|
||||
UniInstrument(inst - 1);
|
||||
if (note)
|
||||
UniNote(note + 3 * OCTAVE - 1);
|
||||
EffectCvt(eff, dat);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
static UBYTE *MED_Convert0(int count, int col)
|
||||
{
|
||||
int t;
|
||||
UBYTE a, b, inst, note, eff, dat;
|
||||
MMD0NOTE *n;
|
||||
|
||||
UniReset();
|
||||
for (t = 0; t < count; t++) {
|
||||
n = &d0note(t, col);
|
||||
a = n->a;
|
||||
b = n->b;
|
||||
|
||||
note = a & 0x3f;
|
||||
a >>= 6;
|
||||
a = ((a & 1) << 1) | (a >> 1);
|
||||
inst = (b >> 4) | (a << 4);
|
||||
eff = b & 0xf;
|
||||
dat = n->c;
|
||||
|
||||
if (inst)
|
||||
UniInstrument(inst - 1);
|
||||
if (note)
|
||||
UniNote(note + 3 * OCTAVE - 1);
|
||||
EffectCvt(eff, dat);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
static BOOL LoadMEDPatterns(void)
|
||||
{
|
||||
int t, row, col;
|
||||
UWORD numtracks, numlines, maxlines = 0, track = 0;
|
||||
MMD0NOTE *mmdp;
|
||||
|
||||
/* first, scan patterns to see how many channels are used */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
_mm_fseek(modreader, ba[t], SEEK_SET);
|
||||
numtracks = _mm_read_UBYTE(modreader);
|
||||
numlines = _mm_read_UBYTE(modreader);
|
||||
|
||||
if (numtracks > of.numchn)
|
||||
of.numchn = numtracks;
|
||||
if (numlines > maxlines)
|
||||
maxlines = numlines;
|
||||
}
|
||||
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
if (!AllocTracks())
|
||||
return 0;
|
||||
if (!AllocPatterns())
|
||||
return 0;
|
||||
|
||||
if (!
|
||||
(mmd0pat =
|
||||
(MMD0NOTE *)_mm_calloc(of.numchn * (maxlines + 1),
|
||||
sizeof(MMD0NOTE)))) return 0;
|
||||
|
||||
/* second read: read and convert patterns */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
_mm_fseek(modreader, ba[t], SEEK_SET);
|
||||
numtracks = _mm_read_UBYTE(modreader);
|
||||
numlines = _mm_read_UBYTE(modreader);
|
||||
|
||||
of.pattrows[t] = ++numlines;
|
||||
memset(mmdp = mmd0pat, 0, of.numchn * maxlines * sizeof(MMD0NOTE));
|
||||
for (row = numlines; row; row--) {
|
||||
for (col = numtracks; col; col--, mmdp++) {
|
||||
mmdp->a = _mm_read_UBYTE(modreader);
|
||||
mmdp->b = _mm_read_UBYTE(modreader);
|
||||
mmdp->c = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
}
|
||||
|
||||
for (col = 0; col < of.numchn; col++)
|
||||
of.tracks[track++] = MED_Convert0(numlines, col);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL LoadMMD1Patterns(void)
|
||||
{
|
||||
int t, row, col;
|
||||
UWORD numtracks, numlines, maxlines = 0, track = 0;
|
||||
MMD1NOTE *mmdp;
|
||||
|
||||
/* first, scan patterns to see how many channels are used */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
_mm_fseek(modreader, ba[t], SEEK_SET);
|
||||
numtracks = _mm_read_M_UWORD(modreader);
|
||||
numlines = _mm_read_M_UWORD(modreader);
|
||||
if (numtracks > of.numchn)
|
||||
of.numchn = numtracks;
|
||||
if (numlines > maxlines)
|
||||
maxlines = numlines;
|
||||
}
|
||||
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
if (!AllocTracks())
|
||||
return 0;
|
||||
if (!AllocPatterns())
|
||||
return 0;
|
||||
|
||||
if (!
|
||||
(mmd1pat =
|
||||
(MMD1NOTE *)_mm_calloc(of.numchn * (maxlines + 1),
|
||||
sizeof(MMD1NOTE)))) return 0;
|
||||
|
||||
/* second read: really read and convert patterns */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
_mm_fseek(modreader, ba[t], SEEK_SET);
|
||||
numtracks = _mm_read_M_UWORD(modreader);
|
||||
numlines = _mm_read_M_UWORD(modreader);
|
||||
|
||||
_mm_fseek(modreader, sizeof(ULONG), SEEK_CUR);
|
||||
of.pattrows[t] = ++numlines;
|
||||
memset(mmdp = mmd1pat, 0, of.numchn * maxlines * sizeof(MMD1NOTE));
|
||||
|
||||
for (row = numlines; row; row--) {
|
||||
for (col = numtracks; col; col--, mmdp++) {
|
||||
mmdp->a = _mm_read_UBYTE(modreader);
|
||||
mmdp->b = _mm_read_UBYTE(modreader);
|
||||
mmdp->c = _mm_read_UBYTE(modreader);
|
||||
mmdp->d = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
}
|
||||
|
||||
for (col = 0; col < of.numchn; col++)
|
||||
of.tracks[track++] = MED_Convert1(numlines, col);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL MED_Load(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
ULONG sa[64];
|
||||
MEDINSTHEADER s;
|
||||
SAMPLE *q;
|
||||
MEDSAMPLE *mss;
|
||||
|
||||
/* try to read module header */
|
||||
mh->id = _mm_read_M_ULONG(modreader);
|
||||
mh->modlen = _mm_read_M_ULONG(modreader);
|
||||
mh->MEDSONGP = _mm_read_M_ULONG(modreader);
|
||||
mh->psecnum = _mm_read_M_UWORD(modreader);
|
||||
mh->pseq = _mm_read_M_UWORD(modreader);
|
||||
mh->MEDBlockPP = _mm_read_M_ULONG(modreader);
|
||||
mh->reserved1 = _mm_read_M_ULONG(modreader);
|
||||
mh->MEDINSTHEADERPP = _mm_read_M_ULONG(modreader);
|
||||
mh->reserved2 = _mm_read_M_ULONG(modreader);
|
||||
mh->MEDEXPP = _mm_read_M_ULONG(modreader);
|
||||
mh->reserved3 = _mm_read_M_ULONG(modreader);
|
||||
mh->pstate = _mm_read_M_UWORD(modreader);
|
||||
mh->pblock = _mm_read_M_UWORD(modreader);
|
||||
mh->pline = _mm_read_M_UWORD(modreader);
|
||||
mh->pseqnum = _mm_read_M_UWORD(modreader);
|
||||
mh->actplayline = _mm_read_M_SWORD(modreader);
|
||||
mh->counter = _mm_read_UBYTE(modreader);
|
||||
mh->extra_songs = _mm_read_UBYTE(modreader);
|
||||
|
||||
/* Seek to MEDSONG struct */
|
||||
_mm_fseek(modreader, mh->MEDSONGP, SEEK_SET);
|
||||
|
||||
/* Load the MED Song Header */
|
||||
mss = ms->sample; /* load the sample data first */
|
||||
for (t = 63; t; t--, mss++) {
|
||||
mss->rep = _mm_read_M_UWORD(modreader);
|
||||
mss->replen = _mm_read_M_UWORD(modreader);
|
||||
mss->midich = _mm_read_UBYTE(modreader);
|
||||
mss->midipreset = _mm_read_UBYTE(modreader);
|
||||
mss->svol = _mm_read_UBYTE(modreader);
|
||||
mss->strans = _mm_read_SBYTE(modreader);
|
||||
}
|
||||
|
||||
ms->numblocks = _mm_read_M_UWORD(modreader);
|
||||
ms->songlen = _mm_read_M_UWORD(modreader);
|
||||
_mm_read_UBYTES(ms->playseq, 256, modreader);
|
||||
ms->deftempo = _mm_read_M_UWORD(modreader);
|
||||
ms->playtransp = _mm_read_SBYTE(modreader);
|
||||
ms->flags = _mm_read_UBYTE(modreader);
|
||||
ms->flags2 = _mm_read_UBYTE(modreader);
|
||||
ms->tempo2 = _mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(ms->trkvol, 16, modreader);
|
||||
ms->mastervol = _mm_read_UBYTE(modreader);
|
||||
ms->numsamples = _mm_read_UBYTE(modreader);
|
||||
|
||||
/* check for a bad header */
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load extension structure */
|
||||
if (mh->MEDEXPP) {
|
||||
_mm_fseek(modreader, mh->MEDEXPP, SEEK_SET);
|
||||
me->nextmod = _mm_read_M_ULONG(modreader);
|
||||
me->exp_smp = _mm_read_M_ULONG(modreader);
|
||||
me->s_ext_entries = _mm_read_M_UWORD(modreader);
|
||||
me->s_ext_entrsz = _mm_read_M_UWORD(modreader);
|
||||
me->annotxt = _mm_read_M_ULONG(modreader);
|
||||
me->annolen = _mm_read_M_ULONG(modreader);
|
||||
me->iinfo = _mm_read_M_ULONG(modreader);
|
||||
me->i_ext_entries = _mm_read_M_UWORD(modreader);
|
||||
me->i_ext_entrsz = _mm_read_M_UWORD(modreader);
|
||||
me->jumpmask = _mm_read_M_ULONG(modreader);
|
||||
me->rgbtable = _mm_read_M_ULONG(modreader);
|
||||
me->channelsplit = _mm_read_M_ULONG(modreader);
|
||||
me->n_info = _mm_read_M_ULONG(modreader);
|
||||
me->songname = _mm_read_M_ULONG(modreader);
|
||||
me->songnamelen = _mm_read_M_ULONG(modreader);
|
||||
me->dumps = _mm_read_M_ULONG(modreader);
|
||||
}
|
||||
|
||||
/* seek to and read the samplepointer array */
|
||||
_mm_fseek(modreader, mh->MEDINSTHEADERPP, SEEK_SET);
|
||||
if (!_mm_read_M_ULONGS(sa, ms->numsamples, modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* alloc and read the blockpointer array */
|
||||
if (!(ba = (ULONG *)_mm_calloc(ms->numblocks, sizeof(ULONG))))
|
||||
return 0;
|
||||
_mm_fseek(modreader, mh->MEDBlockPP, SEEK_SET);
|
||||
if (!_mm_read_M_ULONGS(ba, ms->numblocks, modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copy song positions */
|
||||
if (!AllocPositions(ms->songlen))
|
||||
return 0;
|
||||
for (t = 0; t < ms->songlen; t++)
|
||||
of.positions[t] = ms->playseq[t];
|
||||
|
||||
decimalvolumes = (ms->flags & 0x10) ? 0 : 1;
|
||||
bpmtempos = (ms->flags2 & 0x20) ? 1 : 0;
|
||||
|
||||
if (bpmtempos) {
|
||||
int bpmlen = (ms->flags2 & 0x1f) + 1;
|
||||
of.initspeed = ms->tempo2;
|
||||
of.inittempo = ms->deftempo * bpmlen / 4;
|
||||
|
||||
if (bpmlen != 4) {
|
||||
/* Let's do some math : compute GCD of BPM beat length and speed */
|
||||
int a, b;
|
||||
|
||||
a = bpmlen;
|
||||
b = ms->tempo2;
|
||||
|
||||
if (a > b) {
|
||||
t = b;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
while ((a != b) && (a)) {
|
||||
t = a;
|
||||
a = b - a;
|
||||
b = t;
|
||||
if (a > b) {
|
||||
t = b;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
}
|
||||
|
||||
of.initspeed /= b;
|
||||
of.inittempo = ms->deftempo * bpmlen / (4 * b);
|
||||
}
|
||||
} else {
|
||||
of.initspeed = ms->tempo2;
|
||||
of.inittempo = ms->deftempo ? ((UWORD)ms->deftempo * 125) / 33 : 128;
|
||||
if ((ms->deftempo <= 10) && (ms->deftempo))
|
||||
of.inittempo = (of.inittempo * 33) / 6;
|
||||
of.flags |= UF_HIGHBPM;
|
||||
}
|
||||
MED_Version[12] = mh->id;
|
||||
of.modtype = strdup(MED_Version);
|
||||
of.numchn = 0; /* will be counted later */
|
||||
of.numpat = ms->numblocks;
|
||||
of.numpos = ms->songlen;
|
||||
of.numins = ms->numsamples;
|
||||
of.numsmp = of.numins;
|
||||
of.reppos = 0;
|
||||
if ((mh->MEDEXPP) && (me->songname) && (me->songnamelen)) {
|
||||
char *name;
|
||||
|
||||
_mm_fseek(modreader, me->songname, SEEK_SET);
|
||||
name = _mm_malloc(me->songnamelen);
|
||||
_mm_read_UBYTES(name, me->songnamelen, modreader);
|
||||
of.songname = DupStr(name, me->songnamelen, 1);
|
||||
free(name);
|
||||
} else
|
||||
of.songname = DupStr(NULL, 0, 0);
|
||||
if ((mh->MEDEXPP) && (me->annotxt) && (me->annolen)) {
|
||||
_mm_fseek(modreader, me->annotxt, SEEK_SET);
|
||||
ReadComment(me->annolen);
|
||||
}
|
||||
|
||||
if (!AllocSamples())
|
||||
return 0;
|
||||
q = of.samples;
|
||||
for (t = 0; t < of.numins; t++) {
|
||||
q->flags = SF_SIGNED;
|
||||
q->volume = 64;
|
||||
if (sa[t]) {
|
||||
_mm_fseek(modreader, sa[t], SEEK_SET);
|
||||
s.length = _mm_read_M_ULONG(modreader);
|
||||
s.type = _mm_read_M_SWORD(modreader);
|
||||
|
||||
if (s.type) {
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr, "\rNon-sample instruments not supported in MED loader yet\n");
|
||||
#endif
|
||||
if (!curious) {
|
||||
_mm_errno = MMERR_MED_SYNTHSAMPLES;
|
||||
return 0;
|
||||
}
|
||||
s.length = 0;
|
||||
}
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->length = s.length;
|
||||
q->seekpos = _mm_ftell(modreader);
|
||||
q->loopstart = ms->sample[t].rep << 1;
|
||||
q->loopend = q->loopstart + (ms->sample[t].replen << 1);
|
||||
|
||||
if (ms->sample[t].replen > 1)
|
||||
q->flags |= SF_LOOP;
|
||||
|
||||
/* don't load sample if length>='MMD0'...
|
||||
such kluges make libmikmod's code unique !!! */
|
||||
if (q->length >= MMD0_string)
|
||||
q->length = 0;
|
||||
} else
|
||||
q->length = 0;
|
||||
|
||||
if ((mh->MEDEXPP) && (me->exp_smp) &&
|
||||
(t < me->s_ext_entries) && (me->s_ext_entrsz >= 4)) {
|
||||
MEDINSTEXT ie;
|
||||
|
||||
_mm_fseek(modreader, me->exp_smp + t * me->s_ext_entrsz,
|
||||
SEEK_SET);
|
||||
ie.hold = _mm_read_UBYTE(modreader);
|
||||
ie.decay = _mm_read_UBYTE(modreader);
|
||||
ie.suppress_midi_off = _mm_read_UBYTE(modreader);
|
||||
ie.finetune = _mm_read_SBYTE(modreader);
|
||||
|
||||
q->speed = finetune[ie.finetune & 0xf];
|
||||
} else
|
||||
q->speed = 8363;
|
||||
|
||||
if ((mh->MEDEXPP) && (me->iinfo) &&
|
||||
(t < me->i_ext_entries) && (me->i_ext_entrsz >= 40)) {
|
||||
MEDINSTINFO ii;
|
||||
|
||||
_mm_fseek(modreader, me->iinfo + t * me->i_ext_entrsz, SEEK_SET);
|
||||
_mm_read_UBYTES(ii.name, 40, modreader);
|
||||
q->samplename = DupStr((char*)ii.name, 40, 1);
|
||||
} else
|
||||
q->samplename = NULL;
|
||||
|
||||
q++;
|
||||
}
|
||||
|
||||
if (mh->id == MMD0_string) {
|
||||
if (!LoadMEDPatterns()) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
} else if (mh->id == MMD1_string) {
|
||||
if (!LoadMMD1Patterns()) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
_mm_errno = MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *MED_LoadTitle(void)
|
||||
{
|
||||
ULONG posit, namelen;
|
||||
CHAR *name, *retvalue = NULL;
|
||||
|
||||
_mm_fseek(modreader, 0x20, SEEK_SET);
|
||||
posit = _mm_read_M_ULONG(modreader);
|
||||
|
||||
if (posit) {
|
||||
_mm_fseek(modreader, posit + 0x2C, SEEK_SET);
|
||||
posit = _mm_read_M_ULONG(modreader);
|
||||
namelen = _mm_read_M_ULONG(modreader);
|
||||
|
||||
_mm_fseek(modreader, posit, SEEK_SET);
|
||||
name = _mm_malloc(namelen);
|
||||
_mm_read_UBYTES(name, namelen, modreader);
|
||||
retvalue = DupStr(name, namelen, 1);
|
||||
free(name);
|
||||
}
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_med = {
|
||||
NULL,
|
||||
"MED",
|
||||
"MED (OctaMED)",
|
||||
MED_Init,
|
||||
MED_Test,
|
||||
MED_Load,
|
||||
MED_Cleanup,
|
||||
MED_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
512
project/jni/mikmod/loaders/load_mod.c
Normal file
512
project/jni/mikmod/loaders/load_mod.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_mod.c,v 1.2 2004/01/21 13:33:11 raph Exp $
|
||||
|
||||
Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct MSAMPINFO {
|
||||
CHAR samplename[23]; /* 22 in module, 23 in memory */
|
||||
UWORD length;
|
||||
UBYTE finetune;
|
||||
UBYTE volume;
|
||||
UWORD reppos;
|
||||
UWORD replen;
|
||||
} MSAMPINFO;
|
||||
|
||||
typedef struct MODULEHEADER {
|
||||
CHAR songname[21]; /* the songname.. 20 in module, 21 in memory */
|
||||
MSAMPINFO samples[31]; /* all sampleinfo */
|
||||
UBYTE songlength; /* number of patterns used */
|
||||
UBYTE magic1; /* should be 127 */
|
||||
UBYTE positions[128]; /* which pattern to play at pos */
|
||||
UBYTE magic2[4]; /* string "M.K." or "FLT4" or "FLT8" */
|
||||
} MODULEHEADER;
|
||||
|
||||
typedef struct MODTYPE {
|
||||
CHAR id[5];
|
||||
UBYTE channels;
|
||||
CHAR *name;
|
||||
} MODTYPE;
|
||||
|
||||
typedef struct MODNOTE {
|
||||
UBYTE a, b, c, d;
|
||||
} MODNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
#define MODULEHEADERSIZE 0x438
|
||||
|
||||
static CHAR protracker[] = "Protracker";
|
||||
static CHAR startrekker[] = "Startrekker";
|
||||
static CHAR fasttracker[] = "Fasttracker";
|
||||
static CHAR oktalyser[] = "Oktalyser";
|
||||
static CHAR oktalyzer[] = "Oktalyzer";
|
||||
static CHAR taketracker[] = "TakeTracker";
|
||||
static CHAR orpheus[] = "Imago Orpheus (MOD format)";
|
||||
|
||||
static MODULEHEADER *mh = NULL;
|
||||
static MODNOTE *patbuf = NULL;
|
||||
static int modtype, trekker;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
/* given the module ID, determine the number of channels and the tracker
|
||||
description ; also alters modtype */
|
||||
static BOOL MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
|
||||
{
|
||||
modtype = trekker = 0;
|
||||
|
||||
/* Protracker and variants */
|
||||
if ((!memcmp(id, "M.K.", 4)) || (!memcmp(id, "M!K!", 4))) {
|
||||
*descr = protracker;
|
||||
modtype = 0;
|
||||
*numchn = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Star Tracker */
|
||||
if (((!memcmp(id, "FLT", 3)) || (!memcmp(id, "EXO", 3))) &&
|
||||
(isdigit(id[3]))) {
|
||||
*descr = startrekker;
|
||||
modtype = trekker = 1;
|
||||
*numchn = id[3] - '0';
|
||||
if (*numchn == 4 || *numchn == 8)
|
||||
return 1;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
else
|
||||
fprintf(stderr, "\rUnknown FLT%d module type\n", *numchn);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Oktalyzer (Amiga) */
|
||||
if (!memcmp(id, "OKTA", 4)) {
|
||||
*descr = oktalyzer;
|
||||
modtype = 1;
|
||||
*numchn = 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Oktalyser (Atari) */
|
||||
if (!memcmp(id, "CD81", 4)) {
|
||||
*descr = oktalyser;
|
||||
modtype = 1;
|
||||
*numchn = 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Fasttracker */
|
||||
if ((!memcmp(id + 1, "CHN", 3)) && (isdigit(id[0]))) {
|
||||
*descr = fasttracker;
|
||||
modtype = 1;
|
||||
*numchn = id[0] - '0';
|
||||
return 1;
|
||||
}
|
||||
/* Fasttracker or Taketracker */
|
||||
if (((!memcmp(id + 2, "CH", 2)) || (!memcmp(id + 2, "CN", 2)))
|
||||
&& (isdigit(id[0])) && (isdigit(id[1]))) {
|
||||
if (id[3] == 'H') {
|
||||
*descr = fasttracker;
|
||||
modtype = 2; /* this can also be Imago Orpheus */
|
||||
} else {
|
||||
*descr = taketracker;
|
||||
modtype = 1;
|
||||
}
|
||||
*numchn = (id[0] - '0') * 10 + (id[1] - '0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL MOD_Test(void)
|
||||
{
|
||||
UBYTE id[4], numchn;
|
||||
CHAR *descr;
|
||||
|
||||
_mm_fseek(modreader, MODULEHEADERSIZE, SEEK_SET);
|
||||
if (!_mm_read_UBYTES(id, 4, modreader))
|
||||
return 0;
|
||||
|
||||
if (MOD_CheckType(id, &numchn, &descr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL MOD_Init(void)
|
||||
{
|
||||
if (!(mh = (MODULEHEADER *)_mm_malloc(sizeof(MODULEHEADER))))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MOD_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(patbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
Old (amiga) noteinfo:
|
||||
|
||||
_____byte 1_____ byte2_ _____byte 3_____ byte4_
|
||||
/ \ / \ / \ / \
|
||||
0000 0000-00000000 0000 0000-00000000
|
||||
|
||||
Upper four 12 bits for Lower four Effect command.
|
||||
bits of sam- note period. bits of sam-
|
||||
ple number. ple number.
|
||||
|
||||
*/
|
||||
|
||||
static UBYTE ConvertNote(MODNOTE *n, UBYTE lasteffect)
|
||||
{
|
||||
UBYTE instrument, effect, effdat, note;
|
||||
UWORD period;
|
||||
UBYTE lastnote = 0;
|
||||
|
||||
/* extract the various information from the 4 bytes that make up a note */
|
||||
instrument = (n->a & 0x10) | (n->c >> 4);
|
||||
period = (((UWORD)n->a & 0xf) << 8) + n->b;
|
||||
effect = n->c & 0xf;
|
||||
effdat = n->d;
|
||||
|
||||
/* Convert the period to a note number */
|
||||
note = 0;
|
||||
if (period) {
|
||||
for (note = 0; note < 7 * OCTAVE; note++)
|
||||
if (period >= npertab[note])
|
||||
break;
|
||||
if (note == 7 * OCTAVE)
|
||||
note = 0;
|
||||
else
|
||||
note++;
|
||||
}
|
||||
|
||||
if (instrument) {
|
||||
/* if instrument does not exist, note cut */
|
||||
if ((instrument > 31) || (!mh->samples[instrument - 1].length)) {
|
||||
UniPTEffect(0xc, 0);
|
||||
if (effect == 0xc)
|
||||
effect = effdat = 0;
|
||||
} else {
|
||||
/* Protracker handling */
|
||||
if (!modtype) {
|
||||
/* if we had a note, then change instrument... */
|
||||
if (note)
|
||||
UniInstrument(instrument - 1);
|
||||
/* ...otherwise, only adjust volume... */
|
||||
else {
|
||||
/* ...unless an effect was specified, which forces a new
|
||||
note to be played */
|
||||
if (effect || effdat) {
|
||||
UniInstrument(instrument - 1);
|
||||
note = lastnote;
|
||||
} else
|
||||
UniPTEffect(0xc,
|
||||
mh->samples[instrument -
|
||||
1].volume & 0x7f);
|
||||
}
|
||||
} else {
|
||||
/* Fasttracker handling */
|
||||
UniInstrument(instrument - 1);
|
||||
if (!note)
|
||||
note = lastnote;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (note) {
|
||||
UniNote(note + 2 * OCTAVE - 1);
|
||||
lastnote = note;
|
||||
}
|
||||
|
||||
/* Convert pattern jump from Dec to Hex */
|
||||
if (effect == 0xd)
|
||||
effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf);
|
||||
|
||||
/* Volume slide, up has priority */
|
||||
if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
|
||||
effdat &= 0xf0;
|
||||
|
||||
/* Handle ``heavy'' volumes correctly */
|
||||
if ((effect == 0xc) && (effdat > 0x40))
|
||||
effdat = 0x40;
|
||||
|
||||
/* An isolated 100, 200 or 300 effect should be ignored (no
|
||||
"standalone" porta memory in mod files). However, a sequence such
|
||||
as 1XX, 100, 100, 100 is fine. */
|
||||
if ((!effdat) && ((effect == 1)||(effect == 2)||(effect ==3)) &&
|
||||
(lasteffect < 0x10) && (effect != lasteffect))
|
||||
effect = 0;
|
||||
|
||||
UniPTEffect(effect, effdat);
|
||||
if (effect == 8)
|
||||
of.flags |= UF_PANNING;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static UBYTE *ConvertTrack(MODNOTE *n, int numchn)
|
||||
{
|
||||
int t;
|
||||
UBYTE lasteffect = 0x10; /* non existant effect */
|
||||
|
||||
UniReset();
|
||||
for (t = 0; t < 64; t++) {
|
||||
lasteffect = ConvertNote(n,lasteffect);
|
||||
UniNewline();
|
||||
n += numchn;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
/* Loads all patterns of a modfile and converts them into the 3 byte format. */
|
||||
static BOOL ML_LoadPatterns(void)
|
||||
{
|
||||
int t, s, tracks = 0;
|
||||
|
||||
if (!AllocPatterns())
|
||||
return 0;
|
||||
if (!AllocTracks())
|
||||
return 0;
|
||||
|
||||
/* Allocate temporary buffer for loading and converting the patterns */
|
||||
if (!(patbuf = (MODNOTE *)_mm_calloc(64U * of.numchn, sizeof(MODNOTE))))
|
||||
return 0;
|
||||
|
||||
if (trekker && of.numchn == 8) {
|
||||
/* Startrekker module dual pattern */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
for (s = 0; s < (64U * 4); s++) {
|
||||
patbuf[s].a = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].b = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].c = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].d = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
for (s = 0; s < 4; s++)
|
||||
if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4)))
|
||||
return 0;
|
||||
for (s = 0; s < (64U * 4); s++) {
|
||||
patbuf[s].a = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].b = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].c = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].d = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
for (s = 0; s < 4; s++)
|
||||
if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4)))
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Generic module pattern */
|
||||
for (t = 0; t < of.numpat; t++) {
|
||||
/* Load the pattern into the temp buffer and convert it */
|
||||
for (s = 0; s < (64U * of.numchn); s++) {
|
||||
patbuf[s].a = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].b = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].c = _mm_read_UBYTE(modreader);
|
||||
patbuf[s].d = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
for (s = 0; s < of.numchn; s++)
|
||||
if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, of.numchn)))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL MOD_Load(BOOL curious)
|
||||
{
|
||||
int t, scan;
|
||||
SAMPLE *q;
|
||||
MSAMPINFO *s;
|
||||
CHAR *descr;
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string((CHAR *)mh->songname, 20, modreader);
|
||||
mh->songname[20] = 0; /* just in case */
|
||||
|
||||
for (t = 0; t < 31; t++) {
|
||||
s = &mh->samples[t];
|
||||
_mm_read_string(s->samplename, 22, modreader);
|
||||
s->samplename[22] = 0; /* just in case */
|
||||
s->length = _mm_read_M_UWORD(modreader);
|
||||
s->finetune = _mm_read_UBYTE(modreader);
|
||||
s->volume = _mm_read_UBYTE(modreader);
|
||||
s->reppos = _mm_read_M_UWORD(modreader);
|
||||
s->replen = _mm_read_M_UWORD(modreader);
|
||||
}
|
||||
|
||||
mh->songlength = _mm_read_UBYTE(modreader);
|
||||
|
||||
/* this fixes mods which declare more than 128 positions.
|
||||
* eg: beatwave.mod */
|
||||
if (mh->songlength > 128) { mh->songlength = 128; }
|
||||
|
||||
mh->magic1 = _mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->positions, 128, modreader);
|
||||
_mm_read_UBYTES(mh->magic2, 4, modreader);
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
if (!(MOD_CheckType(mh->magic2, &of.numchn, &descr))) {
|
||||
_mm_errno = MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if (trekker && of.numchn == 8)
|
||||
for (t = 0; t < 128; t++)
|
||||
/* if module pretends to be FLT8, yet the order table
|
||||
contains odd numbers, chances are it's a lying FLT4... */
|
||||
if (mh->positions[t] & 1) {
|
||||
of.numchn = 4;
|
||||
break;
|
||||
}
|
||||
if (trekker && of.numchn == 8)
|
||||
for (t = 0; t < 128; t++)
|
||||
mh->positions[t] >>= 1;
|
||||
|
||||
of.songname = DupStr(mh->songname, 21, 1);
|
||||
of.numpos = mh->songlength;
|
||||
of.reppos = 0;
|
||||
|
||||
/* Count the number of patterns */
|
||||
of.numpat = 0;
|
||||
for (t = 0; t < of.numpos; t++)
|
||||
if (mh->positions[t] > of.numpat)
|
||||
of.numpat = mh->positions[t];
|
||||
|
||||
/* since some old modules embed extra patterns, we have to check the
|
||||
whole list to get the samples' file offsets right - however we can find
|
||||
garbage here, so check carefully */
|
||||
scan = 1;
|
||||
for (t = of.numpos; t < 128; t++)
|
||||
if (mh->positions[t] >= 0x80)
|
||||
scan = 0;
|
||||
if (scan)
|
||||
for (t = of.numpos; t < 128; t++) {
|
||||
if (mh->positions[t] > of.numpat)
|
||||
of.numpat = mh->positions[t];
|
||||
if ((curious) && (mh->positions[t]))
|
||||
of.numpos = t + 1;
|
||||
}
|
||||
of.numpat++;
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
|
||||
if (!AllocPositions(of.numpos))
|
||||
return 0;
|
||||
for (t = 0; t < of.numpos; t++)
|
||||
of.positions[t] = mh->positions[t];
|
||||
|
||||
/* Finally, init the sampleinfo structures */
|
||||
of.numins = of.numsmp = 31;
|
||||
if (!AllocSamples())
|
||||
return 0;
|
||||
s = mh->samples;
|
||||
q = of.samples;
|
||||
for (t = 0; t < of.numins; t++) {
|
||||
/* convert the samplename */
|
||||
q->samplename = DupStr(s->samplename, 23, 1);
|
||||
/* init the sampleinfo variables and convert the size pointers */
|
||||
q->speed = finetune[s->finetune & 0xf];
|
||||
q->volume = s->volume & 0x7f;
|
||||
q->loopstart = (ULONG)s->reppos << 1;
|
||||
q->loopend = q->loopstart + ((ULONG)s->replen << 1);
|
||||
q->length = (ULONG)s->length << 1;
|
||||
q->flags = SF_SIGNED;
|
||||
/* Imago Orpheus creates MODs with 16 bit samples, check */
|
||||
if ((modtype == 2) && (s->volume & 0x80)) {
|
||||
q->flags |= SF_16BITS;
|
||||
descr = orpheus;
|
||||
}
|
||||
if (s->replen > 2)
|
||||
q->flags |= SF_LOOP;
|
||||
|
||||
s++;
|
||||
q++;
|
||||
}
|
||||
|
||||
of.modtype = strdup(descr);
|
||||
|
||||
if (!ML_LoadPatterns())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CHAR *MOD_LoadTitle(void)
|
||||
{
|
||||
CHAR s[21];
|
||||
|
||||
_mm_fseek(modreader, 0, SEEK_SET);
|
||||
if (!_mm_read_UBYTES(s, 20, modreader))
|
||||
return NULL;
|
||||
s[20] = 0; /* just in case */
|
||||
|
||||
return (DupStr(s, 21, 1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_mod = {
|
||||
NULL,
|
||||
"Standard module",
|
||||
"MOD (31 instruments)",
|
||||
MOD_Init,
|
||||
MOD_Test,
|
||||
MOD_Load,
|
||||
MOD_Cleanup,
|
||||
MOD_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
285
project/jni/mikmod/loaders/load_mtm.c
Normal file
285
project/jni/mikmod/loaders/load_mtm.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_mtm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
MTM module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct MTMHEADER {
|
||||
UBYTE id[3]; /* MTM file marker */
|
||||
UBYTE version; /* upper major, lower nibble minor version number */
|
||||
CHAR songname[20]; /* ASCIIZ songname */
|
||||
UWORD numtracks; /* number of tracks saved */
|
||||
UBYTE lastpattern; /* last pattern number saved */
|
||||
UBYTE lastorder; /* last order number to play (songlength-1) */
|
||||
UWORD commentsize; /* length of comment field */
|
||||
UBYTE numsamples; /* number of samples saved */
|
||||
UBYTE attribute; /* attribute byte (unused) */
|
||||
UBYTE beatspertrack;
|
||||
UBYTE numchannels; /* number of channels used */
|
||||
UBYTE panpos[32]; /* voice pan positions */
|
||||
} MTMHEADER;
|
||||
|
||||
typedef struct MTMSAMPLE {
|
||||
CHAR samplename[22];
|
||||
ULONG length;
|
||||
ULONG reppos;
|
||||
ULONG repend;
|
||||
UBYTE finetune;
|
||||
UBYTE volume;
|
||||
UBYTE attribute;
|
||||
} MTMSAMPLE;
|
||||
|
||||
typedef struct MTMNOTE {
|
||||
UBYTE a,b,c;
|
||||
} MTMNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static MTMHEADER *mh = NULL;
|
||||
static MTMNOTE *mtmtrk = NULL;
|
||||
static UWORD pat[32];
|
||||
|
||||
static CHAR MTM_Version[] = "MTM";
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL MTM_Test(void)
|
||||
{
|
||||
UBYTE id[3];
|
||||
|
||||
if(!_mm_read_UBYTES(id,3,modreader)) return 0;
|
||||
if(!memcmp(id,"MTM",3)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL MTM_Init(void)
|
||||
{
|
||||
if(!(mtmtrk=(MTMNOTE*)_mm_calloc(64,sizeof(MTMNOTE)))) return 0;
|
||||
if(!(mh=(MTMHEADER*)_mm_malloc(sizeof(MTMHEADER)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MTM_Cleanup(void)
|
||||
{
|
||||
_mm_free(mtmtrk);
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static UBYTE* MTM_Convert(void)
|
||||
{
|
||||
int t;
|
||||
UBYTE a,b,inst,note,eff,dat;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
a=mtmtrk[t].a;
|
||||
b=mtmtrk[t].b;
|
||||
inst=((a&0x3)<<4)|(b>>4);
|
||||
note=a>>2;
|
||||
eff=b&0xf;
|
||||
dat=mtmtrk[t].c;
|
||||
|
||||
if(inst) UniInstrument(inst-1);
|
||||
if(note) UniNote(note+2*OCTAVE);
|
||||
|
||||
/* MTM bug workaround : when the effect is volslide, slide-up *always*
|
||||
overrides slide-down. */
|
||||
if(eff==0xa && (dat&0xf0)) dat&=0xf0;
|
||||
|
||||
/* Convert pattern jump from Dec to Hex */
|
||||
if(eff==0xd)
|
||||
dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
|
||||
UniPTEffect(eff,dat);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL MTM_Load(BOOL curious)
|
||||
{
|
||||
int t,u;
|
||||
MTMSAMPLE s;
|
||||
SAMPLE *q;
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_UBYTES(mh->id,3,modreader);
|
||||
mh->version =_mm_read_UBYTE(modreader);
|
||||
_mm_read_string(mh->songname,20,modreader);
|
||||
mh->numtracks =_mm_read_I_UWORD(modreader);
|
||||
mh->lastpattern =_mm_read_UBYTE(modreader);
|
||||
mh->lastorder =_mm_read_UBYTE(modreader);
|
||||
mh->commentsize =_mm_read_I_UWORD(modreader);
|
||||
mh->numsamples =_mm_read_UBYTE(modreader);
|
||||
mh->attribute =_mm_read_UBYTE(modreader);
|
||||
mh->beatspertrack=_mm_read_UBYTE(modreader);
|
||||
mh->numchannels =_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->panpos,32,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
of.modtype = strdup(MTM_Version);
|
||||
of.numchn = mh->numchannels;
|
||||
of.numtrk = mh->numtracks+1; /* get number of channels */
|
||||
of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
|
||||
of.numpos = mh->lastorder+1; /* copy the songlength */
|
||||
of.numpat = mh->lastpattern+1;
|
||||
of.reppos = 0;
|
||||
of.flags |= UF_PANNING;
|
||||
for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<< 4;
|
||||
of.numins=of.numsmp=mh->numsamples;
|
||||
|
||||
if(!AllocSamples()) return 0;
|
||||
q=of.samples;
|
||||
for(t=0;t<of.numins;t++) {
|
||||
/* try to read sample info */
|
||||
_mm_read_string(s.samplename,22,modreader);
|
||||
s.length =_mm_read_I_ULONG(modreader);
|
||||
s.reppos =_mm_read_I_ULONG(modreader);
|
||||
s.repend =_mm_read_I_ULONG(modreader);
|
||||
s.finetune =_mm_read_UBYTE(modreader);
|
||||
s.volume =_mm_read_UBYTE(modreader);
|
||||
s.attribute =_mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->samplename = DupStr(s.samplename,22,1);
|
||||
q->seekpos = 0;
|
||||
q->speed = finetune[s.finetune];
|
||||
q->length = s.length;
|
||||
q->loopstart = s.reppos;
|
||||
q->loopend = s.repend;
|
||||
q->volume = s.volume;
|
||||
if((s.repend-s.reppos)>2) q->flags |= SF_LOOP;
|
||||
|
||||
if(s.attribute&1) {
|
||||
/* If the sample is 16-bits, convert the length and replen
|
||||
byte-values into sample-values */
|
||||
q->flags|=SF_16BITS;
|
||||
q->length>>=1;
|
||||
q->loopstart>>=1;
|
||||
q->loopend>>=1;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
for(t=0;t<of.numpos;t++)
|
||||
of.positions[t]=_mm_read_UBYTE(modreader);
|
||||
for(;t<128;t++) _mm_read_UBYTE(modreader);
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
of.tracks[0]=MTM_Convert(); /* track 0 is empty */
|
||||
for(t=1;t<of.numtrk;t++) {
|
||||
int s;
|
||||
|
||||
for(s=0;s<64;s++) {
|
||||
mtmtrk[s].a=_mm_read_UBYTE(modreader);
|
||||
mtmtrk[s].b=_mm_read_UBYTE(modreader);
|
||||
mtmtrk[s].c=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!(of.tracks[t]=MTM_Convert())) return 0;
|
||||
}
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
_mm_read_I_UWORDS(pat,32,modreader);
|
||||
for(u=0;u<of.numchn;u++)
|
||||
of.patterns[((long)t*of.numchn)+u]=pat[u];
|
||||
}
|
||||
|
||||
/* read comment field */
|
||||
if(mh->commentsize)
|
||||
if(!ReadLinedComment(mh->commentsize, 40)) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *MTM_LoadTitle(void)
|
||||
{
|
||||
CHAR s[20];
|
||||
|
||||
_mm_fseek(modreader,4,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,20,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_mtm={
|
||||
NULL,
|
||||
"MTM",
|
||||
"MTM (MultiTracker Module editor)",
|
||||
MTM_Init,
|
||||
MTM_Test,
|
||||
MTM_Load,
|
||||
MTM_Cleanup,
|
||||
MTM_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
460
project/jni/mikmod/loaders/load_okt.c
Normal file
460
project/jni/mikmod/loaders/load_okt.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_okt.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Oktalyzer (OKT) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
Written by UFO <ufo303@poczta.onet.pl>
|
||||
based on the file description compiled by Harald Zappe
|
||||
<zappe@gaea.sietec.de>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module blocks */
|
||||
|
||||
/* sample information */
|
||||
typedef struct OKTSAMPLE {
|
||||
CHAR sampname[20];
|
||||
ULONG len;
|
||||
UWORD loopbeg;
|
||||
UWORD looplen;
|
||||
UBYTE volume;
|
||||
} OKTSAMPLE;
|
||||
|
||||
typedef struct OKTNOTE {
|
||||
UBYTE note, ins, eff, dat;
|
||||
} OKTNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static OKTNOTE *okttrk = NULL;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL OKT_Test(void)
|
||||
{
|
||||
CHAR id[8];
|
||||
|
||||
if (!_mm_read_UBYTES(id, 8, modreader))
|
||||
return 0;
|
||||
if (!memcmp(id, "OKTASONG", 8))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pattern analysis routine.
|
||||
Effects not implemented (yet) : (in decimal)
|
||||
11 Arpeggio 4: Change note every 50Hz tick between N,H,N,L
|
||||
12 Arpeggio 5: Change note every 50Hz tick between H,H,N
|
||||
N = normal note being played in this channel (1-36)
|
||||
L = normal note number minus upper four bits of 'data'.
|
||||
H = normal note number plus lower four bits of 'data'.
|
||||
13 Decrease note number by 'data' once per tick.
|
||||
17 Increase note number by 'data' once per tick.
|
||||
21 Decrease note number by 'data' once per line.
|
||||
30 Increase note number by 'data' once per line.
|
||||
*/
|
||||
static UBYTE *OKT_ConvertTrack(UBYTE patrows)
|
||||
{
|
||||
int t;
|
||||
UBYTE ins, note, eff, dat;
|
||||
|
||||
UniReset();
|
||||
for (t = 0; t < patrows; t++) {
|
||||
note = okttrk[t].note;
|
||||
ins = okttrk[t].ins;
|
||||
eff = okttrk[t].eff;
|
||||
dat = okttrk[t].dat;
|
||||
|
||||
if (note) {
|
||||
UniNote(note + 3 * OCTAVE - 1);
|
||||
UniInstrument(ins);
|
||||
}
|
||||
|
||||
if (eff)
|
||||
switch (eff) {
|
||||
case 1: /* Porta Up */
|
||||
UniPTEffect(0x1, dat);
|
||||
break;
|
||||
case 2: /* Portamento Down */
|
||||
UniPTEffect(0x2, dat);
|
||||
break;
|
||||
/* case 9: what is this? */
|
||||
case 10: /* Arpeggio 3 */
|
||||
case 11: /* Arpeggio 4 */
|
||||
case 12: /* Arpeggio 5 */
|
||||
UniWriteByte(UNI_OKTARP);
|
||||
UniWriteByte(eff + 3 - 10);
|
||||
UniWriteByte(dat);
|
||||
break;
|
||||
case 15: /* Amiga filter toggle, ignored */
|
||||
break;
|
||||
case 25: /* Pattern Jump */
|
||||
dat = (dat >> 4) * 10 + (dat & 0x0f);
|
||||
UniPTEffect(0xb, dat);
|
||||
break;
|
||||
case 27: /* Release - similar to Keyoff */
|
||||
UniWriteByte(UNI_KEYOFF);
|
||||
break;
|
||||
case 28: /* Set Tempo */
|
||||
UniPTEffect(0xf, dat & 0x0f);
|
||||
break;
|
||||
case 31: /* volume Control */
|
||||
if (dat <= 0x40)
|
||||
UniPTEffect(0xc, dat);
|
||||
else if (dat <= 0x50)
|
||||
UniEffect(UNI_XMEFFECTA, (dat - 0x40)); /* fast fade out */
|
||||
else if (dat <= 0x60)
|
||||
UniEffect(UNI_XMEFFECTA, (dat - 0x50) << 4); /* fast fade in */
|
||||
else if (dat <= 0x70)
|
||||
UniEffect(UNI_XMEFFECTEB, (dat - 0x60)); /* slow fade out */
|
||||
else if (dat <= 0x80)
|
||||
UniEffect(UNI_XMEFFECTEA, (dat - 0x70)); /* slow fade in */
|
||||
break;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
default:
|
||||
fprintf(stderr, "\rUnimplemented effect (%02d,%02x)\n",
|
||||
eff, dat);
|
||||
#endif
|
||||
}
|
||||
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
/* Read "channel modes" i.e. channel number and panning information */
|
||||
static void OKT_doCMOD(void)
|
||||
{
|
||||
/* amiga channel panning table */
|
||||
UBYTE amigapan[4] = { 0x00, 0xff, 0xff, 0x00 };
|
||||
int t;
|
||||
|
||||
of.numchn = 0;
|
||||
of.flags |= UF_PANNING;
|
||||
|
||||
for (t = 0; t < 4; t++)
|
||||
if (_mm_read_M_UWORD(modreader)) {
|
||||
/* two channels tied to the same Amiga hardware voice */
|
||||
of.panning[of.numchn++] = amigapan[t];
|
||||
of.panning[of.numchn++] = amigapan[t];
|
||||
} else
|
||||
/* one channel tied to the Amiga hardware voice */
|
||||
of.panning[of.numchn++] = amigapan[t];
|
||||
}
|
||||
|
||||
/* Read sample information */
|
||||
static BOOL OKT_doSAMP(int len)
|
||||
{
|
||||
int t;
|
||||
SAMPLE *q;
|
||||
OKTSAMPLE s;
|
||||
|
||||
of.numins = of.numsmp = (len / 0x20);
|
||||
if (!AllocSamples())
|
||||
return 0;
|
||||
|
||||
for (t = 0, q = of.samples; t < of.numins; t++, q++) {
|
||||
_mm_read_UBYTES(s.sampname, 20, modreader);
|
||||
s.len = _mm_read_M_ULONG(modreader);
|
||||
s.loopbeg = _mm_read_M_UWORD(modreader) * 2;
|
||||
s.looplen = _mm_read_M_UWORD(modreader) * 2;
|
||||
_mm_read_UBYTE(modreader);
|
||||
s.volume = _mm_read_UBYTE(modreader);
|
||||
_mm_read_M_UWORD(modreader);
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s.len)
|
||||
q->seekpos = q->length = q->loopstart = q->loopend = q->flags = 0;
|
||||
else {
|
||||
s.len--;
|
||||
/* sanity checks */
|
||||
if (s.loopbeg > s.len)
|
||||
s.loopbeg = s.len;
|
||||
if (s.loopbeg + s.looplen > s.len)
|
||||
s.looplen = s.len - s.loopbeg;
|
||||
if (s.looplen < 2)
|
||||
s.looplen = 0;
|
||||
|
||||
q->length = s.len;
|
||||
q->loopstart = s.loopbeg;
|
||||
q->loopend = s.looplen + q->loopstart;
|
||||
q->volume = s.volume;
|
||||
q->flags = SF_SIGNED;
|
||||
|
||||
if (s.looplen)
|
||||
q->flags |= SF_LOOP;
|
||||
}
|
||||
q->samplename = DupStr(s.sampname, 20, 1);
|
||||
q->speed = 8287;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read speed information */
|
||||
static void OKT_doSPEE(void)
|
||||
{
|
||||
int tempo = _mm_read_M_UWORD(modreader);
|
||||
|
||||
of.initspeed = tempo;
|
||||
}
|
||||
|
||||
/* Read song length information */
|
||||
static void OKT_doSLEN(void)
|
||||
{
|
||||
of.numpat = _mm_read_M_UWORD(modreader);
|
||||
}
|
||||
|
||||
/* Read pattern length information */
|
||||
static void OKT_doPLEN(void)
|
||||
{
|
||||
of.numpos = _mm_read_M_UWORD(modreader);
|
||||
}
|
||||
|
||||
/* Read order table */
|
||||
static BOOL OKT_doPATT(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (!of.numpos || !AllocPositions(of.numpos))
|
||||
return 0;
|
||||
|
||||
for (t = 0; t < 128; t++)
|
||||
if (t < of.numpos)
|
||||
of.positions[t] = _mm_read_UBYTE(modreader);
|
||||
else
|
||||
break;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL OKT_doPBOD(int patnum)
|
||||
{
|
||||
char *patbuf;
|
||||
int rows, i;
|
||||
int u;
|
||||
|
||||
if (!patnum) {
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
|
||||
if (!AllocTracks() || !AllocPatterns())
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read pattern */
|
||||
of.pattrows[patnum] = rows = _mm_read_M_UWORD(modreader);
|
||||
|
||||
if (!(okttrk = (OKTNOTE *) _mm_calloc(rows, sizeof(OKTNOTE))) ||
|
||||
!(patbuf = (char *)_mm_calloc(rows * of.numchn, sizeof(OKTNOTE))))
|
||||
return 0;
|
||||
_mm_read_UBYTES(patbuf, rows * of.numchn * sizeof(OKTNOTE), modreader);
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < of.numchn; i++) {
|
||||
for (u = 0; u < rows; u++) {
|
||||
okttrk[u].note = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE)];
|
||||
okttrk[u].ins = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 1];
|
||||
okttrk[u].eff = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 2];
|
||||
okttrk[u].dat = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 3];
|
||||
}
|
||||
|
||||
if (!(of.tracks[patnum * of.numchn + i] = OKT_ConvertTrack(rows)))
|
||||
return 0;
|
||||
}
|
||||
_mm_free(patbuf);
|
||||
_mm_free(okttrk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void OKT_doSBOD(int insnum)
|
||||
{
|
||||
of.samples[insnum].seekpos = _mm_ftell(modreader);
|
||||
}
|
||||
|
||||
BOOL OKT_Load(BOOL curious)
|
||||
{
|
||||
UBYTE id[4];
|
||||
ULONG len;
|
||||
ULONG fp;
|
||||
BOOL seen_cmod = 0, seen_samp = 0, seen_slen = 0, seen_plen = 0, seen_patt
|
||||
= 0, seen_spee = 0;
|
||||
int patnum = 0, insnum = 0;
|
||||
|
||||
/* skip OKTALYZER header */
|
||||
_mm_fseek(modreader, 8, SEEK_SET);
|
||||
of.songname = strdup("");
|
||||
|
||||
of.modtype = strdup("Amiga Oktalyzer");
|
||||
of.numpos = of.reppos = 0;
|
||||
|
||||
/* default values */
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
|
||||
while (1) {
|
||||
/* read block header */
|
||||
_mm_read_UBYTES(id, 4, modreader);
|
||||
len = _mm_read_M_ULONG(modreader);
|
||||
|
||||
if (_mm_eof(modreader))
|
||||
break;
|
||||
fp = _mm_ftell(modreader);
|
||||
|
||||
if (!memcmp(id, "CMOD", 4)) {
|
||||
if (!seen_cmod) {
|
||||
OKT_doCMOD();
|
||||
seen_cmod = 1;
|
||||
} else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id, "SAMP", 4)) {
|
||||
if (!seen_samp && OKT_doSAMP(len))
|
||||
seen_samp = 1;
|
||||
else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id, "SPEE", 4)) {
|
||||
if (!seen_spee) {
|
||||
OKT_doSPEE();
|
||||
seen_spee = 1;
|
||||
} else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id, "SLEN", 4)) {
|
||||
if (!seen_slen) {
|
||||
OKT_doSLEN();
|
||||
seen_slen = 1;
|
||||
} else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id, "PLEN", 4)) {
|
||||
if (!seen_plen) {
|
||||
OKT_doPLEN();
|
||||
seen_plen = 1;
|
||||
} else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id, "PATT", 4)) {
|
||||
if (!seen_plen) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
if (!seen_patt && OKT_doPATT())
|
||||
seen_patt = 1;
|
||||
else {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id,"PBOD", 4)) {
|
||||
/* need to know numpat and numchn */
|
||||
if (!seen_slen || !seen_cmod || (patnum >= of.numpat)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
if (!OKT_doPBOD(patnum++)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
} else if (!memcmp(id,"SBOD",4)) {
|
||||
/* need to know numsmp */
|
||||
if (!seen_samp) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
while ((insnum < of.numins) && !of.samples[insnum].length)
|
||||
insnum++;
|
||||
if (insnum >= of.numins) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
OKT_doSBOD(insnum++);
|
||||
}
|
||||
|
||||
/* goto next block start position */
|
||||
_mm_fseek(modreader, fp + len, SEEK_SET);
|
||||
}
|
||||
|
||||
if (!seen_cmod || !seen_samp || !seen_patt ||
|
||||
!seen_slen || !seen_plen || (patnum != of.numpat)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *OKT_LoadTitle(void)
|
||||
{
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_okt = {
|
||||
NULL,
|
||||
"OKT",
|
||||
"OKT (Amiga Oktalyzer)",
|
||||
NULL,
|
||||
OKT_Test,
|
||||
OKT_Load,
|
||||
NULL,
|
||||
OKT_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
470
project/jni/mikmod/loaders/load_s3m.c
Normal file
470
project/jni/mikmod/loaders/load_s3m.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_s3m.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Screamtracker (S3M) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* header */
|
||||
typedef struct S3MHEADER {
|
||||
CHAR songname[28];
|
||||
UBYTE t1a;
|
||||
UBYTE type;
|
||||
UBYTE unused1[2];
|
||||
UWORD ordnum;
|
||||
UWORD insnum;
|
||||
UWORD patnum;
|
||||
UWORD flags;
|
||||
UWORD tracker;
|
||||
UWORD fileformat;
|
||||
CHAR scrm[4];
|
||||
UBYTE mastervol;
|
||||
UBYTE initspeed;
|
||||
UBYTE inittempo;
|
||||
UBYTE mastermult;
|
||||
UBYTE ultraclick;
|
||||
UBYTE pantable;
|
||||
UBYTE unused2[8];
|
||||
UWORD special;
|
||||
UBYTE channels[32];
|
||||
} S3MHEADER;
|
||||
|
||||
/* sample information */
|
||||
typedef struct S3MSAMPLE {
|
||||
UBYTE type;
|
||||
CHAR filename[12];
|
||||
UBYTE memsegh;
|
||||
UWORD memsegl;
|
||||
ULONG length;
|
||||
ULONG loopbeg;
|
||||
ULONG loopend;
|
||||
UBYTE volume;
|
||||
UBYTE dsk;
|
||||
UBYTE pack;
|
||||
UBYTE flags;
|
||||
ULONG c2spd;
|
||||
UBYTE unused[12];
|
||||
CHAR sampname[28];
|
||||
CHAR scrs[4];
|
||||
} S3MSAMPLE;
|
||||
|
||||
typedef struct S3MNOTE {
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
} S3MNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static S3MNOTE *s3mbuf = NULL; /* pointer to a complete S3M pattern */
|
||||
static S3MHEADER *mh = NULL;
|
||||
static UWORD *paraptr = NULL; /* parapointer array (see S3M docs) */
|
||||
static unsigned int tracker; /* tracker id */
|
||||
|
||||
/* tracker identifiers */
|
||||
#define NUMTRACKERS 4
|
||||
static CHAR* S3M_Version[] = {
|
||||
"Screamtracker x.xx",
|
||||
"Imago Orpheus x.xx (S3M format)",
|
||||
"Impulse Tracker x.xx (S3M format)",
|
||||
"Unknown tracker x.xx (S3M format)",
|
||||
"Impulse Tracker 2.14p3 (S3M format)",
|
||||
"Impulse Tracker 2.14p4 (S3M format)"
|
||||
};
|
||||
/* version number position in above array */
|
||||
static int numeric[NUMTRACKERS]={14,14,16,16};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL S3M_Test(void)
|
||||
{
|
||||
UBYTE id[4];
|
||||
|
||||
_mm_fseek(modreader,0x2c,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(id,4,modreader)) return 0;
|
||||
if(!memcmp(id,"SCRM",4)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL S3M_Init(void)
|
||||
{
|
||||
if(!(s3mbuf=(S3MNOTE*)_mm_malloc(32*64*sizeof(S3MNOTE)))) return 0;
|
||||
if(!(mh=(S3MHEADER*)_mm_malloc(sizeof(S3MHEADER)))) return 0;
|
||||
if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
|
||||
memset(poslookup,-1,256);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void S3M_Cleanup(void)
|
||||
{
|
||||
_mm_free(s3mbuf);
|
||||
_mm_free(paraptr);
|
||||
_mm_free(poslookup);
|
||||
_mm_free(mh);
|
||||
_mm_free(origpositions);
|
||||
}
|
||||
|
||||
/* Because so many s3m files have 16 channels as the set number used, but really
|
||||
only use far less (usually 8 to 12 still), I had to make this function, which
|
||||
determines the number of channels that are actually USED by a pattern.
|
||||
|
||||
For every channel that's used, it sets the appropriate array entry of the
|
||||
global variable 'remap'
|
||||
|
||||
NOTE: You must first seek to the file location of the pattern before calling
|
||||
this procedure.
|
||||
|
||||
Returns 1 on fail. */
|
||||
static BOOL S3M_GetNumChannels(void)
|
||||
{
|
||||
int row=0,flag,ch;
|
||||
|
||||
while(row<64) {
|
||||
flag=_mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
ch=flag&31;
|
||||
if(mh->channels[ch]<32) remap[ch] = 0;
|
||||
if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
|
||||
if(flag&64) _mm_read_UBYTE(modreader);
|
||||
if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
|
||||
} else row++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL S3M_ReadPattern(void)
|
||||
{
|
||||
int row=0,flag,ch;
|
||||
S3MNOTE *n,dummy;
|
||||
|
||||
/* clear pattern data */
|
||||
memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
|
||||
|
||||
while(row<64) {
|
||||
flag=_mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
ch=remap[flag&31];
|
||||
|
||||
if(ch!=-1)
|
||||
n=&s3mbuf[(64U*ch)+row];
|
||||
else
|
||||
n=&dummy;
|
||||
|
||||
if(flag&32) {
|
||||
n->note=_mm_read_UBYTE(modreader);
|
||||
n->ins=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
if(flag&64) {
|
||||
n->vol=_mm_read_UBYTE(modreader);
|
||||
if (n->vol>64) n->vol=64;
|
||||
}
|
||||
if(flag&128) {
|
||||
n->cmd=_mm_read_UBYTE(modreader);
|
||||
n->inf=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
} else row++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
|
||||
{
|
||||
int t;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
UBYTE note,ins,vol;
|
||||
|
||||
note=tr[t].note;
|
||||
ins=tr[t].ins;
|
||||
vol=tr[t].vol;
|
||||
|
||||
if((ins)&&(ins!=255)) UniInstrument(ins-1);
|
||||
if(note!=255) {
|
||||
if(note==254) {
|
||||
UniPTEffect(0xc,0); /* note cut command */
|
||||
vol=255;
|
||||
} else
|
||||
UniNote(((note>>4)*OCTAVE)+(note&0xf)); /* normal note */
|
||||
}
|
||||
if(vol<255) UniPTEffect(0xc,vol);
|
||||
|
||||
S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,
|
||||
tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE);
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
BOOL S3M_Load(BOOL curious)
|
||||
{
|
||||
int t,u,track = 0;
|
||||
SAMPLE *q;
|
||||
UBYTE pan[32];
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string(mh->songname,28,modreader);
|
||||
mh->t1a =_mm_read_UBYTE(modreader);
|
||||
mh->type =_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->unused1,2,modreader);
|
||||
mh->ordnum =_mm_read_I_UWORD(modreader);
|
||||
mh->insnum =_mm_read_I_UWORD(modreader);
|
||||
mh->patnum =_mm_read_I_UWORD(modreader);
|
||||
mh->flags =_mm_read_I_UWORD(modreader);
|
||||
mh->tracker =_mm_read_I_UWORD(modreader);
|
||||
mh->fileformat =_mm_read_I_UWORD(modreader);
|
||||
_mm_read_string(mh->scrm,4,modreader);
|
||||
mh->mastervol =_mm_read_UBYTE(modreader);
|
||||
mh->initspeed =_mm_read_UBYTE(modreader);
|
||||
mh->inittempo =_mm_read_UBYTE(modreader);
|
||||
mh->mastermult =_mm_read_UBYTE(modreader);
|
||||
mh->ultraclick =_mm_read_UBYTE(modreader);
|
||||
mh->pantable =_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->unused2,8,modreader);
|
||||
mh->special =_mm_read_I_UWORD(modreader);
|
||||
_mm_read_UBYTES(mh->channels,32,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* then we can decide the module type */
|
||||
tracker=mh->tracker>>12;
|
||||
if((!tracker)||(tracker>=NUMTRACKERS))
|
||||
tracker=NUMTRACKERS-1; /* unknown tracker */
|
||||
else {
|
||||
if(mh->tracker>=0x3217)
|
||||
tracker=NUMTRACKERS+1; /* IT 2.14p4 */
|
||||
else if(mh->tracker>=0x3216)
|
||||
tracker=NUMTRACKERS; /* IT 2.14p3 */
|
||||
else tracker--;
|
||||
}
|
||||
of.modtype = strdup(S3M_Version[tracker]);
|
||||
if(tracker<NUMTRACKERS) {
|
||||
of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';
|
||||
of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';
|
||||
of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0';
|
||||
}
|
||||
/* set module variables */
|
||||
of.songname = DupStr(mh->songname,28,0);
|
||||
of.numpat = mh->patnum;
|
||||
of.reppos = 0;
|
||||
of.numins = of.numsmp = mh->insnum;
|
||||
of.initspeed = mh->initspeed;
|
||||
of.inittempo = mh->inittempo;
|
||||
of.initvolume = mh->mastervol<<1;
|
||||
of.flags |= UF_ARPMEM | UF_PANNING;
|
||||
if((mh->tracker==0x1300)||(mh->flags&64))
|
||||
of.flags|=UF_S3MSLIDES;
|
||||
of.bpmlimit = 32;
|
||||
|
||||
/* read the order data */
|
||||
if(!AllocPositions(mh->ordnum)) return 0;
|
||||
if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
|
||||
|
||||
for(t=0;t<mh->ordnum;t++) {
|
||||
origpositions[t]=_mm_read_UBYTE(modreader);
|
||||
if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
|
||||
origpositions[t]=255/*mh->patnum-1*/;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
poslookupcnt=mh->ordnum;
|
||||
S3MIT_CreateOrders(curious);
|
||||
|
||||
if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
|
||||
return 0;
|
||||
|
||||
/* read the instrument+pattern parapointers */
|
||||
_mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
|
||||
|
||||
if(mh->pantable==252) {
|
||||
/* read the panning table (ST 3.2 addition. See below for further
|
||||
portions of channel panning [past reampper]). */
|
||||
_mm_read_UBYTES(pan,32,modreader);
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load samples */
|
||||
if(!AllocSamples()) return 0;
|
||||
q = of.samples;
|
||||
for(t=0;t<of.numins;t++) {
|
||||
S3MSAMPLE s;
|
||||
|
||||
/* seek to instrument position */
|
||||
_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
|
||||
/* and load sample info */
|
||||
s.type =_mm_read_UBYTE(modreader);
|
||||
_mm_read_string(s.filename,12,modreader);
|
||||
s.memsegh =_mm_read_UBYTE(modreader);
|
||||
s.memsegl =_mm_read_I_UWORD(modreader);
|
||||
s.length =_mm_read_I_ULONG(modreader);
|
||||
s.loopbeg =_mm_read_I_ULONG(modreader);
|
||||
s.loopend =_mm_read_I_ULONG(modreader);
|
||||
s.volume =_mm_read_UBYTE(modreader);
|
||||
s.dsk =_mm_read_UBYTE(modreader);
|
||||
s.pack =_mm_read_UBYTE(modreader);
|
||||
s.flags =_mm_read_UBYTE(modreader);
|
||||
s.c2spd =_mm_read_I_ULONG(modreader);
|
||||
_mm_read_UBYTES(s.unused,12,modreader);
|
||||
_mm_read_string(s.sampname,28,modreader);
|
||||
_mm_read_string(s.scrs,4,modreader);
|
||||
|
||||
/* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
|
||||
if (s.length > 64000)
|
||||
s.length = 64000;
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->samplename = DupStr(s.sampname,28,0);
|
||||
q->speed = s.c2spd;
|
||||
q->length = s.length;
|
||||
q->loopstart = s.loopbeg;
|
||||
q->loopend = s.loopend;
|
||||
q->volume = s.volume;
|
||||
q->seekpos = (((long)s.memsegh)<<16|s.memsegl)<<4;
|
||||
|
||||
if(s.flags&1) q->flags |= SF_LOOP;
|
||||
if(s.flags&4) q->flags |= SF_16BITS;
|
||||
if(mh->fileformat==1) q->flags |= SF_SIGNED;
|
||||
|
||||
/* don't load sample if it doesn't have the SCRS tag */
|
||||
if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
|
||||
|
||||
q++;
|
||||
}
|
||||
|
||||
/* determine the number of channels actually used. */
|
||||
of.numchn = 0;
|
||||
memset(remap,-1,32*sizeof(UBYTE));
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
/* seek to pattern position (+2 skip pattern length) */
|
||||
_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
|
||||
if(S3M_GetNumChannels()) return 0;
|
||||
}
|
||||
|
||||
/* build the remap array */
|
||||
for(t=0;t<32;t++)
|
||||
if(!remap[t])
|
||||
remap[t]=of.numchn++;
|
||||
|
||||
/* set panning positions after building remap chart! */
|
||||
for(t=0;t<32;t++)
|
||||
if((mh->channels[t]<32)&&(remap[t]!=-1)) {
|
||||
if(mh->channels[t]<8)
|
||||
of.panning[remap[t]]=0x30;
|
||||
else
|
||||
of.panning[remap[t]]=0xc0;
|
||||
}
|
||||
if(mh->pantable==252)
|
||||
/* set panning positions according to panning table (new for st3.2) */
|
||||
for(t=0;t<32;t++)
|
||||
if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
|
||||
of.panning[remap[t]]=(pan[t]&0xf)<<4;
|
||||
|
||||
/* load pattern info */
|
||||
of.numtrk=of.numpat*of.numchn;
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
/* seek to pattern position (+2 skip pattern length) */
|
||||
_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
|
||||
if(!S3M_ReadPattern()) return 0;
|
||||
for(u=0;u<of.numchn;u++)
|
||||
if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *S3M_LoadTitle(void)
|
||||
{
|
||||
CHAR s[28];
|
||||
|
||||
_mm_fseek(modreader,0,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,28,0));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_s3m={
|
||||
NULL,
|
||||
"S3M",
|
||||
"S3M (Scream Tracker 3)",
|
||||
S3M_Init,
|
||||
S3M_Test,
|
||||
S3M_Load,
|
||||
S3M_Cleanup,
|
||||
S3M_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
374
project/jni/mikmod/loaders/load_stm.c
Normal file
374
project/jni/mikmod/loaders/load_stm.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_stm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Screamtracker 2 (STM) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* sample information */
|
||||
typedef struct STMSAMPLE {
|
||||
CHAR filename[12];
|
||||
UBYTE unused; /* 0x00 */
|
||||
UBYTE instdisk; /* Instrument disk */
|
||||
UWORD reserved;
|
||||
UWORD length; /* Sample length */
|
||||
UWORD loopbeg; /* Loop start point */
|
||||
UWORD loopend; /* Loop end point */
|
||||
UBYTE volume; /* Volume */
|
||||
UBYTE reserved2;
|
||||
UWORD c2spd; /* Good old c2spd */
|
||||
ULONG reserved3;
|
||||
UWORD isa;
|
||||
} STMSAMPLE;
|
||||
|
||||
/* header */
|
||||
typedef struct STMHEADER {
|
||||
CHAR songname[20];
|
||||
CHAR trackername[8]; /* !Scream! for ST 2.xx */
|
||||
UBYTE unused; /* 0x1A */
|
||||
UBYTE filetype; /* 1=song, 2=module */
|
||||
UBYTE ver_major;
|
||||
UBYTE ver_minor;
|
||||
UBYTE inittempo; /* initspeed= stm inittempo>>4 */
|
||||
UBYTE numpat; /* number of patterns */
|
||||
UBYTE globalvol;
|
||||
UBYTE reserved[13];
|
||||
STMSAMPLE sample[31]; /* STM sample data */
|
||||
UBYTE patorder[128]; /* Docs say 64 - actually 128 */
|
||||
} STMHEADER;
|
||||
|
||||
typedef struct STMNOTE {
|
||||
UBYTE note,insvol,volcmd,cmdinf;
|
||||
} STMNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static STMNOTE *stmbuf = NULL;
|
||||
static STMHEADER *mh = NULL;
|
||||
|
||||
/* tracker identifiers */
|
||||
static CHAR* STM_Version[STM_NTRACKERS] = {
|
||||
"Screamtracker 2",
|
||||
"Converted by MOD2STM (STM format)",
|
||||
"Wuzamod (STM format)"
|
||||
};
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL STM_Test(void)
|
||||
{
|
||||
UBYTE str[44];
|
||||
int t;
|
||||
|
||||
_mm_fseek(modreader,20,SEEK_SET);
|
||||
_mm_read_UBYTES(str,44,modreader);
|
||||
if(str[9]!=2) return 0; /* STM Module = filetype 2 */
|
||||
|
||||
/* Prevent false positives for S3M files */
|
||||
if(!memcmp(str+40,"SCRM",4))
|
||||
return 0;
|
||||
|
||||
for (t=0;t<STM_NTRACKERS;t++)
|
||||
if(!memcmp(str,STM_Signatures[t],8))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL STM_Init(void)
|
||||
{
|
||||
if(!(mh=(STMHEADER*)_mm_malloc(sizeof(STMHEADER)))) return 0;
|
||||
if(!(stmbuf=(STMNOTE*)_mm_calloc(64U*4,sizeof(STMNOTE)))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void STM_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
_mm_free(stmbuf);
|
||||
}
|
||||
|
||||
static void STM_ConvertNote(STMNOTE *n)
|
||||
{
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
|
||||
/* extract the various information from the 4 bytes that make up a note */
|
||||
note = n->note;
|
||||
ins = n->insvol>>3;
|
||||
vol = (n->insvol&7)+((n->volcmd&0x70)>>1);
|
||||
cmd = n->volcmd&15;
|
||||
inf = n->cmdinf;
|
||||
|
||||
if((ins)&&(ins<32)) UniInstrument(ins-1);
|
||||
|
||||
/* special values of [SBYTE0] are handled here
|
||||
we have no idea if these strange values will ever be encountered.
|
||||
but it appears as those stms sound correct. */
|
||||
if((note==254)||(note==252)) {
|
||||
UniPTEffect(0xc,0); /* note cut */
|
||||
n->volcmd|=0x80;
|
||||
} else
|
||||
/* if note < 251, then all three bytes are stored in the file */
|
||||
if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf));
|
||||
|
||||
if((!(n->volcmd&0x80))&&(vol<65)) UniPTEffect(0xc,vol);
|
||||
if(cmd!=255)
|
||||
switch(cmd) {
|
||||
case 1: /* Axx set speed to xx */
|
||||
UniPTEffect(0xf,inf>>4);
|
||||
break;
|
||||
case 2: /* Bxx position jump */
|
||||
UniPTEffect(0xb,inf);
|
||||
break;
|
||||
case 3: /* Cxx patternbreak to row xx */
|
||||
UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
|
||||
break;
|
||||
case 4: /* Dxy volumeslide */
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 5: /* Exy toneslide down */
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
break;
|
||||
case 6: /* Fxy toneslide up */
|
||||
UniEffect(UNI_S3MEFFECTF,inf);
|
||||
break;
|
||||
case 7: /* Gxx Tone portamento,speed xx */
|
||||
UniPTEffect(0x3,inf);
|
||||
break;
|
||||
case 8: /* Hxy vibrato */
|
||||
UniPTEffect(0x4,inf);
|
||||
break;
|
||||
case 9: /* Ixy tremor, ontime x, offtime y */
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
break;
|
||||
case 0: /* protracker arpeggio */
|
||||
if(!inf) break;
|
||||
/* fall through */
|
||||
case 0xa: /* Jxy arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 0xb: /* Kxy Dual command H00 & Dxy */
|
||||
UniPTEffect(0x4,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0xc: /* Lxy Dual command G00 & Dxy */
|
||||
UniPTEffect(0x3,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
/* Support all these above, since ST2 can LOAD these values but can
|
||||
actually only play up to J - and J is only half-way implemented
|
||||
in ST2 */
|
||||
case 0x18: /* Xxx amiga panning command 8xx */
|
||||
UniPTEffect(0x8,inf);
|
||||
of.flags |= UF_PANNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static UBYTE *STM_ConvertTrack(STMNOTE *n)
|
||||
{
|
||||
int t;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
STM_ConvertNote(n);
|
||||
UniNewline();
|
||||
n+=of.numchn;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
static BOOL STM_LoadPatterns(void)
|
||||
{
|
||||
int t,s,tracks=0;
|
||||
|
||||
if(!AllocPatterns()) return 0;
|
||||
if(!AllocTracks()) return 0;
|
||||
|
||||
/* Allocate temporary buffer for loading and converting the patterns */
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
for(s=0;s<(64U*of.numchn);s++) {
|
||||
stmbuf[s].note = _mm_read_UBYTE(modreader);
|
||||
stmbuf[s].insvol = _mm_read_UBYTE(modreader);
|
||||
stmbuf[s].volcmd = _mm_read_UBYTE(modreader);
|
||||
stmbuf[s].cmdinf = _mm_read_UBYTE(modreader);
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(s=0;s<of.numchn;s++)
|
||||
if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL STM_Load(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
ULONG MikMod_ISA; /* We must generate our own ISA, it's not stored in stm */
|
||||
SAMPLE *q;
|
||||
|
||||
/* try to read stm header */
|
||||
_mm_read_string(mh->songname,20,modreader);
|
||||
_mm_read_string(mh->trackername,8,modreader);
|
||||
mh->unused =_mm_read_UBYTE(modreader);
|
||||
mh->filetype =_mm_read_UBYTE(modreader);
|
||||
mh->ver_major =_mm_read_UBYTE(modreader);
|
||||
mh->ver_minor =_mm_read_UBYTE(modreader);
|
||||
mh->inittempo =_mm_read_UBYTE(modreader);
|
||||
if(!mh->inittempo) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
mh->numpat =_mm_read_UBYTE(modreader);
|
||||
mh->globalvol =_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh->reserved,13,modreader);
|
||||
|
||||
for(t=0;t<31;t++) {
|
||||
STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
|
||||
|
||||
_mm_read_string(s->filename,12,modreader);
|
||||
s->unused =_mm_read_UBYTE(modreader);
|
||||
s->instdisk =_mm_read_UBYTE(modreader);
|
||||
s->reserved =_mm_read_I_UWORD(modreader);
|
||||
s->length =_mm_read_I_UWORD(modreader);
|
||||
s->loopbeg =_mm_read_I_UWORD(modreader);
|
||||
s->loopend =_mm_read_I_UWORD(modreader);
|
||||
s->volume =_mm_read_UBYTE(modreader);
|
||||
s->reserved2=_mm_read_UBYTE(modreader);
|
||||
s->c2spd =_mm_read_I_UWORD(modreader);
|
||||
s->reserved3=_mm_read_I_ULONG(modreader);
|
||||
s->isa =_mm_read_I_UWORD(modreader);
|
||||
}
|
||||
_mm_read_UBYTES(mh->patorder,128,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
for(t=0;t<STM_NTRACKERS;t++)
|
||||
if(!memcmp(mh->trackername,STM_Signatures[t],8)) break;
|
||||
of.modtype = strdup(STM_Version[t]);
|
||||
of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
|
||||
of.numpat = mh->numpat;
|
||||
of.inittempo = 125; /* mh->inittempo+0x1c; */
|
||||
of.initspeed = mh->inittempo>>4;
|
||||
of.numchn = 4; /* get number of channels */
|
||||
of.reppos = 0;
|
||||
of.flags |= UF_S3MSLIDES;
|
||||
of.bpmlimit = 32;
|
||||
|
||||
t=0;
|
||||
if(!AllocPositions(0x80)) return 0;
|
||||
/* 99 terminates the patorder list */
|
||||
while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) {
|
||||
of.positions[t]=mh->patorder[t];
|
||||
t++;
|
||||
}
|
||||
if(mh->patorder[t]<=99) t++;
|
||||
of.numpos=t;
|
||||
of.numtrk=of.numpat*of.numchn;
|
||||
of.numins=of.numsmp=31;
|
||||
|
||||
if(!AllocSamples()) return 0;
|
||||
if(!STM_LoadPatterns()) return 0;
|
||||
MikMod_ISA=_mm_ftell(modreader);
|
||||
MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
|
||||
|
||||
for(q=of.samples,t=0;t<of.numsmp;t++,q++) {
|
||||
/* load sample info */
|
||||
q->samplename = DupStr(mh->sample[t].filename,12,1);
|
||||
q->speed = (mh->sample[t].c2spd * 8363) / 8448;
|
||||
q->volume = mh->sample[t].volume;
|
||||
q->length = mh->sample[t].length;
|
||||
if (/*(!mh->sample[t].volume)||*/(q->length==1)) q->length=0;
|
||||
q->loopstart = mh->sample[t].loopbeg;
|
||||
q->loopend = mh->sample[t].loopend;
|
||||
q->seekpos = MikMod_ISA;
|
||||
|
||||
MikMod_ISA+=q->length;
|
||||
MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
|
||||
|
||||
/* contrary to the STM specs, sample data is signed */
|
||||
q->flags = SF_SIGNED;
|
||||
|
||||
if(q->loopend && q->loopend != 0xffff)
|
||||
q->flags|=SF_LOOP;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *STM_LoadTitle(void)
|
||||
{
|
||||
CHAR s[20];
|
||||
|
||||
_mm_fseek(modreader,0,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,20,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_stm={
|
||||
NULL,
|
||||
"STM",
|
||||
"STM (Scream Tracker)",
|
||||
STM_Init,
|
||||
STM_Test,
|
||||
STM_Load,
|
||||
STM_Cleanup,
|
||||
STM_LoadTitle
|
||||
};
|
||||
|
||||
|
||||
/* ex:set ts=4: */
|
||||
439
project/jni/mikmod/loaders/load_stx.c
Normal file
439
project/jni/mikmod/loaders/load_stx.c
Normal file
@@ -0,0 +1,439 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_stx.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
STMIK 0.2 (STX) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Written by Claudio Matsuoka <claudio@helllabs.org>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* header */
|
||||
typedef struct STXHEADER {
|
||||
CHAR songname[20];
|
||||
CHAR trackername[8];
|
||||
UWORD patsize;
|
||||
UWORD unknown1;
|
||||
UWORD patptr;
|
||||
UWORD insptr;
|
||||
UWORD chnptr; /* not sure */
|
||||
UWORD unknown2;
|
||||
UWORD unknown3;
|
||||
UBYTE mastermult;
|
||||
UBYTE initspeed;
|
||||
UWORD unknown4;
|
||||
UWORD unknown5;
|
||||
UWORD patnum;
|
||||
UWORD insnum;
|
||||
UWORD ordnum;
|
||||
UWORD unknown6;
|
||||
UWORD unknown7;
|
||||
UWORD unknown8;
|
||||
CHAR scrm[4];
|
||||
} STXHEADER;
|
||||
|
||||
/* sample information */
|
||||
typedef struct STXSAMPLE {
|
||||
UBYTE type;
|
||||
CHAR filename[12];
|
||||
UBYTE memsegh;
|
||||
UWORD memsegl;
|
||||
ULONG length;
|
||||
ULONG loopbeg;
|
||||
ULONG loopend;
|
||||
UBYTE volume;
|
||||
UBYTE dsk;
|
||||
UBYTE pack;
|
||||
UBYTE flags;
|
||||
ULONG c2spd;
|
||||
UBYTE unused[12];
|
||||
CHAR sampname[28];
|
||||
CHAR scrs[4];
|
||||
} STXSAMPLE;
|
||||
|
||||
typedef struct STXNOTE {
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
} STXNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static STXNOTE *stxbuf = NULL; /* pointer to a complete STX pattern */
|
||||
static STXHEADER *mh = NULL;
|
||||
static UWORD *paraptr = NULL; /* parapointer array (see STX docs) */
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
static BOOL STX_Test(void)
|
||||
{
|
||||
UBYTE id[8];
|
||||
int t;
|
||||
|
||||
_mm_fseek(modreader,0x3C,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(id,4,modreader)) return 0;
|
||||
if(memcmp(id,"SCRM",4)) return 0;
|
||||
|
||||
_mm_fseek(modreader,0x14,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(id,8,modreader)) return 0;
|
||||
|
||||
for(t=0;t<STM_NTRACKERS;t++)
|
||||
if(!memcmp(id,STM_Signatures[t],8)) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL STX_Init(void)
|
||||
{
|
||||
if(!(stxbuf=(STXNOTE*)_mm_malloc(4*64*sizeof(STXNOTE)))) return 0;
|
||||
if(!(mh=(STXHEADER*)_mm_malloc(sizeof(STXHEADER)))) return 0;
|
||||
if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
|
||||
memset(poslookup,-1,256);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void STX_Cleanup(void)
|
||||
{
|
||||
_mm_free(stxbuf);
|
||||
_mm_free(paraptr);
|
||||
_mm_free(poslookup);
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static BOOL STX_ReadPattern(void)
|
||||
{
|
||||
int row=0,flag,ch;
|
||||
STXNOTE *n,dummy;
|
||||
|
||||
/* clear pattern data */
|
||||
memset(stxbuf,255,4*64*sizeof(STXNOTE));
|
||||
|
||||
while(row<64) {
|
||||
flag=_mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
ch=flag&31;
|
||||
|
||||
if((ch>=0)&&(ch<4))
|
||||
n=&stxbuf[(64U*ch)+row];
|
||||
else
|
||||
n=&dummy;
|
||||
|
||||
if(flag&32) {
|
||||
n->note=_mm_read_UBYTE(modreader);
|
||||
n->ins=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
if(flag&64) {
|
||||
n->vol=_mm_read_UBYTE(modreader);
|
||||
if(n->vol>64) n->vol=64;
|
||||
}
|
||||
if(flag&128) {
|
||||
n->cmd=_mm_read_UBYTE(modreader);
|
||||
n->inf=_mm_read_UBYTE(modreader);
|
||||
}
|
||||
} else row++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UBYTE* STX_ConvertTrack(STXNOTE* tr)
|
||||
{
|
||||
int t;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<64;t++) {
|
||||
UBYTE note,ins,vol,cmd,inf;
|
||||
|
||||
note=tr[t].note;
|
||||
ins=tr[t].ins;
|
||||
vol=tr[t].vol;
|
||||
cmd=tr[t].cmd;
|
||||
inf=tr[t].inf;
|
||||
|
||||
if((ins)&&(ins!=255)) UniInstrument(ins-1);
|
||||
if((note)&&(note!=255)) {
|
||||
if(note==254) {
|
||||
UniPTEffect(0xc,0); /* note cut command */
|
||||
vol=255;
|
||||
} else UniNote(24+((note>>4)*OCTAVE)+(note&0xf)); /* normal note */
|
||||
}
|
||||
|
||||
if(vol<255) UniPTEffect(0xc,vol);
|
||||
|
||||
if(cmd<255) switch(cmd) {
|
||||
case 1: /* Axx set speed to xx */
|
||||
UniPTEffect(0xf,inf>>4);
|
||||
break;
|
||||
case 2: /* Bxx position jump */
|
||||
UniPTEffect(0xb,inf);
|
||||
break;
|
||||
case 3: /* Cxx patternbreak to row xx */
|
||||
UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
|
||||
break;
|
||||
case 4: /* Dxy volumeslide */
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 5: /* Exy toneslide down */
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
break;
|
||||
case 6: /* Fxy toneslide up */
|
||||
UniEffect(UNI_S3MEFFECTF,inf);
|
||||
break;
|
||||
case 7: /* Gxx Tone portamento,speed xx */
|
||||
UniPTEffect(0x3,inf);
|
||||
break;
|
||||
case 8: /* Hxy vibrato */
|
||||
UniPTEffect(0x4,inf);
|
||||
break;
|
||||
case 9: /* Ixy tremor, ontime x, offtime y */
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
break;
|
||||
case 0: /* protracker arpeggio */
|
||||
if(!inf) break;
|
||||
/* fall through */
|
||||
case 0xa: /* Jxy arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 0xb: /* Kxy Dual command H00 & Dxy */
|
||||
UniPTEffect(0x4,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0xc: /* Lxy Dual command G00 & Dxy */
|
||||
UniPTEffect(0x3,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
/* Support all these above, since ST2 can LOAD these values but can
|
||||
actually only play up to J - and J is only half-way implemented
|
||||
in ST2 */
|
||||
case 0x18: /* Xxx amiga panning command 8xx */
|
||||
UniPTEffect(0x8,inf);
|
||||
of.flags |= UF_PANNING;
|
||||
break;
|
||||
}
|
||||
UniNewline();
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
static BOOL STX_Load(BOOL curious)
|
||||
{
|
||||
int t,u,track = 0;
|
||||
int version = 0;
|
||||
SAMPLE *q;
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string(mh->songname,20,modreader);
|
||||
_mm_read_string(mh->trackername,8,modreader);
|
||||
mh->patsize =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown1 =_mm_read_I_UWORD(modreader);
|
||||
mh->patptr =_mm_read_I_UWORD(modreader);
|
||||
mh->insptr =_mm_read_I_UWORD(modreader);
|
||||
mh->chnptr =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown2 =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown3 =_mm_read_I_UWORD(modreader);
|
||||
mh->mastermult =_mm_read_UBYTE(modreader);
|
||||
mh->initspeed =_mm_read_UBYTE(modreader)>>4;
|
||||
mh->unknown4 =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown5 =_mm_read_I_UWORD(modreader);
|
||||
mh->patnum =_mm_read_I_UWORD(modreader);
|
||||
mh->insnum =_mm_read_I_UWORD(modreader);
|
||||
mh->ordnum =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown6 =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown7 =_mm_read_I_UWORD(modreader);
|
||||
mh->unknown8 =_mm_read_I_UWORD(modreader);
|
||||
_mm_read_string(mh->scrm,4,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.songname = DupStr(mh->songname,20,1);
|
||||
of.numpat = mh->patnum;
|
||||
of.reppos = 0;
|
||||
of.numins = of.numsmp = mh->insnum;
|
||||
of.initspeed = mh->initspeed;
|
||||
of.inittempo = 125;
|
||||
of.numchn = 4;
|
||||
of.flags |= UF_S3MSLIDES;
|
||||
of.bpmlimit = 32;
|
||||
|
||||
if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
|
||||
return 0;
|
||||
|
||||
/* read the instrument+pattern parapointers */
|
||||
_mm_fseek(modreader,mh->insptr<<4,SEEK_SET);
|
||||
_mm_read_I_UWORDS(paraptr,of.numins,modreader);
|
||||
_mm_fseek(modreader,mh->patptr<<4,SEEK_SET);
|
||||
_mm_read_I_UWORDS(paraptr+of.numins,of.numpat,modreader);
|
||||
|
||||
/* check module version */
|
||||
_mm_fseek(modreader,paraptr[of.numins]<<4,SEEK_SET);
|
||||
version=_mm_read_I_UWORD(modreader);
|
||||
if(version==mh->patsize) {
|
||||
version = 0x10;
|
||||
of.modtype = strdup("STMIK 0.2 (STM2STX 1.0)");
|
||||
} else {
|
||||
version = 0x11;
|
||||
of.modtype = strdup("STMIK 0.2 (STM2STX 1.1)");
|
||||
}
|
||||
|
||||
/* read the order data */
|
||||
_mm_fseek(modreader,(mh->chnptr<<4)+32,SEEK_SET);
|
||||
if(!AllocPositions(mh->ordnum)) return 0;
|
||||
for(t=0;t<mh->ordnum;t++) {
|
||||
of.positions[t]=_mm_read_UBYTE(modreader);
|
||||
_mm_fseek(modreader,4,SEEK_CUR);
|
||||
}
|
||||
|
||||
of.numpos=0;poslookupcnt=mh->ordnum;
|
||||
for(t=0;t<mh->ordnum;t++) {
|
||||
int order=of.positions[t];
|
||||
if(order==255) order=LAST_PATTERN;
|
||||
of.positions[of.numpos]=order;
|
||||
poslookup[t]=of.numpos; /* bug fix for freaky S3Ms */
|
||||
if(of.positions[t]<254) of.numpos++;
|
||||
else
|
||||
/* special end of song pattern */
|
||||
if((order==LAST_PATTERN)&&(!curious)) break;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load samples */
|
||||
if(!AllocSamples()) return 0;
|
||||
for(q=of.samples,t=0;t<of.numins;t++,q++) {
|
||||
STXSAMPLE s;
|
||||
|
||||
/* seek to instrument position */
|
||||
_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
|
||||
/* and load sample info */
|
||||
s.type =_mm_read_UBYTE(modreader);
|
||||
_mm_read_string(s.filename,12,modreader);
|
||||
s.memsegh =_mm_read_UBYTE(modreader);
|
||||
s.memsegl =_mm_read_I_UWORD(modreader);
|
||||
s.length =_mm_read_I_ULONG(modreader);
|
||||
s.loopbeg =_mm_read_I_ULONG(modreader);
|
||||
s.loopend =_mm_read_I_ULONG(modreader);
|
||||
s.volume =_mm_read_UBYTE(modreader);
|
||||
s.dsk =_mm_read_UBYTE(modreader);
|
||||
s.pack =_mm_read_UBYTE(modreader);
|
||||
s.flags =_mm_read_UBYTE(modreader);
|
||||
s.c2spd =_mm_read_I_ULONG(modreader);
|
||||
_mm_read_UBYTES(s.unused,12,modreader);
|
||||
_mm_read_string(s.sampname,28,modreader);
|
||||
_mm_read_string(s.scrs,4,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->samplename = DupStr(s.sampname,28,1);
|
||||
q->speed = (s.c2spd * 8363) / 8448;
|
||||
q->length = s.length;
|
||||
q->loopstart = s.loopbeg;
|
||||
q->loopend = s.loopend;
|
||||
q->volume = s.volume;
|
||||
q->seekpos = (((long)s.memsegh)<<16|s.memsegl)<<4;
|
||||
q->flags |= SF_SIGNED;
|
||||
|
||||
if(s.flags&1) q->flags |= SF_LOOP;
|
||||
if(s.flags&4) q->flags |= SF_16BITS;
|
||||
}
|
||||
|
||||
/* load pattern info */
|
||||
of.numtrk=of.numpat*of.numchn;
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
for(t=0;t<of.numpat;t++) {
|
||||
/* seek to pattern position (+2 skip pattern length) */
|
||||
_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+
|
||||
(version==0x10?2:0),SEEK_SET);
|
||||
if(!STX_ReadPattern()) return 0;
|
||||
for(u=0;u<of.numchn;u++)
|
||||
if(!(of.tracks[track++]=STX_ConvertTrack(&stxbuf[u*64]))) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CHAR *STX_LoadTitle(void)
|
||||
{
|
||||
CHAR s[28];
|
||||
|
||||
_mm_fseek(modreader,0,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,28,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_stx={
|
||||
NULL,
|
||||
"STX",
|
||||
"STX (Scream Tracker Music Interface Kit)",
|
||||
STX_Init,
|
||||
STX_Test,
|
||||
STX_Load,
|
||||
STX_Cleanup,
|
||||
STX_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
335
project/jni/mikmod/loaders/load_ult.c
Normal file
335
project/jni/mikmod/loaders/load_ult.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_ult.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Ultratracker (ULT) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
/* header */
|
||||
typedef struct ULTHEADER {
|
||||
CHAR id[16];
|
||||
CHAR songtitle[32];
|
||||
UBYTE reserved;
|
||||
} ULTHEADER;
|
||||
|
||||
/* sample information */
|
||||
typedef struct ULTSAMPLE {
|
||||
CHAR samplename[32];
|
||||
CHAR dosname[12];
|
||||
SLONG loopstart;
|
||||
SLONG loopend;
|
||||
SLONG sizestart;
|
||||
SLONG sizeend;
|
||||
UBYTE volume;
|
||||
UBYTE flags;
|
||||
UWORD speed;
|
||||
SWORD finetune;
|
||||
} ULTSAMPLE;
|
||||
|
||||
typedef struct ULTEVENT {
|
||||
UBYTE note,sample,eff,dat1,dat2;
|
||||
} ULTEVENT;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
#define ULTS_16BITS 4
|
||||
#define ULTS_LOOP 8
|
||||
#define ULTS_REVERSE 16
|
||||
|
||||
#define ULT_VERSION_LEN 18
|
||||
static CHAR ULT_Version[ULT_VERSION_LEN]="Ultra Tracker v1.x";
|
||||
|
||||
static ULTEVENT ev;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL ULT_Test(void)
|
||||
{
|
||||
CHAR id[16];
|
||||
|
||||
if(!_mm_read_string(id,15,modreader)) return 0;
|
||||
if(strncmp(id,"MAS_UTrack_V00",14)) return 0;
|
||||
if((id[14]<'1')||(id[14]>'4')) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL ULT_Init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ULT_Cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static UBYTE ReadUltEvent(ULTEVENT* event)
|
||||
{
|
||||
UBYTE flag,rep=1;
|
||||
|
||||
flag = _mm_read_UBYTE(modreader);
|
||||
if(flag==0xfc) {
|
||||
rep = _mm_read_UBYTE(modreader);
|
||||
event->note =_mm_read_UBYTE(modreader);
|
||||
} else
|
||||
event->note = flag;
|
||||
|
||||
event->sample =_mm_read_UBYTE(modreader);
|
||||
event->eff =_mm_read_UBYTE(modreader);
|
||||
event->dat1 =_mm_read_UBYTE(modreader);
|
||||
event->dat2 =_mm_read_UBYTE(modreader);
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
BOOL ULT_Load(BOOL curious)
|
||||
{
|
||||
int t,u,tracks=0;
|
||||
SAMPLE *q;
|
||||
ULTSAMPLE s;
|
||||
ULTHEADER mh;
|
||||
UBYTE nos,noc,nop;
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string(mh.id,15,modreader);
|
||||
_mm_read_string(mh.songtitle,32,modreader);
|
||||
mh.reserved=_mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULT_Version[ULT_VERSION_LEN-1]='3'+(mh.id[14]-'1');
|
||||
of.modtype = DupStr(ULT_Version,ULT_VERSION_LEN,1);
|
||||
of.initspeed = 6;
|
||||
of.inittempo = 125;
|
||||
of.reppos = 0;
|
||||
|
||||
/* read songtext */
|
||||
if ((mh.id[14]>'1')&&(mh.reserved))
|
||||
if(!ReadLinedComment(mh.reserved * 32, 32)) return 0;
|
||||
|
||||
nos=_mm_read_UBYTE(modreader);
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
of.songname=DupStr(mh.songtitle,32,1);
|
||||
of.numins=of.numsmp=nos;
|
||||
|
||||
if(!AllocSamples()) return 0;
|
||||
q = of.samples;
|
||||
for(t=0;t<nos;t++) {
|
||||
/* try to read sample info */
|
||||
_mm_read_string(s.samplename,32,modreader);
|
||||
_mm_read_string(s.dosname,12,modreader);
|
||||
s.loopstart =_mm_read_I_ULONG(modreader);
|
||||
s.loopend =_mm_read_I_ULONG(modreader);
|
||||
s.sizestart =_mm_read_I_ULONG(modreader);
|
||||
s.sizeend =_mm_read_I_ULONG(modreader);
|
||||
s.volume =_mm_read_UBYTE(modreader);
|
||||
s.flags =_mm_read_UBYTE(modreader);
|
||||
s.speed =(mh.id[14]>='4')?_mm_read_I_UWORD(modreader):8363;
|
||||
s.finetune =_mm_read_I_SWORD(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->samplename=DupStr(s.samplename,32,1);
|
||||
/* The correct formula for the coefficient would be
|
||||
pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point
|
||||
here, we'll use a first order approximation here.
|
||||
1/567290 == Ln(2)/OCTAVE/32768 */
|
||||
q->speed=s.speed+s.speed*(((SLONG)s.speed*(SLONG)s.finetune)/567290);
|
||||
q->length = s.sizeend-s.sizestart;
|
||||
q->volume = s.volume>>2;
|
||||
q->loopstart = s.loopstart;
|
||||
q->loopend = s.loopend;
|
||||
q->flags = SF_SIGNED;
|
||||
if(s.flags&ULTS_LOOP) q->flags|=SF_LOOP;
|
||||
if(s.flags&ULTS_16BITS) {
|
||||
s.sizeend+=(s.sizeend-s.sizestart);
|
||||
s.sizestart<<=1;
|
||||
q->flags|=SF_16BITS;
|
||||
q->loopstart>>=1;
|
||||
q->loopend>>=1;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
|
||||
if(!AllocPositions(256)) return 0;
|
||||
for(t=0;t<256;t++)
|
||||
of.positions[t]=_mm_read_UBYTE(modreader);
|
||||
for(t=0;t<256;t++)
|
||||
if(of.positions[t]==255) {
|
||||
of.positions[t]=LAST_PATTERN;
|
||||
break;
|
||||
}
|
||||
of.numpos=t;
|
||||
|
||||
noc=_mm_read_UBYTE(modreader);
|
||||
nop=_mm_read_UBYTE(modreader);
|
||||
|
||||
of.numchn=++noc;
|
||||
of.numpat=++nop;
|
||||
of.numtrk=of.numchn*of.numpat;
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
for(u=0;u<of.numchn;u++)
|
||||
for(t=0;t<of.numpat;t++)
|
||||
of.patterns[(t*of.numchn)+u]=tracks++;
|
||||
|
||||
/* read pan position table for v1.5 and higher */
|
||||
if(mh.id[14]>='3') {
|
||||
for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modreader)<<4;
|
||||
of.flags |= UF_PANNING;
|
||||
}
|
||||
|
||||
for(t=0;t<of.numtrk;t++) {
|
||||
int rep,row=0;
|
||||
|
||||
UniReset();
|
||||
while(row<64) {
|
||||
rep=ReadUltEvent(&ev);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(rep--) {
|
||||
UBYTE eff;
|
||||
int offset;
|
||||
|
||||
if(ev.sample) UniInstrument(ev.sample-1);
|
||||
if(ev.note) UniNote(ev.note+2*OCTAVE-1);
|
||||
|
||||
/* first effect - various fixes by Alexander Kerkhove and
|
||||
Thomas Neumann */
|
||||
eff = ev.eff>>4;
|
||||
switch(eff) {
|
||||
case 0x3: /* tone portamento */
|
||||
UniEffect(UNI_ITEFFECTG,ev.dat2);
|
||||
break;
|
||||
case 0x5:
|
||||
break;
|
||||
case 0x9: /* sample offset */
|
||||
offset=(ev.dat2<<8)|((ev.eff&0xf)==9?ev.dat1:0);
|
||||
UniEffect(UNI_ULTEFFECT9,offset);
|
||||
break;
|
||||
case 0xb: /* panning */
|
||||
UniPTEffect(8,ev.dat2*0xf);
|
||||
of.flags |= UF_PANNING;
|
||||
break;
|
||||
case 0xc: /* volume */
|
||||
UniPTEffect(eff,ev.dat2>>2);
|
||||
break;
|
||||
default:
|
||||
UniPTEffect(eff,ev.dat2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* second effect */
|
||||
eff=ev.eff&0xf;
|
||||
switch(eff) {
|
||||
case 0x3: /* tone portamento */
|
||||
UniEffect(UNI_ITEFFECTG,ev.dat1);
|
||||
break;
|
||||
case 0x5:
|
||||
break;
|
||||
case 0x9: /* sample offset */
|
||||
if((ev.eff>>4)!=9)
|
||||
UniEffect(UNI_ULTEFFECT9,((UWORD)ev.dat1)<<8);
|
||||
break;
|
||||
case 0xb: /* panning */
|
||||
UniPTEffect(8,ev.dat1*0xf);
|
||||
of.flags |= UF_PANNING;
|
||||
break;
|
||||
case 0xc: /* volume */
|
||||
UniPTEffect(eff,ev.dat1>>2);
|
||||
break;
|
||||
default:
|
||||
UniPTEffect(eff,ev.dat1);
|
||||
break;
|
||||
}
|
||||
|
||||
UniNewline();
|
||||
row++;
|
||||
}
|
||||
}
|
||||
if(!(of.tracks[t]=UniDup())) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *ULT_LoadTitle(void)
|
||||
{
|
||||
CHAR s[32];
|
||||
|
||||
_mm_fseek(modreader,15,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,32,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,32,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_ult={
|
||||
NULL,
|
||||
"ULT",
|
||||
"ULT (UltraTracker)",
|
||||
ULT_Init,
|
||||
ULT_Test,
|
||||
ULT_Load,
|
||||
ULT_Cleanup,
|
||||
ULT_LoadTitle
|
||||
};
|
||||
|
||||
|
||||
/* ex:set ts=4: */
|
||||
717
project/jni/mikmod/loaders/load_uni.c
Normal file
717
project/jni/mikmod/loaders/load_uni.c
Normal file
@@ -0,0 +1,717 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_uni.c,v 1.2 2004/02/06 19:29:03 raph Exp $
|
||||
|
||||
UNIMOD (libmikmod's and APlayer's internal module format) loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct UNIHEADER {
|
||||
CHAR id[4];
|
||||
UBYTE numchn;
|
||||
UWORD numpos;
|
||||
UWORD reppos;
|
||||
UWORD numpat;
|
||||
UWORD numtrk;
|
||||
UWORD numins;
|
||||
UWORD numsmp;
|
||||
UBYTE initspeed;
|
||||
UBYTE inittempo;
|
||||
UBYTE initvolume;
|
||||
UWORD flags;
|
||||
UBYTE numvoices;
|
||||
UWORD bpmlimit;
|
||||
|
||||
UBYTE positions[256];
|
||||
UBYTE panning[32];
|
||||
} UNIHEADER;
|
||||
|
||||
typedef struct UNISMP05 {
|
||||
UWORD c2spd;
|
||||
UWORD transpose;
|
||||
UBYTE volume;
|
||||
UBYTE panning;
|
||||
ULONG length;
|
||||
ULONG loopstart;
|
||||
ULONG loopend;
|
||||
UWORD flags;
|
||||
CHAR* samplename;
|
||||
UBYTE vibtype;
|
||||
UBYTE vibsweep;
|
||||
UBYTE vibdepth;
|
||||
UBYTE vibrate;
|
||||
} UNISMP05;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static UWORD universion;
|
||||
static UNIHEADER mh;
|
||||
|
||||
#define UNI_SMPINCR 64
|
||||
static UNISMP05 *wh=NULL,*s=NULL;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
static char* readstring(void)
|
||||
{
|
||||
char *s=NULL;
|
||||
UWORD len;
|
||||
|
||||
len=_mm_read_I_UWORD(modreader);
|
||||
if(len) {
|
||||
s=_mm_malloc(len+1);
|
||||
_mm_read_UBYTES(s,len,modreader);
|
||||
s[len]=0;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
BOOL UNI_Test(void)
|
||||
{
|
||||
char id[6];
|
||||
|
||||
if(!_mm_read_UBYTES(id,6,modreader)) return 0;
|
||||
|
||||
/* UNIMod created by MikCvt */
|
||||
if(!(memcmp(id,"UN0",3))) {
|
||||
if((id[3]>='4')&&(id[3]<='6')) return 1;
|
||||
}
|
||||
/* UNIMod created by APlayer */
|
||||
if(!(memcmp(id,"APUN\01",5))) {
|
||||
if((id[5]>=1)&&(id[5]<=6)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL UNI_Init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UNI_Cleanup(void)
|
||||
{
|
||||
_mm_free(wh);
|
||||
s=NULL;
|
||||
}
|
||||
|
||||
static UBYTE* readtrack(void)
|
||||
{
|
||||
UBYTE *t;
|
||||
UWORD len;
|
||||
int cur=0,chunk;
|
||||
|
||||
if(universion>=6)
|
||||
len=_mm_read_M_UWORD(modreader);
|
||||
else
|
||||
len=_mm_read_I_UWORD(modreader);
|
||||
|
||||
if(!len) return NULL;
|
||||
if(!(t=_mm_malloc(len))) return NULL;
|
||||
_mm_read_UBYTES(t,len,modreader);
|
||||
|
||||
/* Check if the track is correct */
|
||||
while(1) {
|
||||
chunk=t[cur++];
|
||||
if(!chunk) break;
|
||||
chunk=(chunk&0x1f)-1;
|
||||
while(chunk>0) {
|
||||
int opcode,oplen;
|
||||
|
||||
if(cur>=len) {
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
opcode=t[cur];
|
||||
|
||||
/* Remap opcodes */
|
||||
if (universion <= 5) {
|
||||
if (opcode > 29) {
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
switch (opcode) {
|
||||
/* UNI_NOTE .. UNI_S3MEFFECTQ are the same */
|
||||
case 25:
|
||||
opcode = UNI_S3MEFFECTT;
|
||||
break;
|
||||
case 26:
|
||||
opcode = UNI_XMEFFECTA;
|
||||
break;
|
||||
case 27:
|
||||
opcode = UNI_XMEFFECTG;
|
||||
break;
|
||||
case 28:
|
||||
opcode = UNI_XMEFFECTH;
|
||||
break;
|
||||
case 29:
|
||||
opcode = UNI_XMEFFECTP;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* APlayer < 1.05 does not have XMEFFECT6 */
|
||||
if (opcode >= UNI_XMEFFECT6 && universion < 0x105)
|
||||
opcode++;
|
||||
/* APlayer < 1.03 does not have ITEFFECTT */
|
||||
if (opcode >= UNI_ITEFFECTT && universion < 0x103)
|
||||
opcode++;
|
||||
/* APlayer < 1.02 does not have ITEFFECTZ */
|
||||
if (opcode >= UNI_ITEFFECTZ && universion < 0x102)
|
||||
opcode++;
|
||||
}
|
||||
|
||||
if((!opcode)||(opcode>=UNI_LAST)) {
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
t[cur]=opcode;
|
||||
oplen=unioperands[opcode]+1;
|
||||
cur+=oplen;
|
||||
chunk-=oplen;
|
||||
}
|
||||
if((chunk<0)||(cur>=len)) {
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static BOOL loadsmp6(void)
|
||||
{
|
||||
int t;
|
||||
SAMPLE *s;
|
||||
|
||||
s=of.samples;
|
||||
for(t=0;t<of.numsmp;t++,s++) {
|
||||
int flags;
|
||||
|
||||
flags = _mm_read_M_UWORD(modreader);
|
||||
s->flags=0;
|
||||
if(flags&0x0004) s->flags|=SF_STEREO;
|
||||
if(flags&0x0002) s->flags|=SF_SIGNED;
|
||||
if(flags&0x0001) s->flags|=SF_16BITS;
|
||||
/* convert flags */
|
||||
if(universion>=0x104) {
|
||||
if(flags&0x2000) s->flags|=SF_UST_LOOP;
|
||||
if(flags&0x1000) s->flags|=SF_OWNPAN;
|
||||
if(flags&0x0800) s->flags|=SF_SUSTAIN;
|
||||
if(flags&0x0400) s->flags|=SF_REVERSE;
|
||||
if(flags&0x0200) s->flags|=SF_BIDI;
|
||||
if(flags&0x0100) s->flags|=SF_LOOP;
|
||||
if(flags&0x0020) s->flags|=SF_ITPACKED;
|
||||
if(flags&0x0010) s->flags|=SF_DELTA;
|
||||
if(flags&0x0008) s->flags|=SF_BIG_ENDIAN;
|
||||
} else if(universion>=0x102) {
|
||||
if(flags&0x0800) s->flags|=SF_UST_LOOP;
|
||||
if(flags&0x0400) s->flags|=SF_OWNPAN;
|
||||
if(flags&0x0200) s->flags|=SF_SUSTAIN;
|
||||
if(flags&0x0100) s->flags|=SF_REVERSE;
|
||||
if(flags&0x0080) s->flags|=SF_BIDI;
|
||||
if(flags&0x0040) s->flags|=SF_LOOP;
|
||||
if(flags&0x0020) s->flags|=SF_ITPACKED;
|
||||
if(flags&0x0010) s->flags|=SF_DELTA;
|
||||
if(flags&0x0008) s->flags|=SF_BIG_ENDIAN;
|
||||
} else {
|
||||
if(flags&0x400) s->flags|=SF_UST_LOOP;
|
||||
if(flags&0x200) s->flags|=SF_OWNPAN;
|
||||
if(flags&0x100) s->flags|=SF_REVERSE;
|
||||
if(flags&0x080) s->flags|=SF_SUSTAIN;
|
||||
if(flags&0x040) s->flags|=SF_BIDI;
|
||||
if(flags&0x020) s->flags|=SF_LOOP;
|
||||
if(flags&0x010) s->flags|=SF_BIG_ENDIAN;
|
||||
if(flags&0x008) s->flags|=SF_DELTA;
|
||||
}
|
||||
|
||||
s->speed = _mm_read_M_ULONG(modreader);
|
||||
s->volume = _mm_read_UBYTE(modreader);
|
||||
s->panning = _mm_read_M_UWORD(modreader);
|
||||
s->length = _mm_read_M_ULONG(modreader);
|
||||
s->loopstart = _mm_read_M_ULONG(modreader);
|
||||
s->loopend = _mm_read_M_ULONG(modreader);
|
||||
s->susbegin = _mm_read_M_ULONG(modreader);
|
||||
s->susend = _mm_read_M_ULONG(modreader);
|
||||
s->globvol = _mm_read_UBYTE(modreader);
|
||||
s->vibflags = _mm_read_UBYTE(modreader);
|
||||
s->vibtype = _mm_read_UBYTE(modreader);
|
||||
s->vibsweep = _mm_read_UBYTE(modreader);
|
||||
s->vibdepth = _mm_read_UBYTE(modreader);
|
||||
s->vibrate = _mm_read_UBYTE(modreader);
|
||||
|
||||
s->samplename=readstring();
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL loadinstr6(void)
|
||||
{
|
||||
int t,w;
|
||||
INSTRUMENT *i;
|
||||
|
||||
i=of.instruments;
|
||||
for(t=0;t<of.numins;t++,i++) {
|
||||
i->flags = _mm_read_UBYTE(modreader);
|
||||
i->nnatype = _mm_read_UBYTE(modreader);
|
||||
i->dca = _mm_read_UBYTE(modreader);
|
||||
i->dct = _mm_read_UBYTE(modreader);
|
||||
i->globvol = _mm_read_UBYTE(modreader);
|
||||
i->panning = _mm_read_M_UWORD(modreader);
|
||||
i->pitpansep = _mm_read_UBYTE(modreader);
|
||||
i->pitpancenter = _mm_read_UBYTE(modreader);
|
||||
i->rvolvar = _mm_read_UBYTE(modreader);
|
||||
i->rpanvar = _mm_read_UBYTE(modreader);
|
||||
i->volfade = _mm_read_M_UWORD(modreader);
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define UNI_LoadEnvelope6(name) \
|
||||
i-> name##flg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##pts=_mm_read_UBYTE(modreader); \
|
||||
i-> name##susbeg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##susend=_mm_read_UBYTE(modreader); \
|
||||
i-> name##beg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##end=_mm_read_UBYTE(modreader); \
|
||||
for(w=0;w<(universion>=0x100?32:i-> name##pts);w++) { \
|
||||
i-> name##env[w].pos=_mm_read_M_SWORD(modreader); \
|
||||
i-> name##env[w].val=_mm_read_M_SWORD(modreader); \
|
||||
}
|
||||
#else
|
||||
#define UNI_LoadEnvelope6(name) \
|
||||
i-> name/**/flg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/pts=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/susbeg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/susend=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/beg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/end=_mm_read_UBYTE(modreader); \
|
||||
for (w=0;w<(universion>=0x100?32:i-> name/**/pts);w++) { \
|
||||
i-> name/**/env[w].pos=_mm_read_M_SWORD(modreader); \
|
||||
i-> name/**/env[w].val=_mm_read_M_SWORD(modreader); \
|
||||
}
|
||||
#endif
|
||||
|
||||
UNI_LoadEnvelope6(vol);
|
||||
UNI_LoadEnvelope6(pan);
|
||||
UNI_LoadEnvelope6(pit);
|
||||
#undef UNI_LoadEnvelope6
|
||||
|
||||
if(universion>=0x103)
|
||||
_mm_read_M_UWORDS(i->samplenumber,120,modreader);
|
||||
else
|
||||
for(w=0;w<120;w++)
|
||||
i->samplenumber[w]=_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(i->samplenote,120,modreader);
|
||||
|
||||
i->insname=readstring();
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL loadinstr5(void)
|
||||
{
|
||||
INSTRUMENT *i;
|
||||
int t;
|
||||
UWORD wavcnt=0;
|
||||
UBYTE vibtype,vibsweep,vibdepth,vibrate;
|
||||
|
||||
i=of.instruments;
|
||||
for(of.numsmp=t=0;t<of.numins;t++,i++) {
|
||||
int u,numsmp;
|
||||
|
||||
numsmp=_mm_read_UBYTE(modreader);
|
||||
|
||||
memset(i->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
|
||||
for(u=0;u<96;u++)
|
||||
i->samplenumber[u]=of.numsmp+_mm_read_UBYTE(modreader);
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define UNI_LoadEnvelope5(name) \
|
||||
i-> name##flg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##pts=_mm_read_UBYTE(modreader); \
|
||||
i-> name##susbeg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##susend=i-> name##susbeg; \
|
||||
i-> name##beg=_mm_read_UBYTE(modreader); \
|
||||
i-> name##end=_mm_read_UBYTE(modreader); \
|
||||
for(u=0;u<12;u++) { \
|
||||
i-> name##env[u].pos=_mm_read_I_SWORD(modreader); \
|
||||
i-> name##env[u].val=_mm_read_I_SWORD(modreader); \
|
||||
}
|
||||
#else
|
||||
#define UNI_LoadEnvelope5(name) \
|
||||
i-> name/**/flg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/pts=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/susbeg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/susend=i-> name/**/susbeg; \
|
||||
i-> name/**/beg=_mm_read_UBYTE(modreader); \
|
||||
i-> name/**/end=_mm_read_UBYTE(modreader); \
|
||||
for(u=0;u<12;u++) { \
|
||||
i-> name/**/env[u].pos=_mm_read_I_SWORD(modreader); \
|
||||
i-> name/**/env[u].val=_mm_read_I_SWORD(modreader); \
|
||||
}
|
||||
#endif
|
||||
|
||||
UNI_LoadEnvelope5(vol);
|
||||
UNI_LoadEnvelope5(pan);
|
||||
#undef UNI_LoadEnvelope5
|
||||
|
||||
vibtype =_mm_read_UBYTE(modreader);
|
||||
vibsweep =_mm_read_UBYTE(modreader);
|
||||
vibdepth =_mm_read_UBYTE(modreader);
|
||||
vibrate =_mm_read_UBYTE(modreader);
|
||||
|
||||
i->volfade=_mm_read_I_UWORD(modreader);
|
||||
i->insname=readstring();
|
||||
|
||||
for(u=0;u<numsmp;u++,s++,of.numsmp++) {
|
||||
/* Allocate more room for sample information if necessary */
|
||||
if(of.numsmp+u==wavcnt) {
|
||||
wavcnt+=UNI_SMPINCR;
|
||||
if(!(wh=realloc(wh,wavcnt*sizeof(UNISMP05)))) {
|
||||
_mm_errno=MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
s=wh+(wavcnt-UNI_SMPINCR);
|
||||
}
|
||||
|
||||
s->c2spd =_mm_read_I_UWORD(modreader);
|
||||
s->transpose=_mm_read_SBYTE(modreader);
|
||||
s->volume =_mm_read_UBYTE(modreader);
|
||||
s->panning =_mm_read_UBYTE(modreader);
|
||||
s->length =_mm_read_I_ULONG(modreader);
|
||||
s->loopstart=_mm_read_I_ULONG(modreader);
|
||||
s->loopend =_mm_read_I_ULONG(modreader);
|
||||
s->flags =_mm_read_I_UWORD(modreader);
|
||||
s->samplename=readstring();
|
||||
|
||||
s->vibtype =vibtype;
|
||||
s->vibsweep=vibsweep;
|
||||
s->vibdepth=vibdepth;
|
||||
s->vibrate =vibrate;
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
free(wh);wh=NULL;
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if(!of.numsmp) {
|
||||
if(wh) { free(wh);wh=NULL; }
|
||||
_mm_errno=MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL loadsmp5(void)
|
||||
{
|
||||
int t,u;
|
||||
SAMPLE *q;
|
||||
INSTRUMENT *d;
|
||||
|
||||
q=of.samples;s=wh;
|
||||
for(u=0;u<of.numsmp;u++,q++,s++) {
|
||||
q->samplename=s->samplename;
|
||||
|
||||
q->length =s->length;
|
||||
q->loopstart=s->loopstart;
|
||||
q->loopend =s->loopend;
|
||||
q->volume =s->volume;
|
||||
q->speed =s->c2spd;
|
||||
q->panning =s->panning;
|
||||
q->vibtype =s->vibtype;
|
||||
q->vibsweep =s->vibsweep;
|
||||
q->vibdepth =s->vibdepth;
|
||||
q->vibrate =s->vibrate;
|
||||
|
||||
/* convert flags */
|
||||
q->flags=0;
|
||||
if(s->flags&128) q->flags|=SF_REVERSE;
|
||||
if(s->flags& 64) q->flags|=SF_SUSTAIN;
|
||||
if(s->flags& 32) q->flags|=SF_BIDI;
|
||||
if(s->flags& 16) q->flags|=SF_LOOP;
|
||||
if(s->flags& 8) q->flags|=SF_BIG_ENDIAN;
|
||||
if(s->flags& 4) q->flags|=SF_DELTA;
|
||||
if(s->flags& 2) q->flags|=SF_SIGNED;
|
||||
if(s->flags& 1) q->flags|=SF_16BITS;
|
||||
}
|
||||
|
||||
d=of.instruments;s=wh;
|
||||
for(u=0;u<of.numins;u++,d++)
|
||||
for(t=0;t<INSTNOTES;t++)
|
||||
d->samplenote[t]=(d->samplenumber[t]>=of.numsmp)?
|
||||
255:(t+s[d->samplenumber[t]].transpose);
|
||||
|
||||
free(wh);wh=NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL UNI_Load(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
char *modtype,*oldtype=NULL;
|
||||
INSTRUMENT *d;
|
||||
SAMPLE *q;
|
||||
|
||||
/* read module header */
|
||||
_mm_read_UBYTES(mh.id,4,modreader);
|
||||
if(mh.id[3]!='N')
|
||||
universion=mh.id[3]-'0';
|
||||
else
|
||||
universion=0x100;
|
||||
|
||||
if(universion>=6) {
|
||||
if (universion==6)
|
||||
_mm_read_UBYTE(modreader);
|
||||
else
|
||||
universion=_mm_read_M_UWORD(modreader);
|
||||
|
||||
mh.flags =_mm_read_M_UWORD(modreader);
|
||||
mh.numchn =_mm_read_UBYTE(modreader);
|
||||
mh.numvoices =_mm_read_UBYTE(modreader);
|
||||
mh.numpos =_mm_read_M_UWORD(modreader);
|
||||
mh.numpat =_mm_read_M_UWORD(modreader);
|
||||
mh.numtrk =_mm_read_M_UWORD(modreader);
|
||||
mh.numins =_mm_read_M_UWORD(modreader);
|
||||
mh.numsmp =_mm_read_M_UWORD(modreader);
|
||||
mh.reppos =_mm_read_M_UWORD(modreader);
|
||||
mh.initspeed =_mm_read_UBYTE(modreader);
|
||||
mh.inittempo =_mm_read_UBYTE(modreader);
|
||||
mh.initvolume=_mm_read_UBYTE(modreader);
|
||||
/* I expect this to show up soon in APlayer 1.06 format */
|
||||
if (universion >= 0x106)
|
||||
mh.bpmlimit=_mm_read_M_UWORD(modreader);
|
||||
else
|
||||
mh.bpmlimit=32;
|
||||
|
||||
mh.flags &= UF_XMPERIODS | UF_LINEAR | UF_INST | UF_NNA;
|
||||
mh.flags |= UF_PANNING;
|
||||
} else {
|
||||
mh.numchn =_mm_read_UBYTE(modreader);
|
||||
mh.numpos =_mm_read_I_UWORD(modreader);
|
||||
mh.reppos =(universion==5)?_mm_read_I_UWORD(modreader):0;
|
||||
mh.numpat =_mm_read_I_UWORD(modreader);
|
||||
mh.numtrk =_mm_read_I_UWORD(modreader);
|
||||
mh.numins =_mm_read_I_UWORD(modreader);
|
||||
mh.initspeed =_mm_read_UBYTE(modreader);
|
||||
mh.inittempo =_mm_read_UBYTE(modreader);
|
||||
_mm_read_UBYTES(mh.positions,256,modreader);
|
||||
_mm_read_UBYTES(mh.panning,32,modreader);
|
||||
mh.flags =_mm_read_UBYTE(modreader);
|
||||
mh.bpmlimit =32;
|
||||
|
||||
mh.flags &= UF_XMPERIODS | UF_LINEAR;
|
||||
mh.flags |= UF_INST | UF_NOWRAP | UF_PANNING;
|
||||
}
|
||||
|
||||
/* set module parameters */
|
||||
of.flags =mh.flags;
|
||||
of.numchn =mh.numchn;
|
||||
of.numpos =mh.numpos;
|
||||
of.numpat =mh.numpat;
|
||||
of.numtrk =mh.numtrk;
|
||||
of.numins =mh.numins;
|
||||
of.reppos =mh.reppos;
|
||||
of.initspeed =mh.initspeed;
|
||||
of.inittempo =mh.inittempo;
|
||||
if(mh.bpmlimit)
|
||||
of.bpmlimit=mh.bpmlimit;
|
||||
else
|
||||
/* be bug-compatible with older releases */
|
||||
of.bpmlimit=32;
|
||||
|
||||
of.songname=readstring();
|
||||
if(universion<0x102)
|
||||
oldtype=readstring();
|
||||
if(oldtype) {
|
||||
int len=strlen(oldtype)+20;
|
||||
if(!(modtype=_mm_malloc(len))) return 0;
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
|
||||
#else
|
||||
sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
|
||||
#endif
|
||||
} else {
|
||||
if(!(modtype=_mm_malloc(10))) return 0;
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
|
||||
#else
|
||||
sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
|
||||
#endif
|
||||
}
|
||||
of.modtype=strdup(modtype);
|
||||
free(modtype);free(oldtype);
|
||||
of.comment=readstring();
|
||||
|
||||
if(universion>=6) {
|
||||
of.numvoices=mh.numvoices;
|
||||
of.initvolume=mh.initvolume;
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno=MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* positions */
|
||||
if(!AllocPositions(of.numpos)) return 0;
|
||||
if(universion>=6) {
|
||||
if(universion>=0x100)
|
||||
_mm_read_M_UWORDS(of.positions,of.numpos,modreader);
|
||||
else
|
||||
for(t=0;t<of.numpos;t++) of.positions[t]=_mm_read_UBYTE(modreader);
|
||||
_mm_read_M_UWORDS(of.panning,of.numchn,modreader);
|
||||
_mm_read_UBYTES(of.chanvol,of.numchn,modreader);
|
||||
} else {
|
||||
if((mh.numpos>256)||(mh.numchn>32)) {
|
||||
_mm_errno=MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
for(t=0;t<of.numpos;t++) of.positions[t]=mh.positions[t];
|
||||
for(t=0;t<of.numchn;t++) of.panning[t]=mh.panning[t];
|
||||
}
|
||||
/* convert the ``end of song'' pattern code if necessary */
|
||||
if(universion<0x106)
|
||||
for(t=0;t<of.numpos;t++)
|
||||
if(of.positions[t]==255) of.positions[t]=LAST_PATTERN;
|
||||
|
||||
/* instruments and samples */
|
||||
if(universion>=6) {
|
||||
of.numsmp=mh.numsmp;
|
||||
if(!AllocSamples()) return 0;
|
||||
if(!loadsmp6()) return 0;
|
||||
|
||||
if(of.flags&UF_INST) {
|
||||
if(!AllocInstruments()) return 0;
|
||||
if(!loadinstr6()) return 0;
|
||||
}
|
||||
} else {
|
||||
if(!AllocInstruments()) return 0;
|
||||
if(!loadinstr5()) return 0;
|
||||
if(!AllocSamples()) {
|
||||
if(wh) { free(wh);wh=NULL; }
|
||||
return 0;
|
||||
}
|
||||
if(!loadsmp5()) return 0;
|
||||
|
||||
/* check if the original file had no instruments */
|
||||
if(of.numsmp==of.numins) {
|
||||
for(t=0,d=of.instruments;t<of.numins;t++,d++) {
|
||||
int u;
|
||||
|
||||
if((d->volpts)||(d->panpts)||(d->globvol!=64)) break;
|
||||
for(u=0;u<96;u++)
|
||||
if((d->samplenumber[u]!=t)||(d->samplenote[u]!=u)) break;
|
||||
if(u!=96) break;
|
||||
}
|
||||
if(t==of.numins) {
|
||||
of.flags&=~UF_INST;
|
||||
of.flags&=~UF_NOWRAP;
|
||||
for(t=0,d=of.instruments,q=of.samples;t<of.numins;t++,d++,q++) {
|
||||
q->samplename=d->insname;
|
||||
d->insname=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* patterns */
|
||||
if(!AllocPatterns()) return 0;
|
||||
if(universion>=6) {
|
||||
_mm_read_M_UWORDS(of.pattrows,of.numpat,modreader);
|
||||
_mm_read_M_UWORDS(of.patterns,of.numpat*of.numchn,modreader);
|
||||
} else {
|
||||
_mm_read_I_UWORDS(of.pattrows,of.numpat,modreader);
|
||||
_mm_read_I_UWORDS(of.patterns,of.numpat*of.numchn,modreader);
|
||||
}
|
||||
|
||||
/* tracks */
|
||||
if(!AllocTracks()) return 0;
|
||||
for(t=0;t<of.numtrk;t++)
|
||||
if(!(of.tracks[t]=readtrack())) {
|
||||
_mm_errno=MMERR_LOADING_TRACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *UNI_LoadTitle(void)
|
||||
{
|
||||
UBYTE ver;
|
||||
int posit[3]={304,306,26};
|
||||
|
||||
_mm_fseek(modreader,3,SEEK_SET);
|
||||
ver=_mm_read_UBYTE(modreader);
|
||||
if(ver=='N') ver='6';
|
||||
|
||||
_mm_fseek(modreader,posit[ver-'4'],SEEK_SET);
|
||||
return readstring();
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_uni={
|
||||
NULL,
|
||||
"UNI",
|
||||
"APUN (APlayer) and UNI (MikMod)",
|
||||
UNI_Init,
|
||||
UNI_Test,
|
||||
UNI_Load,
|
||||
UNI_Cleanup,
|
||||
UNI_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
815
project/jni/mikmod/loaders/load_xm.c
Normal file
815
project/jni/mikmod/loaders/load_xm.c
Normal file
@@ -0,0 +1,815 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: load_xm.c,v 1.2 2004/02/06 19:29:03 raph Exp $
|
||||
|
||||
Fasttracker (XM) module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Module structure */
|
||||
|
||||
typedef struct XMHEADER {
|
||||
CHAR id[17]; /* ID text: 'Extended module: ' */
|
||||
CHAR songname[21]; /* Module name */
|
||||
CHAR trackername[20]; /* Tracker name */
|
||||
UWORD version; /* Version number */
|
||||
ULONG headersize; /* Header size */
|
||||
UWORD songlength; /* Song length (in patten order table) */
|
||||
UWORD restart; /* Restart position */
|
||||
UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */
|
||||
UWORD numpat; /* Number of patterns (max 256) */
|
||||
UWORD numins; /* Number of instruments (max 128) */
|
||||
UWORD flags;
|
||||
UWORD tempo; /* Default tempo */
|
||||
UWORD bpm; /* Default BPM */
|
||||
UBYTE orders[256]; /* Pattern order table */
|
||||
} XMHEADER;
|
||||
|
||||
typedef struct XMINSTHEADER {
|
||||
ULONG size; /* Instrument size */
|
||||
CHAR name[22]; /* Instrument name */
|
||||
UBYTE type; /* Instrument type (always 0) */
|
||||
UWORD numsmp; /* Number of samples in instrument */
|
||||
ULONG ssize;
|
||||
} XMINSTHEADER;
|
||||
|
||||
#define XMENVCNT (12*2)
|
||||
#define XMNOTECNT (8*OCTAVE)
|
||||
typedef struct XMPATCHHEADER {
|
||||
UBYTE what[XMNOTECNT]; /* Sample number for all notes */
|
||||
UWORD volenv[XMENVCNT]; /* Points for volume envelope */
|
||||
UWORD panenv[XMENVCNT]; /* Points for panning envelope */
|
||||
UBYTE volpts; /* Number of volume points */
|
||||
UBYTE panpts; /* Number of panning points */
|
||||
UBYTE volsus; /* Volume sustain point */
|
||||
UBYTE volbeg; /* Volume loop start point */
|
||||
UBYTE volend; /* Volume loop end point */
|
||||
UBYTE pansus; /* Panning sustain point */
|
||||
UBYTE panbeg; /* Panning loop start point */
|
||||
UBYTE panend; /* Panning loop end point */
|
||||
UBYTE volflg; /* Volume type: bit 0: On; 1: Sustain; 2: Loop */
|
||||
UBYTE panflg; /* Panning type: bit 0: On; 1: Sustain; 2: Loop */
|
||||
UBYTE vibflg; /* Vibrato type */
|
||||
UBYTE vibsweep; /* Vibrato sweep */
|
||||
UBYTE vibdepth; /* Vibrato depth */
|
||||
UBYTE vibrate; /* Vibrato rate */
|
||||
UWORD volfade; /* Volume fadeout */
|
||||
} XMPATCHHEADER;
|
||||
|
||||
typedef struct XMWAVHEADER {
|
||||
ULONG length; /* Sample length */
|
||||
ULONG loopstart; /* Sample loop start */
|
||||
ULONG looplength; /* Sample loop length */
|
||||
UBYTE volume; /* Volume */
|
||||
SBYTE finetune; /* Finetune (signed byte -128..+127) */
|
||||
UBYTE type; /* Loop type */
|
||||
UBYTE panning; /* Panning (0-255) */
|
||||
SBYTE relnote; /* Relative note number (signed byte) */
|
||||
UBYTE reserved;
|
||||
CHAR samplename[22]; /* Sample name */
|
||||
UBYTE vibtype; /* Vibrato type */
|
||||
UBYTE vibsweep; /* Vibrato sweep */
|
||||
UBYTE vibdepth; /* Vibrato depth */
|
||||
UBYTE vibrate; /* Vibrato rate */
|
||||
} XMWAVHEADER;
|
||||
|
||||
typedef struct XMPATHEADER {
|
||||
ULONG size; /* Pattern header length */
|
||||
UBYTE packing; /* Packing type (always 0) */
|
||||
UWORD numrows; /* Number of rows in pattern (1..256) */
|
||||
SWORD packsize; /* Packed patterndata size */
|
||||
} XMPATHEADER;
|
||||
|
||||
typedef struct XMNOTE {
|
||||
UBYTE note,ins,vol,eff,dat;
|
||||
} XMNOTE;
|
||||
|
||||
/*========== Loader variables */
|
||||
|
||||
static XMNOTE *xmpat=NULL;
|
||||
static XMHEADER *mh=NULL;
|
||||
|
||||
/* increment unit for sample array reallocation */
|
||||
#define XM_SMPINCR 64
|
||||
static ULONG *nextwav=NULL;
|
||||
static XMWAVHEADER *wh=NULL,*s=NULL;
|
||||
|
||||
/*========== Loader code */
|
||||
|
||||
BOOL XM_Test(void)
|
||||
{
|
||||
UBYTE id[38];
|
||||
|
||||
if(!_mm_read_UBYTES(id,38,modreader)) return 0;
|
||||
if(memcmp(id,"Extended Module: ",17)) return 0;
|
||||
if(id[37]==0x1a) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL XM_Init(void)
|
||||
{
|
||||
if(!(mh=(XMHEADER *)_mm_malloc(sizeof(XMHEADER)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void XM_Cleanup(void)
|
||||
{
|
||||
_mm_free(mh);
|
||||
}
|
||||
|
||||
static int XM_ReadNote(XMNOTE* n)
|
||||
{
|
||||
UBYTE cmp,result=1;
|
||||
|
||||
memset(n,0,sizeof(XMNOTE));
|
||||
cmp=_mm_read_UBYTE(modreader);
|
||||
|
||||
if(cmp&0x80) {
|
||||
if(cmp&1) { result++;n->note = _mm_read_UBYTE(modreader); }
|
||||
if(cmp&2) { result++;n->ins = _mm_read_UBYTE(modreader); }
|
||||
if(cmp&4) { result++;n->vol = _mm_read_UBYTE(modreader); }
|
||||
if(cmp&8) { result++;n->eff = _mm_read_UBYTE(modreader); }
|
||||
if(cmp&16) { result++;n->dat = _mm_read_UBYTE(modreader); }
|
||||
} else {
|
||||
n->note = cmp;
|
||||
n->ins = _mm_read_UBYTE(modreader);
|
||||
n->vol = _mm_read_UBYTE(modreader);
|
||||
n->eff = _mm_read_UBYTE(modreader);
|
||||
n->dat = _mm_read_UBYTE(modreader);
|
||||
result += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
|
||||
{
|
||||
int t;
|
||||
UBYTE note,ins,vol,eff,dat;
|
||||
|
||||
UniReset();
|
||||
for(t=0;t<rows;t++) {
|
||||
note = xmtrack->note;
|
||||
ins = xmtrack->ins;
|
||||
vol = xmtrack->vol;
|
||||
eff = xmtrack->eff;
|
||||
dat = xmtrack->dat;
|
||||
|
||||
if(note) {
|
||||
if(note>XMNOTECNT)
|
||||
UniEffect(UNI_KEYFADE,0);
|
||||
else
|
||||
UniNote(note-1);
|
||||
}
|
||||
if(ins) UniInstrument(ins-1);
|
||||
|
||||
switch(vol>>4) {
|
||||
case 0x6: /* volslide down */
|
||||
if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
|
||||
break;
|
||||
case 0x7: /* volslide up */
|
||||
if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
|
||||
break;
|
||||
|
||||
/* volume-row fine volume slide is compatible with protracker
|
||||
EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
|
||||
opposed to 'take the last sliding value'. */
|
||||
case 0x8: /* finevol down */
|
||||
UniPTEffect(0xe,0xb0|(vol&0xf));
|
||||
break;
|
||||
case 0x9: /* finevol up */
|
||||
UniPTEffect(0xe,0xa0|(vol&0xf));
|
||||
break;
|
||||
case 0xa: /* set vibrato speed */
|
||||
UniEffect(UNI_XMEFFECT4,vol<<4);
|
||||
break;
|
||||
case 0xb: /* vibrato */
|
||||
UniEffect(UNI_XMEFFECT4,vol&0xf);
|
||||
break;
|
||||
case 0xc: /* set panning */
|
||||
UniPTEffect(0x8,vol<<4);
|
||||
break;
|
||||
case 0xd: /* panning slide left (only slide when data not zero) */
|
||||
if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
|
||||
break;
|
||||
case 0xe: /* panning slide right (only slide when data not zero) */
|
||||
if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
|
||||
break;
|
||||
case 0xf: /* tone porta */
|
||||
UniPTEffect(0x3,vol<<4);
|
||||
break;
|
||||
default:
|
||||
if((vol>=0x10)&&(vol<=0x50))
|
||||
UniPTEffect(0xc,vol-0x10);
|
||||
}
|
||||
|
||||
switch(eff) {
|
||||
case 0x4:
|
||||
UniEffect(UNI_XMEFFECT4,dat);
|
||||
break;
|
||||
case 0x6:
|
||||
UniEffect(UNI_XMEFFECT6,dat);
|
||||
break;
|
||||
case 0xa:
|
||||
UniEffect(UNI_XMEFFECTA,dat);
|
||||
break;
|
||||
case 0xe: /* Extended effects */
|
||||
switch(dat>>4) {
|
||||
case 0x1: /* XM fine porta up */
|
||||
UniEffect(UNI_XMEFFECTE1,dat&0xf);
|
||||
break;
|
||||
case 0x2: /* XM fine porta down */
|
||||
UniEffect(UNI_XMEFFECTE2,dat&0xf);
|
||||
break;
|
||||
case 0xa: /* XM fine volume up */
|
||||
UniEffect(UNI_XMEFFECTEA,dat&0xf);
|
||||
break;
|
||||
case 0xb: /* XM fine volume down */
|
||||
UniEffect(UNI_XMEFFECTEB,dat&0xf);
|
||||
break;
|
||||
default:
|
||||
UniPTEffect(eff,dat);
|
||||
}
|
||||
break;
|
||||
case 'G'-55: /* G - set global volume */
|
||||
UniEffect(UNI_XMEFFECTG,dat>64?128:dat<<1);
|
||||
break;
|
||||
case 'H'-55: /* H - global volume slide */
|
||||
UniEffect(UNI_XMEFFECTH,dat);
|
||||
break;
|
||||
case 'K'-55: /* K - keyOff and KeyFade */
|
||||
UniEffect(UNI_KEYFADE,dat);
|
||||
break;
|
||||
case 'L'-55: /* L - set envelope position */
|
||||
UniEffect(UNI_XMEFFECTL,dat);
|
||||
break;
|
||||
case 'P'-55: /* P - panning slide */
|
||||
UniEffect(UNI_XMEFFECTP,dat);
|
||||
break;
|
||||
case 'R'-55: /* R - multi retrig note */
|
||||
UniEffect(UNI_S3MEFFECTQ,dat);
|
||||
break;
|
||||
case 'T'-55: /* T - Tremor */
|
||||
UniEffect(UNI_S3MEFFECTI,dat);
|
||||
break;
|
||||
case 'X'-55:
|
||||
switch(dat>>4) {
|
||||
case 1: /* X1 - Extra Fine Porta up */
|
||||
UniEffect(UNI_XMEFFECTX1,dat&0xf);
|
||||
break;
|
||||
case 2: /* X2 - Extra Fine Porta down */
|
||||
UniEffect(UNI_XMEFFECTX2,dat&0xf);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(eff<=0xf) {
|
||||
/* the pattern jump destination is written in decimal,
|
||||
but it seems some poor tracker software writes them
|
||||
in hexadecimal... (sigh) */
|
||||
if (eff==0xd)
|
||||
/* don't change anything if we're sure it's in hexa */
|
||||
if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
|
||||
/* otherwise, convert from dec to hex */
|
||||
dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
|
||||
UniPTEffect(eff,dat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
UniNewline();
|
||||
xmtrack++;
|
||||
}
|
||||
return UniDup();
|
||||
}
|
||||
|
||||
static BOOL LoadPatterns(BOOL dummypat)
|
||||
{
|
||||
int t,u,v,numtrk;
|
||||
|
||||
if(!AllocTracks()) return 0;
|
||||
if(!AllocPatterns()) return 0;
|
||||
|
||||
numtrk=0;
|
||||
for(t=0;t<mh->numpat;t++) {
|
||||
XMPATHEADER ph;
|
||||
|
||||
ph.size =_mm_read_I_ULONG(modreader);
|
||||
if (ph.size<(mh->version==0x0102?8:9)) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
ph.packing =_mm_read_UBYTE(modreader);
|
||||
if(ph.packing) {
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
if(mh->version==0x0102)
|
||||
ph.numrows =_mm_read_UBYTE(modreader)+1;
|
||||
else
|
||||
ph.numrows =_mm_read_I_UWORD(modreader);
|
||||
ph.packsize =_mm_read_I_UWORD(modreader);
|
||||
|
||||
ph.size-=(mh->version==0x0102?8:9);
|
||||
if(ph.size)
|
||||
_mm_fseek(modreader,ph.size,SEEK_CUR);
|
||||
|
||||
of.pattrows[t]=ph.numrows;
|
||||
|
||||
if(ph.numrows) {
|
||||
if(!(xmpat=(XMNOTE*)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
|
||||
return 0;
|
||||
|
||||
/* when packsize is 0, don't try to load a pattern.. it's empty. */
|
||||
if(ph.packsize)
|
||||
for(u=0;u<ph.numrows;u++)
|
||||
for(v=0;v<of.numchn;v++) {
|
||||
if(!ph.packsize) break;
|
||||
|
||||
ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
|
||||
if(ph.packsize<0) {
|
||||
free(xmpat);xmpat=NULL;
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(ph.packsize) {
|
||||
_mm_fseek(modreader,ph.packsize,SEEK_CUR);
|
||||
}
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
free(xmpat);xmpat=NULL;
|
||||
_mm_errno=MMERR_LOADING_PATTERN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(v=0;v<of.numchn;v++)
|
||||
of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
|
||||
|
||||
free(xmpat);xmpat=NULL;
|
||||
} else {
|
||||
for(v=0;v<of.numchn;v++)
|
||||
of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
|
||||
}
|
||||
}
|
||||
|
||||
if(dummypat) {
|
||||
of.pattrows[t]=64;
|
||||
if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
|
||||
for(v=0;v<of.numchn;v++)
|
||||
of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
|
||||
free(xmpat);xmpat=NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void FixEnvelope(ENVPT *cur, int pts)
|
||||
{
|
||||
int u, old, tmp;
|
||||
ENVPT *prev;
|
||||
|
||||
/* Some broken XM editing program will only save the low byte
|
||||
of the position value. Try to compensate by adding the
|
||||
missing high byte. */
|
||||
|
||||
prev = cur++;
|
||||
old = prev->pos;
|
||||
|
||||
for (u = 1; u < pts; u++, prev++, cur++) {
|
||||
if (cur->pos < prev->pos) {
|
||||
if (cur->pos < 0x100) {
|
||||
if (cur->pos > old) /* same hex century */
|
||||
tmp = cur->pos + (prev->pos - old);
|
||||
else
|
||||
tmp = cur->pos | ((prev->pos + 0x100) & 0xff00);
|
||||
old = cur->pos;
|
||||
cur->pos = tmp;
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n",
|
||||
u, pts, prev->pos, old, cur->pos);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MIKMOD_DEBUG
|
||||
/* different brokenness style... fix unknown */
|
||||
fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n",
|
||||
u, pts, old, cur->pos);
|
||||
#endif
|
||||
old = cur->pos;
|
||||
}
|
||||
} else
|
||||
old = cur->pos;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL LoadInstruments(void)
|
||||
{
|
||||
int t,u;
|
||||
INSTRUMENT *d;
|
||||
ULONG next=0;
|
||||
UWORD wavcnt=0;
|
||||
|
||||
if(!AllocInstruments()) return 0;
|
||||
d=of.instruments;
|
||||
for(t=0;t<of.numins;t++,d++) {
|
||||
XMINSTHEADER ih;
|
||||
long headend;
|
||||
|
||||
memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
|
||||
|
||||
/* read instrument header */
|
||||
headend = _mm_ftell(modreader);
|
||||
ih.size = _mm_read_I_ULONG(modreader);
|
||||
headend += ih.size;
|
||||
_mm_read_string(ih.name, 22, modreader);
|
||||
ih.type = _mm_read_UBYTE(modreader);
|
||||
ih.numsmp = _mm_read_I_UWORD(modreader);
|
||||
|
||||
d->insname = DupStr(ih.name,22,1);
|
||||
|
||||
if((SWORD)ih.size>29) {
|
||||
ih.ssize = _mm_read_I_ULONG(modreader);
|
||||
if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
|
||||
XMPATCHHEADER pth;
|
||||
int p;
|
||||
|
||||
_mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
|
||||
_mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
|
||||
_mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
|
||||
pth.volpts = _mm_read_UBYTE(modreader);
|
||||
pth.panpts = _mm_read_UBYTE(modreader);
|
||||
pth.volsus = _mm_read_UBYTE(modreader);
|
||||
pth.volbeg = _mm_read_UBYTE(modreader);
|
||||
pth.volend = _mm_read_UBYTE(modreader);
|
||||
pth.pansus = _mm_read_UBYTE(modreader);
|
||||
pth.panbeg = _mm_read_UBYTE(modreader);
|
||||
pth.panend = _mm_read_UBYTE(modreader);
|
||||
pth.volflg = _mm_read_UBYTE(modreader);
|
||||
pth.panflg = _mm_read_UBYTE(modreader);
|
||||
pth.vibflg = _mm_read_UBYTE(modreader);
|
||||
pth.vibsweep = _mm_read_UBYTE(modreader);
|
||||
pth.vibdepth = _mm_read_UBYTE(modreader);
|
||||
pth.vibrate = _mm_read_UBYTE(modreader);
|
||||
pth.volfade = _mm_read_I_UWORD(modreader);
|
||||
|
||||
/* read the remainder of the header
|
||||
(2 bytes for 1.03, 22 for 1.04) */
|
||||
for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
|
||||
|
||||
/* we can't trust the envelope point count here, as some
|
||||
modules have incorrect values (K_OSPACE.XM reports 32 volume
|
||||
points, for example). */
|
||||
if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2;
|
||||
if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
|
||||
|
||||
if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
|
||||
if(nextwav) { free(nextwav);nextwav=NULL; }
|
||||
if(wh) { free(wh);wh=NULL; }
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(u=0;u<XMNOTECNT;u++)
|
||||
d->samplenumber[u]=pth.what[u]+of.numsmp;
|
||||
d->volfade = pth.volfade;
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define XM_ProcessEnvelope(name) \
|
||||
for (u = 0; u < (XMENVCNT >> 1); u++) { \
|
||||
d-> name##env[u].pos = pth. name##env[u << 1]; \
|
||||
d-> name##env[u].val = pth. name##env[(u << 1)+ 1]; \
|
||||
} \
|
||||
if (pth. name##flg&1) d-> name##flg|=EF_ON; \
|
||||
if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN; \
|
||||
if (pth. name##flg&4) d-> name##flg|=EF_LOOP; \
|
||||
d-> name##susbeg=d-> name##susend=pth. name##sus; \
|
||||
d-> name##beg=pth. name##beg; \
|
||||
d-> name##end=pth. name##end; \
|
||||
d-> name##pts=pth. name##pts; \
|
||||
\
|
||||
/* scale envelope */ \
|
||||
for (p=0;p<XMENVCNT/2;p++) \
|
||||
d-> name##env[p].val<<=2; \
|
||||
\
|
||||
if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \
|
||||
d-> name##flg&=~EF_ON
|
||||
#else
|
||||
#define XM_ProcessEnvelope(name) \
|
||||
for (u = 0; u < (XMENVCNT >> 1); u++) { \
|
||||
d-> name/**/env[u].pos = pth. name/**/env[u << 1]; \
|
||||
d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1]; \
|
||||
} \
|
||||
if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON; \
|
||||
if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \
|
||||
if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \
|
||||
d-> name/**/susbeg=d-> name/**/susend= \
|
||||
pth. name/**/sus; \
|
||||
d-> name/**/beg=pth. name/**/beg; \
|
||||
d-> name/**/end=pth. name/**/end; \
|
||||
d-> name/**/pts=pth. name/**/pts; \
|
||||
\
|
||||
/* scale envelope */ \
|
||||
for (p=0;p<XMENVCNT/2;p++) \
|
||||
d-> name/**/env[p].val<<=2; \
|
||||
\
|
||||
if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
|
||||
d-> name/**/flg&=~EF_ON
|
||||
#endif
|
||||
|
||||
XM_ProcessEnvelope(vol);
|
||||
XM_ProcessEnvelope(pan);
|
||||
#undef XM_ProcessEnvelope
|
||||
|
||||
if (d->volflg & EF_ON)
|
||||
FixEnvelope(d->volenv, d->volpts);
|
||||
if (d->panflg & EF_ON)
|
||||
FixEnvelope(d->panenv, d->panpts);
|
||||
|
||||
/* Samples are stored outside the instrument struct now, so we
|
||||
have to load them all into a temp area, count the of.numsmp
|
||||
along the way and then do an AllocSamples() and move
|
||||
everything over */
|
||||
if(mh->version>0x0103) next = 0;
|
||||
for(u=0;u<ih.numsmp;u++,s++) {
|
||||
/* Allocate more room for sample information if necessary */
|
||||
if(of.numsmp+u==wavcnt) {
|
||||
wavcnt+=XM_SMPINCR;
|
||||
if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
|
||||
if(wh) { free(wh);wh=NULL; }
|
||||
_mm_errno = MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
|
||||
free(nextwav);nextwav=NULL;
|
||||
_mm_errno = MMERR_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
s=wh+(wavcnt-XM_SMPINCR);
|
||||
}
|
||||
|
||||
s->length =_mm_read_I_ULONG (modreader);
|
||||
s->loopstart =_mm_read_I_ULONG (modreader);
|
||||
s->looplength =_mm_read_I_ULONG (modreader);
|
||||
s->volume =_mm_read_UBYTE (modreader);
|
||||
s->finetune =_mm_read_SBYTE (modreader);
|
||||
s->type =_mm_read_UBYTE (modreader);
|
||||
s->panning =_mm_read_UBYTE (modreader);
|
||||
s->relnote =_mm_read_SBYTE (modreader);
|
||||
s->vibtype = pth.vibflg;
|
||||
s->vibsweep = pth.vibsweep;
|
||||
s->vibdepth = pth.vibdepth*4;
|
||||
s->vibrate = pth.vibrate;
|
||||
s->reserved =_mm_read_UBYTE (modreader);
|
||||
_mm_read_string(s->samplename, 22, modreader);
|
||||
|
||||
nextwav[of.numsmp+u]=next;
|
||||
next+=s->length;
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
free(nextwav);free(wh);
|
||||
nextwav=NULL;wh=NULL;
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(mh->version>0x0103) {
|
||||
for(u=0;u<ih.numsmp;u++)
|
||||
nextwav[of.numsmp++]+=_mm_ftell(modreader);
|
||||
_mm_fseek(modreader,next,SEEK_CUR);
|
||||
} else
|
||||
of.numsmp+=ih.numsmp;
|
||||
} else {
|
||||
/* read the remainder of the header */
|
||||
for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
free(nextwav);free(wh);
|
||||
nextwav=NULL;wh=NULL;
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if(!of.numsmp) {
|
||||
if(nextwav) { free(nextwav);nextwav=NULL; }
|
||||
if(wh) { free(wh);wh=NULL; }
|
||||
_mm_errno = MMERR_LOADING_SAMPLEINFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL XM_Load(BOOL curious)
|
||||
{
|
||||
INSTRUMENT *d;
|
||||
SAMPLE *q;
|
||||
int t,u;
|
||||
BOOL dummypat=0;
|
||||
char tracker[21],modtype[60];
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string(mh->id,17,modreader);
|
||||
_mm_read_string(mh->songname,21,modreader);
|
||||
_mm_read_string(mh->trackername,20,modreader);
|
||||
mh->version =_mm_read_I_UWORD(modreader);
|
||||
if((mh->version<0x102)||(mh->version>0x104)) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
mh->headersize =_mm_read_I_ULONG(modreader);
|
||||
mh->songlength =_mm_read_I_UWORD(modreader);
|
||||
mh->restart =_mm_read_I_UWORD(modreader);
|
||||
mh->numchn =_mm_read_I_UWORD(modreader);
|
||||
mh->numpat =_mm_read_I_UWORD(modreader);
|
||||
mh->numins =_mm_read_I_UWORD(modreader);
|
||||
mh->flags =_mm_read_I_UWORD(modreader);
|
||||
mh->tempo =_mm_read_I_UWORD(modreader);
|
||||
mh->bpm =_mm_read_I_UWORD(modreader);
|
||||
if(!mh->bpm) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
_mm_read_UBYTES(mh->orders,256,modreader);
|
||||
|
||||
if(_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set module variables */
|
||||
of.initspeed = mh->tempo;
|
||||
of.inittempo = mh->bpm;
|
||||
strncpy(tracker,mh->trackername,20);tracker[20]=0;
|
||||
for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
|
||||
|
||||
/* some modules have the tracker name empty */
|
||||
if (!tracker[0])
|
||||
strcpy(tracker,"Unknown tracker");
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(modtype,60,"%s (XM format %d.%02d)",
|
||||
tracker,mh->version>>8,mh->version&0xff);
|
||||
#else
|
||||
sprintf(modtype,"%s (XM format %d.%02d)",
|
||||
tracker,mh->version>>8,mh->version&0xff);
|
||||
#endif
|
||||
of.modtype = strdup(modtype);
|
||||
of.numchn = mh->numchn;
|
||||
of.numpat = mh->numpat;
|
||||
of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
|
||||
of.songname = DupStr(mh->songname,20,1);
|
||||
of.numpos = mh->songlength; /* copy the songlength */
|
||||
of.reppos = mh->restart<mh->songlength?mh->restart:0;
|
||||
of.numins = mh->numins;
|
||||
of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
|
||||
UF_PANNING;
|
||||
if(mh->flags&1) of.flags |= UF_LINEAR;
|
||||
of.bpmlimit = 32;
|
||||
|
||||
memset(of.chanvol,64,of.numchn); /* store channel volumes */
|
||||
|
||||
if(!AllocPositions(of.numpos+1)) return 0;
|
||||
for(t=0;t<of.numpos;t++)
|
||||
of.positions[t]=mh->orders[t];
|
||||
|
||||
/* We have to check for any pattern numbers in the order list greater than
|
||||
the number of patterns total. If one or more is found, we set it equal to
|
||||
the pattern total and make a dummy pattern to workaround the problem */
|
||||
for(t=0;t<of.numpos;t++) {
|
||||
if(of.positions[t]>=of.numpat) {
|
||||
of.positions[t]=of.numpat;
|
||||
dummypat=1;
|
||||
}
|
||||
}
|
||||
if(dummypat) {
|
||||
of.numpat++;of.numtrk+=of.numchn;
|
||||
}
|
||||
|
||||
if(mh->version<0x0104) {
|
||||
if(!LoadInstruments()) return 0;
|
||||
if(!LoadPatterns(dummypat)) return 0;
|
||||
for(t=0;t<of.numsmp;t++)
|
||||
nextwav[t]+=_mm_ftell(modreader);
|
||||
} else {
|
||||
if(!LoadPatterns(dummypat)) return 0;
|
||||
if(!LoadInstruments()) return 0;
|
||||
}
|
||||
|
||||
if(!AllocSamples()) {
|
||||
free(nextwav);free(wh);
|
||||
nextwav=NULL;wh=NULL;
|
||||
return 0;
|
||||
}
|
||||
q = of.samples;
|
||||
s = wh;
|
||||
for(u=0;u<of.numsmp;u++,q++,s++) {
|
||||
q->samplename = DupStr(s->samplename,22,1);
|
||||
q->length = s->length;
|
||||
q->loopstart = s->loopstart;
|
||||
q->loopend = s->loopstart+s->looplength;
|
||||
q->volume = s->volume;
|
||||
q->speed = s->finetune+128;
|
||||
q->panning = s->panning;
|
||||
q->seekpos = nextwav[u];
|
||||
q->vibtype = s->vibtype;
|
||||
q->vibsweep = s->vibsweep;
|
||||
q->vibdepth = s->vibdepth;
|
||||
q->vibrate = s->vibrate;
|
||||
|
||||
if(s->type & 0x10) {
|
||||
q->length >>= 1;
|
||||
q->loopstart >>= 1;
|
||||
q->loopend >>= 1;
|
||||
}
|
||||
|
||||
q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
|
||||
if(s->type&0x3) q->flags|=SF_LOOP;
|
||||
if(s->type&0x2) q->flags|=SF_BIDI;
|
||||
if(s->type&0x10) q->flags|=SF_16BITS;
|
||||
}
|
||||
|
||||
d=of.instruments;
|
||||
s=wh;
|
||||
for(u=0;u<of.numins;u++,d++)
|
||||
for(t=0;t<XMNOTECNT;t++) {
|
||||
if (d->samplenumber[t]>=of.numsmp)
|
||||
d->samplenote[t]=255;
|
||||
else {
|
||||
int note=t+s[d->samplenumber[t]].relnote;
|
||||
d->samplenote[t]=(note<0)?0:note;
|
||||
}
|
||||
}
|
||||
|
||||
free(wh);free(nextwav);
|
||||
wh=NULL;nextwav=NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHAR *XM_LoadTitle(void)
|
||||
{
|
||||
CHAR s[21];
|
||||
|
||||
_mm_fseek(modreader,17,SEEK_SET);
|
||||
if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
|
||||
|
||||
return(DupStr(s,21,1));
|
||||
}
|
||||
|
||||
/*========== Loader information */
|
||||
|
||||
MIKMODAPI MLOADER load_xm={
|
||||
NULL,
|
||||
"XM",
|
||||
"XM (FastTracker 2)",
|
||||
XM_Init,
|
||||
XM_Test,
|
||||
XM_Load,
|
||||
XM_Cleanup,
|
||||
XM_LoadTitle
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
59
project/jni/mikmod/mmio/mmalloc.c
Normal file
59
project/jni/mikmod/mmio/mmalloc.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mmalloc.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Dynamic memory routines
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
/* Same as malloc, but sets error variable _mm_error when fails */
|
||||
void* _mm_malloc(size_t size)
|
||||
{
|
||||
void *d;
|
||||
|
||||
if(!(d=calloc(1,size))) {
|
||||
_mm_errno = MMERR_OUT_OF_MEMORY;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/* Same as calloc, but sets error variable _mm_error when fails */
|
||||
void* _mm_calloc(size_t nitems,size_t size)
|
||||
{
|
||||
void *d;
|
||||
|
||||
if(!(d=calloc(nitems,size))) {
|
||||
_mm_errno = MMERR_OUT_OF_MEMORY;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
197
project/jni/mikmod/mmio/mmerror.c
Normal file
197
project/jni/mikmod/mmio/mmerror.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mmerror.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Error handling functions.
|
||||
Register an error handler with _mm_RegisterErrorHandler() and you're all set.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
The global variables _mm_errno, and _mm_critical are set before the error
|
||||
handler in called. See below for the values of these variables.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
CHAR *_mm_errmsg[MMERR_MAX+1] =
|
||||
{
|
||||
/* No error */
|
||||
|
||||
"No error",
|
||||
|
||||
/* Generic errors */
|
||||
|
||||
"Could not open requested file",
|
||||
"Out of memory",
|
||||
"Dynamic linking failed",
|
||||
|
||||
/* Sample errors */
|
||||
|
||||
"Out of memory to load sample",
|
||||
"Out of sample handles to load sample",
|
||||
"Sample format not recognized",
|
||||
|
||||
/* Module errors */
|
||||
|
||||
"Failure loading module pattern",
|
||||
"Failure loading module track",
|
||||
"Failure loading module header",
|
||||
"Failure loading sampleinfo",
|
||||
"Module format not recognized",
|
||||
"Module sample format not recognized",
|
||||
"Synthsounds not supported in MED files",
|
||||
"Compressed sample is invalid",
|
||||
|
||||
/* Driver errors: */
|
||||
|
||||
"Sound device not detected",
|
||||
"Device number out of range",
|
||||
"Software mixer failure",
|
||||
"Could not open sound device",
|
||||
"This driver supports 8 bit linear output only",
|
||||
"This driver supports 16 bit linear output only",
|
||||
"This driver supports stereo output only",
|
||||
"This driver supports uLaw output (8 bit mono, 8 kHz) only",
|
||||
"Unable to set non-blocking mode for audio device",
|
||||
|
||||
/* AudioFile driver errors */
|
||||
|
||||
"Cannot find suitable AudioFile audio port",
|
||||
|
||||
/* AIX driver errors */
|
||||
|
||||
"Configuration (init step) of audio device failed",
|
||||
"Configuration (control step) of audio device failed",
|
||||
"Configuration (start step) of audio device failed",
|
||||
|
||||
/* ALSA driver errors */
|
||||
|
||||
/* EsounD driver errors */
|
||||
|
||||
/* Ultrasound driver errors */
|
||||
|
||||
"Ultrasound driver only works in 16 bit stereo 44 KHz",
|
||||
"Ultrasound card could not be reset",
|
||||
"Could not start Ultrasound timer",
|
||||
|
||||
/* HP driver errors */
|
||||
|
||||
"Unable to select 16bit-linear sample format",
|
||||
"Could not select requested sample-rate",
|
||||
"Could not select requested number of channels",
|
||||
"Unable to select audio output",
|
||||
"Unable to get audio description",
|
||||
"Could not set transmission buffer size",
|
||||
|
||||
/* Open Sound System driver errors */
|
||||
|
||||
"Could not set fragment size",
|
||||
"Could not set sample size",
|
||||
"Could not set mono/stereo setting",
|
||||
"Could not set sample rate",
|
||||
|
||||
/* SGI driver errors */
|
||||
|
||||
"Unsupported sample rate",
|
||||
"Hardware does not support 16 bit sound",
|
||||
"Hardware does not support 8 bit sound",
|
||||
"Hardware does not support stereo sound",
|
||||
"Hardware does not support mono sound",
|
||||
|
||||
/* Sun driver errors */
|
||||
|
||||
"Sound device initialization failed",
|
||||
|
||||
/* OS/2 drivers errors */
|
||||
|
||||
"Could not set mixing parameters",
|
||||
"Could not create playback semaphores",
|
||||
"Could not create playback timer",
|
||||
"Could not create playback thread",
|
||||
|
||||
/* DirectSound driver errors */
|
||||
|
||||
"Could not set playback priority",
|
||||
"Could not create playback buffers",
|
||||
"Could not set playback format",
|
||||
"Could not register callback",
|
||||
"Could not register event",
|
||||
"Could not create playback thread",
|
||||
"Could not initialize playback thread",
|
||||
|
||||
/* Windows Multimedia API driver errors */
|
||||
|
||||
"Invalid device handle",
|
||||
"The resource is already allocated",
|
||||
"Invalid device identifier",
|
||||
"Unsupported output format",
|
||||
"Unknown error",
|
||||
|
||||
/* Macintosh driver errors */
|
||||
|
||||
"Unsupported sample rate",
|
||||
"Could not start playback",
|
||||
|
||||
/* Invalid error */
|
||||
|
||||
"Invalid error code"
|
||||
};
|
||||
|
||||
MIKMODAPI char *MikMod_strerror(int code)
|
||||
{
|
||||
if ((code<0)||(code>MMERR_MAX)) code=MMERR_MAX+1;
|
||||
return _mm_errmsg[code];
|
||||
}
|
||||
|
||||
/* User installed error callback */
|
||||
MikMod_handler_t _mm_errorhandler = NULL;
|
||||
MIKMODAPI int _mm_errno = 0;
|
||||
MIKMODAPI BOOL _mm_critical = 0;
|
||||
|
||||
MikMod_handler_t _mm_registererrorhandler(MikMod_handler_t proc)
|
||||
{
|
||||
MikMod_handler_t oldproc=_mm_errorhandler;
|
||||
|
||||
_mm_errorhandler = proc;
|
||||
return oldproc;
|
||||
}
|
||||
|
||||
MIKMODAPI MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t proc)
|
||||
{
|
||||
MikMod_handler_t result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=_mm_registererrorhandler(proc);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
378
project/jni/mikmod/mmio/mmio.c
Normal file
378
project/jni/mikmod/mmio/mmio.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mmio.c,v 1.2 2004/02/06 19:29:05 raph Exp $
|
||||
|
||||
Portable file I/O routines
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
The way this module works:
|
||||
|
||||
- _mm_fopen will call the errorhandler [see mmerror.c] in addition to
|
||||
setting _mm_errno on exit.
|
||||
- _mm_iobase is for internal use. It is used by Player_LoadFP to
|
||||
ensure that it works properly with wad files.
|
||||
- _mm_read_I_* and _mm_read_M_* differ : the first is for reading data
|
||||
written by a little endian (intel) machine, and the second is for reading
|
||||
big endian (Mac, RISC, Alpha) machine data.
|
||||
- _mm_write functions work the same as the _mm_read functions.
|
||||
- _mm_read_string is for reading binary strings. It is basically the same
|
||||
as an fread of bytes.
|
||||
|
||||
*/
|
||||
|
||||
/* FIXME
|
||||
the _mm_iobase variable ought to be MREADER-specific. It will eventually
|
||||
become a private field of the MREADER structure, but this will require a
|
||||
soname version bump.
|
||||
|
||||
In the meantime, the drawback is that if you use the xxx_LoadFP functions,
|
||||
you can't have several MREADER objects with different iobase values.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fclose(FILE *);
|
||||
extern int fgetc(FILE *);
|
||||
extern int fputc(int, FILE *);
|
||||
extern size_t fread(void *, size_t, size_t, FILE *);
|
||||
extern int fseek(FILE *, long, int);
|
||||
extern size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
#endif
|
||||
|
||||
#define COPY_BUFSIZE 1024
|
||||
|
||||
static long _mm_iobase=0,temp_iobase=0;
|
||||
|
||||
FILE* _mm_fopen(CHAR* fname,CHAR* attrib)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if(!(fp=fopen(fname,attrib))) {
|
||||
_mm_errno = MMERR_OPENING_FILE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
BOOL _mm_FileExists(CHAR* fname)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if(!(fp=fopen(fname,"r"))) return 0;
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _mm_fclose(FILE *fp)
|
||||
{
|
||||
return fclose(fp);
|
||||
}
|
||||
|
||||
/* Sets the current file-position as the new _mm_iobase */
|
||||
void _mm_iobase_setcur(MREADER* reader)
|
||||
{
|
||||
temp_iobase=_mm_iobase; /* store old value in case of revert */
|
||||
_mm_iobase=reader->Tell(reader);
|
||||
}
|
||||
|
||||
/* Reverts to the last known _mm_iobase value. */
|
||||
void _mm_iobase_revert(void)
|
||||
{
|
||||
_mm_iobase=temp_iobase;
|
||||
}
|
||||
|
||||
/*========== File Reader */
|
||||
|
||||
typedef struct MFILEREADER {
|
||||
MREADER core;
|
||||
FILE* file;
|
||||
} MFILEREADER;
|
||||
|
||||
static BOOL _mm_FileReader_Eof(MREADER* reader)
|
||||
{
|
||||
return feof(((MFILEREADER*)reader)->file);
|
||||
}
|
||||
|
||||
static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)
|
||||
{
|
||||
return fread(ptr,size,1,((MFILEREADER*)reader)->file);
|
||||
}
|
||||
|
||||
static int _mm_FileReader_Get(MREADER* reader)
|
||||
{
|
||||
return fgetc(((MFILEREADER*)reader)->file);
|
||||
}
|
||||
|
||||
static BOOL _mm_FileReader_Seek(MREADER* reader,long offset,int whence)
|
||||
{
|
||||
return fseek(((MFILEREADER*)reader)->file,
|
||||
(whence==SEEK_SET)?offset+_mm_iobase:offset,whence);
|
||||
}
|
||||
|
||||
static long _mm_FileReader_Tell(MREADER* reader)
|
||||
{
|
||||
return ftell(((MFILEREADER*)reader)->file)-_mm_iobase;
|
||||
}
|
||||
|
||||
MREADER *_mm_new_file_reader(FILE* fp)
|
||||
{
|
||||
MFILEREADER* reader=(MFILEREADER*)_mm_malloc(sizeof(MFILEREADER));
|
||||
if (reader) {
|
||||
reader->core.Eof =&_mm_FileReader_Eof;
|
||||
reader->core.Read=&_mm_FileReader_Read;
|
||||
reader->core.Get =&_mm_FileReader_Get;
|
||||
reader->core.Seek=&_mm_FileReader_Seek;
|
||||
reader->core.Tell=&_mm_FileReader_Tell;
|
||||
reader->file=fp;
|
||||
}
|
||||
return (MREADER*)reader;
|
||||
}
|
||||
|
||||
void _mm_delete_file_reader (MREADER* reader)
|
||||
{
|
||||
if(reader) free(reader);
|
||||
}
|
||||
|
||||
/*========== File Writer */
|
||||
|
||||
typedef struct MFILEWRITER {
|
||||
MWRITER core;
|
||||
FILE* file;
|
||||
} MFILEWRITER;
|
||||
|
||||
static BOOL _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence)
|
||||
{
|
||||
return fseek(((MFILEWRITER*)writer)->file,offset,whence);
|
||||
}
|
||||
|
||||
static long _mm_FileWriter_Tell(MWRITER* writer)
|
||||
{
|
||||
return ftell(((MFILEWRITER*)writer)->file);
|
||||
}
|
||||
|
||||
static BOOL _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size)
|
||||
{
|
||||
return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size);
|
||||
}
|
||||
|
||||
static BOOL _mm_FileWriter_Put(MWRITER* writer,int value)
|
||||
{
|
||||
return fputc(value,((MFILEWRITER*)writer)->file);
|
||||
}
|
||||
|
||||
MWRITER *_mm_new_file_writer(FILE* fp)
|
||||
{
|
||||
MFILEWRITER* writer=(MFILEWRITER*)_mm_malloc(sizeof(MFILEWRITER));
|
||||
if (writer) {
|
||||
writer->core.Seek =&_mm_FileWriter_Seek;
|
||||
writer->core.Tell =&_mm_FileWriter_Tell;
|
||||
writer->core.Write=&_mm_FileWriter_Write;
|
||||
writer->core.Put =&_mm_FileWriter_Put;
|
||||
writer->file=fp;
|
||||
}
|
||||
return (MWRITER*) writer;
|
||||
}
|
||||
|
||||
void _mm_delete_file_writer (MWRITER* writer)
|
||||
{
|
||||
if(writer) free (writer);
|
||||
}
|
||||
|
||||
/*========== Write functions */
|
||||
|
||||
void _mm_write_string(CHAR* data,MWRITER* writer)
|
||||
{
|
||||
if(data)
|
||||
_mm_write_UBYTES(data,strlen(data),writer);
|
||||
}
|
||||
|
||||
void _mm_write_M_UWORD(UWORD data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_UBYTE(data>>8,writer);
|
||||
_mm_write_UBYTE(data&0xff,writer);
|
||||
}
|
||||
|
||||
void _mm_write_I_UWORD(UWORD data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_UBYTE(data&0xff,writer);
|
||||
_mm_write_UBYTE(data>>8,writer);
|
||||
}
|
||||
|
||||
void _mm_write_M_ULONG(ULONG data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_M_UWORD(data>>16,writer);
|
||||
_mm_write_M_UWORD(data&0xffff,writer);
|
||||
}
|
||||
|
||||
void _mm_write_I_ULONG(ULONG data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_I_UWORD(data&0xffff,writer);
|
||||
_mm_write_I_UWORD(data>>16,writer);
|
||||
}
|
||||
|
||||
void _mm_write_M_SWORD(SWORD data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_M_UWORD((UWORD)data,writer);
|
||||
}
|
||||
|
||||
void _mm_write_I_SWORD(SWORD data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_I_UWORD((UWORD)data,writer);
|
||||
}
|
||||
|
||||
void _mm_write_M_SLONG(SLONG data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_M_ULONG((ULONG)data,writer);
|
||||
}
|
||||
|
||||
void _mm_write_I_SLONG(SLONG data,MWRITER* writer)
|
||||
{
|
||||
_mm_write_I_ULONG((ULONG)data,writer);
|
||||
}
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
|
||||
void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \
|
||||
{ \
|
||||
while(number-->0) \
|
||||
_mm_write_##type_name(*(buffer++),writer); \
|
||||
}
|
||||
#else
|
||||
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
|
||||
void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \
|
||||
{ \
|
||||
while(number-->0) \
|
||||
_mm_write_/**/type_name(*(buffer++),writer); \
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD)
|
||||
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG)
|
||||
DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG)
|
||||
|
||||
/*========== Read functions */
|
||||
|
||||
int _mm_read_string(CHAR* buffer,int number,MREADER* reader)
|
||||
{
|
||||
return reader->Read(reader,buffer,number);
|
||||
}
|
||||
|
||||
UWORD _mm_read_M_UWORD(MREADER* reader)
|
||||
{
|
||||
UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8;
|
||||
result|=_mm_read_UBYTE(reader);
|
||||
return result;
|
||||
}
|
||||
|
||||
UWORD _mm_read_I_UWORD(MREADER* reader)
|
||||
{
|
||||
UWORD result=_mm_read_UBYTE(reader);
|
||||
result|=((UWORD)_mm_read_UBYTE(reader))<<8;
|
||||
return result;
|
||||
}
|
||||
|
||||
ULONG _mm_read_M_ULONG(MREADER* reader)
|
||||
{
|
||||
ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16;
|
||||
result|=_mm_read_M_UWORD(reader);
|
||||
return result;
|
||||
}
|
||||
|
||||
ULONG _mm_read_I_ULONG(MREADER* reader)
|
||||
{
|
||||
ULONG result=_mm_read_I_UWORD(reader);
|
||||
result|=((ULONG)_mm_read_I_UWORD(reader))<<16;
|
||||
return result;
|
||||
}
|
||||
|
||||
SWORD _mm_read_M_SWORD(MREADER* reader)
|
||||
{
|
||||
return((SWORD)_mm_read_M_UWORD(reader));
|
||||
}
|
||||
|
||||
SWORD _mm_read_I_SWORD(MREADER* reader)
|
||||
{
|
||||
return((SWORD)_mm_read_I_UWORD(reader));
|
||||
}
|
||||
|
||||
SLONG _mm_read_M_SLONG(MREADER* reader)
|
||||
{
|
||||
return((SLONG)_mm_read_M_ULONG(reader));
|
||||
}
|
||||
|
||||
SLONG _mm_read_I_SLONG(MREADER* reader)
|
||||
{
|
||||
return((SLONG)_mm_read_I_ULONG(reader));
|
||||
}
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER || defined MPW_C
|
||||
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
|
||||
int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \
|
||||
{ \
|
||||
while(number-->0) \
|
||||
*(buffer++)=_mm_read_##type_name(reader); \
|
||||
return !reader->Eof(reader); \
|
||||
}
|
||||
#else
|
||||
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
|
||||
int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \
|
||||
{ \
|
||||
while(number-->0) \
|
||||
*(buffer++)=_mm_read_/**/type_name(reader); \
|
||||
return !reader->Eof(reader); \
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD)
|
||||
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG)
|
||||
DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG)
|
||||
|
||||
/* ex:set ts=4: */
|
||||
122
project/jni/mikmod/playercode/mdreg.c
Normal file
122
project/jni/mikmod/playercode/mdreg.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mdreg.c,v 1.5 2004/02/20 22:08:35 raph Exp $
|
||||
|
||||
Routine for registering all drivers in libmikmod for the current platform.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
void _mm_registeralldrivers(void)
|
||||
{
|
||||
/* Register network drivers */
|
||||
#ifdef DRV_AF
|
||||
_mm_registerdriver(&drv_AF);
|
||||
#endif
|
||||
#ifdef DRV_ESD
|
||||
_mm_registerdriver(&drv_esd);
|
||||
#endif
|
||||
|
||||
/* Register hardware drivers - hardware mixing */
|
||||
#ifdef DRV_ULTRA
|
||||
_mm_registerdriver(&drv_ultra);
|
||||
#endif
|
||||
|
||||
/* Register hardware drivers - software mixing */
|
||||
#ifdef DRV_AIX
|
||||
_mm_registerdriver(&drv_aix);
|
||||
#endif
|
||||
#ifdef DRV_ALSA
|
||||
_mm_registerdriver(&drv_alsa);
|
||||
#endif
|
||||
#ifdef DRV_HP
|
||||
_mm_registerdriver(&drv_hp);
|
||||
#endif
|
||||
#ifdef DRV_OSS
|
||||
_mm_registerdriver(&drv_oss);
|
||||
#endif
|
||||
#ifdef DRV_SGI
|
||||
_mm_registerdriver(&drv_sgi);
|
||||
#endif
|
||||
#ifdef DRV_SUN
|
||||
_mm_registerdriver(&drv_sun);
|
||||
#endif
|
||||
#ifdef DRV_DART
|
||||
_mm_registerdriver(&drv_dart);
|
||||
#endif
|
||||
#ifdef DRV_OS2
|
||||
_mm_registerdriver(&drv_os2);
|
||||
#endif
|
||||
#ifdef DRV_DS
|
||||
_mm_registerdriver(&drv_ds);
|
||||
#endif
|
||||
#ifdef DRV_WIN
|
||||
_mm_registerdriver(&drv_win);
|
||||
#endif
|
||||
#ifdef DRV_MAC
|
||||
_mm_registerdriver(&drv_mac);
|
||||
#endif
|
||||
#ifdef DRV_OSX
|
||||
_mm_registerdriver(&drv_osx);
|
||||
#endif
|
||||
|
||||
/* dos drivers */
|
||||
#ifdef DRV_WSS
|
||||
/* wss first, since some cards emulate sb */
|
||||
_mm_registerdriver(&drv_wss);
|
||||
#endif
|
||||
#ifdef DRV_SB
|
||||
_mm_registerdriver(&drv_sb);
|
||||
#endif
|
||||
|
||||
/* Register disk writers */
|
||||
_mm_registerdriver(&drv_raw);
|
||||
_mm_registerdriver(&drv_wav);
|
||||
#ifdef DRV_AIFF
|
||||
_mm_registerdriver(&drv_aiff);
|
||||
#endif
|
||||
|
||||
/* Register other drivers */
|
||||
#ifdef DRV_PIPE
|
||||
_mm_registerdriver(&drv_pipe);
|
||||
#endif
|
||||
#ifndef macintosh
|
||||
_mm_registerdriver(&drv_stdout);
|
||||
#endif
|
||||
|
||||
_mm_registerdriver(&drv_nos);
|
||||
}
|
||||
|
||||
void MikMod_RegisterAllDrivers(void)
|
||||
{
|
||||
MUTEX_LOCK(lists);
|
||||
_mm_registeralldrivers();
|
||||
MUTEX_UNLOCK(lists);
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
948
project/jni/mikmod/playercode/mdriver.c
Normal file
948
project/jni/mikmod/playercode/mdriver.c
Normal file
@@ -0,0 +1,948 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mdriver.c,v 1.3 2004/02/18 13:29:19 raph Exp $
|
||||
|
||||
These routines are used to access the available soundcard drivers.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
static MDRIVER *firstdriver=NULL;
|
||||
MIKMODAPI MDRIVER *md_driver=NULL;
|
||||
extern MODULE *pf; /* modfile being played */
|
||||
|
||||
/* Initial global settings */
|
||||
MIKMODAPI UWORD md_device = 0; /* autodetect */
|
||||
MIKMODAPI UWORD md_mixfreq = 44100;
|
||||
MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS |
|
||||
DMODE_SURROUND |DMODE_SOFT_MUSIC |
|
||||
DMODE_SOFT_SNDFX;
|
||||
MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */
|
||||
MIKMODAPI UBYTE md_reverb = 0; /* no reverb */
|
||||
MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */
|
||||
MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */
|
||||
MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */
|
||||
UWORD md_bpm = 125; /* tempo */
|
||||
|
||||
/* Do not modify the numchn variables yourself! use MD_SetVoices() */
|
||||
UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0;
|
||||
UBYTE md_hardchn=0,md_softchn=0;
|
||||
|
||||
void (*md_player)(void) = Player_HandleTick;
|
||||
static BOOL isplaying=0, initialized = 0;
|
||||
static UBYTE *sfxinfo;
|
||||
static int sfxpool;
|
||||
|
||||
static SAMPLE **md_sample = NULL;
|
||||
|
||||
/* Previous driver in use */
|
||||
static SWORD olddevice = -1;
|
||||
|
||||
/* Limits the number of hardware voices to the specified amount.
|
||||
This function should only be used by the low-level drivers. */
|
||||
static void LimitHardVoices(int limit)
|
||||
{
|
||||
int t=0;
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
|
||||
if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_SNDFX))
|
||||
md_hardchn=md_sfxchn;
|
||||
else
|
||||
md_hardchn=0;
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn += md_sngchn;
|
||||
|
||||
while (md_hardchn>limit) {
|
||||
if (++t & 1) {
|
||||
if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
|
||||
} else {
|
||||
if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
|
||||
}
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_SNDFX))
|
||||
md_hardchn=md_sfxchn;
|
||||
else
|
||||
md_hardchn=0;
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_MUSIC))
|
||||
md_hardchn+=md_sngchn;
|
||||
}
|
||||
md_numchn=md_hardchn+md_softchn;
|
||||
}
|
||||
|
||||
/* Limits the number of hardware voices to the specified amount.
|
||||
This function should only be used by the low-level drivers. */
|
||||
static void LimitSoftVoices(int limit)
|
||||
{
|
||||
int t=0;
|
||||
|
||||
if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
|
||||
if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
|
||||
|
||||
if (md_mode & DMODE_SOFT_SNDFX)
|
||||
md_softchn=md_sfxchn;
|
||||
else
|
||||
md_softchn=0;
|
||||
|
||||
if (md_mode & DMODE_SOFT_MUSIC) md_softchn+=md_sngchn;
|
||||
|
||||
while (md_softchn>limit) {
|
||||
if (++t & 1) {
|
||||
if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
|
||||
} else {
|
||||
if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
|
||||
}
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_SNDFX))
|
||||
md_softchn=md_sfxchn;
|
||||
else
|
||||
md_softchn=0;
|
||||
|
||||
if (!(md_mode & DMODE_SOFT_MUSIC))
|
||||
md_softchn+=md_sngchn;
|
||||
}
|
||||
md_numchn=md_hardchn+md_softchn;
|
||||
}
|
||||
|
||||
/* Note: 'type' indicates whether the returned value should be for music or for
|
||||
sound effects. */
|
||||
ULONG MD_SampleSpace(int type)
|
||||
{
|
||||
if(type==MD_MUSIC)
|
||||
type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
|
||||
else if(type==MD_SNDFX)
|
||||
type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
|
||||
|
||||
return md_driver->FreeSampleSpace(type);
|
||||
}
|
||||
|
||||
ULONG MD_SampleLength(int type,SAMPLE* s)
|
||||
{
|
||||
if(type==MD_MUSIC)
|
||||
type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
|
||||
else
|
||||
if(type==MD_SNDFX)
|
||||
type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
|
||||
|
||||
return md_driver->RealSampleLength(type,s);
|
||||
}
|
||||
|
||||
MIKMODAPI CHAR* MikMod_InfoDriver(void)
|
||||
{
|
||||
int t,len=0;
|
||||
MDRIVER *l;
|
||||
CHAR *list=NULL;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
/* compute size of buffer */
|
||||
for(l=firstdriver;l;l=l->next)
|
||||
len+=4+(l->next?1:0)+strlen(l->Version);
|
||||
|
||||
if(len)
|
||||
if((list=_mm_malloc(len*sizeof(CHAR)))) {
|
||||
list[0]=0;
|
||||
/* list all registered device drivers : */
|
||||
for(t=1,l=firstdriver;l;l=l->next,t++)
|
||||
sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s",
|
||||
list,t,l->Version);
|
||||
}
|
||||
MUTEX_UNLOCK(lists);
|
||||
return list;
|
||||
}
|
||||
|
||||
void _mm_registerdriver(struct MDRIVER* drv)
|
||||
{
|
||||
MDRIVER *cruise = firstdriver;
|
||||
|
||||
/* don't register a MISSING() driver */
|
||||
if ((drv->Name) && (drv->Version)) {
|
||||
if (cruise) {
|
||||
while (cruise->next) cruise = cruise->next;
|
||||
cruise->next = drv;
|
||||
} else
|
||||
firstdriver = drv;
|
||||
}
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_RegisterDriver(struct MDRIVER* drv)
|
||||
{
|
||||
/* if we try to register an invalid driver, or an already registered driver,
|
||||
ignore this attempt */
|
||||
if ((!drv)||(drv->next)||(!drv->Name))
|
||||
return;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
_mm_registerdriver(drv);
|
||||
MUTEX_UNLOCK(lists);
|
||||
}
|
||||
|
||||
MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias)
|
||||
{
|
||||
int rank=1;
|
||||
MDRIVER *cruise;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
cruise=firstdriver;
|
||||
while(cruise) {
|
||||
if (cruise->Alias) {
|
||||
if (!(strcasecmp(alias,cruise->Alias))) break;
|
||||
rank++;
|
||||
}
|
||||
cruise=cruise->next;
|
||||
}
|
||||
if(!cruise) rank=0;
|
||||
MUTEX_UNLOCK(lists);
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
MIKMODAPI MDRIVER *MikMod_DriverByOrdinal(int ordinal)
|
||||
{
|
||||
MDRIVER *cruise;
|
||||
|
||||
/* Allow only driver ordinals > 0 */
|
||||
if (!ordinal)
|
||||
return 0;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
cruise = firstdriver;
|
||||
while (cruise && --ordinal)
|
||||
cruise = cruise->next;
|
||||
MUTEX_UNLOCK(lists);
|
||||
return cruise;
|
||||
}
|
||||
|
||||
SWORD MD_SampleLoad(SAMPLOAD* s, int type)
|
||||
{
|
||||
SWORD result;
|
||||
|
||||
if(type==MD_MUSIC)
|
||||
type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
|
||||
else if(type==MD_SNDFX)
|
||||
type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
|
||||
|
||||
SL_Init(s);
|
||||
result=md_driver->SampleLoad(s,type);
|
||||
SL_Exit(s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MD_SampleUnload(SWORD handle)
|
||||
{
|
||||
md_driver->SampleUnload(handle);
|
||||
}
|
||||
|
||||
MIKMODAPI MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player)
|
||||
{
|
||||
MikMod_player_t result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=md_player;
|
||||
md_player=player;
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_Update(void)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
if(isplaying) {
|
||||
if((!pf)||(!pf->forbid))
|
||||
md_driver->Update();
|
||||
else {
|
||||
if (md_driver->Pause)
|
||||
md_driver->Pause();
|
||||
}
|
||||
}
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
void Voice_SetVolume_internal(SBYTE voice,UWORD vol)
|
||||
{
|
||||
ULONG tmp;
|
||||
|
||||
if((voice<0)||(voice>=md_numchn)) return;
|
||||
|
||||
/* range checks */
|
||||
if(md_musicvolume>128) md_musicvolume=128;
|
||||
if(md_sndfxvolume>128) md_sndfxvolume=128;
|
||||
if(md_volume>128) md_volume=128;
|
||||
|
||||
tmp=(ULONG)vol*(ULONG)md_volume*
|
||||
((voice<md_sngchn)?(ULONG)md_musicvolume:(ULONG)md_sndfxvolume);
|
||||
md_driver->VoiceSetVolume(voice,tmp/16384UL);
|
||||
}
|
||||
|
||||
MIKMODAPI void Voice_SetVolume(SBYTE voice,UWORD vol)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
Voice_SetVolume_internal(voice,vol);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
MIKMODAPI UWORD Voice_GetVolume(SBYTE voice)
|
||||
{
|
||||
UWORD result=0;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
if((voice>=0)&&(voice<md_numchn))
|
||||
result=md_driver->VoiceGetVolume(voice);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Voice_SetFrequency_internal(SBYTE voice,ULONG frq)
|
||||
{
|
||||
if((voice<0)||(voice>=md_numchn)) return;
|
||||
if((md_sample[voice])&&(md_sample[voice]->divfactor))
|
||||
frq/=md_sample[voice]->divfactor;
|
||||
md_driver->VoiceSetFrequency(voice,frq);
|
||||
}
|
||||
|
||||
MIKMODAPI void Voice_SetFrequency(SBYTE voice,ULONG frq)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
Voice_SetFrequency_internal(voice,frq);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
MIKMODAPI ULONG Voice_GetFrequency(SBYTE voice)
|
||||
{
|
||||
ULONG result=0;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
if((voice>=0)&&(voice<md_numchn))
|
||||
result=md_driver->VoiceGetFrequency(voice);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Voice_SetPanning_internal(SBYTE voice,ULONG pan)
|
||||
{
|
||||
if((voice<0)||(voice>=md_numchn)) return;
|
||||
if(pan!=PAN_SURROUND) {
|
||||
if(md_pansep>128) md_pansep=128;
|
||||
if(md_mode & DMODE_REVERSE) pan=255-pan;
|
||||
pan = (((SWORD)(pan-128)*md_pansep)/128)+128;
|
||||
}
|
||||
md_driver->VoiceSetPanning(voice, pan);
|
||||
}
|
||||
|
||||
MIKMODAPI void Voice_SetPanning(SBYTE voice,ULONG pan)
|
||||
{
|
||||
#ifdef MIKMOD_DEBUG
|
||||
if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255)))
|
||||
fprintf(stderr,"\rVoice_SetPanning called with pan=%ld\n",(long)pan);
|
||||
#endif
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
Voice_SetPanning_internal(voice,pan);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
MIKMODAPI ULONG Voice_GetPanning(SBYTE voice)
|
||||
{
|
||||
ULONG result=PAN_CENTER;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
if((voice>=0)&&(voice<md_numchn))
|
||||
result=md_driver->VoiceGetPanning(voice);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start)
|
||||
{
|
||||
ULONG repend;
|
||||
|
||||
if((voice<0)||(voice>=md_numchn)) return;
|
||||
|
||||
md_sample[voice]=s;
|
||||
repend=s->loopend;
|
||||
|
||||
if(s->flags&SF_LOOP)
|
||||
/* repend can't be bigger than size */
|
||||
if(repend>s->length) repend=s->length;
|
||||
|
||||
md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
|
||||
}
|
||||
|
||||
MIKMODAPI void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start)
|
||||
{
|
||||
if(start>s->length) return;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
Voice_Play_internal(voice,s,start);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
void Voice_Stop_internal(SBYTE voice)
|
||||
{
|
||||
if((voice<0)||(voice>=md_numchn)) return;
|
||||
if(voice>=md_sngchn)
|
||||
/* It is a sound effects channel, so flag the voice as non-critical! */
|
||||
sfxinfo[voice-md_sngchn]=0;
|
||||
md_driver->VoiceStop(voice);
|
||||
}
|
||||
|
||||
MIKMODAPI void Voice_Stop(SBYTE voice)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
Voice_Stop_internal(voice);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
BOOL Voice_Stopped_internal(SBYTE voice)
|
||||
{
|
||||
if((voice<0)||(voice>=md_numchn)) return 0;
|
||||
return(md_driver->VoiceStopped(voice));
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL Voice_Stopped(SBYTE voice)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=Voice_Stopped_internal(voice);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI SLONG Voice_GetPosition(SBYTE voice)
|
||||
{
|
||||
SLONG result=0;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
if((voice>=0)&&(voice<md_numchn)) {
|
||||
if (md_driver->VoiceGetPosition)
|
||||
result=(md_driver->VoiceGetPosition(voice));
|
||||
else
|
||||
result=-1;
|
||||
}
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI ULONG Voice_RealVolume(SBYTE voice)
|
||||
{
|
||||
ULONG result=0;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
if((voice>=0)&&(voice<md_numchn)&& md_driver->VoiceRealVolume)
|
||||
result=(md_driver->VoiceRealVolume(voice));
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL _mm_init(CHAR *cmdline)
|
||||
{
|
||||
UWORD t;
|
||||
|
||||
_mm_critical = 1;
|
||||
|
||||
/* if md_device==0, try to find a device number */
|
||||
if(!md_device) {
|
||||
cmdline=NULL;
|
||||
|
||||
for(t=1,md_driver=firstdriver;md_driver;md_driver=md_driver->next,t++)
|
||||
if(md_driver->IsPresent()) break;
|
||||
|
||||
if(!md_driver) {
|
||||
_mm_errno = MMERR_DETECTING_DEVICE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
md_driver = &drv_nos;
|
||||
return 1;
|
||||
}
|
||||
|
||||
md_device = t;
|
||||
} else {
|
||||
/* if n>0, use that driver */
|
||||
for(t=1,md_driver=firstdriver;(md_driver)&&(t!=md_device);md_driver=md_driver->next)
|
||||
t++;
|
||||
|
||||
if(!md_driver) {
|
||||
_mm_errno = MMERR_INVALID_DEVICE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
md_driver = &drv_nos;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* arguments here might be necessary for the presence check to succeed */
|
||||
if(cmdline&&(md_driver->CommandLine))
|
||||
md_driver->CommandLine(cmdline);
|
||||
|
||||
if(!md_driver->IsPresent()) {
|
||||
_mm_errno = MMERR_DETECTING_DEVICE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
md_driver = &drv_nos;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
olddevice = md_device;
|
||||
if(md_driver->Init()) {
|
||||
MikMod_Exit_internal();
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return 1;
|
||||
}
|
||||
|
||||
initialized=1;
|
||||
_mm_critical=0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL MikMod_Init(CHAR *cmdline)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
MUTEX_LOCK(lists);
|
||||
result=_mm_init(cmdline);
|
||||
MUTEX_UNLOCK(lists);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MikMod_Exit_internal(void)
|
||||
{
|
||||
MikMod_DisableOutput_internal();
|
||||
md_driver->Exit();
|
||||
md_numchn = md_sfxchn = md_sngchn = 0;
|
||||
md_driver = &drv_nos;
|
||||
|
||||
if(sfxinfo) free(sfxinfo);
|
||||
if(md_sample) free(md_sample);
|
||||
md_sample = NULL;
|
||||
sfxinfo = NULL;
|
||||
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_Exit(void)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
MUTEX_LOCK(lists);
|
||||
MikMod_Exit_internal();
|
||||
MUTEX_UNLOCK(lists);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
/* Reset the driver using the new global variable settings.
|
||||
If the driver has not been initialized, it will be now. */
|
||||
static BOOL _mm_reset(CHAR *cmdline)
|
||||
{
|
||||
BOOL wasplaying = 0;
|
||||
|
||||
if(!initialized) return _mm_init(cmdline);
|
||||
|
||||
if (isplaying) {
|
||||
wasplaying = 1;
|
||||
md_driver->PlayStop();
|
||||
}
|
||||
|
||||
if((!md_driver->Reset)||(md_device != olddevice)) {
|
||||
/* md_driver->Reset was NULL, or md_device was changed, so do a full
|
||||
reset of the driver. */
|
||||
md_driver->Exit();
|
||||
if(_mm_init(cmdline)) {
|
||||
MikMod_Exit_internal();
|
||||
if(_mm_errno)
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if(md_driver->Reset()) {
|
||||
MikMod_Exit_internal();
|
||||
if(_mm_errno)
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasplaying) md_driver->PlayStart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL MikMod_Reset(CHAR *cmdline)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
MUTEX_LOCK(lists);
|
||||
result=_mm_reset(cmdline);
|
||||
MUTEX_UNLOCK(lists);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* If either parameter is -1, the current set value will be retained. */
|
||||
BOOL MikMod_SetNumVoices_internal(int music, int sfx)
|
||||
{
|
||||
BOOL resume = 0;
|
||||
int t, oldchn = 0;
|
||||
|
||||
if((!music)&&(!sfx)) return 1;
|
||||
_mm_critical = 1;
|
||||
if(isplaying) {
|
||||
MikMod_DisableOutput_internal();
|
||||
oldchn = md_numchn;
|
||||
resume = 1;
|
||||
}
|
||||
|
||||
if(sfxinfo) free(sfxinfo);
|
||||
if(md_sample) free(md_sample);
|
||||
md_sample = NULL;
|
||||
sfxinfo = NULL;
|
||||
|
||||
if(music!=-1) md_sngchn = music;
|
||||
if(sfx!=-1) md_sfxchn = sfx;
|
||||
md_numchn = md_sngchn + md_sfxchn;
|
||||
|
||||
LimitHardVoices(md_driver->HardVoiceLimit);
|
||||
LimitSoftVoices(md_driver->SoftVoiceLimit);
|
||||
|
||||
if(md_driver->SetNumVoices()) {
|
||||
MikMod_Exit_internal();
|
||||
if(_mm_errno)
|
||||
if(_mm_errorhandler!=NULL) _mm_errorhandler();
|
||||
md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(md_sngchn+md_sfxchn)
|
||||
md_sample=(SAMPLE**)_mm_calloc(md_sngchn+md_sfxchn,sizeof(SAMPLE*));
|
||||
if(md_sfxchn)
|
||||
sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn,sizeof(UBYTE));
|
||||
|
||||
/* make sure the player doesn't start with garbage */
|
||||
for(t=oldchn;t<md_numchn;t++) Voice_Stop_internal(t);
|
||||
|
||||
sfxpool = 0;
|
||||
if(resume) MikMod_EnableOutput_internal();
|
||||
_mm_critical = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL MikMod_SetNumVoices(int music, int sfx)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=MikMod_SetNumVoices_internal(music,sfx);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL MikMod_EnableOutput_internal(void)
|
||||
{
|
||||
_mm_critical = 1;
|
||||
if(!isplaying) {
|
||||
if(md_driver->PlayStart()) return 1;
|
||||
isplaying = 1;
|
||||
}
|
||||
_mm_critical = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL MikMod_EnableOutput(void)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=MikMod_EnableOutput_internal();
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MikMod_DisableOutput_internal(void)
|
||||
{
|
||||
if(isplaying && md_driver) {
|
||||
isplaying = 0;
|
||||
md_driver->PlayStop();
|
||||
}
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_DisableOutput(void)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
MikMod_DisableOutput_internal();
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
BOOL MikMod_Active_internal(void)
|
||||
{
|
||||
return isplaying;
|
||||
}
|
||||
|
||||
MIKMODAPI BOOL MikMod_Active(void)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=MikMod_Active_internal();
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Plays a sound effects sample. Picks a voice from the number of voices
|
||||
allocated for use as sound effects (loops through voices, skipping all active
|
||||
criticals).
|
||||
|
||||
Returns the voice that the sound is being played on. */
|
||||
SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags)
|
||||
{
|
||||
int orig=sfxpool;/* for cases where all channels are critical */
|
||||
int c;
|
||||
|
||||
if(!md_sfxchn) return -1;
|
||||
if(s->volume>64) s->volume = 64;
|
||||
|
||||
/* check the first location after sfxpool */
|
||||
do {
|
||||
if(sfxinfo[sfxpool]&SFX_CRITICAL) {
|
||||
if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) {
|
||||
sfxinfo[sfxpool]=flags;
|
||||
Voice_Play_internal(c,s,start);
|
||||
md_driver->VoiceSetVolume(c,s->volume<<2);
|
||||
Voice_SetPanning_internal(c,s->panning);
|
||||
md_driver->VoiceSetFrequency(c,s->speed);
|
||||
sfxpool++;
|
||||
if(sfxpool>=md_sfxchn) sfxpool=0;
|
||||
return c;
|
||||
}
|
||||
} else {
|
||||
sfxinfo[sfxpool]=flags;
|
||||
Voice_Play_internal(c=sfxpool+md_sngchn,s,start);
|
||||
md_driver->VoiceSetVolume(c,s->volume<<2);
|
||||
Voice_SetPanning_internal(c,s->panning);
|
||||
md_driver->VoiceSetFrequency(c,s->speed);
|
||||
sfxpool++;
|
||||
if(sfxpool>=md_sfxchn) sfxpool=0;
|
||||
return c;
|
||||
}
|
||||
|
||||
sfxpool++;
|
||||
if(sfxpool>=md_sfxchn) sfxpool = 0;
|
||||
} while(sfxpool!=orig);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
MIKMODAPI SBYTE Sample_Play(SAMPLE *s,ULONG start,UBYTE flags)
|
||||
{
|
||||
SBYTE result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=Sample_Play_internal(s,start,flags);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI long MikMod_GetVersion(void)
|
||||
{
|
||||
return LIBMIKMOD_VERSION;
|
||||
}
|
||||
|
||||
/*========== MT-safe stuff */
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#define INIT_MUTEX(name) \
|
||||
pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER
|
||||
#elif defined(__OS2__)||defined(__EMX__)
|
||||
#define INIT_MUTEX(name) \
|
||||
HMTX _mm_mutex_##name
|
||||
#elif defined(WIN32)
|
||||
#define INIT_MUTEX(name) \
|
||||
HANDLE _mm_mutex_##name
|
||||
#else
|
||||
#define INIT_MUTEX(name) \
|
||||
void *_mm_mutex_##name = NULL
|
||||
#endif
|
||||
|
||||
INIT_MUTEX(vars);
|
||||
INIT_MUTEX(lists);
|
||||
|
||||
MIKMODAPI BOOL MikMod_InitThreads(void)
|
||||
{
|
||||
static int firstcall=1;
|
||||
static int result=0;
|
||||
|
||||
if (firstcall) {
|
||||
firstcall=0;
|
||||
#ifdef HAVE_PTHREAD
|
||||
result=1;
|
||||
#elif defined(__OS2__)||defined(__EMX__)
|
||||
if(DosCreateMutexSem((PSZ)NULL,&_mm_mutex_lists,0,0) ||
|
||||
DosCreateMutexSem((PSZ)NULL,&_mm_mutex_vars,0,0)) {
|
||||
_mm_mutex_lists=_mm_mutex_vars=(HMTX)NULL;
|
||||
result=0;
|
||||
} else
|
||||
result=1;
|
||||
#elif defined(WIN32)
|
||||
if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))||
|
||||
(!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)"))))
|
||||
result=0;
|
||||
else
|
||||
result=1;
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_Unlock(void)
|
||||
{
|
||||
MUTEX_UNLOCK(lists);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_Lock(void)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
MUTEX_LOCK(lists);
|
||||
}
|
||||
|
||||
/*========== Parameter extraction helper */
|
||||
|
||||
CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,BOOL implicit)
|
||||
{
|
||||
CHAR *ret=NULL;
|
||||
|
||||
if(cmdline) {
|
||||
CHAR *buf=strstr(cmdline,atomname);
|
||||
|
||||
if((buf)&&((buf==cmdline)||(*(buf-1)==','))) {
|
||||
CHAR *ptr=buf+strlen(atomname);
|
||||
|
||||
if(*ptr=='=') {
|
||||
for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++);
|
||||
ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
|
||||
if(ret)
|
||||
strncpy(ret,buf,ptr-buf);
|
||||
} else if((*ptr==',')||(!*ptr)) {
|
||||
if(implicit) {
|
||||
ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
|
||||
if(ret)
|
||||
strncpy(ret,buf,ptr-buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined unix || (defined __APPLE__ && defined __MACH__)
|
||||
|
||||
/*========== Posix helper functions */
|
||||
|
||||
/* Check if the file is a regular or nonexistant file (or a link to a such a
|
||||
file), and that, should the calling program be setuid, the access rights are
|
||||
reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise.
|
||||
The goal is to prevent a setuid root libmikmod application from overriding
|
||||
files like /etc/passwd with digital sound... */
|
||||
BOOL MD_Access(CHAR *filename)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if(!stat(filename,&buf)) {
|
||||
/* not a regular file ? */
|
||||
if(!S_ISREG(buf.st_mode)) return 0;
|
||||
/* more than one hard link to the file ? */
|
||||
if(buf.st_nlink>1) return 0;
|
||||
/* check access rights with the real user and group id */
|
||||
if(getuid()==buf.st_uid) {
|
||||
if(!(buf.st_mode&S_IWUSR)) return 0;
|
||||
} else if(getgid()==buf.st_gid) {
|
||||
if(!(buf.st_mode&S_IWGRP)) return 0;
|
||||
} else
|
||||
if(!(buf.st_mode&S_IWOTH)) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Drop all root privileges we might have */
|
||||
BOOL MD_DropPrivileges(void)
|
||||
{
|
||||
if(!geteuid()) {
|
||||
if(getuid()) {
|
||||
/* we are setuid root -> drop setuid to become the real user */
|
||||
if(setuid(getuid())) return 1;
|
||||
} else {
|
||||
/* we are run as root -> drop all and become user 'nobody' */
|
||||
struct passwd *nobody;
|
||||
int uid;
|
||||
|
||||
if(!(nobody=getpwnam("nobody"))) return 1; /* no such user ? */
|
||||
uid=nobody->pw_uid;
|
||||
if (!uid) /* user 'nobody' has root privileges ? weird... */
|
||||
return 1;
|
||||
if (setuid(uid)) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
2119
project/jni/mikmod/playercode/mdulaw.c
Normal file
2119
project/jni/mikmod/playercode/mdulaw.c
Normal file
File diff suppressed because it is too large
Load Diff
564
project/jni/mikmod/playercode/mloader.c
Normal file
564
project/jni/mikmod/playercode/mloader.c
Normal file
@@ -0,0 +1,564 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mloader.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
These routines are used to access the available module loaders
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
MREADER *modreader;
|
||||
MODULE of;
|
||||
|
||||
static MLOADER *firstloader=NULL;
|
||||
|
||||
UWORD finetune[16]={
|
||||
8363,8413,8463,8529,8581,8651,8723,8757,
|
||||
7895,7941,7985,8046,8107,8169,8232,8280
|
||||
};
|
||||
|
||||
MIKMODAPI CHAR* MikMod_InfoLoader(void)
|
||||
{
|
||||
int len=0;
|
||||
MLOADER *l;
|
||||
CHAR *list=NULL;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
/* compute size of buffer */
|
||||
for(l=firstloader;l;l=l->next) len+=1+(l->next?1:0)+strlen(l->version);
|
||||
|
||||
if(len)
|
||||
if((list=_mm_malloc(len*sizeof(CHAR)))) {
|
||||
list[0]=0;
|
||||
/* list all registered module loders */
|
||||
for(l=firstloader;l;l=l->next)
|
||||
sprintf(list,(l->next)?"%s%s\n":"%s%s",list,l->version);
|
||||
}
|
||||
MUTEX_UNLOCK(lists);
|
||||
return list;
|
||||
}
|
||||
|
||||
void _mm_registerloader(MLOADER* ldr)
|
||||
{
|
||||
MLOADER *cruise=firstloader;
|
||||
|
||||
if(cruise) {
|
||||
while(cruise->next) cruise = cruise->next;
|
||||
cruise->next=ldr;
|
||||
} else
|
||||
firstloader=ldr;
|
||||
}
|
||||
|
||||
MIKMODAPI void MikMod_RegisterLoader(struct MLOADER* ldr)
|
||||
{
|
||||
/* if we try to register an invalid loader, or an already registered loader,
|
||||
ignore this attempt */
|
||||
if ((!ldr)||(ldr->next))
|
||||
return;
|
||||
|
||||
MUTEX_LOCK(lists);
|
||||
_mm_registerloader(ldr);
|
||||
MUTEX_UNLOCK(lists);
|
||||
}
|
||||
|
||||
BOOL ReadComment(UWORD len)
|
||||
{
|
||||
if(len) {
|
||||
int i;
|
||||
|
||||
if(!(of.comment=(CHAR*)_mm_malloc(len+1))) return 0;
|
||||
_mm_read_UBYTES(of.comment,len,modreader);
|
||||
|
||||
/* translate IT linefeeds */
|
||||
for(i=0;i<len;i++)
|
||||
if(of.comment[i]=='\r') of.comment[i]='\n';
|
||||
|
||||
of.comment[len]=0; /* just in case */
|
||||
}
|
||||
if(!of.comment[0]) {
|
||||
free(of.comment);
|
||||
of.comment=NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL ReadLinedComment(UWORD len,UWORD linelen)
|
||||
{
|
||||
CHAR *tempcomment,*line,*storage;
|
||||
UWORD total=0,t,lines;
|
||||
int i;
|
||||
|
||||
lines = (len + linelen - 1) / linelen;
|
||||
if (len) {
|
||||
if(!(tempcomment=(CHAR*)_mm_malloc(len+1))) return 0;
|
||||
if(!(storage=(CHAR*)_mm_malloc(linelen+1))) {
|
||||
free(tempcomment);
|
||||
return 0;
|
||||
}
|
||||
memset(tempcomment, ' ', len);
|
||||
_mm_read_UBYTES(tempcomment,len,modreader);
|
||||
|
||||
/* compute message length */
|
||||
for(line=tempcomment,total=t=0;t<lines;t++,line+=linelen) {
|
||||
for(i=linelen;(i>=0)&&(line[i]==' ');i--) line[i]=0;
|
||||
for(i=0;i<linelen;i++) if (!line[i]) break;
|
||||
total+=1+i;
|
||||
}
|
||||
|
||||
if(total>lines) {
|
||||
if(!(of.comment=(CHAR*)_mm_malloc(total+1))) {
|
||||
free(storage);
|
||||
free(tempcomment);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* convert message */
|
||||
for(line=tempcomment,t=0;t<lines;t++,line+=linelen) {
|
||||
for(i=0;i<linelen;i++) if(!(storage[i]=line[i])) break;
|
||||
storage[i]=0; /* if (i==linelen) */
|
||||
strcat(of.comment,storage);strcat(of.comment,"\r");
|
||||
}
|
||||
free(storage);
|
||||
free(tempcomment);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL AllocPositions(int total)
|
||||
{
|
||||
if(!total) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if(!(of.positions=_mm_calloc(total,sizeof(UWORD)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL AllocPatterns(void)
|
||||
{
|
||||
int s,t,tracks = 0;
|
||||
|
||||
if((!of.numpat)||(!of.numchn)) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
/* Allocate track sequencing array */
|
||||
if(!(of.patterns=(UWORD*)_mm_calloc((ULONG)(of.numpat+1)*of.numchn,sizeof(UWORD)))) return 0;
|
||||
if(!(of.pattrows=(UWORD*)_mm_calloc(of.numpat+1,sizeof(UWORD)))) return 0;
|
||||
|
||||
for(t=0;t<=of.numpat;t++) {
|
||||
of.pattrows[t]=64;
|
||||
for(s=0;s<of.numchn;s++)
|
||||
of.patterns[(t*of.numchn)+s]=tracks++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL AllocTracks(void)
|
||||
{
|
||||
if(!of.numtrk) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if(!(of.tracks=(UBYTE **)_mm_calloc(of.numtrk,sizeof(UBYTE *)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL AllocInstruments(void)
|
||||
{
|
||||
int t,n;
|
||||
|
||||
if(!of.numins) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if(!(of.instruments=(INSTRUMENT*)_mm_calloc(of.numins,sizeof(INSTRUMENT))))
|
||||
return 0;
|
||||
|
||||
for(t=0;t<of.numins;t++) {
|
||||
for(n=0;n<INSTNOTES;n++) {
|
||||
/* Init note / sample lookup table */
|
||||
of.instruments[t].samplenote[n] = n;
|
||||
of.instruments[t].samplenumber[n] = t;
|
||||
}
|
||||
of.instruments[t].globvol = 64;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL AllocSamples(void)
|
||||
{
|
||||
UWORD u;
|
||||
|
||||
if(!of.numsmp) {
|
||||
_mm_errno=MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if(!(of.samples=(SAMPLE*)_mm_calloc(of.numsmp,sizeof(SAMPLE)))) return 0;
|
||||
|
||||
for(u=0;u<of.numsmp;u++) {
|
||||
of.samples[u].panning = 128; /* center */
|
||||
of.samples[u].handle = -1;
|
||||
of.samples[u].globvol = 64;
|
||||
of.samples[u].volume = 64;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL ML_LoadSamples(void)
|
||||
{
|
||||
SAMPLE *s;
|
||||
int u;
|
||||
|
||||
for(u=of.numsmp,s=of.samples;u;u--,s++)
|
||||
if(s->length) SL_RegisterSample(s,MD_MUSIC,modreader);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Creates a CSTR out of a character buffer of 'len' bytes, but strips any
|
||||
terminating non-printing characters like 0, spaces etc. */
|
||||
CHAR *DupStr(CHAR* s,UWORD len,BOOL strict)
|
||||
{
|
||||
UWORD t;
|
||||
CHAR *d=NULL;
|
||||
|
||||
/* Scan for last printing char in buffer [includes high ascii up to 254] */
|
||||
while(len) {
|
||||
if(s[len-1]>0x20) break;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Scan forward for possible NULL character */
|
||||
if(strict) {
|
||||
for(t=0;t<len;t++) if (!s[t]) break;
|
||||
if (t<len) len=t;
|
||||
}
|
||||
|
||||
/* When the buffer wasn't completely empty, allocate a cstring and copy the
|
||||
buffer into that string, except for any control-chars */
|
||||
if((d=(CHAR*)_mm_malloc(sizeof(CHAR)*(len+1)))) {
|
||||
for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t];
|
||||
d[len]=0;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static void ML_XFreeSample(SAMPLE *s)
|
||||
{
|
||||
if(s->handle>=0)
|
||||
MD_SampleUnload(s->handle);
|
||||
if(s->samplename) free(s->samplename);
|
||||
}
|
||||
|
||||
static void ML_XFreeInstrument(INSTRUMENT *i)
|
||||
{
|
||||
if(i->insname) free(i->insname);
|
||||
}
|
||||
|
||||
static void ML_FreeEx(MODULE *mf)
|
||||
{
|
||||
UWORD t;
|
||||
|
||||
if(mf->songname) free(mf->songname);
|
||||
if(mf->comment) free(mf->comment);
|
||||
|
||||
if(mf->modtype) free(mf->modtype);
|
||||
if(mf->positions) free(mf->positions);
|
||||
if(mf->patterns) free(mf->patterns);
|
||||
if(mf->pattrows) free(mf->pattrows);
|
||||
|
||||
if(mf->tracks) {
|
||||
for(t=0;t<mf->numtrk;t++)
|
||||
if(mf->tracks[t]) free(mf->tracks[t]);
|
||||
free(mf->tracks);
|
||||
}
|
||||
if(mf->instruments) {
|
||||
for(t=0;t<mf->numins;t++)
|
||||
ML_XFreeInstrument(&mf->instruments[t]);
|
||||
free(mf->instruments);
|
||||
}
|
||||
if(mf->samples) {
|
||||
for(t=0;t<mf->numsmp;t++)
|
||||
if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]);
|
||||
free(mf->samples);
|
||||
}
|
||||
memset(mf,0,sizeof(MODULE));
|
||||
if(mf!=&of) free(mf);
|
||||
}
|
||||
|
||||
static MODULE *ML_AllocUniMod(void)
|
||||
{
|
||||
MODULE *mf;
|
||||
|
||||
return (mf=_mm_malloc(sizeof(MODULE)));
|
||||
}
|
||||
|
||||
void Player_Free_internal(MODULE *mf)
|
||||
{
|
||||
if(mf) {
|
||||
Player_Exit_internal(mf);
|
||||
ML_FreeEx(mf);
|
||||
}
|
||||
}
|
||||
|
||||
MIKMODAPI void Player_Free(MODULE *mf)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
Player_Free_internal(mf);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
static CHAR* Player_LoadTitle_internal(MREADER *reader)
|
||||
{
|
||||
MLOADER *l;
|
||||
|
||||
modreader=reader;
|
||||
_mm_errno = 0;
|
||||
_mm_critical = 0;
|
||||
_mm_iobase_setcur(modreader);
|
||||
|
||||
/* Try to find a loader that recognizes the module */
|
||||
for(l=firstloader;l;l=l->next) {
|
||||
_mm_rewind(modreader);
|
||||
if(l->Test()) break;
|
||||
}
|
||||
|
||||
if(!l) {
|
||||
_mm_errno = MMERR_NOT_A_MODULE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return l->LoadTitle();
|
||||
}
|
||||
|
||||
MIKMODAPI CHAR* Player_LoadTitleFP(FILE *fp)
|
||||
{
|
||||
CHAR* result=NULL;
|
||||
MREADER* reader;
|
||||
|
||||
if(fp && (reader=_mm_new_file_reader(fp))) {
|
||||
MUTEX_LOCK(lists);
|
||||
result=Player_LoadTitle_internal(reader);
|
||||
MUTEX_UNLOCK(lists);
|
||||
_mm_delete_file_reader(reader);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI CHAR* Player_LoadTitle(CHAR* filename)
|
||||
{
|
||||
CHAR* result=NULL;
|
||||
FILE* fp;
|
||||
MREADER* reader;
|
||||
|
||||
if((fp=_mm_fopen(filename,"rb"))) {
|
||||
if((reader=_mm_new_file_reader(fp))) {
|
||||
MUTEX_LOCK(lists);
|
||||
result=Player_LoadTitle_internal(reader);
|
||||
MUTEX_UNLOCK(lists);
|
||||
_mm_delete_file_reader(reader);
|
||||
}
|
||||
_mm_fclose(fp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Loads a module given an reader */
|
||||
MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,BOOL curious)
|
||||
{
|
||||
int t;
|
||||
MLOADER *l;
|
||||
BOOL ok;
|
||||
MODULE *mf;
|
||||
|
||||
modreader = reader;
|
||||
_mm_errno = 0;
|
||||
_mm_critical = 0;
|
||||
_mm_iobase_setcur(modreader);
|
||||
|
||||
/* Try to find a loader that recognizes the module */
|
||||
for(l=firstloader;l;l=l->next) {
|
||||
_mm_rewind(modreader);
|
||||
if(l->Test()) break;
|
||||
}
|
||||
|
||||
if(!l) {
|
||||
_mm_errno = MMERR_NOT_A_MODULE;
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
_mm_rewind(modreader);_mm_iobase_revert();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init unitrk routines */
|
||||
if(!UniInit()) {
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
_mm_rewind(modreader);_mm_iobase_revert();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init the module structure with vanilla settings */
|
||||
memset(&of,0,sizeof(MODULE));
|
||||
of.bpmlimit = 33;
|
||||
of.initvolume = 128;
|
||||
for (t = 0; t < UF_MAXCHAN; t++) of.chanvol[t] = 64;
|
||||
for (t = 0; t < UF_MAXCHAN; t++)
|
||||
of.panning[t] = ((t + 1) & 2) ? PAN_RIGHT : PAN_LEFT;
|
||||
|
||||
/* init module loader and load the header / patterns */
|
||||
if (!l->Init || l->Init()) {
|
||||
_mm_rewind(modreader);
|
||||
ok = l->Load(curious);
|
||||
/* propagate inflags=flags for in-module samples */
|
||||
for (t = 0; t < of.numsmp; t++)
|
||||
if (of.samples[t].inflags == 0)
|
||||
of.samples[t].inflags = of.samples[t].flags;
|
||||
} else
|
||||
ok = 0;
|
||||
|
||||
/* free loader and unitrk allocations */
|
||||
if (l->Cleanup) l->Cleanup();
|
||||
UniCleanup();
|
||||
|
||||
if(!ok) {
|
||||
ML_FreeEx(&of);
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
_mm_rewind(modreader);_mm_iobase_revert();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!ML_LoadSamples()) {
|
||||
ML_FreeEx(&of);
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
_mm_rewind(modreader);_mm_iobase_revert();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(mf=ML_AllocUniMod())) {
|
||||
ML_FreeEx(&of);
|
||||
_mm_rewind(modreader);_mm_iobase_revert();
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the module doesn't have any specific panning, create a
|
||||
MOD-like panning, with the channels half-separated. */
|
||||
if (!(of.flags & UF_PANNING))
|
||||
for (t = 0; t < of.numchn; t++)
|
||||
of.panning[t] = ((t + 1) & 2) ? PAN_HALFRIGHT : PAN_HALFLEFT;
|
||||
|
||||
/* Copy the static MODULE contents into the dynamic MODULE struct. */
|
||||
memcpy(mf,&of,sizeof(MODULE));
|
||||
|
||||
if(maxchan>0) {
|
||||
if(!(mf->flags&UF_NNA)&&(mf->numchn<maxchan))
|
||||
maxchan = mf->numchn;
|
||||
else
|
||||
if((mf->numvoices)&&(mf->numvoices<maxchan))
|
||||
maxchan = mf->numvoices;
|
||||
|
||||
if(maxchan<mf->numchn) mf->flags |= UF_NNA;
|
||||
|
||||
if(MikMod_SetNumVoices_internal(maxchan,-1)) {
|
||||
_mm_iobase_revert();
|
||||
Player_Free(mf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(SL_LoadSamples()) {
|
||||
_mm_iobase_revert();
|
||||
Player_Free_internal(mf);
|
||||
return NULL;
|
||||
}
|
||||
if(Player_Init(mf)) {
|
||||
_mm_iobase_revert();
|
||||
Player_Free_internal(mf);
|
||||
mf=NULL;
|
||||
}
|
||||
_mm_iobase_revert();
|
||||
return mf;
|
||||
}
|
||||
|
||||
MIKMODAPI MODULE* Player_LoadGeneric(MREADER *reader,int maxchan,BOOL curious)
|
||||
{
|
||||
MODULE* result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
MUTEX_LOCK(lists);
|
||||
result=Player_LoadGeneric_internal(reader,maxchan,curious);
|
||||
MUTEX_UNLOCK(lists);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Loads a module given a file pointer.
|
||||
File is loaded from the current file seek position. */
|
||||
MIKMODAPI MODULE* Player_LoadFP(FILE* fp,int maxchan,BOOL curious)
|
||||
{
|
||||
MODULE* result=NULL;
|
||||
struct MREADER* reader=_mm_new_file_reader (fp);
|
||||
|
||||
if (reader) {
|
||||
result=Player_LoadGeneric(reader,maxchan,curious);
|
||||
_mm_delete_file_reader(reader);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Open a module via its filename. The loader will initialize the specified
|
||||
song-player 'player'. */
|
||||
MIKMODAPI MODULE* Player_Load(CHAR* filename,int maxchan,BOOL curious)
|
||||
{
|
||||
FILE *fp;
|
||||
MODULE *mf=NULL;
|
||||
|
||||
if((fp=_mm_fopen(filename,"rb"))) {
|
||||
mf=Player_LoadFP(fp,maxchan,curious);
|
||||
_mm_fclose(fp);
|
||||
}
|
||||
return mf;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
65
project/jni/mikmod/playercode/mlreg.c
Normal file
65
project/jni/mikmod/playercode/mlreg.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mlreg.c,v 1.2 2004/01/28 00:49:56 raph Exp $
|
||||
|
||||
Routine for registering all loaders in libmikmod for the current platform.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
void MikMod_RegisterAllLoaders_internal(void)
|
||||
{
|
||||
_mm_registerloader(&load_669);
|
||||
_mm_registerloader(&load_amf);
|
||||
_mm_registerloader(&load_asy);
|
||||
_mm_registerloader(&load_dsm);
|
||||
_mm_registerloader(&load_far);
|
||||
_mm_registerloader(&load_gdm);
|
||||
_mm_registerloader(&load_it);
|
||||
_mm_registerloader(&load_imf);
|
||||
_mm_registerloader(&load_mod);
|
||||
_mm_registerloader(&load_med);
|
||||
_mm_registerloader(&load_mtm);
|
||||
_mm_registerloader(&load_okt);
|
||||
_mm_registerloader(&load_s3m);
|
||||
_mm_registerloader(&load_stm);
|
||||
_mm_registerloader(&load_stx);
|
||||
_mm_registerloader(&load_ult);
|
||||
_mm_registerloader(&load_uni);
|
||||
_mm_registerloader(&load_xm);
|
||||
|
||||
_mm_registerloader(&load_m15);
|
||||
}
|
||||
|
||||
void MikMod_RegisterAllLoaders(void)
|
||||
{
|
||||
MUTEX_LOCK(lists);
|
||||
MikMod_RegisterAllLoaders_internal();
|
||||
MUTEX_UNLOCK(lists);
|
||||
}
|
||||
/* ex:set ts=4: */
|
||||
336
project/jni/mikmod/playercode/mlutil.c
Normal file
336
project/jni/mikmod/playercode/mlutil.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mlutil.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Utility functions for the module loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
/*========== Shared tracker identifiers */
|
||||
|
||||
CHAR *STM_Signatures[STM_NTRACKERS] = {
|
||||
"!Scream!",
|
||||
"BMOD2STM",
|
||||
"WUZAMOD!"
|
||||
};
|
||||
|
||||
CHAR *STM_Version[STM_NTRACKERS] = {
|
||||
"Screamtracker 2",
|
||||
"Converted by MOD2STM (STM format)",
|
||||
"Wuzamod (STM format)"
|
||||
};
|
||||
|
||||
/*========== Shared loader variables */
|
||||
|
||||
SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */
|
||||
UBYTE* poslookup=NULL; /* lookup table for pattern jumps after blank
|
||||
pattern removal */
|
||||
UBYTE poslookupcnt;
|
||||
UWORD* origpositions=NULL;
|
||||
|
||||
BOOL filters; /* resonant filters in use */
|
||||
UBYTE activemacro; /* active midi macro number for Sxx,xx<80h */
|
||||
UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */
|
||||
FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */
|
||||
|
||||
/*========== Linear periods stuff */
|
||||
|
||||
int* noteindex=NULL; /* remap value for linear period modules */
|
||||
static int noteindexcount=0;
|
||||
|
||||
int *AllocLinear(void)
|
||||
{
|
||||
if(of.numsmp>noteindexcount) {
|
||||
noteindexcount=of.numsmp;
|
||||
noteindex=realloc(noteindex,noteindexcount*sizeof(int));
|
||||
}
|
||||
return noteindex;
|
||||
}
|
||||
|
||||
void FreeLinear(void)
|
||||
{
|
||||
if(noteindex) {
|
||||
free(noteindex);
|
||||
noteindex=NULL;
|
||||
}
|
||||
noteindexcount=0;
|
||||
}
|
||||
|
||||
int speed_to_finetune(ULONG speed,int sample)
|
||||
{
|
||||
int ctmp=0,tmp,note=1,finetune=0;
|
||||
|
||||
speed>>=1;
|
||||
while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) {
|
||||
ctmp=tmp;
|
||||
note++;
|
||||
}
|
||||
|
||||
if(tmp!=speed) {
|
||||
if((tmp-speed)<(speed-ctmp))
|
||||
while(tmp>speed)
|
||||
tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune));
|
||||
else {
|
||||
note--;
|
||||
while(ctmp<speed)
|
||||
ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++finetune));
|
||||
}
|
||||
}
|
||||
|
||||
noteindex[sample]=note-4*OCTAVE;
|
||||
return finetune;
|
||||
}
|
||||
|
||||
/*========== Order stuff */
|
||||
|
||||
/* handles S3M and IT orders */
|
||||
void S3MIT_CreateOrders(BOOL curious)
|
||||
{
|
||||
int t;
|
||||
|
||||
of.numpos = 0;
|
||||
memset(of.positions,0,poslookupcnt*sizeof(UWORD));
|
||||
memset(poslookup,-1,256);
|
||||
for(t=0;t<poslookupcnt;t++) {
|
||||
int order=origpositions[t];
|
||||
if(order==255) order=LAST_PATTERN;
|
||||
of.positions[of.numpos]=order;
|
||||
poslookup[t]=of.numpos; /* bug fix for freaky S3Ms / ITs */
|
||||
if(origpositions[t]<254) of.numpos++;
|
||||
else
|
||||
/* end of song special order */
|
||||
if((order==LAST_PATTERN)&&(!(curious--))) break;
|
||||
}
|
||||
}
|
||||
|
||||
/*========== Effect stuff */
|
||||
|
||||
/* handles S3M and IT effects */
|
||||
void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags)
|
||||
{
|
||||
UBYTE hi,lo;
|
||||
|
||||
lo=inf&0xf;
|
||||
hi=inf>>4;
|
||||
|
||||
/* process S3M / IT specific command structure */
|
||||
|
||||
if(cmd!=255) {
|
||||
switch(cmd) {
|
||||
case 1: /* Axx set speed to xx */
|
||||
UniEffect(UNI_S3MEFFECTA,inf);
|
||||
break;
|
||||
case 2: /* Bxx position jump */
|
||||
if (inf<poslookupcnt) {
|
||||
/* switch to curious mode if necessary, for example
|
||||
sympex.it, deep joy.it */
|
||||
if(((SBYTE)poslookup[inf]<0)&&(origpositions[inf]!=255))
|
||||
S3MIT_CreateOrders(1);
|
||||
|
||||
if(!((SBYTE)poslookup[inf]<0))
|
||||
UniPTEffect(0xb,poslookup[inf]);
|
||||
}
|
||||
break;
|
||||
case 3: /* Cxx patternbreak to row xx */
|
||||
if ((flags & S3MIT_OLDSTYLE) && !(flags & S3MIT_IT))
|
||||
UniPTEffect(0xd,(inf>>4)*10+(inf&0xf));
|
||||
else
|
||||
UniPTEffect(0xd,inf);
|
||||
break;
|
||||
case 4: /* Dxy volumeslide */
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 5: /* Exy toneslide down */
|
||||
UniEffect(UNI_S3MEFFECTE,inf);
|
||||
break;
|
||||
case 6: /* Fxy toneslide up */
|
||||
UniEffect(UNI_S3MEFFECTF,inf);
|
||||
break;
|
||||
case 7: /* Gxx Tone portamento, speed xx */
|
||||
if (flags & S3MIT_OLDSTYLE)
|
||||
UniPTEffect(0x3,inf);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTG,inf);
|
||||
break;
|
||||
case 8: /* Hxy vibrato */
|
||||
if (flags & S3MIT_OLDSTYLE)
|
||||
UniPTEffect(0x4,inf);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTH,inf);
|
||||
break;
|
||||
case 9: /* Ixy tremor, ontime x, offtime y */
|
||||
if (flags & S3MIT_OLDSTYLE)
|
||||
UniEffect(UNI_S3MEFFECTI,inf);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTI,inf);
|
||||
break;
|
||||
case 0xa: /* Jxy arpeggio */
|
||||
UniPTEffect(0x0,inf);
|
||||
break;
|
||||
case 0xb: /* Kxy Dual command H00 & Dxy */
|
||||
if (flags & S3MIT_OLDSTYLE)
|
||||
UniPTEffect(0x4,0);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTH,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0xc: /* Lxy Dual command G00 & Dxy */
|
||||
if (flags & S3MIT_OLDSTYLE)
|
||||
UniPTEffect(0x3,0);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTG,0);
|
||||
UniEffect(UNI_S3MEFFECTD,inf);
|
||||
break;
|
||||
case 0xd: /* Mxx Set Channel Volume */
|
||||
UniEffect(UNI_ITEFFECTM,inf);
|
||||
break;
|
||||
case 0xe: /* Nxy Slide Channel Volume */
|
||||
UniEffect(UNI_ITEFFECTN,inf);
|
||||
break;
|
||||
case 0xf: /* Oxx set sampleoffset xx00h */
|
||||
UniPTEffect(0x9,inf);
|
||||
break;
|
||||
case 0x10: /* Pxy Slide Panning Commands */
|
||||
UniEffect(UNI_ITEFFECTP,inf);
|
||||
break;
|
||||
case 0x11: /* Qxy Retrig (+volumeslide) */
|
||||
UniWriteByte(UNI_S3MEFFECTQ);
|
||||
if(inf && !lo && !(flags & S3MIT_OLDSTYLE))
|
||||
UniWriteByte(1);
|
||||
else
|
||||
UniWriteByte(inf);
|
||||
break;
|
||||
case 0x12: /* Rxy tremolo speed x, depth y */
|
||||
UniEffect(UNI_S3MEFFECTR,inf);
|
||||
break;
|
||||
case 0x13: /* Sxx special commands */
|
||||
if (inf>=0xf0) {
|
||||
/* change resonant filter settings if necessary */
|
||||
if((filters)&&((inf&0xf)!=activemacro)) {
|
||||
activemacro=inf&0xf;
|
||||
for(inf=0;inf<0x80;inf++)
|
||||
filtersettings[inf].filter=filtermacros[activemacro];
|
||||
}
|
||||
} else {
|
||||
/* Scream Tracker does not have samples larger than
|
||||
64 Kb, thus doesn't need the SAx effect */
|
||||
if ((flags & S3MIT_SCREAM) && ((inf & 0xf0) == 0xa0))
|
||||
break;
|
||||
|
||||
UniEffect(UNI_ITEFFECTS0,inf);
|
||||
}
|
||||
break;
|
||||
case 0x14: /* Txx tempo */
|
||||
if(inf>=0x20)
|
||||
UniEffect(UNI_S3MEFFECTT,inf);
|
||||
else {
|
||||
if(!(flags & S3MIT_OLDSTYLE))
|
||||
/* IT Tempo slide */
|
||||
UniEffect(UNI_ITEFFECTT,inf);
|
||||
}
|
||||
break;
|
||||
case 0x15: /* Uxy Fine Vibrato speed x, depth y */
|
||||
if(flags & S3MIT_OLDSTYLE)
|
||||
UniEffect(UNI_S3MEFFECTU,inf);
|
||||
else
|
||||
UniEffect(UNI_ITEFFECTU,inf);
|
||||
break;
|
||||
case 0x16: /* Vxx Set Global Volume */
|
||||
UniEffect(UNI_XMEFFECTG,inf);
|
||||
break;
|
||||
case 0x17: /* Wxy Global Volume Slide */
|
||||
UniEffect(UNI_ITEFFECTW,inf);
|
||||
break;
|
||||
case 0x18: /* Xxx amiga command 8xx */
|
||||
if(flags & S3MIT_OLDSTYLE) {
|
||||
if(inf>128)
|
||||
UniEffect(UNI_ITEFFECTS0,0x91); /* surround */
|
||||
else
|
||||
UniPTEffect(0x8,(inf==128)?255:(inf<<1));
|
||||
} else
|
||||
UniPTEffect(0x8,inf);
|
||||
break;
|
||||
case 0x19: /* Yxy Panbrello speed x, depth y */
|
||||
UniEffect(UNI_ITEFFECTY,inf);
|
||||
break;
|
||||
case 0x1a: /* Zxx midi/resonant filters */
|
||||
if(filtersettings[inf].filter) {
|
||||
UniWriteByte(UNI_ITEFFECTZ);
|
||||
UniWriteByte(filtersettings[inf].filter);
|
||||
UniWriteByte(filtersettings[inf].inf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*========== Unitrk stuff */
|
||||
|
||||
/* Generic effect writing routine */
|
||||
void UniEffect(UWORD eff,UWORD dat)
|
||||
{
|
||||
if((!eff)||(eff>=UNI_LAST)) return;
|
||||
|
||||
UniWriteByte(eff);
|
||||
if(unioperands[eff]==2)
|
||||
UniWriteWord(dat);
|
||||
else
|
||||
UniWriteByte(dat);
|
||||
}
|
||||
|
||||
/* Appends UNI_PTEFFECTX opcode to the unitrk stream. */
|
||||
void UniPTEffect(UBYTE eff, UBYTE dat)
|
||||
{
|
||||
#ifdef MIKMOD_DEBUG
|
||||
if (eff>=0x10)
|
||||
fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff);
|
||||
else
|
||||
#endif
|
||||
if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat);
|
||||
}
|
||||
|
||||
/* Appends UNI_VOLEFFECT + effect/dat to unistream. */
|
||||
void UniVolEffect(UWORD eff,UBYTE dat)
|
||||
{
|
||||
if((eff)||(dat)) { /* don't write empty effect */
|
||||
UniWriteByte(UNI_VOLEFFECTS);
|
||||
UniWriteByte(eff);UniWriteByte(dat);
|
||||
}
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
3391
project/jni/mikmod/playercode/mplayer.c
Normal file
3391
project/jni/mikmod/playercode/mplayer.c
Normal file
File diff suppressed because it is too large
Load Diff
303
project/jni/mikmod/playercode/munitrk.c
Normal file
303
project/jni/mikmod/playercode/munitrk.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: munitrk.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
All routines dealing with the manipulation of UNITRK streams
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Unibuffer chunk size */
|
||||
#define BUFPAGE 128
|
||||
|
||||
UWORD unioperands[UNI_LAST]={
|
||||
0, /* not used */
|
||||
1, /* UNI_NOTE */
|
||||
1, /* UNI_INSTRUMENT */
|
||||
1, /* UNI_PTEFFECT0 */
|
||||
1, /* UNI_PTEFFECT1 */
|
||||
1, /* UNI_PTEFFECT2 */
|
||||
1, /* UNI_PTEFFECT3 */
|
||||
1, /* UNI_PTEFFECT4 */
|
||||
1, /* UNI_PTEFFECT5 */
|
||||
1, /* UNI_PTEFFECT6 */
|
||||
1, /* UNI_PTEFFECT7 */
|
||||
1, /* UNI_PTEFFECT8 */
|
||||
1, /* UNI_PTEFFECT9 */
|
||||
1, /* UNI_PTEFFECTA */
|
||||
1, /* UNI_PTEFFECTB */
|
||||
1, /* UNI_PTEFFECTC */
|
||||
1, /* UNI_PTEFFECTD */
|
||||
1, /* UNI_PTEFFECTE */
|
||||
1, /* UNI_PTEFFECTF */
|
||||
1, /* UNI_S3MEFFECTA */
|
||||
1, /* UNI_S3MEFFECTD */
|
||||
1, /* UNI_S3MEFFECTE */
|
||||
1, /* UNI_S3MEFFECTF */
|
||||
1, /* UNI_S3MEFFECTI */
|
||||
1, /* UNI_S3MEFFECTQ */
|
||||
1, /* UNI_S3MEFFECTR */
|
||||
1, /* UNI_S3MEFFECTT */
|
||||
1, /* UNI_S3MEFFECTU */
|
||||
0, /* UNI_KEYOFF */
|
||||
1, /* UNI_KEYFADE */
|
||||
2, /* UNI_VOLEFFECTS */
|
||||
1, /* UNI_XMEFFECT4 */
|
||||
1, /* UNI_XMEFFECT6 */
|
||||
1, /* UNI_XMEFFECTA */
|
||||
1, /* UNI_XMEFFECTE1 */
|
||||
1, /* UNI_XMEFFECTE2 */
|
||||
1, /* UNI_XMEFFECTEA */
|
||||
1, /* UNI_XMEFFECTEB */
|
||||
1, /* UNI_XMEFFECTG */
|
||||
1, /* UNI_XMEFFECTH */
|
||||
1, /* UNI_XMEFFECTL */
|
||||
1, /* UNI_XMEFFECTP */
|
||||
1, /* UNI_XMEFFECTX1 */
|
||||
1, /* UNI_XMEFFECTX2 */
|
||||
1, /* UNI_ITEFFECTG */
|
||||
1, /* UNI_ITEFFECTH */
|
||||
1, /* UNI_ITEFFECTI */
|
||||
1, /* UNI_ITEFFECTM */
|
||||
1, /* UNI_ITEFFECTN */
|
||||
1, /* UNI_ITEFFECTP */
|
||||
1, /* UNI_ITEFFECTT */
|
||||
1, /* UNI_ITEFFECTU */
|
||||
1, /* UNI_ITEFFECTW */
|
||||
1, /* UNI_ITEFFECTY */
|
||||
2, /* UNI_ITEFFECTZ */
|
||||
1, /* UNI_ITEFFECTS0 */
|
||||
2, /* UNI_ULTEFFECT9 */
|
||||
2, /* UNI_MEDSPEED */
|
||||
0, /* UNI_MEDEFFECTF1 */
|
||||
0, /* UNI_MEDEFFECTF2 */
|
||||
0, /* UNI_MEDEFFECTF3 */
|
||||
2, /* UNI_OKTARP */
|
||||
};
|
||||
|
||||
/* Sparse description of the internal module format
|
||||
------------------------------------------------
|
||||
|
||||
A UNITRK stream is an array of bytes representing a single track of a pattern.
|
||||
It's made up of 'repeat/length' bytes, opcodes and operands (sort of a assembly
|
||||
language):
|
||||
|
||||
rrrlllll
|
||||
[REP/LEN][OPCODE][OPERAND][OPCODE][OPERAND] [REP/LEN][OPCODE][OPERAND]..
|
||||
^ ^ ^
|
||||
|-------ROWS 0 - 0+REP of a track---------| |-------ROWS xx - xx+REP of a track...
|
||||
|
||||
The rep/len byte contains the number of bytes in the current row, _including_
|
||||
the length byte itself (So the LENGTH byte of row 0 in the previous example
|
||||
would have a value of 5). This makes it easy to search through a stream for a
|
||||
particular row. A track is concluded by a 0-value length byte.
|
||||
|
||||
The upper 3 bits of the rep/len byte contain the number of times -1 this row
|
||||
is repeated for this track. (so a value of 7 means this row is repeated 8 times)
|
||||
|
||||
Opcodes can range from 1 to 255 but currently only opcodes 1 to 62 are being
|
||||
used. Each opcode can have a different number of operands. You can find the
|
||||
number of operands to a particular opcode by using the opcode as an index into
|
||||
the 'unioperands' table.
|
||||
|
||||
*/
|
||||
|
||||
/*========== Reading routines */
|
||||
|
||||
static UBYTE *rowstart; /* startadress of a row */
|
||||
static UBYTE *rowend; /* endaddress of a row (exclusive) */
|
||||
static UBYTE *rowpc; /* current unimod(tm) programcounter */
|
||||
|
||||
static UBYTE lastbyte; /* for UniSkipOpcode() */
|
||||
|
||||
void UniSetRow(UBYTE* t)
|
||||
{
|
||||
rowstart = t;
|
||||
rowpc = rowstart;
|
||||
rowend = t?rowstart+(*(rowpc++)&0x1f):t;
|
||||
}
|
||||
|
||||
UBYTE UniGetByte(void)
|
||||
{
|
||||
return lastbyte = (rowpc<rowend)?*(rowpc++):0;
|
||||
}
|
||||
|
||||
UWORD UniGetWord(void)
|
||||
{
|
||||
return ((UWORD)UniGetByte()<<8)|UniGetByte();
|
||||
}
|
||||
|
||||
void UniSkipOpcode(void)
|
||||
{
|
||||
if (lastbyte < UNI_LAST) {
|
||||
UWORD t = unioperands[lastbyte];
|
||||
|
||||
while (t--)
|
||||
UniGetByte();
|
||||
}
|
||||
}
|
||||
|
||||
/* Finds the address of row number 'row' in the UniMod(tm) stream 't' returns
|
||||
NULL if the row can't be found. */
|
||||
UBYTE *UniFindRow(UBYTE* t,UWORD row)
|
||||
{
|
||||
UBYTE c,l;
|
||||
|
||||
if(t)
|
||||
while(1) {
|
||||
c = *t; /* get rep/len byte */
|
||||
if(!c) return NULL; /* zero ? -> end of track.. */
|
||||
l = (c>>5)+1; /* extract repeat value */
|
||||
if(l>row) break; /* reached wanted row? -> return pointer */
|
||||
row -= l; /* haven't reached row yet.. update row */
|
||||
t += c&0x1f; /* point t to the next row */
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/*========== Writing routines */
|
||||
|
||||
static UBYTE *unibuf; /* pointer to the temporary unitrk buffer */
|
||||
static UWORD unimax; /* buffer size */
|
||||
|
||||
static UWORD unipc; /* buffer cursor */
|
||||
static UWORD unitt; /* current row index */
|
||||
static UWORD lastp; /* previous row index */
|
||||
|
||||
/* Resets index-pointers to create a new track. */
|
||||
void UniReset(void)
|
||||
{
|
||||
unitt = 0; /* reset index to rep/len byte */
|
||||
unipc = 1; /* first opcode will be written to index 1 */
|
||||
lastp = 0; /* no previous row yet */
|
||||
unibuf[0] = 0; /* clear rep/len byte */
|
||||
}
|
||||
|
||||
/* Expands the buffer */
|
||||
static BOOL UniExpand(int wanted)
|
||||
{
|
||||
if ((unipc+wanted)>=unimax) {
|
||||
UBYTE *newbuf;
|
||||
|
||||
/* Expand the buffer by BUFPAGE bytes */
|
||||
newbuf=(UBYTE*)realloc(unibuf,(unimax+BUFPAGE)*sizeof(UBYTE));
|
||||
|
||||
/* Check if realloc succeeded */
|
||||
if(newbuf) {
|
||||
unibuf = newbuf;
|
||||
unimax+=BUFPAGE;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Appends one byte of data to the current row of a track. */
|
||||
void UniWriteByte(UBYTE data)
|
||||
{
|
||||
if (UniExpand(1))
|
||||
/* write byte to current position and update */
|
||||
unibuf[unipc++]=data;
|
||||
}
|
||||
|
||||
void UniWriteWord(UWORD data)
|
||||
{
|
||||
if (UniExpand(2)) {
|
||||
unibuf[unipc++]=data>>8;
|
||||
unibuf[unipc++]=data&0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL MyCmp(UBYTE* a,UBYTE* b,UWORD l)
|
||||
{
|
||||
UWORD t;
|
||||
|
||||
for(t=0;t<l;t++)
|
||||
if(*(a++)!=*(b++)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Closes the current row of a unitrk stream (updates the rep/len byte) and sets
|
||||
pointers to start a new row. */
|
||||
void UniNewline(void)
|
||||
{
|
||||
UWORD n,l,len;
|
||||
|
||||
n = (unibuf[lastp]>>5)+1; /* repeat of previous row */
|
||||
l = (unibuf[lastp]&0x1f); /* length of previous row */
|
||||
|
||||
len = unipc-unitt; /* length of current row */
|
||||
|
||||
/* Now, check if the previous and the current row are identical.. when they
|
||||
are, just increase the repeat field of the previous row */
|
||||
if(n<8 && len==l && MyCmp(&unibuf[lastp+1],&unibuf[unitt+1],len-1)) {
|
||||
unibuf[lastp]+=0x20;
|
||||
unipc = unitt+1;
|
||||
} else {
|
||||
if (UniExpand(unitt-unipc)) {
|
||||
/* current and previous row aren't equal... update the pointers */
|
||||
unibuf[unitt] = len;
|
||||
lastp = unitt;
|
||||
unitt = unipc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminates the current unitrk stream and returns a pointer to a copy of the
|
||||
stream. */
|
||||
UBYTE* UniDup(void)
|
||||
{
|
||||
UBYTE *d;
|
||||
|
||||
if (!UniExpand(unitt-unipc)) return NULL;
|
||||
unibuf[unitt] = 0;
|
||||
|
||||
if(!(d=(UBYTE *)_mm_malloc(unipc))) return NULL;
|
||||
memcpy(d,unibuf,unipc);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
BOOL UniInit(void)
|
||||
{
|
||||
unimax = BUFPAGE;
|
||||
|
||||
if(!(unibuf=(UBYTE*)_mm_malloc(unimax*sizeof(UBYTE)))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UniCleanup(void)
|
||||
{
|
||||
if(unibuf) free(unibuf);
|
||||
unibuf = NULL;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
198
project/jni/mikmod/playercode/mwav.c
Normal file
198
project/jni/mikmod/playercode/mwav.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: mwav.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
WAV sample loader
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
FIXME: Stereo .WAV files are not yet supported as samples.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
extern int fprintf(FILE *, const char *, ...);
|
||||
#endif
|
||||
|
||||
typedef struct WAV {
|
||||
CHAR rID[4];
|
||||
ULONG rLen;
|
||||
CHAR wID[4];
|
||||
CHAR fID[4];
|
||||
ULONG fLen;
|
||||
UWORD wFormatTag;
|
||||
UWORD nChannels;
|
||||
ULONG nSamplesPerSec;
|
||||
ULONG nAvgBytesPerSec;
|
||||
UWORD nBlockAlign;
|
||||
UWORD nFormatSpecific;
|
||||
} WAV;
|
||||
|
||||
SAMPLE* Sample_LoadGeneric_internal(MREADER* reader)
|
||||
{
|
||||
SAMPLE *si=NULL;
|
||||
WAV wh;
|
||||
BOOL have_fmt=0;
|
||||
|
||||
/* read wav header */
|
||||
_mm_read_string(wh.rID,4,reader);
|
||||
wh.rLen = _mm_read_I_ULONG(reader);
|
||||
_mm_read_string(wh.wID,4,reader);
|
||||
|
||||
/* check for correct header */
|
||||
if(_mm_eof(reader)|| memcmp(wh.rID,"RIFF",4) || memcmp(wh.wID,"WAVE",4)) {
|
||||
_mm_errno = MMERR_UNKNOWN_WAVE_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* scan all RIFF blocks until we find the sample data */
|
||||
for(;;) {
|
||||
CHAR dID[4];
|
||||
ULONG len,start;
|
||||
|
||||
_mm_read_string(dID,4,reader);
|
||||
len = _mm_read_I_ULONG(reader);
|
||||
/* truncated file ? */
|
||||
if (_mm_eof(reader)) {
|
||||
_mm_errno=MMERR_UNKNOWN_WAVE_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
start = _mm_ftell(reader);
|
||||
|
||||
/* sample format block
|
||||
should be present only once and before a data block */
|
||||
if(!memcmp(dID,"fmt ",4)) {
|
||||
wh.wFormatTag = _mm_read_I_UWORD(reader);
|
||||
wh.nChannels = _mm_read_I_UWORD(reader);
|
||||
wh.nSamplesPerSec = _mm_read_I_ULONG(reader);
|
||||
wh.nAvgBytesPerSec = _mm_read_I_ULONG(reader);
|
||||
wh.nBlockAlign = _mm_read_I_UWORD(reader);
|
||||
wh.nFormatSpecific = _mm_read_I_UWORD(reader);
|
||||
|
||||
#ifdef MIKMOD_DEBUG
|
||||
fprintf(stderr,"\rwavloader : wFormatTag=%04x blockalign=%04x nFormatSpc=%04x\n",
|
||||
wh.wFormatTag,wh.nBlockAlign,wh.nFormatSpecific);
|
||||
#endif
|
||||
|
||||
if((have_fmt)||(wh.nChannels>1)) {
|
||||
_mm_errno=MMERR_UNKNOWN_WAVE_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
have_fmt=1;
|
||||
} else
|
||||
/* sample data block
|
||||
should be present only once and after a format block */
|
||||
if(!memcmp(dID,"data",4)) {
|
||||
if(!have_fmt) {
|
||||
_mm_errno=MMERR_UNKNOWN_WAVE_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
if(!(si=(SAMPLE*)_mm_malloc(sizeof(SAMPLE)))) return NULL;
|
||||
si->speed = wh.nSamplesPerSec/wh.nChannels;
|
||||
si->volume = 64;
|
||||
si->length = len;
|
||||
if(wh.nBlockAlign == 2) {
|
||||
si->flags = SF_16BITS | SF_SIGNED;
|
||||
si->length >>= 1;
|
||||
}
|
||||
si->inflags = si->flags;
|
||||
SL_RegisterSample(si,MD_SNDFX,reader);
|
||||
SL_LoadSamples();
|
||||
|
||||
/* skip any other remaining blocks - so in case of repeated sample
|
||||
fragments, we'll return the first anyway instead of an error */
|
||||
break;
|
||||
}
|
||||
/* onto next block */
|
||||
_mm_fseek(reader,start+len,SEEK_SET);
|
||||
if (_mm_eof(reader))
|
||||
break;
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
MIKMODAPI SAMPLE* Sample_LoadGeneric(MREADER* reader)
|
||||
{
|
||||
SAMPLE* result;
|
||||
|
||||
MUTEX_LOCK(vars);
|
||||
result=Sample_LoadGeneric_internal(reader);
|
||||
MUTEX_UNLOCK(vars);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI SAMPLE* Sample_LoadFP(FILE *fp)
|
||||
{
|
||||
SAMPLE* result=NULL;
|
||||
MREADER* reader;
|
||||
|
||||
if((reader=_mm_new_file_reader(fp))) {
|
||||
result=Sample_LoadGeneric(reader);
|
||||
_mm_delete_file_reader(reader);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MIKMODAPI SAMPLE* Sample_Load(CHAR* filename)
|
||||
{
|
||||
FILE *fp;
|
||||
SAMPLE *si=NULL;
|
||||
|
||||
if(!(md_mode & DMODE_SOFT_SNDFX)) return NULL;
|
||||
if((fp=_mm_fopen(filename,"rb"))) {
|
||||
si = Sample_LoadFP(fp);
|
||||
_mm_fclose(fp);
|
||||
}
|
||||
return si;
|
||||
}
|
||||
|
||||
MIKMODAPI void Sample_Free(SAMPLE* si)
|
||||
{
|
||||
if(si) {
|
||||
MD_SampleUnload(si->handle);
|
||||
free(si);
|
||||
}
|
||||
}
|
||||
|
||||
void Sample_Free_internal(SAMPLE *si)
|
||||
{
|
||||
MUTEX_LOCK(vars);
|
||||
Sample_Free(si);
|
||||
MUTEX_UNLOCK(vars);
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
48
project/jni/mikmod/playercode/npertab.c
Normal file
48
project/jni/mikmod/playercode/npertab.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: npertab.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
MOD format period table. Used by both the MOD and M15 (15-inst mod) Loaders.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
UWORD npertab[7 * OCTAVE] = {
|
||||
/* Octaves 6 -> 0 */
|
||||
/* C C# D D# E F F# G G# A A# B */
|
||||
0x6b0,0x650,0x5f4,0x5a0,0x54c,0x500,0x4b8,0x474,0x434,0x3f8,0x3c0,0x38a,
|
||||
0x358,0x328,0x2fa,0x2d0,0x2a6,0x280,0x25c,0x23a,0x21a,0x1fc,0x1e0,0x1c5,
|
||||
0x1ac,0x194,0x17d,0x168,0x153,0x140,0x12e,0x11d,0x10d,0x0fe,0x0f0,0x0e2,
|
||||
0x0d6,0x0ca,0x0be,0x0b4,0x0aa,0x0a0,0x097,0x08f,0x087,0x07f,0x078,0x071,
|
||||
0x06b,0x065,0x05f,0x05a,0x055,0x050,0x04b,0x047,0x043,0x03f,0x03c,0x038,
|
||||
0x035,0x032,0x02f,0x02d,0x02a,0x028,0x025,0x023,0x021,0x01f,0x01e,0x01c,
|
||||
0x01b,0x019,0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,0x00f,0x00e
|
||||
};
|
||||
|
||||
/* ex:set ts=4: */
|
||||
|
||||
519
project/jni/mikmod/playercode/sloader.c
Normal file
519
project/jni/mikmod/playercode/sloader.c
Normal file
@@ -0,0 +1,519 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: sloader.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
|
||||
|
||||
Routines for loading samples. The sample loader utilizes the routines
|
||||
provided by the "registered" sample loader.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
static int sl_rlength;
|
||||
static SWORD sl_old;
|
||||
static SWORD *sl_buffer=NULL;
|
||||
static SAMPLOAD *musiclist=NULL,*sndfxlist=NULL;
|
||||
|
||||
/* size of the loader buffer in words */
|
||||
#define SLBUFSIZE 2048
|
||||
|
||||
/* IT-Compressed status structure */
|
||||
typedef struct ITPACK {
|
||||
UWORD bits; /* current number of bits */
|
||||
UWORD bufbits; /* bits in buffer */
|
||||
SWORD last; /* last output */
|
||||
UBYTE buf; /* bit buffer */
|
||||
} ITPACK;
|
||||
|
||||
BOOL SL_Init(SAMPLOAD* s)
|
||||
{
|
||||
if(!sl_buffer)
|
||||
if(!(sl_buffer=_mm_malloc(SLBUFSIZE*sizeof(SWORD)))) return 0;
|
||||
|
||||
sl_rlength = s->length;
|
||||
if(s->infmt & SF_16BITS) sl_rlength>>=1;
|
||||
sl_old = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SL_Exit(SAMPLOAD *s)
|
||||
{
|
||||
if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR);
|
||||
if(sl_buffer) {
|
||||
free(sl_buffer);
|
||||
sl_buffer=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* unpack a 8bit IT packed sample */
|
||||
static BOOL read_itcompr8(ITPACK* status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt)
|
||||
{
|
||||
SWORD *dest=sl_buffer,*end=sl_buffer+count;
|
||||
UWORD x,y,needbits,havebits,new_count=0;
|
||||
UWORD bits = status->bits;
|
||||
UWORD bufbits = status->bufbits;
|
||||
SBYTE last = status->last;
|
||||
UBYTE buf = status->buf;
|
||||
|
||||
while (dest<end) {
|
||||
needbits=new_count?3:bits;
|
||||
x=havebits=0;
|
||||
while (needbits) {
|
||||
/* feed buffer */
|
||||
if (!bufbits) {
|
||||
if((*incnt)--)
|
||||
buf=_mm_read_UBYTE(reader);
|
||||
else
|
||||
buf=0;
|
||||
bufbits=8;
|
||||
}
|
||||
/* get as many bits as necessary */
|
||||
y = needbits<bufbits?needbits:bufbits;
|
||||
x|= (buf & ((1<<y)- 1))<<havebits;
|
||||
buf>>=y;
|
||||
bufbits-=y;
|
||||
needbits-=y;
|
||||
havebits+=y;
|
||||
}
|
||||
if (new_count) {
|
||||
new_count = 0;
|
||||
if (++x >= bits)
|
||||
x++;
|
||||
bits = x;
|
||||
continue;
|
||||
}
|
||||
if (bits<7) {
|
||||
if (x==(1<<(bits-1))) {
|
||||
new_count = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (bits<9) {
|
||||
y = (0xff >> (9-bits)) - 4;
|
||||
if ((x>y)&&(x<=y+8)) {
|
||||
if ((x-=y)>=bits)
|
||||
x++;
|
||||
bits = x;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (bits<10) {
|
||||
if (x>=0x100) {
|
||||
bits=x-0x100+1;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* error in compressed data... */
|
||||
_mm_errno=MMERR_ITPACK_INVALID_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits<8) /* extend sign */
|
||||
x = ((SBYTE)(x <<(8-bits))) >> (8-bits);
|
||||
*(dest++)= (last+=x) << 8; /* convert to 16 bit */
|
||||
}
|
||||
status->bits = bits;
|
||||
status->bufbits = bufbits;
|
||||
status->last = last;
|
||||
status->buf = buf;
|
||||
return dest-sl_buffer;
|
||||
}
|
||||
|
||||
/* unpack a 16bit IT packed sample */
|
||||
static BOOL read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt)
|
||||
{
|
||||
SWORD *dest=sl_buffer,*end=sl_buffer+count;
|
||||
SLONG x,y,needbits,havebits,new_count=0;
|
||||
UWORD bits = status->bits;
|
||||
UWORD bufbits = status->bufbits;
|
||||
SWORD last = status->last;
|
||||
UBYTE buf = status->buf;
|
||||
|
||||
while (dest<end) {
|
||||
needbits=new_count?4:bits;
|
||||
x=havebits=0;
|
||||
while (needbits) {
|
||||
/* feed buffer */
|
||||
if (!bufbits) {
|
||||
if((*incnt)--)
|
||||
buf=_mm_read_UBYTE(reader);
|
||||
else
|
||||
buf=0;
|
||||
bufbits=8;
|
||||
}
|
||||
/* get as many bits as necessary */
|
||||
y=needbits<bufbits?needbits:bufbits;
|
||||
x|=(buf &((1<<y)-1))<<havebits;
|
||||
buf>>=y;
|
||||
bufbits-=y;
|
||||
needbits-=y;
|
||||
havebits+=y;
|
||||
}
|
||||
if (new_count) {
|
||||
new_count = 0;
|
||||
if (++x >= bits)
|
||||
x++;
|
||||
bits = x;
|
||||
continue;
|
||||
}
|
||||
if (bits<7) {
|
||||
if (x==(1<<(bits-1))) {
|
||||
new_count=1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (bits<17) {
|
||||
y=(0xffff>>(17-bits))-8;
|
||||
if ((x>y)&&(x<=y+16)) {
|
||||
if ((x-=y)>=bits)
|
||||
x++;
|
||||
bits = x;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (bits<18) {
|
||||
if (x>=0x10000) {
|
||||
bits=x-0x10000+1;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* error in compressed data... */
|
||||
_mm_errno=MMERR_ITPACK_INVALID_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits<16) /* extend sign */
|
||||
x = ((SWORD)(x<<(16-bits)))>>(16-bits);
|
||||
*(dest++)=(last+=x);
|
||||
}
|
||||
status->bits = bits;
|
||||
status->bufbits = bufbits;
|
||||
status->last = last;
|
||||
status->buf = buf;
|
||||
return dest-sl_buffer;
|
||||
}
|
||||
|
||||
static BOOL SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor,ULONG length,MREADER* reader,BOOL dither)
|
||||
{
|
||||
SBYTE *bptr = (SBYTE*)buffer;
|
||||
SWORD *wptr = (SWORD*)buffer;
|
||||
int stodo,t,u;
|
||||
|
||||
int result,c_block=0; /* compression bytes until next block */
|
||||
ITPACK status;
|
||||
UWORD incnt;
|
||||
|
||||
while(length) {
|
||||
stodo=(length<SLBUFSIZE)?length:SLBUFSIZE;
|
||||
|
||||
if(infmt&SF_ITPACKED) {
|
||||
sl_rlength=0;
|
||||
if (!c_block) {
|
||||
status.bits = (infmt & SF_16BITS) ? 17 : 9;
|
||||
status.last = status.bufbits = 0;
|
||||
incnt=_mm_read_I_UWORD(reader);
|
||||
c_block = (infmt & SF_16BITS) ? 0x4000 : 0x8000;
|
||||
if(infmt&SF_DELTA) sl_old=0;
|
||||
}
|
||||
if (infmt & SF_16BITS) {
|
||||
if(!(result=read_itcompr16(&status,reader,sl_buffer,stodo,&incnt)))
|
||||
return 1;
|
||||
} else {
|
||||
if(!(result=read_itcompr8(&status,reader,sl_buffer,stodo,&incnt)))
|
||||
return 1;
|
||||
}
|
||||
if(result!=stodo) {
|
||||
_mm_errno=MMERR_ITPACK_INVALID_DATA;
|
||||
return 1;
|
||||
}
|
||||
c_block -= stodo;
|
||||
} else {
|
||||
if(infmt&SF_16BITS) {
|
||||
if(infmt&SF_BIG_ENDIAN)
|
||||
_mm_read_M_SWORDS(sl_buffer,stodo,reader);
|
||||
else
|
||||
_mm_read_I_SWORDS(sl_buffer,stodo,reader);
|
||||
} else {
|
||||
SBYTE *src;
|
||||
SWORD *dest;
|
||||
|
||||
reader->Read(reader,sl_buffer,sizeof(SBYTE)*stodo);
|
||||
src = (SBYTE*)sl_buffer;
|
||||
dest = sl_buffer;
|
||||
src += stodo;dest += stodo;
|
||||
|
||||
for(t=0;t<stodo;t++) {
|
||||
src--;dest--;
|
||||
*dest = (*src)<<8;
|
||||
}
|
||||
}
|
||||
sl_rlength-=stodo;
|
||||
}
|
||||
|
||||
if(infmt & SF_DELTA)
|
||||
for(t=0;t<stodo;t++) {
|
||||
sl_buffer[t] += sl_old;
|
||||
sl_old = sl_buffer[t];
|
||||
}
|
||||
|
||||
if((infmt^outfmt) & SF_SIGNED)
|
||||
for(t=0;t<stodo;t++)
|
||||
sl_buffer[t]^= 0x8000;
|
||||
|
||||
if(scalefactor) {
|
||||
int idx = 0;
|
||||
SLONG scaleval;
|
||||
|
||||
/* Sample Scaling... average values for better results. */
|
||||
t= 0;
|
||||
while(t<stodo && length) {
|
||||
scaleval = 0;
|
||||
for(u=scalefactor;u && t<stodo;u--,t++)
|
||||
scaleval+=sl_buffer[t];
|
||||
sl_buffer[idx++]=scaleval/(scalefactor-u);
|
||||
length--;
|
||||
}
|
||||
stodo = idx;
|
||||
} else
|
||||
length -= stodo;
|
||||
|
||||
if (dither) {
|
||||
if((infmt & SF_STEREO) && !(outfmt & SF_STEREO)) {
|
||||
/* dither stereo to mono, average together every two samples */
|
||||
SLONG avgval;
|
||||
int idx = 0;
|
||||
|
||||
t=0;
|
||||
while(t<stodo && length) {
|
||||
avgval=sl_buffer[t++];
|
||||
avgval+=sl_buffer[t++];
|
||||
sl_buffer[idx++]=avgval>>1;
|
||||
length-=2;
|
||||
}
|
||||
stodo = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if(outfmt & SF_16BITS) {
|
||||
for(t=0;t<stodo;t++)
|
||||
*(wptr++)=sl_buffer[t];
|
||||
} else {
|
||||
for(t=0;t<stodo;t++)
|
||||
*(bptr++)=sl_buffer[t]>>8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SL_Load(void* buffer,SAMPLOAD *smp,ULONG length)
|
||||
{
|
||||
return SL_LoadInternal(buffer,smp->infmt,smp->outfmt,smp->scalefactor,
|
||||
length,smp->reader,0);
|
||||
}
|
||||
|
||||
/* Registers a sample for loading when SL_LoadSamples() is called. */
|
||||
SAMPLOAD* SL_RegisterSample(SAMPLE* s,int type,MREADER* reader)
|
||||
{
|
||||
SAMPLOAD *news,**samplist,*cruise;
|
||||
|
||||
if(type==MD_MUSIC) {
|
||||
samplist = &musiclist;
|
||||
cruise = musiclist;
|
||||
} else
|
||||
if (type==MD_SNDFX) {
|
||||
samplist = &sndfxlist;
|
||||
cruise = sndfxlist;
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
/* Allocate and add structure to the END of the list */
|
||||
if(!(news=(SAMPLOAD*)_mm_malloc(sizeof(SAMPLOAD)))) return NULL;
|
||||
|
||||
if(cruise) {
|
||||
while(cruise->next) cruise=cruise->next;
|
||||
cruise->next = news;
|
||||
} else
|
||||
*samplist = news;
|
||||
|
||||
news->infmt = s->flags & SF_FORMATMASK;
|
||||
news->outfmt = news->infmt;
|
||||
news->reader = reader;
|
||||
news->sample = s;
|
||||
news->length = s->length;
|
||||
news->loopstart = s->loopstart;
|
||||
news->loopend = s->loopend;
|
||||
|
||||
return news;
|
||||
}
|
||||
|
||||
static void FreeSampleList(SAMPLOAD* s)
|
||||
{
|
||||
SAMPLOAD *old;
|
||||
|
||||
while(s) {
|
||||
old = s;
|
||||
s = s->next;
|
||||
free(old);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the total amount of memory required by the samplelist queue. */
|
||||
static ULONG SampleTotal(SAMPLOAD* samplist,int type)
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
while(samplist) {
|
||||
samplist->sample->flags=
|
||||
(samplist->sample->flags&~SF_FORMATMASK)|samplist->outfmt;
|
||||
total += MD_SampleLength(type,samplist->sample);
|
||||
samplist=samplist->next;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static ULONG RealSpeed(SAMPLOAD *s)
|
||||
{
|
||||
return(s->sample->speed/(s->scalefactor?s->scalefactor:1));
|
||||
}
|
||||
|
||||
static BOOL DitherSamples(SAMPLOAD* samplist,int type)
|
||||
{
|
||||
SAMPLOAD *c2smp=NULL;
|
||||
ULONG maxsize, speed;
|
||||
SAMPLOAD *s;
|
||||
|
||||
if(!samplist) return 0;
|
||||
|
||||
if((maxsize=MD_SampleSpace(type)*1024))
|
||||
while(SampleTotal(samplist,type)>maxsize) {
|
||||
/* First Pass - check for any 16 bit samples */
|
||||
s = samplist;
|
||||
while(s) {
|
||||
if(s->outfmt & SF_16BITS) {
|
||||
SL_Sample16to8(s);
|
||||
break;
|
||||
}
|
||||
s=s->next;
|
||||
}
|
||||
/* Second pass (if no 16bits found above) is to take the sample with
|
||||
the highest speed and dither it by half. */
|
||||
if(!s) {
|
||||
s = samplist;
|
||||
speed = 0;
|
||||
while(s) {
|
||||
if((s->sample->length) && (RealSpeed(s)>speed)) {
|
||||
speed=RealSpeed(s);
|
||||
c2smp=s;
|
||||
}
|
||||
s=s->next;
|
||||
}
|
||||
if (c2smp)
|
||||
SL_HalveSample(c2smp,2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Samples dithered, now load them ! */
|
||||
s = samplist;
|
||||
while(s) {
|
||||
/* sample has to be loaded ? -> increase number of samples, allocate
|
||||
memory and load sample. */
|
||||
if(s->sample->length) {
|
||||
if(s->sample->seekpos)
|
||||
_mm_fseek(s->reader, s->sample->seekpos, SEEK_SET);
|
||||
|
||||
/* Call the sample load routine of the driver module. It has to
|
||||
return a 'handle' (>=0) that identifies the sample. */
|
||||
s->sample->handle = MD_SampleLoad(s, type);
|
||||
s->sample->flags = (s->sample->flags & ~SF_FORMATMASK) | s->outfmt;
|
||||
if(s->sample->handle<0) {
|
||||
FreeSampleList(samplist);
|
||||
if(_mm_errorhandler) _mm_errorhandler();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
FreeSampleList(samplist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SL_LoadSamples(void)
|
||||
{
|
||||
BOOL ok;
|
||||
|
||||
_mm_critical = 0;
|
||||
|
||||
if((!musiclist)&&(!sndfxlist)) return 0;
|
||||
ok=DitherSamples(musiclist,MD_MUSIC)||DitherSamples(sndfxlist,MD_SNDFX);
|
||||
musiclist=sndfxlist=NULL;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SL_Sample16to8(SAMPLOAD* s)
|
||||
{
|
||||
s->outfmt &= ~SF_16BITS;
|
||||
s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
|
||||
}
|
||||
|
||||
void SL_Sample8to16(SAMPLOAD* s)
|
||||
{
|
||||
s->outfmt |= SF_16BITS;
|
||||
s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
|
||||
}
|
||||
|
||||
void SL_SampleSigned(SAMPLOAD* s)
|
||||
{
|
||||
s->outfmt |= SF_SIGNED;
|
||||
s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
|
||||
}
|
||||
|
||||
void SL_SampleUnsigned(SAMPLOAD* s)
|
||||
{
|
||||
s->outfmt &= ~SF_SIGNED;
|
||||
s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
|
||||
}
|
||||
|
||||
void SL_HalveSample(SAMPLOAD* s,int factor)
|
||||
{
|
||||
s->scalefactor=factor>0?factor:2;
|
||||
|
||||
s->sample->divfactor = s->scalefactor;
|
||||
s->sample->length = s->length / s->scalefactor;
|
||||
s->sample->loopstart = s->loopstart / s->scalefactor;
|
||||
s->sample->loopend = s->loopend / s->scalefactor;
|
||||
}
|
||||
|
||||
|
||||
/* ex:set ts=4: */
|
||||
968
project/jni/mikmod/playercode/virtch.c
Normal file
968
project/jni/mikmod/playercode/virtch.c
Normal file
@@ -0,0 +1,968 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
|
||||
AUTHORS for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: virtch.c,v 1.2 2004/02/13 13:31:54 raph Exp $
|
||||
|
||||
Sample mixing routines, using a 32 bits mixing buffer.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Optional features include:
|
||||
(a) 4-step reverb (for 16 bit output only)
|
||||
(b) Interpolation of sample data during mixing
|
||||
(c) Dolby Surround Sound
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
/*
|
||||
Constant definitions
|
||||
====================
|
||||
|
||||
BITSHIFT
|
||||
Controls the maximum volume of the sound output. All data is shifted
|
||||
right by BITSHIFT after being mixed. Higher values result in quieter
|
||||
sound and less chance of distortion.
|
||||
|
||||
REVERBERATION
|
||||
Controls the duration of the reverb. Larger values represent a shorter
|
||||
reverb loop. Smaller values extend the reverb but can result in more of
|
||||
an echo-ish sound.
|
||||
|
||||
*/
|
||||
|
||||
#define BITSHIFT 9
|
||||
#define REVERBERATION 110000L
|
||||
|
||||
#define FRACBITS 11
|
||||
#define FRACMASK ((1L<<FRACBITS)-1L)
|
||||
|
||||
#define TICKLSIZE 8192
|
||||
#define TICKWSIZE (TICKLSIZE<<1)
|
||||
#define TICKBSIZE (TICKWSIZE<<1)
|
||||
|
||||
#define CLICK_SHIFT 6
|
||||
#define CLICK_BUFFER (1L<<CLICK_SHIFT)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
typedef struct VINFO {
|
||||
UBYTE kick; /* =1 -> sample has to be restarted */
|
||||
UBYTE active; /* =1 -> sample is playing */
|
||||
UWORD flags; /* 16/8 bits looping/one-shot */
|
||||
SWORD handle; /* identifies the sample */
|
||||
ULONG start; /* start index */
|
||||
ULONG size; /* samplesize */
|
||||
ULONG reppos; /* loop start */
|
||||
ULONG repend; /* loop end */
|
||||
ULONG frq; /* current frequency */
|
||||
int vol; /* current volume */
|
||||
int pan; /* current panning position */
|
||||
|
||||
int rampvol;
|
||||
int lvolsel,rvolsel; /* Volume factor in range 0-255 */
|
||||
int oldlvol,oldrvol;
|
||||
|
||||
SLONGLONG current; /* current index in the sample */
|
||||
SLONGLONG increment; /* increment value */
|
||||
} VINFO;
|
||||
|
||||
static SWORD **Samples;
|
||||
static VINFO *vinf=NULL,*vnf;
|
||||
static long tickleft,samplesthatfit,vc_memory=0;
|
||||
static int vc_softchn;
|
||||
static SLONGLONG idxsize,idxlpos,idxlend;
|
||||
static SLONG *vc_tickbuf=NULL;
|
||||
static UWORD vc_mode;
|
||||
|
||||
/* Reverb control variables */
|
||||
|
||||
static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8;
|
||||
static ULONG RVRindex;
|
||||
|
||||
/* For Mono or Left Channel */
|
||||
static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL,
|
||||
*RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL;
|
||||
|
||||
/* For Stereo only (Right Channel) */
|
||||
static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL,
|
||||
*RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL;
|
||||
|
||||
#ifdef NATIVE_64BIT_INT
|
||||
#define NATIVE SLONGLONG
|
||||
#else
|
||||
#define NATIVE SLONG
|
||||
#endif
|
||||
|
||||
/*========== 32 bit sample mixers - only for 32 bit platforms */
|
||||
#ifndef NATIVE_64BIT_INT
|
||||
|
||||
static SLONG Mix32MonoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32StereoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
|
||||
while(todo--) {
|
||||
sample=srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
*dest++ += rvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32SurroundNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
|
||||
if (lvolsel>=rvolsel) {
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel*sample;
|
||||
*dest++ -= lvolsel*sample;
|
||||
}
|
||||
} else {
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ -= rvolsel*sample;
|
||||
*dest++ += rvolsel*sample;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32MonoInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
|
||||
if (rampvol) {
|
||||
SLONG oldlvol = vnf->oldlvol - lvolsel;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32StereoInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
|
||||
if (rampvol) {
|
||||
SLONG oldlvol = vnf->oldlvol - lvolsel;
|
||||
SLONG oldrvol = vnf->oldrvol - rvolsel;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
*dest++ += ((rvolsel << CLICK_SHIFT) + oldrvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
*dest++ += rvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32SurroundInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
SLONG oldvol, vol;
|
||||
|
||||
if (lvolsel >= rvolsel) {
|
||||
vol = lvolsel;
|
||||
oldvol = vnf->oldlvol;
|
||||
} else {
|
||||
vol = rvolsel;
|
||||
oldvol = vnf->oldrvol;
|
||||
}
|
||||
|
||||
if (rampvol) {
|
||||
oldvol -= vol;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
*dest++ += sample;
|
||||
*dest++ -= sample;
|
||||
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += vol*sample;
|
||||
*dest++ -= vol*sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*========== 64 bit sample mixers - all platforms */
|
||||
|
||||
static SLONGLONG MixMonoNormal(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixStereoNormal(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
|
||||
while(todo--) {
|
||||
sample=srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
*dest++ += rvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixSurroundNormal(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
|
||||
if(vnf->lvolsel>=vnf->rvolsel) {
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel*sample;
|
||||
*dest++ -= lvolsel*sample;
|
||||
}
|
||||
} else {
|
||||
while(todo--) {
|
||||
sample = srce[index >> FRACBITS];
|
||||
index += increment;
|
||||
|
||||
*dest++ -= rvolsel*sample;
|
||||
*dest++ += rvolsel*sample;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixMonoInterp(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
|
||||
if (rampvol) {
|
||||
SLONG oldlvol = vnf->oldlvol - lvolsel;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixStereoInterp(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
|
||||
if (rampvol) {
|
||||
SLONG oldlvol = vnf->oldlvol - lvolsel;
|
||||
SLONG oldrvol = vnf->oldrvol - rvolsel;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
*dest++ +=((rvolsel << CLICK_SHIFT) + oldrvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += lvolsel * sample;
|
||||
*dest++ += rvolsel * sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixSurroundInterp(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SLONG sample;
|
||||
SLONG lvolsel = vnf->lvolsel;
|
||||
SLONG rvolsel = vnf->rvolsel;
|
||||
SLONG rampvol = vnf->rampvol;
|
||||
SLONG oldvol, vol;
|
||||
|
||||
if (lvolsel >= rvolsel) {
|
||||
vol = lvolsel;
|
||||
oldvol = vnf->oldlvol;
|
||||
} else {
|
||||
vol = rvolsel;
|
||||
oldvol = vnf->oldrvol;
|
||||
}
|
||||
|
||||
if (rampvol) {
|
||||
oldvol -= vol;
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
|
||||
* sample >> CLICK_SHIFT;
|
||||
*dest++ += sample;
|
||||
*dest++ -= sample;
|
||||
if (!--rampvol)
|
||||
break;
|
||||
}
|
||||
vnf->rampvol = rampvol;
|
||||
if (todo < 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
while(todo--) {
|
||||
sample=(SLONG)srce[index>>FRACBITS]+
|
||||
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS])
|
||||
*(index&FRACMASK)>>FRACBITS);
|
||||
index += increment;
|
||||
|
||||
*dest++ += vol*sample;
|
||||
*dest++ -= vol*sample;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static void (*MixReverb)(SLONG* srce,NATIVE count);
|
||||
|
||||
/* Reverb macros */
|
||||
#define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n
|
||||
#define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7)
|
||||
#define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7)
|
||||
|
||||
static void MixReverb_Normal(SLONG* srce,NATIVE count)
|
||||
{
|
||||
unsigned int speedup;
|
||||
int ReverbPct;
|
||||
unsigned int loc1,loc2,loc3,loc4;
|
||||
unsigned int loc5,loc6,loc7,loc8;
|
||||
|
||||
ReverbPct=58+(md_reverb<<2);
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
while(count--) {
|
||||
/* Compute the left channel echo buffers */
|
||||
speedup = *srce >> 3;
|
||||
|
||||
COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
|
||||
COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
|
||||
|
||||
/* Prepare to compute actual finalized data */
|
||||
RVRindex++;
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
/* left channel */
|
||||
*srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
|
||||
RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
|
||||
}
|
||||
}
|
||||
|
||||
static void MixReverb_Stereo(SLONG* srce,NATIVE count)
|
||||
{
|
||||
unsigned int speedup;
|
||||
int ReverbPct;
|
||||
unsigned int loc1, loc2, loc3, loc4;
|
||||
unsigned int loc5, loc6, loc7, loc8;
|
||||
|
||||
ReverbPct = 92+(md_reverb<<1);
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
while(count--) {
|
||||
/* Compute the left channel echo buffers */
|
||||
speedup = *srce >> 3;
|
||||
|
||||
COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
|
||||
COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
|
||||
|
||||
/* Compute the right channel echo buffers */
|
||||
speedup = srce[1] >> 3;
|
||||
|
||||
COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4);
|
||||
COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8);
|
||||
|
||||
/* Prepare to compute actual finalized data */
|
||||
RVRindex++;
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
/* left channel then right channel */
|
||||
*srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
|
||||
RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
|
||||
|
||||
*srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
|
||||
RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
|
||||
}
|
||||
}
|
||||
|
||||
/* Mixing macros */
|
||||
#define EXTRACT_SAMPLE_FP(var,size) var=(*srce++>>(BITSHIFT-size)) * ((1.0f / 32768.0f) / (1 << size))
|
||||
#define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var
|
||||
#define PUT_SAMPLE_FP(var) *dste++=var
|
||||
|
||||
static void Mix32ToFP(float* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
float x1,x2,x3,x4;
|
||||
int remain;
|
||||
|
||||
#define FP_SHIFT 4
|
||||
|
||||
remain=count&3;
|
||||
for(count>>=2;count;count--) {
|
||||
EXTRACT_SAMPLE_FP(x1,FP_SHIFT); EXTRACT_SAMPLE_FP(x2,FP_SHIFT);
|
||||
EXTRACT_SAMPLE_FP(x3,FP_SHIFT); EXTRACT_SAMPLE_FP(x4,FP_SHIFT);
|
||||
|
||||
CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f);
|
||||
CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f);
|
||||
|
||||
PUT_SAMPLE_FP(x1); PUT_SAMPLE_FP(x2);
|
||||
PUT_SAMPLE_FP(x3); PUT_SAMPLE_FP(x4);
|
||||
}
|
||||
while(remain--) {
|
||||
EXTRACT_SAMPLE_FP(x1,FP_SHIFT);
|
||||
CHECK_SAMPLE_FP(x1,1.0f);
|
||||
PUT_SAMPLE_FP(x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Mixing macros */
|
||||
#define EXTRACT_SAMPLE(var,size) var=*srce++>>(BITSHIFT+16-size)
|
||||
#define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var
|
||||
#define PUT_SAMPLE(var) *dste++=var
|
||||
|
||||
static void Mix32To16(SWORD* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
SLONG x1,x2,x3,x4;
|
||||
int remain;
|
||||
|
||||
remain=count&3;
|
||||
for(count>>=2;count;count--) {
|
||||
EXTRACT_SAMPLE(x1,16); EXTRACT_SAMPLE(x2,16);
|
||||
EXTRACT_SAMPLE(x3,16); EXTRACT_SAMPLE(x4,16);
|
||||
|
||||
CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
|
||||
CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
|
||||
|
||||
PUT_SAMPLE(x1); PUT_SAMPLE(x2); PUT_SAMPLE(x3); PUT_SAMPLE(x4);
|
||||
}
|
||||
while(remain--) {
|
||||
EXTRACT_SAMPLE(x1,16);
|
||||
CHECK_SAMPLE(x1,32768);
|
||||
PUT_SAMPLE(x1);
|
||||
}
|
||||
}
|
||||
|
||||
static void Mix32To8(SBYTE* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
SWORD x1,x2,x3,x4;
|
||||
int remain;
|
||||
|
||||
remain=count&3;
|
||||
for(count>>=2;count;count--) {
|
||||
EXTRACT_SAMPLE(x1,8); EXTRACT_SAMPLE(x2,8);
|
||||
EXTRACT_SAMPLE(x3,8); EXTRACT_SAMPLE(x4,8);
|
||||
|
||||
CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
|
||||
CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
|
||||
|
||||
PUT_SAMPLE(x1+128); PUT_SAMPLE(x2+128);
|
||||
PUT_SAMPLE(x3+128); PUT_SAMPLE(x4+128);
|
||||
}
|
||||
while(remain--) {
|
||||
EXTRACT_SAMPLE(x1,8);
|
||||
CHECK_SAMPLE(x1,128);
|
||||
PUT_SAMPLE(x1+128);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddChannel(SLONG* ptr,NATIVE todo)
|
||||
{
|
||||
SLONGLONG end,done;
|
||||
SWORD *s;
|
||||
|
||||
if(!(s=Samples[vnf->handle])) {
|
||||
vnf->current = vnf->active = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the 'current' index so the sample loops, or stops playing if it
|
||||
reached the end of the sample */
|
||||
while(todo>0) {
|
||||
SLONGLONG endpos;
|
||||
|
||||
if(vnf->flags & SF_REVERSE) {
|
||||
/* The sample is playing in reverse */
|
||||
if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) {
|
||||
/* the sample is looping and has reached the loopstart index */
|
||||
if(vnf->flags & SF_BIDI) {
|
||||
/* sample is doing bidirectional loops, so 'bounce' the
|
||||
current index against the idxlpos */
|
||||
vnf->current = idxlpos+(idxlpos-vnf->current);
|
||||
vnf->flags &= ~SF_REVERSE;
|
||||
vnf->increment = -vnf->increment;
|
||||
} else
|
||||
/* normal backwards looping, so set the current position to
|
||||
loopend index */
|
||||
vnf->current=idxlend-(idxlpos-vnf->current);
|
||||
} else {
|
||||
/* the sample is not looping, so check if it reached index 0 */
|
||||
if(vnf->current < 0) {
|
||||
/* playing index reached 0, so stop playing this sample */
|
||||
vnf->current = vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* The sample is playing forward */
|
||||
if((vnf->flags & SF_LOOP) &&
|
||||
(vnf->current >= idxlend)) {
|
||||
/* the sample is looping, check the loopend index */
|
||||
if(vnf->flags & SF_BIDI) {
|
||||
/* sample is doing bidirectional loops, so 'bounce' the
|
||||
current index against the idxlend */
|
||||
vnf->flags |= SF_REVERSE;
|
||||
vnf->increment = -vnf->increment;
|
||||
vnf->current = idxlend-(vnf->current-idxlend);
|
||||
} else
|
||||
/* normal backwards looping, so set the current position
|
||||
to loopend index */
|
||||
vnf->current=idxlpos+(vnf->current-idxlend);
|
||||
} else {
|
||||
/* sample is not looping, so check if it reached the last
|
||||
position */
|
||||
if(vnf->current >= idxsize) {
|
||||
/* yes, so stop playing this sample */
|
||||
vnf->current = vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
|
||||
(vnf->flags&SF_LOOP)?idxlend:idxsize;
|
||||
|
||||
/* if the sample is not blocked... */
|
||||
if((end==vnf->current)||(!vnf->increment))
|
||||
done=0;
|
||||
else {
|
||||
done=MIN((end-vnf->current)/vnf->increment+1,todo);
|
||||
if(done<0) done=0;
|
||||
}
|
||||
|
||||
if(!done) {
|
||||
vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
endpos=vnf->current+done*vnf->increment;
|
||||
|
||||
if(vnf->vol) {
|
||||
#ifndef NATIVE_64BIT_INT
|
||||
/* use the 32 bit mixers as often as we can (they're much faster) */
|
||||
if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) {
|
||||
if((md_mode & DMODE_INTERP)) {
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND))
|
||||
vnf->current=Mix32SurroundInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=Mix32StereoInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=Mix32MonoInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND))
|
||||
vnf->current=Mix32SurroundNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=Mix32StereoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=Mix32MonoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if((md_mode & DMODE_INTERP)) {
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND))
|
||||
vnf->current=MixSurroundInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=MixStereoInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=MixMonoInterp
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND))
|
||||
vnf->current=MixSurroundNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=MixStereoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=MixMonoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
}
|
||||
} else
|
||||
/* update sample position */
|
||||
vnf->current=endpos;
|
||||
|
||||
todo-=done;
|
||||
ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done;
|
||||
}
|
||||
}
|
||||
|
||||
#define _IN_VIRTCH_
|
||||
#include "virtch_common.c"
|
||||
#undef _IN_VIRTCH_
|
||||
|
||||
void VC1_WriteSamples(SBYTE* buf,ULONG todo)
|
||||
{
|
||||
int left,portion=0,count;
|
||||
SBYTE *buffer;
|
||||
int t, pan, vol;
|
||||
|
||||
while(todo) {
|
||||
if(!tickleft) {
|
||||
if(vc_mode & DMODE_SOFT_MUSIC) md_player();
|
||||
tickleft=(md_mixfreq*125L)/(md_bpm*50L);
|
||||
}
|
||||
left = MIN(tickleft, todo);
|
||||
buffer = buf;
|
||||
tickleft -= left;
|
||||
todo -= left;
|
||||
buf += samples2bytes(left);
|
||||
|
||||
while(left) {
|
||||
portion = MIN(left, samplesthatfit);
|
||||
count = (vc_mode & DMODE_STEREO)?(portion<<1):portion;
|
||||
memset(vc_tickbuf, 0, count<<2);
|
||||
for(t=0;t<vc_softchn;t++) {
|
||||
vnf = &vinf[t];
|
||||
|
||||
if(vnf->kick) {
|
||||
vnf->current=((SLONGLONG)vnf->start)<<FRACBITS;
|
||||
vnf->kick =0;
|
||||
vnf->active =1;
|
||||
}
|
||||
|
||||
if(!vnf->frq) vnf->active = 0;
|
||||
|
||||
if(vnf->active) {
|
||||
vnf->increment=((SLONGLONG)(vnf->frq<<FRACBITS))/md_mixfreq;
|
||||
if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment;
|
||||
vol = vnf->vol; pan = vnf->pan;
|
||||
|
||||
vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel;
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if(pan != PAN_SURROUND) {
|
||||
vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8;
|
||||
vnf->rvolsel=(vol*pan)>>8;
|
||||
} else
|
||||
vnf->lvolsel=vnf->rvolsel=vol/2;
|
||||
} else
|
||||
vnf->lvolsel=vol;
|
||||
|
||||
idxsize = (vnf->size)? ((SLONGLONG)vnf->size << FRACBITS)-1 : 0;
|
||||
idxlend = (vnf->repend)? ((SLONGLONG)vnf->repend << FRACBITS)-1 : 0;
|
||||
idxlpos = (SLONGLONG)vnf->reppos << FRACBITS;
|
||||
AddChannel(vc_tickbuf, portion);
|
||||
}
|
||||
}
|
||||
|
||||
if(md_reverb) {
|
||||
if(md_reverb>15) md_reverb=15;
|
||||
MixReverb(vc_tickbuf, portion);
|
||||
}
|
||||
|
||||
if(vc_mode & DMODE_FLOAT)
|
||||
Mix32ToFP((float*) buffer, vc_tickbuf, count);
|
||||
else if(vc_mode & DMODE_16BITS)
|
||||
Mix32To16((SWORD*) buffer, vc_tickbuf, count);
|
||||
else
|
||||
Mix32To8((SBYTE*) buffer, vc_tickbuf, count);
|
||||
|
||||
buffer += samples2bytes(portion);
|
||||
left -= portion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL VC1_Init(void)
|
||||
{
|
||||
VC_SetupPointers();
|
||||
|
||||
if (md_mode&DMODE_HQMIXER)
|
||||
return VC2_Init();
|
||||
|
||||
if(!(Samples=(SWORD**)_mm_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) {
|
||||
_mm_errno = MMERR_INITIALIZING_MIXER;
|
||||
return 1;
|
||||
}
|
||||
if(!vc_tickbuf)
|
||||
if(!(vc_tickbuf=(SLONG*)_mm_malloc((TICKLSIZE+32)*sizeof(SLONG)))) {
|
||||
_mm_errno = MMERR_INITIALIZING_MIXER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal;
|
||||
vc_mode = md_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL VC1_PlayStart(void)
|
||||
{
|
||||
samplesthatfit=TICKLSIZE;
|
||||
if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
|
||||
tickleft = 0;
|
||||
|
||||
RVc1 = (5000L * md_mixfreq) / REVERBERATION;
|
||||
RVc2 = (5078L * md_mixfreq) / REVERBERATION;
|
||||
RVc3 = (5313L * md_mixfreq) / REVERBERATION;
|
||||
RVc4 = (5703L * md_mixfreq) / REVERBERATION;
|
||||
RVc5 = (6250L * md_mixfreq) / REVERBERATION;
|
||||
RVc6 = (6953L * md_mixfreq) / REVERBERATION;
|
||||
RVc7 = (7813L * md_mixfreq) / REVERBERATION;
|
||||
RVc8 = (8828L * md_mixfreq) / REVERBERATION;
|
||||
|
||||
if(!(RVbufL1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
|
||||
|
||||
if(!(RVbufR1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
|
||||
|
||||
RVRindex = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VC1_PlayStop(void)
|
||||
{
|
||||
if(RVbufL1) free(RVbufL1);
|
||||
if(RVbufL2) free(RVbufL2);
|
||||
if(RVbufL3) free(RVbufL3);
|
||||
if(RVbufL4) free(RVbufL4);
|
||||
if(RVbufL5) free(RVbufL5);
|
||||
if(RVbufL6) free(RVbufL6);
|
||||
if(RVbufL7) free(RVbufL7);
|
||||
if(RVbufL8) free(RVbufL8);
|
||||
RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL;
|
||||
if(RVbufR1) free(RVbufR1);
|
||||
if(RVbufR2) free(RVbufR2);
|
||||
if(RVbufR3) free(RVbufR3);
|
||||
if(RVbufR4) free(RVbufR4);
|
||||
if(RVbufR5) free(RVbufR5);
|
||||
if(RVbufR6) free(RVbufR6);
|
||||
if(RVbufR7) free(RVbufR7);
|
||||
if(RVbufR8) free(RVbufR8);
|
||||
RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL;
|
||||
}
|
||||
|
||||
BOOL VC1_SetNumVoices(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(!(vc_softchn=md_softchn)) return 0;
|
||||
|
||||
if(vinf) free(vinf);
|
||||
if(!(vinf= _mm_calloc(sizeof(VINFO),vc_softchn))) return 1;
|
||||
|
||||
for(t=0;t<vc_softchn;t++) {
|
||||
vinf[t].frq=10000;
|
||||
vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
938
project/jni/mikmod/playercode/virtch2.c
Normal file
938
project/jni/mikmod/playercode/virtch2.c
Normal file
@@ -0,0 +1,938 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
|
||||
complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: virtch2.c,v 1.2 2004/02/13 13:31:54 raph Exp $
|
||||
|
||||
High-quality sample mixing routines, using a 32 bits mixing buffer,
|
||||
interpolation, and sample smoothing to improve sound quality and remove
|
||||
clicks.
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
/*
|
||||
|
||||
Future Additions:
|
||||
Low-Pass filter to remove annoying staticy buzz.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
/*
|
||||
Constant Definitions
|
||||
====================
|
||||
|
||||
MAXVOL_FACTOR (was BITSHIFT in virtch.c)
|
||||
Controls the maximum volume of the output data. All mixed data is
|
||||
divided by this number after mixing, so larger numbers result in
|
||||
quieter mixing. Smaller numbers will increase the likeliness of
|
||||
distortion on loud modules.
|
||||
|
||||
REVERBERATION
|
||||
Larger numbers result in shorter reverb duration. Longer reverb
|
||||
durations can cause unwanted static and make the reverb sound more
|
||||
like a crappy echo.
|
||||
|
||||
SAMPLING_SHIFT
|
||||
Specified the shift multiplier which controls by how much the mixing
|
||||
rate is multiplied while mixing. Higher values can improve quality by
|
||||
smoothing the sound and reducing pops and clicks. Note, this is a shift
|
||||
value, so a value of 2 becomes a mixing-rate multiplier of 4, and a
|
||||
value of 3 = 8, etc.
|
||||
|
||||
FRACBITS
|
||||
The number of bits per integer devoted to the fractional part of the
|
||||
number. Generally, this number should not be changed for any reason.
|
||||
|
||||
!!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0
|
||||
|
||||
*/
|
||||
|
||||
#define MAXVOL_FACTOR (1<<9)
|
||||
#define REVERBERATION 11000L
|
||||
|
||||
#define SAMPLING_SHIFT 2
|
||||
#define SAMPLING_FACTOR (1UL<<SAMPLING_SHIFT)
|
||||
|
||||
#define FRACBITS 28
|
||||
#define FRACMASK ((1UL<<FRACBITS)-1UL)
|
||||
|
||||
#define TICKLSIZE 8192
|
||||
#define TICKWSIZE (TICKLSIZE * 2)
|
||||
#define TICKBSIZE (TICKWSIZE * 2)
|
||||
|
||||
#define CLICK_SHIFT_BASE 6
|
||||
#define CLICK_SHIFT (CLICK_SHIFT_BASE + SAMPLING_SHIFT)
|
||||
#define CLICK_BUFFER (1L << CLICK_SHIFT)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
typedef struct VINFO {
|
||||
UBYTE kick; /* =1 -> sample has to be restarted */
|
||||
UBYTE active; /* =1 -> sample is playing */
|
||||
UWORD flags; /* 16/8 bits looping/one-shot */
|
||||
SWORD handle; /* identifies the sample */
|
||||
ULONG start; /* start index */
|
||||
ULONG size; /* samplesize */
|
||||
ULONG reppos; /* loop start */
|
||||
ULONG repend; /* loop end */
|
||||
ULONG frq; /* current frequency */
|
||||
int vol; /* current volume */
|
||||
int pan; /* current panning position */
|
||||
|
||||
int click;
|
||||
int rampvol;
|
||||
SLONG lastvalL,lastvalR;
|
||||
int lvolsel,rvolsel; /* Volume factor in range 0-255 */
|
||||
int oldlvol,oldrvol;
|
||||
|
||||
SLONGLONG current; /* current index in the sample */
|
||||
SLONGLONG increment; /* increment value */
|
||||
} VINFO;
|
||||
|
||||
static SWORD **Samples;
|
||||
static VINFO *vinf=NULL,*vnf;
|
||||
static long tickleft,samplesthatfit,vc_memory=0;
|
||||
static int vc_softchn;
|
||||
static SLONGLONG idxsize,idxlpos,idxlend;
|
||||
static SLONG *vc_tickbuf=NULL;
|
||||
static UWORD vc_mode;
|
||||
|
||||
/* Reverb control variables */
|
||||
|
||||
static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8;
|
||||
static ULONG RVRindex;
|
||||
|
||||
/* For Mono or Left Channel */
|
||||
static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL,
|
||||
*RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL;
|
||||
|
||||
/* For Stereo only (Right Channel) */
|
||||
static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL,
|
||||
*RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL;
|
||||
|
||||
#ifdef NATIVE_64BIT_INT
|
||||
#define NATIVE SLONGLONG
|
||||
#else
|
||||
#define NATIVE SLONG
|
||||
#endif
|
||||
|
||||
/*========== 32 bit sample mixers - only for 32 bit platforms */
|
||||
#ifndef NATIVE_64BIT_INT
|
||||
|
||||
static SLONG Mix32MonoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
SLONG i,f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=(((SLONG)(srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONG)srce[i+1]*f)) >> FRACBITS);
|
||||
index+=increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
*dest++ += (long)(
|
||||
( ( (SLONG)(vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
|
||||
(SLONG)sample ) >> CLICK_SHIFT );
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONG)sample ) +
|
||||
(vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT );
|
||||
vnf->click--;
|
||||
} else
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel * sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32StereoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,ULONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
SLONG i,f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=((((SLONG)srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONG)srce[i+1] * f)) >> FRACBITS);
|
||||
index += increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONG)vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
|
||||
) * (SLONG)sample ) >> CLICK_SHIFT );
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONG)vnf->oldrvol*vnf->rampvol) +
|
||||
(vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
|
||||
) * (SLONG)sample ) >> CLICK_SHIFT );
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
*dest++ += (long)(
|
||||
( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONG)sample ) + (vnf->lastvalL * vnf->click) )
|
||||
>> CLICK_SHIFT );
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONG)sample ) + (vnf->lastvalR * vnf->click) )
|
||||
>> CLICK_SHIFT );
|
||||
vnf->click--;
|
||||
} else {
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
*dest++ +=vnf->rvolsel*sample;
|
||||
}
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel*sample;
|
||||
vnf->lastvalR=vnf->rvolsel*sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONG Mix32StereoSurround(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,ULONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
long whoop;
|
||||
SLONG i, f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=((((SLONG)srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONG)srce[i+1]*f)) >> FRACBITS);
|
||||
index+=increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
whoop=(long)(
|
||||
( ( (SLONG)(vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
|
||||
(SLONG)sample) >> CLICK_SHIFT );
|
||||
*dest++ +=whoop;
|
||||
*dest++ -=whoop;
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
whoop = (long)(
|
||||
( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONG)sample) +
|
||||
(vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT );
|
||||
*dest++ +=whoop;
|
||||
*dest++ -=whoop;
|
||||
vnf->click--;
|
||||
} else {
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
*dest++ -=vnf->lvolsel*sample;
|
||||
}
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel*sample;
|
||||
vnf->lastvalR=vnf->lvolsel*sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*========== 64 bit mixers */
|
||||
|
||||
static SLONGLONG MixMonoNormal(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
SLONGLONG i,f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=(((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONGLONG)srce[i+1]*f)) >> FRACBITS);
|
||||
index+=increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
*dest++ += (long)(
|
||||
( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
|
||||
(SLONGLONG)sample ) >> CLICK_SHIFT );
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONGLONG)sample ) +
|
||||
(vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT );
|
||||
vnf->click--;
|
||||
} else
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel * sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixStereoNormal(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,ULONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
SLONGLONG i,f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONGLONG)srce[i+1] * f)) >> FRACBITS);
|
||||
index += increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
|
||||
) * (SLONGLONG)sample ) >> CLICK_SHIFT );
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) +
|
||||
(vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
|
||||
) * (SLONGLONG)sample ) >> CLICK_SHIFT );
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
*dest++ += (long)(
|
||||
( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) )
|
||||
>> CLICK_SHIFT );
|
||||
*dest++ += (long)(
|
||||
( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) )
|
||||
>> CLICK_SHIFT );
|
||||
vnf->click--;
|
||||
} else {
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
*dest++ +=vnf->rvolsel*sample;
|
||||
}
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel*sample;
|
||||
vnf->lastvalR=vnf->rvolsel*sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static SLONGLONG MixStereoSurround(SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,ULONG todo)
|
||||
{
|
||||
SWORD sample=0;
|
||||
long whoop;
|
||||
SLONGLONG i, f;
|
||||
|
||||
while(todo--) {
|
||||
i=index>>FRACBITS,f=index&FRACMASK;
|
||||
sample=((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) +
|
||||
((SLONGLONG)srce[i+1]*f)) >> FRACBITS);
|
||||
index+=increment;
|
||||
|
||||
if(vnf->rampvol) {
|
||||
whoop=(long)(
|
||||
( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) +
|
||||
(vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
|
||||
(SLONGLONG)sample) >> CLICK_SHIFT );
|
||||
*dest++ +=whoop;
|
||||
*dest++ -=whoop;
|
||||
vnf->rampvol--;
|
||||
} else
|
||||
if(vnf->click) {
|
||||
whoop = (long)(
|
||||
( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
|
||||
(SLONGLONG)sample) +
|
||||
(vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT );
|
||||
*dest++ +=whoop;
|
||||
*dest++ -=whoop;
|
||||
vnf->click--;
|
||||
} else {
|
||||
*dest++ +=vnf->lvolsel*sample;
|
||||
*dest++ -=vnf->lvolsel*sample;
|
||||
}
|
||||
}
|
||||
vnf->lastvalL=vnf->lvolsel*sample;
|
||||
vnf->lastvalR=vnf->lvolsel*sample;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void(*Mix32toFP)(float* dste,SLONG* srce,NATIVE count);
|
||||
static void(*Mix32to16)(SWORD* dste,SLONG* srce,NATIVE count);
|
||||
static void(*Mix32to8)(SBYTE* dste,SLONG* srce,NATIVE count);
|
||||
static void(*MixReverb)(SLONG* srce,NATIVE count);
|
||||
|
||||
/* Reverb macros */
|
||||
#define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n
|
||||
#define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7)
|
||||
#define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7)
|
||||
|
||||
static void MixReverb_Normal(SLONG* srce,NATIVE count)
|
||||
{
|
||||
NATIVE speedup;
|
||||
int ReverbPct;
|
||||
unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
|
||||
|
||||
ReverbPct=58+(md_reverb*4);
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
while(count--) {
|
||||
/* Compute the left channel echo buffers */
|
||||
speedup = *srce >> 3;
|
||||
|
||||
COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
|
||||
COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
|
||||
|
||||
/* Prepare to compute actual finalized data */
|
||||
RVRindex++;
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
/* left channel */
|
||||
*srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
|
||||
RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
|
||||
}
|
||||
}
|
||||
|
||||
static void MixReverb_Stereo(SLONG *srce,NATIVE count)
|
||||
{
|
||||
NATIVE speedup;
|
||||
int ReverbPct;
|
||||
unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
|
||||
|
||||
ReverbPct=58+(md_reverb*4);
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
while(count--) {
|
||||
/* Compute the left channel echo buffers */
|
||||
speedup = *srce >> 3;
|
||||
|
||||
COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
|
||||
COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
|
||||
|
||||
/* Compute the right channel echo buffers */
|
||||
speedup = srce[1] >> 3;
|
||||
|
||||
COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4);
|
||||
COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8);
|
||||
|
||||
/* Prepare to compute actual finalized data */
|
||||
RVRindex++;
|
||||
|
||||
COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
|
||||
COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
|
||||
|
||||
/* left channel */
|
||||
*srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
|
||||
RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
|
||||
|
||||
/* right channel */
|
||||
*srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
|
||||
RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
|
||||
}
|
||||
}
|
||||
|
||||
/* Mixing macros */
|
||||
#define EXTRACT_SAMPLE_FP(var,attenuation) var=*srce++*((1.0f / 32768.0f) / (MAXVOL_FACTOR*attenuation))
|
||||
#define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var
|
||||
|
||||
static void Mix32ToFP_Normal(float* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
float x1,x2,tmpx;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx=0.0f;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f);
|
||||
|
||||
CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f);
|
||||
|
||||
tmpx+=x1+x2;
|
||||
}
|
||||
*dste++ =tmpx*(1.0f/SAMPLING_FACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
static void Mix32ToFP_Stereo(float* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
float x1,x2,x3,x4,tmpx,tmpy;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx=tmpy=0.0f;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f);
|
||||
EXTRACT_SAMPLE_FP(x3,1.0f); EXTRACT_SAMPLE_FP(x4,1.0f);
|
||||
|
||||
CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f);
|
||||
CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f);
|
||||
|
||||
tmpx+=x1+x3;
|
||||
tmpy+=x2+x4;
|
||||
}
|
||||
*dste++ =tmpx*(1.0f/SAMPLING_FACTOR);
|
||||
*dste++ =tmpy*(1.0f/SAMPLING_FACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mixing macros */
|
||||
#define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation)
|
||||
#define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var
|
||||
|
||||
static void Mix32To16_Normal(SWORD* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
NATIVE x1,x2,tmpx;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx=0;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
|
||||
|
||||
CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
|
||||
|
||||
tmpx+=x1+x2;
|
||||
}
|
||||
*dste++ =tmpx/SAMPLING_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mix32To16_Stereo(SWORD* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
NATIVE x1,x2,x3,x4,tmpx,tmpy;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx=tmpy=0;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
|
||||
EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1);
|
||||
|
||||
CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
|
||||
CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
|
||||
|
||||
tmpx+=x1+x3;
|
||||
tmpy+=x2+x4;
|
||||
}
|
||||
*dste++ =tmpx/SAMPLING_FACTOR;
|
||||
*dste++ =tmpy/SAMPLING_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mix32To8_Normal(SBYTE* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
NATIVE x1,x2,tmpx;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx = 0;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
|
||||
|
||||
CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
|
||||
|
||||
tmpx+=x1+x2;
|
||||
}
|
||||
*dste++ =(tmpx/SAMPLING_FACTOR)+128;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mix32To8_Stereo(SBYTE* dste,SLONG* srce,NATIVE count)
|
||||
{
|
||||
NATIVE x1,x2,x3,x4,tmpx,tmpy;
|
||||
int i;
|
||||
|
||||
for(count/=SAMPLING_FACTOR;count;count--) {
|
||||
tmpx=tmpy=0;
|
||||
|
||||
for(i=SAMPLING_FACTOR/2;i;i--) {
|
||||
EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
|
||||
EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256);
|
||||
|
||||
CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
|
||||
CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
|
||||
|
||||
tmpx+=x1+x3;
|
||||
tmpy+=x2+x4;
|
||||
}
|
||||
*dste++ =(tmpx/SAMPLING_FACTOR)+128;
|
||||
*dste++ =(tmpy/SAMPLING_FACTOR)+128;
|
||||
}
|
||||
}
|
||||
|
||||
static void AddChannel(SLONG* ptr,NATIVE todo)
|
||||
{
|
||||
SLONGLONG end,done;
|
||||
SWORD *s;
|
||||
|
||||
if(!(s=Samples[vnf->handle])) {
|
||||
vnf->current = vnf->active = 0;
|
||||
vnf->lastvalL = vnf->lastvalR = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the 'current' index so the sample loops, or stops playing if it
|
||||
reached the end of the sample */
|
||||
while(todo>0) {
|
||||
SLONGLONG endpos;
|
||||
|
||||
if(vnf->flags & SF_REVERSE) {
|
||||
/* The sample is playing in reverse */
|
||||
if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) {
|
||||
/* the sample is looping and has reached the loopstart index */
|
||||
if(vnf->flags & SF_BIDI) {
|
||||
/* sample is doing bidirectional loops, so 'bounce' the
|
||||
current index against the idxlpos */
|
||||
vnf->current = idxlpos+(idxlpos-vnf->current);
|
||||
vnf->flags &= ~SF_REVERSE;
|
||||
vnf->increment = -vnf->increment;
|
||||
} else
|
||||
/* normal backwards looping, so set the current position to
|
||||
loopend index */
|
||||
vnf->current=idxlend-(idxlpos-vnf->current);
|
||||
} else {
|
||||
/* the sample is not looping, so check if it reached index 0 */
|
||||
if(vnf->current < 0) {
|
||||
/* playing index reached 0, so stop playing this sample */
|
||||
vnf->current = vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* The sample is playing forward */
|
||||
if((vnf->flags & SF_LOOP) &&
|
||||
(vnf->current >= idxlend)) {
|
||||
/* the sample is looping, check the loopend index */
|
||||
if(vnf->flags & SF_BIDI) {
|
||||
/* sample is doing bidirectional loops, so 'bounce' the
|
||||
current index against the idxlend */
|
||||
vnf->flags |= SF_REVERSE;
|
||||
vnf->increment = -vnf->increment;
|
||||
vnf->current = idxlend-(vnf->current-idxlend);
|
||||
} else
|
||||
/* normal backwards looping, so set the current position
|
||||
to loopend index */
|
||||
vnf->current=idxlpos+(vnf->current-idxlend);
|
||||
} else {
|
||||
/* sample is not looping, so check if it reached the last
|
||||
position */
|
||||
if(vnf->current >= idxsize) {
|
||||
/* yes, so stop playing this sample */
|
||||
vnf->current = vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
|
||||
(vnf->flags&SF_LOOP)?idxlend:idxsize;
|
||||
|
||||
/* if the sample is not blocked... */
|
||||
if((end==vnf->current)||(!vnf->increment))
|
||||
done=0;
|
||||
else {
|
||||
done=MIN((end-vnf->current)/vnf->increment+1,todo);
|
||||
if(done<0) done=0;
|
||||
}
|
||||
|
||||
if(!done) {
|
||||
vnf->active = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
endpos=vnf->current+done*vnf->increment;
|
||||
|
||||
if(vnf->vol || vnf->rampvol) {
|
||||
#ifndef NATIVE_64BIT_INT
|
||||
/* use the 32 bit mixers as often as we can (they're much faster) */
|
||||
if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) {
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND))
|
||||
vnf->current=Mix32StereoSurround
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=Mix32StereoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=Mix32MonoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND))
|
||||
vnf->current=MixStereoSurround
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
else
|
||||
vnf->current=MixStereoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
} else
|
||||
vnf->current=MixMonoNormal
|
||||
(s,ptr,vnf->current,vnf->increment,done);
|
||||
}
|
||||
} else {
|
||||
vnf->lastvalL = vnf->lastvalR = 0;
|
||||
/* update sample position */
|
||||
vnf->current=endpos;
|
||||
}
|
||||
|
||||
todo -= done;
|
||||
ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done;
|
||||
}
|
||||
}
|
||||
|
||||
#define _IN_VIRTCH_
|
||||
|
||||
#define VC1_SilenceBytes VC2_SilenceBytes
|
||||
#define VC1_WriteSamples VC2_WriteSamples
|
||||
#define VC1_WriteBytes VC2_WriteBytes
|
||||
#define VC1_Exit VC2_Exit
|
||||
#define VC1_VoiceSetVolume VC2_VoiceSetVolume
|
||||
#define VC1_VoiceGetVolume VC2_VoiceGetVolume
|
||||
#define VC1_VoiceSetPanning VC2_VoiceSetPanning
|
||||
#define VC1_VoiceGetPanning VC2_VoiceGetPanning
|
||||
#define VC1_VoiceSetFrequency VC2_VoiceSetFrequency
|
||||
#define VC1_VoiceGetFrequency VC2_VoiceGetFrequency
|
||||
#define VC1_VoicePlay VC2_VoicePlay
|
||||
#define VC1_VoiceStop VC2_VoiceStop
|
||||
#define VC1_VoiceStopped VC2_VoiceStopped
|
||||
#define VC1_VoiceGetPosition VC2_VoiceGetPosition
|
||||
#define VC1_SampleUnload VC2_SampleUnload
|
||||
#define VC1_SampleLoad VC2_SampleLoad
|
||||
#define VC1_SampleSpace VC2_SampleSpace
|
||||
#define VC1_SampleLength VC2_SampleLength
|
||||
#define VC1_VoiceRealVolume VC2_VoiceRealVolume
|
||||
|
||||
#include "virtch_common.c"
|
||||
#undef _IN_VIRTCH_
|
||||
|
||||
void VC2_WriteSamples(SBYTE* buf,ULONG todo)
|
||||
{
|
||||
int left,portion=0;
|
||||
SBYTE *buffer;
|
||||
int t,pan,vol;
|
||||
|
||||
todo*=SAMPLING_FACTOR;
|
||||
|
||||
while(todo) {
|
||||
if(!tickleft) {
|
||||
if(vc_mode & DMODE_SOFT_MUSIC) md_player();
|
||||
tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L);
|
||||
tickleft&=~(SAMPLING_FACTOR-1);
|
||||
}
|
||||
left = MIN(tickleft, todo);
|
||||
buffer = buf;
|
||||
tickleft -= left;
|
||||
todo -= left;
|
||||
buf += samples2bytes(left)/SAMPLING_FACTOR;
|
||||
|
||||
while(left) {
|
||||
portion = MIN(left, samplesthatfit);
|
||||
memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2));
|
||||
for(t=0;t<vc_softchn;t++) {
|
||||
vnf = &vinf[t];
|
||||
|
||||
if(vnf->kick) {
|
||||
vnf->current=((SLONGLONG)(vnf->start))<<FRACBITS;
|
||||
vnf->kick = 0;
|
||||
vnf->active = 1;
|
||||
vnf->click = CLICK_BUFFER;
|
||||
vnf->rampvol = 0;
|
||||
}
|
||||
|
||||
if(!vnf->frq) vnf->active = 0;
|
||||
|
||||
if(vnf->active) {
|
||||
vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT))
|
||||
/md_mixfreq;
|
||||
if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment;
|
||||
vol = vnf->vol; pan = vnf->pan;
|
||||
|
||||
vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel;
|
||||
if(vc_mode & DMODE_STEREO) {
|
||||
if(pan!=PAN_SURROUND) {
|
||||
vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8;
|
||||
vnf->rvolsel=(vol*pan)>>8;
|
||||
} else {
|
||||
vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480;
|
||||
}
|
||||
} else
|
||||
vnf->lvolsel=vol;
|
||||
|
||||
idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<<FRACBITS)-1:0;
|
||||
idxlend=(vnf->repend)?((SLONGLONG)(vnf->repend)<<FRACBITS)-1:0;
|
||||
idxlpos=(SLONGLONG)(vnf->reppos)<<FRACBITS;
|
||||
AddChannel(vc_tickbuf,portion);
|
||||
}
|
||||
}
|
||||
|
||||
if(md_reverb) {
|
||||
if(md_reverb>15) md_reverb=15;
|
||||
MixReverb(vc_tickbuf,portion);
|
||||
}
|
||||
|
||||
if(vc_mode & DMODE_FLOAT)
|
||||
Mix32toFP((float*)buffer,vc_tickbuf,portion);
|
||||
else if(vc_mode & DMODE_16BITS)
|
||||
Mix32to16((SWORD*)buffer,vc_tickbuf,portion);
|
||||
else
|
||||
Mix32to8((SBYTE*)buffer,vc_tickbuf,portion);
|
||||
|
||||
buffer += samples2bytes(portion) / SAMPLING_FACTOR;
|
||||
left -= portion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL VC2_Init(void)
|
||||
{
|
||||
VC_SetupPointers();
|
||||
|
||||
if (!(md_mode&DMODE_HQMIXER))
|
||||
return VC1_Init();
|
||||
|
||||
if(!(Samples=(SWORD**)_mm_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) {
|
||||
_mm_errno = MMERR_INITIALIZING_MIXER;
|
||||
return 1;
|
||||
}
|
||||
if(!vc_tickbuf)
|
||||
if(!(vc_tickbuf=(SLONG*)_mm_malloc((TICKLSIZE+32)*sizeof(SLONG)))) {
|
||||
_mm_errno = MMERR_INITIALIZING_MIXER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(md_mode & DMODE_STEREO) {
|
||||
Mix32toFP = Mix32ToFP_Stereo;
|
||||
Mix32to16 = Mix32To16_Stereo;
|
||||
Mix32to8 = Mix32To8_Stereo;
|
||||
MixReverb = MixReverb_Stereo;
|
||||
} else {
|
||||
Mix32toFP = Mix32ToFP_Normal;
|
||||
Mix32to16 = Mix32To16_Normal;
|
||||
Mix32to8 = Mix32To8_Normal;
|
||||
MixReverb = MixReverb_Normal;
|
||||
}
|
||||
md_mode |= DMODE_INTERP;
|
||||
vc_mode = md_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL VC2_PlayStart(void)
|
||||
{
|
||||
md_mode|=DMODE_INTERP;
|
||||
|
||||
samplesthatfit = TICKLSIZE;
|
||||
if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
|
||||
tickleft = 0;
|
||||
|
||||
RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10);
|
||||
RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10);
|
||||
|
||||
if(!(RVbufL1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufL8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
|
||||
|
||||
if(!(RVbufR1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
|
||||
if(!(RVbufR8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
|
||||
|
||||
RVRindex = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VC2_PlayStop(void)
|
||||
{
|
||||
if(RVbufL1) free(RVbufL1);
|
||||
if(RVbufL2) free(RVbufL2);
|
||||
if(RVbufL3) free(RVbufL3);
|
||||
if(RVbufL4) free(RVbufL4);
|
||||
if(RVbufL5) free(RVbufL5);
|
||||
if(RVbufL6) free(RVbufL6);
|
||||
if(RVbufL7) free(RVbufL7);
|
||||
if(RVbufL8) free(RVbufL8);
|
||||
if(RVbufR1) free(RVbufR1);
|
||||
if(RVbufR2) free(RVbufR2);
|
||||
if(RVbufR3) free(RVbufR3);
|
||||
if(RVbufR4) free(RVbufR4);
|
||||
if(RVbufR5) free(RVbufR5);
|
||||
if(RVbufR6) free(RVbufR6);
|
||||
if(RVbufR7) free(RVbufR7);
|
||||
if(RVbufR8) free(RVbufR8);
|
||||
|
||||
RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL;
|
||||
RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL;
|
||||
}
|
||||
|
||||
BOOL VC2_SetNumVoices(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
md_mode|=DMODE_INTERP;
|
||||
|
||||
if(!(vc_softchn=md_softchn)) return 0;
|
||||
|
||||
if(vinf) free(vinf);
|
||||
if(!(vinf=_mm_calloc(sizeof(VINFO),vc_softchn))) return 1;
|
||||
|
||||
for(t=0;t<vc_softchn;t++) {
|
||||
vinf[t].frq=10000;
|
||||
vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ex:set ts=4: */
|
||||
459
project/jni/mikmod/playercode/virtch_common.c
Normal file
459
project/jni/mikmod/playercode/virtch_common.c
Normal file
@@ -0,0 +1,459 @@
|
||||
/* MikMod sound library
|
||||
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
||||
for complete list.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This 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 Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
$Id: virtch_common.c,v 1.2 2004/02/13 13:31:54 raph Exp $
|
||||
|
||||
Common source parts between the two software mixers.
|
||||
This file is probably the ugliest part of libmikmod...
|
||||
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef _IN_VIRTCH_
|
||||
|
||||
#include "mikmod_internals.h"
|
||||
|
||||
extern BOOL VC1_Init(void);
|
||||
extern BOOL VC2_Init(void);
|
||||
static BOOL (*VC_Init_ptr)(void)=VC1_Init;
|
||||
extern void VC1_Exit(void);
|
||||
extern void VC2_Exit(void);
|
||||
static void (*VC_Exit_ptr)(void)=VC1_Exit;
|
||||
extern BOOL VC1_SetNumVoices(void);
|
||||
extern BOOL VC2_SetNumVoices(void);
|
||||
static BOOL (*VC_SetNumVoices_ptr)(void);
|
||||
extern ULONG VC1_SampleSpace(int);
|
||||
extern ULONG VC2_SampleSpace(int);
|
||||
static ULONG (*VC_SampleSpace_ptr)(int);
|
||||
extern ULONG VC1_SampleLength(int,SAMPLE*);
|
||||
extern ULONG VC2_SampleLength(int,SAMPLE*);
|
||||
static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*);
|
||||
|
||||
extern BOOL VC1_PlayStart(void);
|
||||
extern BOOL VC2_PlayStart(void);
|
||||
static BOOL (*VC_PlayStart_ptr)(void);
|
||||
extern void VC1_PlayStop(void);
|
||||
extern void VC2_PlayStop(void);
|
||||
static void (*VC_PlayStop_ptr)(void);
|
||||
|
||||
extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
|
||||
extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
|
||||
static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int);
|
||||
extern void VC1_SampleUnload(SWORD);
|
||||
extern void VC2_SampleUnload(SWORD);
|
||||
static void (*VC_SampleUnload_ptr)(SWORD);
|
||||
|
||||
extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
|
||||
extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
|
||||
static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG);
|
||||
extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
|
||||
extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
|
||||
static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG);
|
||||
|
||||
extern void VC1_VoiceSetVolume(UBYTE,UWORD);
|
||||
extern void VC2_VoiceSetVolume(UBYTE,UWORD);
|
||||
static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD);
|
||||
extern UWORD VC1_VoiceGetVolume(UBYTE);
|
||||
extern UWORD VC2_VoiceGetVolume(UBYTE);
|
||||
static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE);
|
||||
extern void VC1_VoiceSetFrequency(UBYTE,ULONG);
|
||||
extern void VC2_VoiceSetFrequency(UBYTE,ULONG);
|
||||
static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG);
|
||||
extern ULONG VC1_VoiceGetFrequency(UBYTE);
|
||||
extern ULONG VC2_VoiceGetFrequency(UBYTE);
|
||||
static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE);
|
||||
extern void VC1_VoiceSetPanning(UBYTE,ULONG);
|
||||
extern void VC2_VoiceSetPanning(UBYTE,ULONG);
|
||||
static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG);
|
||||
extern ULONG VC1_VoiceGetPanning(UBYTE);
|
||||
extern ULONG VC2_VoiceGetPanning(UBYTE);
|
||||
static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE);
|
||||
extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
||||
|
||||
extern void VC1_VoiceStop(UBYTE);
|
||||
extern void VC2_VoiceStop(UBYTE);
|
||||
static void (*VC_VoiceStop_ptr)(UBYTE);
|
||||
extern BOOL VC1_VoiceStopped(UBYTE);
|
||||
extern BOOL VC2_VoiceStopped(UBYTE);
|
||||
static BOOL (*VC_VoiceStopped_ptr)(UBYTE);
|
||||
extern SLONG VC1_VoiceGetPosition(UBYTE);
|
||||
extern SLONG VC2_VoiceGetPosition(UBYTE);
|
||||
static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE);
|
||||
extern ULONG VC1_VoiceRealVolume(UBYTE);
|
||||
extern ULONG VC2_VoiceRealVolume(UBYTE);
|
||||
static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE);
|
||||
|
||||
#if defined __STDC__ || defined _MSC_VER
|
||||
#define VC_PROC0(suffix) \
|
||||
MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); }
|
||||
|
||||
#define VC_FUNC0(suffix,ret) \
|
||||
MIKMODAPI ret VC_##suffix (void) { return VC_##suffix##_ptr(); }
|
||||
|
||||
#define VC_PROC1(suffix,typ1) \
|
||||
MIKMODAPI void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); }
|
||||
|
||||
#define VC_FUNC1(suffix,ret,typ1) \
|
||||
MIKMODAPI ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); }
|
||||
|
||||
#define VC_PROC2(suffix,typ1,typ2) \
|
||||
MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
|
||||
|
||||
#define VC_FUNC2(suffix,ret,typ1,typ2) \
|
||||
MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
|
||||
#else
|
||||
#define VC_PROC0(suffix) \
|
||||
MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); }
|
||||
|
||||
#define VC_FUNC0(suffix,ret) \
|
||||
MIKMODAPI ret VC_/**/suffix (void) { return VC_/**/suffix/**/_ptr(); }
|
||||
|
||||
#define VC_PROC1(suffix,typ1) \
|
||||
MIKMODAPI void VC_/**/suffix (typ1 a) { VC_/**/suffix/**/_ptr(a); }
|
||||
|
||||
#define VC_FUNC1(suffix,ret,typ1) \
|
||||
MIKMODAPI ret VC_/**/suffix (typ1 a) { return VC_/**/suffix/**/_ptr(a); }
|
||||
|
||||
#define VC_PROC2(suffix,typ1,typ2) \
|
||||
MIKMODAPI void VC_/**/suffix (typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); }
|
||||
|
||||
#define VC_FUNC2(suffix,ret,typ1,typ2) \
|
||||
MIKMODAPI ret VC_/**/suffix (typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); }
|
||||
#endif
|
||||
|
||||
VC_FUNC0(Init,BOOL)
|
||||
VC_PROC0(Exit)
|
||||
VC_FUNC0(SetNumVoices,BOOL)
|
||||
VC_FUNC1(SampleSpace,ULONG,int)
|
||||
VC_FUNC2(SampleLength,ULONG,int,SAMPLE*)
|
||||
VC_FUNC0(PlayStart,BOOL)
|
||||
VC_PROC0(PlayStop)
|
||||
VC_FUNC2(SampleLoad,SWORD,struct SAMPLOAD*,int)
|
||||
VC_PROC1(SampleUnload,SWORD)
|
||||
VC_FUNC2(WriteBytes,ULONG,SBYTE*,ULONG)
|
||||
VC_FUNC2(SilenceBytes,ULONG,SBYTE*,ULONG)
|
||||
VC_PROC2(VoiceSetVolume,UBYTE,UWORD)
|
||||
VC_FUNC1(VoiceGetVolume,UWORD,UBYTE)
|
||||
VC_PROC2(VoiceSetFrequency,UBYTE,ULONG)
|
||||
VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE)
|
||||
VC_PROC2(VoiceSetPanning,UBYTE,ULONG)
|
||||
VC_FUNC1(VoiceGetPanning,ULONG,UBYTE)
|
||||
|
||||
void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g)
|
||||
{ VC_VoicePlay_ptr(a,b,c,d,e,f,g); }
|
||||
|
||||
VC_PROC1(VoiceStop,UBYTE)
|
||||
VC_FUNC1(VoiceStopped,BOOL,UBYTE)
|
||||
VC_FUNC1(VoiceGetPosition,SLONG,UBYTE)
|
||||
VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
|
||||
|
||||
void VC_SetupPointers(void)
|
||||
{
|
||||
if (md_mode&DMODE_HQMIXER) {
|
||||
VC_Init_ptr=VC2_Init;
|
||||
VC_Exit_ptr=VC2_Exit;
|
||||
VC_SetNumVoices_ptr=VC2_SetNumVoices;
|
||||
VC_SampleSpace_ptr=VC2_SampleSpace;
|
||||
VC_SampleLength_ptr=VC2_SampleLength;
|
||||
VC_PlayStart_ptr=VC2_PlayStart;
|
||||
VC_PlayStop_ptr=VC2_PlayStop;
|
||||
VC_SampleLoad_ptr=VC2_SampleLoad;
|
||||
VC_SampleUnload_ptr=VC2_SampleUnload;
|
||||
VC_WriteBytes_ptr=VC2_WriteBytes;
|
||||
VC_SilenceBytes_ptr=VC2_SilenceBytes;
|
||||
VC_VoiceSetVolume_ptr=VC2_VoiceSetVolume;
|
||||
VC_VoiceGetVolume_ptr=VC2_VoiceGetVolume;
|
||||
VC_VoiceSetFrequency_ptr=VC2_VoiceSetFrequency;
|
||||
VC_VoiceGetFrequency_ptr=VC2_VoiceGetFrequency;
|
||||
VC_VoiceSetPanning_ptr=VC2_VoiceSetPanning;
|
||||
VC_VoiceGetPanning_ptr=VC2_VoiceGetPanning;
|
||||
VC_VoicePlay_ptr=VC2_VoicePlay;
|
||||
VC_VoiceStop_ptr=VC2_VoiceStop;
|
||||
VC_VoiceStopped_ptr=VC2_VoiceStopped;
|
||||
VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition;
|
||||
VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume;
|
||||
} else {
|
||||
VC_Init_ptr=VC1_Init;
|
||||
VC_Exit_ptr=VC1_Exit;
|
||||
VC_SetNumVoices_ptr=VC1_SetNumVoices;
|
||||
VC_SampleSpace_ptr=VC1_SampleSpace;
|
||||
VC_SampleLength_ptr=VC1_SampleLength;
|
||||
VC_PlayStart_ptr=VC1_PlayStart;
|
||||
VC_PlayStop_ptr=VC1_PlayStop;
|
||||
VC_SampleLoad_ptr=VC1_SampleLoad;
|
||||
VC_SampleUnload_ptr=VC1_SampleUnload;
|
||||
VC_WriteBytes_ptr=VC1_WriteBytes;
|
||||
VC_SilenceBytes_ptr=VC1_SilenceBytes;
|
||||
VC_VoiceSetVolume_ptr=VC1_VoiceSetVolume;
|
||||
VC_VoiceGetVolume_ptr=VC1_VoiceGetVolume;
|
||||
VC_VoiceSetFrequency_ptr=VC1_VoiceSetFrequency;
|
||||
VC_VoiceGetFrequency_ptr=VC1_VoiceGetFrequency;
|
||||
VC_VoiceSetPanning_ptr=VC1_VoiceSetPanning;
|
||||
VC_VoiceGetPanning_ptr=VC1_VoiceGetPanning;
|
||||
VC_VoicePlay_ptr=VC1_VoicePlay;
|
||||
VC_VoiceStop_ptr=VC1_VoiceStop;
|
||||
VC_VoiceStopped_ptr=VC1_VoiceStopped;
|
||||
VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition;
|
||||
VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef _VIRTCH_COMMON_
|
||||
#define _VIRTCH_COMMON_
|
||||
|
||||
static ULONG samples2bytes(ULONG samples)
|
||||
{
|
||||
if(vc_mode & DMODE_FLOAT) samples <<= 2;
|
||||
else if(vc_mode & DMODE_16BITS) samples <<= 1;
|
||||
if(vc_mode & DMODE_STEREO) samples <<= 1;
|
||||
return samples;
|
||||
}
|
||||
|
||||
static ULONG bytes2samples(ULONG bytes)
|
||||
{
|
||||
if(vc_mode & DMODE_FLOAT) bytes >>= 2;
|
||||
else if(vc_mode & DMODE_16BITS) bytes >>= 1;
|
||||
if(vc_mode & DMODE_STEREO) bytes >>= 1;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
|
||||
how the buffer is filled) */
|
||||
ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
|
||||
{
|
||||
todo=samples2bytes(bytes2samples(todo));
|
||||
|
||||
/* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
|
||||
if(vc_mode & DMODE_FLOAT)
|
||||
memset(buf,0,todo);
|
||||
else if(vc_mode & DMODE_16BITS)
|
||||
memset(buf,0,todo);
|
||||
else
|
||||
memset(buf,0x80,todo);
|
||||
|
||||
return todo;
|
||||
}
|
||||
|
||||
void VC1_WriteSamples(SBYTE*,ULONG);
|
||||
|
||||
/* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
|
||||
actually written to 'buf' (which is rounded to number of samples that fit
|
||||
into 'todo' bytes). */
|
||||
ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
|
||||
{
|
||||
if(!vc_softchn)
|
||||
return VC1_SilenceBytes(buf,todo);
|
||||
|
||||
todo = bytes2samples(todo);
|
||||
VC1_WriteSamples(buf,todo);
|
||||
|
||||
return samples2bytes(todo);
|
||||
}
|
||||
|
||||
void VC1_Exit(void)
|
||||
{
|
||||
if(vc_tickbuf) free(vc_tickbuf);
|
||||
if(vinf) free(vinf);
|
||||
if(Samples) free(Samples);
|
||||
|
||||
vc_tickbuf = NULL;
|
||||
vinf = NULL;
|
||||
Samples = NULL;
|
||||
|
||||
VC_SetupPointers();
|
||||
}
|
||||
|
||||
UWORD VC1_VoiceGetVolume(UBYTE voice)
|
||||
{
|
||||
return vinf[voice].vol;
|
||||
}
|
||||
|
||||
ULONG VC1_VoiceGetPanning(UBYTE voice)
|
||||
{
|
||||
return vinf[voice].pan;
|
||||
}
|
||||
|
||||
void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)
|
||||
{
|
||||
vinf[voice].frq=frq;
|
||||
}
|
||||
|
||||
ULONG VC1_VoiceGetFrequency(UBYTE voice)
|
||||
{
|
||||
return vinf[voice].frq;
|
||||
}
|
||||
|
||||
void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
|
||||
{
|
||||
vinf[voice].flags = flags;
|
||||
vinf[voice].handle = handle;
|
||||
vinf[voice].start = start;
|
||||
vinf[voice].size = size;
|
||||
vinf[voice].reppos = reppos;
|
||||
vinf[voice].repend = repend;
|
||||
vinf[voice].kick = 1;
|
||||
}
|
||||
|
||||
void VC1_VoiceStop(UBYTE voice)
|
||||
{
|
||||
vinf[voice].active = 0;
|
||||
}
|
||||
|
||||
BOOL VC1_VoiceStopped(UBYTE voice)
|
||||
{
|
||||
return(vinf[voice].active==0);
|
||||
}
|
||||
|
||||
SLONG VC1_VoiceGetPosition(UBYTE voice)
|
||||
{
|
||||
return(vinf[voice].current>>FRACBITS);
|
||||
}
|
||||
|
||||
void VC1_VoiceSetVolume(UBYTE voice,UWORD vol)
|
||||
{
|
||||
/* protect against clicks if volume variation is too high */
|
||||
if(abs((int)vinf[voice].vol-(int)vol)>32)
|
||||
vinf[voice].rampvol=CLICK_BUFFER;
|
||||
vinf[voice].vol=vol;
|
||||
}
|
||||
|
||||
void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
|
||||
{
|
||||
/* protect against clicks if panning variation is too high */
|
||||
if(abs((int)vinf[voice].pan-(int)pan)>48)
|
||||
vinf[voice].rampvol=CLICK_BUFFER;
|
||||
vinf[voice].pan=pan;
|
||||
}
|
||||
|
||||
/*========== External mixer interface */
|
||||
|
||||
void VC1_SampleUnload(SWORD handle)
|
||||
{
|
||||
if (handle<MAXSAMPLEHANDLES) {
|
||||
if (Samples[handle])
|
||||
free(Samples[handle]);
|
||||
Samples[handle]=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
|
||||
{
|
||||
SAMPLE *s = sload->sample;
|
||||
int handle;
|
||||
ULONG t, length,loopstart,loopend;
|
||||
|
||||
if(type==MD_HARDWARE) return -1;
|
||||
|
||||
/* Find empty slot to put sample address in */
|
||||
for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
|
||||
if(!Samples[handle]) break;
|
||||
|
||||
if(handle==MAXSAMPLEHANDLES) {
|
||||
_mm_errno = MMERR_OUT_OF_HANDLES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reality check for loop settings */
|
||||
if (s->loopend > s->length)
|
||||
s->loopend = s->length;
|
||||
if (s->loopstart >= s->loopend)
|
||||
s->flags &= ~SF_LOOP;
|
||||
|
||||
length = s->length;
|
||||
loopstart = s->loopstart;
|
||||
loopend = s->loopend;
|
||||
|
||||
SL_SampleSigned(sload);
|
||||
SL_Sample8to16(sload);
|
||||
|
||||
if(!(Samples[handle]=(SWORD*)_mm_malloc((length+20)<<1))) {
|
||||
_mm_errno = MMERR_SAMPLE_TOO_BIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read sample into buffer */
|
||||
if (SL_Load(Samples[handle],sload,length))
|
||||
return -1;
|
||||
|
||||
/* Unclick sample */
|
||||
if(s->flags & SF_LOOP) {
|
||||
if(s->flags & SF_BIDI)
|
||||
for(t=0;t<16;t++)
|
||||
Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
|
||||
else
|
||||
for(t=0;t<16;t++)
|
||||
Samples[handle][loopend+t]=Samples[handle][t+loopstart];
|
||||
} else
|
||||
for(t=0;t<16;t++)
|
||||
Samples[handle][t+length]=0;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
ULONG VC1_SampleSpace(int type)
|
||||
{
|
||||
return vc_memory;
|
||||
}
|
||||
|
||||
ULONG VC1_SampleLength(int type,SAMPLE* s)
|
||||
{
|
||||
if (!s) return 0;
|
||||
|
||||
return (s->length*((s->flags&SF_16BITS)?2:1))+16;
|
||||
}
|
||||
|
||||
ULONG VC1_VoiceRealVolume(UBYTE voice)
|
||||
{
|
||||
ULONG i,s,size;
|
||||
int k,j;
|
||||
SWORD *smp;
|
||||
SLONG t;
|
||||
|
||||
t = vinf[voice].current>>FRACBITS;
|
||||
if(!vinf[voice].active) return 0;
|
||||
|
||||
s = vinf[voice].handle;
|
||||
size = vinf[voice].size;
|
||||
|
||||
i=64; t-=64; k=0; j=0;
|
||||
if(i>size) i = size;
|
||||
if(t<0) t = 0;
|
||||
if(t+i > size) t = size-i;
|
||||
|
||||
i &= ~1; /* make sure it's EVEN. */
|
||||
|
||||
smp = &Samples[s][t];
|
||||
for(;i;i--,smp++) {
|
||||
if(k<*smp) k = *smp;
|
||||
if(j>*smp) j = *smp;
|
||||
}
|
||||
return abs(k-j);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ex:set ts=4: */
|
||||
@@ -5,15 +5,16 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := sdl_mixer
|
||||
|
||||
LOCAL_CFLAGS := -O3 -I$(LOCAL_PATH) -I$(LOCAL_PATH)/../sdl-$(SDL_VERSION)/include -I$(LOCAL_PATH)/include \
|
||||
-I$(LOCAL_PATH)/../mad/include -I$(LOCAL_PATH)/../flac/include -I$(LOCAL_PATH)/../ogg/include -I$(LOCAL_PATH)/../vorbis/include -I$(LOCAL_PATH)/../tremor/include \
|
||||
-DWAV_MUSIC -DOGG_USE_TREMOR -DOGG_MUSIC -DFLAC_MUSIC
|
||||
-I$(LOCAL_PATH)/../mad/include -I$(LOCAL_PATH)/../flac/include -I$(LOCAL_PATH)/../ogg/include \
|
||||
-I$(LOCAL_PATH)/../vorbis/include -I$(LOCAL_PATH)/../tremor/include -I$(LOCAL_PATH)/../mikmod/include \
|
||||
-DWAV_MUSIC -DOGG_USE_TREMOR -DOGG_MUSIC -DFLAC_MUSIC -DMOD_MUSIC
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c))
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := sdl-$(SDL_VERSION)
|
||||
LOCAL_STATIC_LIBRARIES := flac
|
||||
LOCAL_STATIC_LIBRARIES := flac mikmod
|
||||
|
||||
ifeq "$(TARGET_ARCH_ABI)" "armeabi"
|
||||
LOCAL_CFLAGS += -DOGG_USE_TREMOR
|
||||
|
||||
Reference in New Issue
Block a user