Added timidity for use in openttd
This commit is contained in:
8
project/jni/timidity/AUTHORS
Normal file
8
project/jni/timidity/AUTHORS
Normal file
@@ -0,0 +1,8 @@
|
||||
* Tuukka Toivonen <toivonen@clinet.fi>
|
||||
wrote TiMidity and maintained it until version v0.2i.
|
||||
|
||||
* Torbjörn Andersson <d91tan@Update.UU.SE>
|
||||
code cleanup and import it to the SDL_sound library as MIDI decoder.
|
||||
|
||||
* Konstantin Korikov <lostclus@ua.fm>
|
||||
make a separate library from SDL_sound MIDI decoder.
|
||||
24
project/jni/timidity/Android.mk
Normal file
24
project/jni/timidity/Android.mk
Normal file
@@ -0,0 +1,24 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := timidity
|
||||
|
||||
APP_SUBDIRS := $(patsubst $(LOCAL_PATH)/%, %, $(shell find $(LOCAL_PATH)/src -type d))
|
||||
|
||||
LOCAL_CFLAGS := -O3 $(foreach D, $(APP_SUBDIRS), -I$(LOCAL_PATH)/$(D)) \
|
||||
-I$(LOCAL_PATH)/include -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_SHARED_LIBRARY)
|
||||
39
project/jni/timidity/CHANGES
Normal file
39
project/jni/timidity/CHANGES
Normal file
@@ -0,0 +1,39 @@
|
||||
This version of TiMidity should contain all the fixes from the
|
||||
November 15 2004 SDL_sound Subversion snapshot. In addition, I've made some
|
||||
changes of my own, e.g.:
|
||||
|
||||
* Replacing SDL types and endian-handling with owns.
|
||||
|
||||
* File access to the config file and instruments is done through
|
||||
stdio functions. File access to MIDI files is done through abstract
|
||||
input stream. Implemented functions to create input stream from
|
||||
file name, from stdio file pointer, from memory, from callback functions.
|
||||
|
||||
* Renamed interface functions
|
||||
Timidity_Init -> mid_init
|
||||
Timidity_Init_NoConfig -> mid_init_no_config
|
||||
Timidity_SetVolume -> mid_song_set_volume
|
||||
Timidity_PlaySome -> mid_song_read_wave
|
||||
Timidity_LoadDLS -> mid_dlspatches_load
|
||||
Timidity_FreeDLS -> mid_dlspatches_free
|
||||
Timidity_LoadDLSSong -> mid_song_load_dls
|
||||
Timidity_LoadSong -> mid_song_load
|
||||
Timidity_Start -> mid_song_start
|
||||
Timidity_Seek -> mid_song_seek
|
||||
Timidity_GetSongLength -> mid_song_get_total_time
|
||||
Timidity_FreeSong -> mid_song_free
|
||||
|
||||
* Most structures and macro definition made hidden and placed in
|
||||
timidity_internal.h.
|
||||
|
||||
* Results of mid_song_read_wave (Timidity_PlaySome) not
|
||||
depends with internal sample buffer size.
|
||||
|
||||
* mid_init can accept timidity config file name.
|
||||
|
||||
* Added functions: mid_song_get_time, mid_song_get_meta.
|
||||
|
||||
* Added examples/tests midi2raw.c and playmidi.c.
|
||||
|
||||
--
|
||||
Konstantin Korikov <lostclus@ua.fm>
|
||||
513
project/jni/timidity/COPYING
Normal file
513
project/jni/timidity/COPYING
Normal file
@@ -0,0 +1,513 @@
|
||||
Please note that the included source from TiMidity, is also licensed
|
||||
under the following terms (GNU LGPL), but can also be used separately
|
||||
under the GNU GPL, or the Perl Artistic License. Those licensing
|
||||
terms are not reprinted here, but can be found on the web easily.
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
53
project/jni/timidity/ChangeLog
Normal file
53
project/jni/timidity/ChangeLog
Normal file
@@ -0,0 +1,53 @@
|
||||
2004-11-23 Konstantin Korikov <lostclus@ua.fm>
|
||||
|
||||
* configure.ac: Changed version to 0.1.0.
|
||||
|
||||
* NEWS: NEWS updated.
|
||||
|
||||
* libtimidity.spec.in: Spec updated.
|
||||
|
||||
2004-11-22 Konstantin Korikov <lostclus@ua.fm>
|
||||
|
||||
* src/timidity.h.in, tests/midi2raw.c, tests/playmidi.c,
|
||||
src/readmidi.c: Replaced MID_SONG_TITLE to MID_SONG_TEXT.
|
||||
|
||||
* README: README updated.
|
||||
|
||||
* tests/playmidi.c: Added ao_close() call.
|
||||
|
||||
* src/playmidi.c: Fixed mid_song_seek, seeking to high positions.
|
||||
|
||||
* configure.ac, libtimidity.pc.in, libtimidity.spec.in,
|
||||
Makefile.am: Added pkg-config metadata file.
|
||||
|
||||
2004-11-21 Konstantin Korikov <lostclus@ua.fm>
|
||||
|
||||
* libtimidity.spec.in: Call ldconfig in post and postun scriplets.
|
||||
|
||||
* CHANGES, COPYING, ChangeLog, src/Makefile.am, src/common.c,
|
||||
src/common.h, src/dls1.h, src/dls2.h, src/instrum.c,
|
||||
src/instrum.h, src/instrum_dls.c, src/instrum_dls.h,
|
||||
src/mix.c, src/mix.h, src/options.h, src/output.c,
|
||||
src/output.h, src/playmidi.c, src/playmidi.h, src/readmidi.c,
|
||||
src/readmidi.h, src/resample.c, src/resample.h, src/stream.c,
|
||||
src/tables.c, src/tables.h, src/timidity.c, src/timidity.h.in,
|
||||
src/timidity_internal.h, tests/Makefile.am, tests/ame002.mid,
|
||||
tests/midi2raw.c, tests/playmidi.c, tests/runtest.sh: Imported
|
||||
sources.
|
||||
|
||||
* CHANGES, COPYING, ChangeLog, src/Makefile.am, src/common.c,
|
||||
src/common.h, src/dls1.h, src/dls2.h, src/instrum.c,
|
||||
src/instrum.h, src/instrum_dls.c, src/instrum_dls.h,
|
||||
src/mix.c, src/mix.h, src/options.h, src/output.c,
|
||||
src/output.h, src/playmidi.c, src/playmidi.h, src/readmidi.c,
|
||||
src/readmidi.h, src/resample.c, src/resample.h, src/stream.c,
|
||||
src/tables.c, src/tables.h, src/timidity.c, src/timidity.h.in,
|
||||
src/timidity_internal.h, tests/Makefile.am, tests/ame002.mid,
|
||||
tests/midi2raw.c, tests/playmidi.c, tests/runtest.sh: New file.
|
||||
|
||||
* AUTHORS, INSTALL, Makefile.am, NEWS, README, README.timidity,
|
||||
TODO, configure.ac, libtimidity.spec.in: Imported sources.
|
||||
|
||||
* AUTHORS, INSTALL, Makefile.am, NEWS, README, README.timidity,
|
||||
TODO, configure.ac, libtimidity.spec.in: New file.
|
||||
|
||||
229
project/jni/timidity/INSTALL
Normal file
229
project/jni/timidity/INSTALL
Normal file
@@ -0,0 +1,229 @@
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
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, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
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 you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' 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. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
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 support 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' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
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 machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
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.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--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.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
3
project/jni/timidity/NEWS
Normal file
3
project/jni/timidity/NEWS
Normal file
@@ -0,0 +1,3 @@
|
||||
2004-11-23 - 0.1.0 released
|
||||
|
||||
First release.
|
||||
12
project/jni/timidity/README
Normal file
12
project/jni/timidity/README
Normal file
@@ -0,0 +1,12 @@
|
||||
libTiMidity -- MIDI to WAVE converter library.
|
||||
|
||||
This library is based on the TiMidity decoder from SDL_sound library.
|
||||
Purpose to create this library is to avoid unnecessary dependences.
|
||||
SDL_sound requires SDL and some other libraries, that not needed to
|
||||
process MIDI files. In addition libTiMidity provides more suitable
|
||||
API to work with MIDI songs, it enables to specify full path to the
|
||||
timidity configuration file, and have function to retrieve meta data
|
||||
from MIDI song.
|
||||
|
||||
If you have propositions regarding development of this library please
|
||||
mail to me <lostclus@ua.fm>
|
||||
85
project/jni/timidity/README.timidity
Normal file
85
project/jni/timidity/README.timidity
Normal file
@@ -0,0 +1,85 @@
|
||||
---------------------------------*-text-*---------------------------------
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This is the README file for TiMidity v0.2i
|
||||
|
||||
TiMidity is a MIDI to WAVE converter that uses Gravis
|
||||
Ultrasound(*)-compatible patch files to generate digital audio data
|
||||
from General MIDI files. The audio data can be played through any
|
||||
sound device or stored on disk. On a fast machine, music can be
|
||||
played in real time. TiMidity runs under Linux, FreeBSD, HP-UX, SunOS, and
|
||||
Win32, and porting to other systems with gcc should be easy.
|
||||
|
||||
TiMidity Features:
|
||||
|
||||
* 32 or more dynamically allocated fully independent voices
|
||||
* Compatibility with GUS patch files
|
||||
* Output to 16- or 8-bit PCM or uLaw audio device, file, or
|
||||
stdout at any sampling rate
|
||||
* Optional interactive mode with real-time status display
|
||||
under ncurses and SLang terminal control libraries. Also
|
||||
a user friendly motif interface since version 0.2h
|
||||
* Support for transparent loading of compressed MIDI files and
|
||||
patch files
|
||||
|
||||
* Support for the following MIDI events:
|
||||
- Program change
|
||||
- Key pressure
|
||||
- Channel main volume
|
||||
- Tempo
|
||||
- Panning
|
||||
- Damper pedal (Sustain)
|
||||
- Pitch wheel
|
||||
- Pitch wheel sensitivity
|
||||
- Change drum set
|
||||
|
||||
* The file "CHANGES" contains a brief list of what has changed since
|
||||
the previous version. Please check it if you've been using a TiMidity
|
||||
version older than 0.2d. You may have to modify your configuration
|
||||
files slightly -- look at the included "gravis.cfg" for examples.
|
||||
|
||||
* Installation instructions are in the file "INSTALL".
|
||||
|
||||
* Instructions for use can be found in the manual page "timidity.man",
|
||||
preformatted in "timidity.txt", and in comments in the configuration
|
||||
files.
|
||||
|
||||
* The GNU General Public License can, as always, be found in the file
|
||||
"COPYING".
|
||||
|
||||
* TiMidity requires sampled instruments (patches) to play MIDI files. You
|
||||
should get the file "timidity-lib-0.1.tar.gz" and unpack it in the same
|
||||
directory where you unpacked the source code archive. You'll want more
|
||||
patches later -- read the file "FAQ" for pointers.
|
||||
|
||||
* The latest version of TiMidity can be found on the TiMidity Home Page,
|
||||
URL http://www.clinet.fi/~toivonen/timidity/
|
||||
|
||||
An alternative URL for Motif version is http://www.loria.fr/~pagel
|
||||
|
||||
* If you have any comments or suggestions, please email me!
|
||||
|
||||
|
||||
Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
[(*) Any Registered Trademarks used anywhere in the documentation or
|
||||
source code for TiMidity are acknowledged as belonging to their
|
||||
respective owners.]
|
||||
2
project/jni/timidity/TODO
Normal file
2
project/jni/timidity/TODO
Normal file
@@ -0,0 +1,2 @@
|
||||
* Need documentation
|
||||
* Error handling API (mid_errno, mid_strerror)
|
||||
93
project/jni/timidity/config.h
Normal file
93
project/jni/timidity/config.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Debug mode */
|
||||
/* #undef DEBUG */
|
||||
|
||||
/* Debug chatter */
|
||||
/* #undef DEBUG_CHATTER */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `dlopen' function. */
|
||||
/* #undef HAVE_DLOPEN */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the <math.h> header file. */
|
||||
#define HAVE_MATH_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `pow' function. */
|
||||
#define HAVE_POW 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libtimidity"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.1.0"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
//#define malloc rpl_malloc
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
206
project/jni/timidity/include/timidity.h
Normal file
206
project/jni/timidity/include/timidity.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
|
||||
libTiMidity -- MIDI to WAVE converter library
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
Copyright (C) 2004 Konstantin Korikov <lostclus@ua.fm>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TIMIDITY_H
|
||||
#define TIMIDITY_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define LIBTIMIDITY_VERSION_MAJOR 0L
|
||||
#define LIBTIMIDITY_VERSION_MINOR 1L
|
||||
#define LIBTIMIDITY_PATCHLEVEL 0L
|
||||
|
||||
#define LIBTIMIDITY_VERSION \
|
||||
((LIBTIMIDITY_VERSION_MAJOR<<16)| \
|
||||
(LIBTIMIDITY_VERSION_MINOR<< 8)| \
|
||||
(LIBTIMIDITY_PATCHLEVEL))
|
||||
|
||||
/* Audio format flags (defaults to LSB byte order)
|
||||
*/
|
||||
#define MID_AUDIO_U8 0x0008 /* Unsigned 8-bit samples */
|
||||
#define MID_AUDIO_S8 0x8008 /* Signed 8-bit samples */
|
||||
#define MID_AUDIO_U16LSB 0x0010 /* Unsigned 16-bit samples */
|
||||
#define MID_AUDIO_S16LSB 0x8010 /* Signed 16-bit samples */
|
||||
#define MID_AUDIO_U16MSB 0x1010 /* As above, but big-endian byte order */
|
||||
#define MID_AUDIO_S16MSB 0x9010 /* As above, but big-endian byte order */
|
||||
#define MID_AUDIO_U16 MID_AUDIO_U16LSB
|
||||
#define MID_AUDIO_S16 MID_AUDIO_S16LSB
|
||||
|
||||
/* Core Library Types
|
||||
*/
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char sint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short sint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int sint32;
|
||||
|
||||
typedef size_t (*MidIStreamReadFunc) (void *ctx, void *ptr, size_t size,
|
||||
size_t nmemb);
|
||||
typedef int (*MidIStreamCloseFunc) (void *ctx);
|
||||
|
||||
typedef struct _MidIStream MidIStream;
|
||||
typedef struct _MidDLSPatches MidDLSPatches;
|
||||
typedef struct _MidSong MidSong;
|
||||
|
||||
typedef struct _MidSongOptions MidSongOptions;
|
||||
struct _MidSongOptions
|
||||
{
|
||||
sint32 rate; /* DSP frequency -- samples per second */
|
||||
uint16 format; /* Audio data format */
|
||||
uint8 channels; /* Number of channels: 1 mono, 2 stereo */
|
||||
uint16 buffer_size; /* Sample buffer size in samples */
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MID_SONG_TEXT = 0,
|
||||
MID_SONG_COPYRIGHT = 1
|
||||
} MidSongMetaId;
|
||||
|
||||
|
||||
/* Core Library Functions
|
||||
* ======================
|
||||
*/
|
||||
|
||||
/* Initialize the library. If config_file is NULL
|
||||
* search for configuratin file in default directories
|
||||
*/
|
||||
extern int mid_init (char *config_file);
|
||||
|
||||
/* Initialize the library without reading any
|
||||
* configuratin file
|
||||
*/
|
||||
extern int mid_init_no_config (void);
|
||||
|
||||
/* Shutdown the library
|
||||
*/
|
||||
extern void mid_exit (void);
|
||||
|
||||
|
||||
/* Input Stream Functions
|
||||
* ======================
|
||||
*/
|
||||
|
||||
/* Create input stream from a file name
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_file (const char *file);
|
||||
|
||||
/* Create input stream from a file pointer
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_fp (FILE * fp, int autoclose);
|
||||
|
||||
/* Create input stream from memory
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_mem (void *mem, size_t size,
|
||||
int autofree);
|
||||
|
||||
/* Create custom input stream
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_callbacks (MidIStreamReadFunc read,
|
||||
MidIStreamCloseFunc close,
|
||||
void *context);
|
||||
|
||||
/* Read data from input stream
|
||||
*/
|
||||
extern size_t mid_istream_read (MidIStream * stream, void *ptr, size_t size,
|
||||
size_t nmemb);
|
||||
|
||||
/* Skip data from input stream
|
||||
*/
|
||||
extern void mid_istream_skip (MidIStream * stream, size_t len);
|
||||
|
||||
/* Close and destroy input stream
|
||||
*/
|
||||
extern int mid_istream_close (MidIStream * stream);
|
||||
|
||||
|
||||
/* DLS Pathes Functions
|
||||
* ====================
|
||||
*/
|
||||
|
||||
/* Load DLS patches
|
||||
*/
|
||||
extern MidDLSPatches *mid_dlspatches_load (MidIStream * stream);
|
||||
|
||||
/* Destroy DLS patches
|
||||
*/
|
||||
extern void mid_dlspatches_free (MidDLSPatches * patches);
|
||||
|
||||
|
||||
/* MIDI Song Functions
|
||||
* ===================
|
||||
*/
|
||||
|
||||
/* Load MIDI song
|
||||
*/
|
||||
extern MidSong *mid_song_load (MidIStream * stream,
|
||||
MidSongOptions * options);
|
||||
|
||||
/* Load MIDI song with specified DLS pathes
|
||||
*/
|
||||
extern MidSong *mid_song_load_dls (MidIStream * stream,
|
||||
MidDLSPatches * patches,
|
||||
MidSongOptions * options);
|
||||
|
||||
/* Set song amplification value
|
||||
*/
|
||||
extern void mid_song_set_volume (MidSong * song, int volume);
|
||||
|
||||
/* Seek song to the start position and initialize conversion
|
||||
*/
|
||||
extern void mid_song_start (MidSong * song);
|
||||
|
||||
/* Read WAVE data
|
||||
*/
|
||||
extern size_t mid_song_read_wave (MidSong * song, void *ptr, size_t size);
|
||||
|
||||
/* Seek song to specified offset in millseconds
|
||||
*/
|
||||
extern void mid_song_seek (MidSong * song, uint32 ms);
|
||||
|
||||
/* Get total song time in millseconds
|
||||
*/
|
||||
extern uint32 mid_song_get_total_time (MidSong * song);
|
||||
|
||||
/* Get current song time in millseconds
|
||||
*/
|
||||
extern uint32 mid_song_get_time (MidSong * song);
|
||||
|
||||
/* Get song meta data. Return NULL if no meta data found
|
||||
*/
|
||||
extern char *mid_song_get_meta (MidSong * song, MidSongMetaId what);
|
||||
|
||||
/* Destroy song
|
||||
*/
|
||||
extern void mid_song_free (MidSong * song);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* TIMIDITY_H */
|
||||
137
project/jni/timidity/src/common.c
Normal file
137
project/jni/timidity/src/common.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
common.c
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* I guess "rb" should be right for any libc */
|
||||
#define OPEN_MODE "rb"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
|
||||
/* The paths in this list will be tried whenever we're reading a file */
|
||||
static PathList *pathlist = NULL; /* This is a linked list */
|
||||
|
||||
/* This is meant to find and open files for reading */
|
||||
FILE *open_file(char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!name || !(*name))
|
||||
{
|
||||
DEBUG_MSG("Attempted to open nameless file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First try the given name */
|
||||
|
||||
DEBUG_MSG("Trying to open %s\n", name);
|
||||
if ((fp = fopen(name, OPEN_MODE)))
|
||||
return fp;
|
||||
|
||||
if (name[0] != PATH_SEP)
|
||||
{
|
||||
char current_filename[1024];
|
||||
PathList *plp = pathlist;
|
||||
int l;
|
||||
|
||||
while (plp) /* Try along the path then */
|
||||
{
|
||||
*current_filename = 0;
|
||||
l = strlen(plp->path);
|
||||
if(l)
|
||||
{
|
||||
strcpy(current_filename, plp->path);
|
||||
if(current_filename[l - 1] != PATH_SEP)
|
||||
{
|
||||
current_filename[l] = PATH_SEP;
|
||||
current_filename[l + 1] = '\0';
|
||||
}
|
||||
}
|
||||
strcat(current_filename, name);
|
||||
DEBUG_MSG("Trying to open %s\n", current_filename);
|
||||
if ((fp = fopen(current_filename, OPEN_MODE)))
|
||||
return fp;
|
||||
plp = plp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing could be opened. */
|
||||
DEBUG_MSG("Could not open %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This'll allocate memory or die. */
|
||||
void *safe_malloc(size_t count)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(count);
|
||||
if (p == NULL)
|
||||
DEBUG_MSG("Sorry. Couldn't malloc %d bytes.\n", count);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* This adds a directory to the path list */
|
||||
void add_to_pathlist(char *s)
|
||||
{
|
||||
PathList *plp = safe_malloc(sizeof(PathList));
|
||||
|
||||
if (plp == NULL)
|
||||
return;
|
||||
|
||||
plp->path = safe_malloc(strlen(s) + 1);
|
||||
if (plp->path == NULL)
|
||||
{
|
||||
free(plp);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(plp->path, s);
|
||||
plp->next = pathlist;
|
||||
pathlist = plp;
|
||||
}
|
||||
|
||||
void free_pathlist(void)
|
||||
{
|
||||
PathList *plp = pathlist;
|
||||
PathList *next;
|
||||
|
||||
while (plp)
|
||||
{
|
||||
next = plp->next;
|
||||
free(plp->path);
|
||||
free(plp);
|
||||
plp = next;
|
||||
}
|
||||
pathlist = NULL;
|
||||
}
|
||||
32
project/jni/timidity/src/common.h
Normal file
32
project/jni/timidity/src/common.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
common.h
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
void *next;
|
||||
} PathList;
|
||||
|
||||
extern FILE *open_file(char *name);
|
||||
extern void add_to_pathlist(char *s);
|
||||
extern void *safe_malloc(size_t count);
|
||||
extern void free_pathlist(void);
|
||||
266
project/jni/timidity/src/dls1.h
Normal file
266
project/jni/timidity/src/dls1.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/*==========================================================================;
|
||||
//
|
||||
// dls1.h
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Interface defines and structures for the Instrument Collection Form
|
||||
// RIFF DLS.
|
||||
//
|
||||
//
|
||||
// Written by Sonic Foundry 1996. Released for public use.
|
||||
//
|
||||
//=========================================================================*/
|
||||
|
||||
#ifndef _INC_DLS1
|
||||
#define _INC_DLS1
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// Layout of an instrument collection:
|
||||
//
|
||||
//
|
||||
// RIFF [] 'DLS ' [dlid,colh,INSTLIST,WAVEPOOL,INFOLIST]
|
||||
//
|
||||
// INSTLIST
|
||||
// LIST [] 'lins'
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
//
|
||||
// RGNLIST
|
||||
// LIST [] 'lrgn'
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
//
|
||||
// ARTLIST
|
||||
// LIST [] 'lart'
|
||||
// 'art1' level 1 Articulation connection graph
|
||||
// 'art2' level 2 Articulation connection graph
|
||||
// '3rd1' Possible 3rd party articulation structure 1
|
||||
// '3rd2' Possible 3rd party articulation structure 2 .... and so on
|
||||
//
|
||||
// WAVEPOOL
|
||||
// ptbl [] [pool table]
|
||||
// LIST [] 'wvpl'
|
||||
// [path],
|
||||
// [path],
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
//
|
||||
// INFOLIST
|
||||
// LIST [] 'INFO'
|
||||
// 'icmt' 'One of those crazy comments.'
|
||||
// 'icop' 'Copyright (C) 1996 Sonic Foundry'
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// FOURCC's used in the DLS file
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define FOURCC_DLS mmioFOURCC('D','L','S',' ')
|
||||
#define FOURCC_DLID mmioFOURCC('d','l','i','d')
|
||||
#define FOURCC_COLH mmioFOURCC('c','o','l','h')
|
||||
#define FOURCC_WVPL mmioFOURCC('w','v','p','l')
|
||||
#define FOURCC_PTBL mmioFOURCC('p','t','b','l')
|
||||
#define FOURCC_PATH mmioFOURCC('p','a','t','h')
|
||||
#define FOURCC_wave mmioFOURCC('w','a','v','e')
|
||||
#define FOURCC_LINS mmioFOURCC('l','i','n','s')
|
||||
#define FOURCC_INS mmioFOURCC('i','n','s',' ')
|
||||
#define FOURCC_INSH mmioFOURCC('i','n','s','h')
|
||||
#define FOURCC_LRGN mmioFOURCC('l','r','g','n')
|
||||
#define FOURCC_RGN mmioFOURCC('r','g','n',' ')
|
||||
#define FOURCC_RGNH mmioFOURCC('r','g','n','h')
|
||||
#define FOURCC_LART mmioFOURCC('l','a','r','t')
|
||||
#define FOURCC_ART1 mmioFOURCC('a','r','t','1')
|
||||
#define FOURCC_WLNK mmioFOURCC('w','l','n','k')
|
||||
#define FOURCC_WSMP mmioFOURCC('w','s','m','p')
|
||||
#define FOURCC_VERS mmioFOURCC('v','e','r','s')
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Articulation connection graph definitions
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/* Generic Sources */
|
||||
#define CONN_SRC_NONE 0x0000
|
||||
#define CONN_SRC_LFO 0x0001
|
||||
#define CONN_SRC_KEYONVELOCITY 0x0002
|
||||
#define CONN_SRC_KEYNUMBER 0x0003
|
||||
#define CONN_SRC_EG1 0x0004
|
||||
#define CONN_SRC_EG2 0x0005
|
||||
#define CONN_SRC_PITCHWHEEL 0x0006
|
||||
|
||||
/* Midi Controllers 0-127 */
|
||||
#define CONN_SRC_CC1 0x0081
|
||||
#define CONN_SRC_CC7 0x0087
|
||||
#define CONN_SRC_CC10 0x008a
|
||||
#define CONN_SRC_CC11 0x008b
|
||||
|
||||
/* Generic Destinations */
|
||||
#define CONN_DST_NONE 0x0000
|
||||
#define CONN_DST_ATTENUATION 0x0001
|
||||
#define CONN_DST_PITCH 0x0003
|
||||
#define CONN_DST_PAN 0x0004
|
||||
|
||||
/* LFO Destinations */
|
||||
#define CONN_DST_LFO_FREQUENCY 0x0104
|
||||
#define CONN_DST_LFO_STARTDELAY 0x0105
|
||||
|
||||
/* EG1 Destinations */
|
||||
#define CONN_DST_EG1_ATTACKTIME 0x0206
|
||||
#define CONN_DST_EG1_DECAYTIME 0x0207
|
||||
#define CONN_DST_EG1_RELEASETIME 0x0209
|
||||
#define CONN_DST_EG1_SUSTAINLEVEL 0x020a
|
||||
|
||||
/* EG2 Destinations */
|
||||
#define CONN_DST_EG2_ATTACKTIME 0x030a
|
||||
#define CONN_DST_EG2_DECAYTIME 0x030b
|
||||
#define CONN_DST_EG2_RELEASETIME 0x030d
|
||||
#define CONN_DST_EG2_SUSTAINLEVEL 0x030e
|
||||
|
||||
#define CONN_TRN_NONE 0x0000
|
||||
#define CONN_TRN_CONCAVE 0x0001
|
||||
|
||||
typedef struct _DLSID {
|
||||
ULONG ulData1;
|
||||
USHORT usData2;
|
||||
USHORT usData3;
|
||||
BYTE abData4[8];
|
||||
} DLSID, FAR *LPDLSID;
|
||||
|
||||
typedef struct _DLSVERSION {
|
||||
DWORD dwVersionMS;
|
||||
DWORD dwVersionLS;
|
||||
} DLSVERSION, FAR *LPDLSVERSION;
|
||||
|
||||
|
||||
typedef struct _CONNECTION {
|
||||
USHORT usSource;
|
||||
USHORT usControl;
|
||||
USHORT usDestination;
|
||||
USHORT usTransform;
|
||||
LONG lScale;
|
||||
} CONNECTION, FAR *LPCONNECTION;
|
||||
|
||||
|
||||
/* Level 1 Articulation Data */
|
||||
|
||||
typedef struct _CONNECTIONLIST {
|
||||
ULONG cbSize; /* size of the connection list structure */
|
||||
ULONG cConnections; /* count of connections in the list */
|
||||
} CONNECTIONLIST, FAR *LPCONNECTIONLIST;
|
||||
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Generic type defines for regions and instruments
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
typedef struct _RGNRANGE {
|
||||
USHORT usLow;
|
||||
USHORT usHigh;
|
||||
} RGNRANGE, FAR * LPRGNRANGE;
|
||||
|
||||
#define F_INSTRUMENT_DRUMS 0x80000000
|
||||
|
||||
typedef struct _MIDILOCALE {
|
||||
ULONG ulBank;
|
||||
ULONG ulInstrument;
|
||||
} MIDILOCALE, FAR *LPMIDILOCALE;
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Header structures found in an DLS file for collection, instruments, and
|
||||
// regions.
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
|
||||
|
||||
typedef struct _RGNHEADER {
|
||||
RGNRANGE RangeKey; /* Key range */
|
||||
RGNRANGE RangeVelocity; /* Velocity Range */
|
||||
USHORT fusOptions; /* Synthesis options for this range */
|
||||
USHORT usKeyGroup; /* Key grouping for non simultaneous play */
|
||||
/* 0 = no group, 1 up is group */
|
||||
/* for Level 1 only groups 1-15 are allowed */
|
||||
} RGNHEADER, FAR *LPRGNHEADER;
|
||||
|
||||
typedef struct _INSTHEADER {
|
||||
ULONG cRegions; /* Count of regions in this instrument */
|
||||
MIDILOCALE Locale; /* Intended MIDI locale of this instrument */
|
||||
} INSTHEADER, FAR *LPINSTHEADER;
|
||||
|
||||
typedef struct _DLSHEADER {
|
||||
ULONG cInstruments; /* Count of instruments in the collection */
|
||||
} DLSHEADER, FAR *LPDLSHEADER;
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////////////
|
||||
// definitions for the Wave link structure
|
||||
////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/* **** For level 1 only WAVELINK_CHANNEL_MONO is valid **** */
|
||||
/* ulChannel allows for up to 32 channels of audio with each bit position */
|
||||
/* specifiying a channel of playback */
|
||||
|
||||
#define WAVELINK_CHANNEL_LEFT 0x0001l
|
||||
#define WAVELINK_CHANNEL_RIGHT 0x0002l
|
||||
|
||||
#define F_WAVELINK_PHASE_MASTER 0x0001
|
||||
|
||||
typedef struct _WAVELINK { /* any paths or links are stored right after struct */
|
||||
USHORT fusOptions; /* options flags for this wave */
|
||||
USHORT usPhaseGroup; /* Phase grouping for locking channels */
|
||||
ULONG ulChannel; /* channel placement */
|
||||
ULONG ulTableIndex; /* index into the wave pool table, 0 based */
|
||||
} WAVELINK, FAR *LPWAVELINK;
|
||||
|
||||
#define POOL_CUE_NULL 0xffffffffl
|
||||
|
||||
typedef struct _POOLCUE {
|
||||
ULONG ulOffset; /* Offset to the entry in the list */
|
||||
} POOLCUE, FAR *LPPOOLCUE;
|
||||
|
||||
typedef struct _POOLTABLE {
|
||||
ULONG cbSize; /* size of the pool table structure */
|
||||
ULONG cCues; /* count of cues in the list */
|
||||
} POOLTABLE, FAR *LPPOOLTABLE;
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////////////
|
||||
// Structures for the "wsmp" chunk
|
||||
////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define F_WSMP_NO_TRUNCATION 0x0001l
|
||||
#define F_WSMP_NO_COMPRESSION 0x0002l
|
||||
|
||||
|
||||
typedef struct _rwsmp {
|
||||
ULONG cbSize;
|
||||
USHORT usUnityNote; /* MIDI Unity Playback Note */
|
||||
SHORT sFineTune; /* Fine Tune in log tuning */
|
||||
LONG lAttenuation; /* Overall Attenuation to be applied to data */
|
||||
ULONG fulOptions; /* Flag options */
|
||||
ULONG cSampleLoops; /* Count of Sample loops, 0 loops is one shot */
|
||||
} WSMPL, FAR *LPWSMPL;
|
||||
|
||||
|
||||
/* This loop type is a normal forward playing loop which is continually */
|
||||
/* played until the envelope reaches an off threshold in the release */
|
||||
/* portion of the volume envelope */
|
||||
|
||||
#define WLOOP_TYPE_FORWARD 0
|
||||
|
||||
typedef struct _rloop {
|
||||
ULONG cbSize;
|
||||
ULONG ulType; /* Loop Type */
|
||||
ULONG ulStart; /* Start of loop in samples */
|
||||
ULONG ulLength; /* Length of loop in samples */
|
||||
} WLOOP, FAR *LPWLOOP;
|
||||
|
||||
#endif /*_INC_DLS1 */
|
||||
130
project/jni/timidity/src/dls2.h
Normal file
130
project/jni/timidity/src/dls2.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
|
||||
dls2.h
|
||||
|
||||
Description:
|
||||
|
||||
Interface defines and structures for the DLS2 extensions of DLS.
|
||||
|
||||
|
||||
Written by Microsoft 1998. Released for public use.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_DLS2
|
||||
#define _INC_DLS2
|
||||
|
||||
/*
|
||||
FOURCC's used in the DLS2 file, in addition to DLS1 chunks
|
||||
*/
|
||||
|
||||
#define FOURCC_RGN2 mmioFOURCC('r','g','n','2')
|
||||
#define FOURCC_LAR2 mmioFOURCC('l','a','r','2')
|
||||
#define FOURCC_ART2 mmioFOURCC('a','r','t','2')
|
||||
#define FOURCC_CDL mmioFOURCC('c','d','l',' ')
|
||||
#define FOURCC_DLID mmioFOURCC('d','l','i','d')
|
||||
|
||||
/*
|
||||
Articulation connection graph definitions. These are in addition to
|
||||
the definitions in the DLS1 header.
|
||||
*/
|
||||
|
||||
/* Generic Sources (in addition to DLS1 sources. */
|
||||
#define CONN_SRC_POLYPRESSURE 0x0007 /* Polyphonic Pressure */
|
||||
#define CONN_SRC_CHANNELPRESSURE 0x0008 /* Channel Pressure */
|
||||
#define CONN_SRC_VIBRATO 0x0009 /* Vibrato LFO */
|
||||
#define CONN_SRC_MONOPRESSURE 0x000a /* MIDI Mono pressure */
|
||||
|
||||
|
||||
/* Midi Controllers */
|
||||
#define CONN_SRC_CC91 0x00db /* Reverb Send */
|
||||
#define CONN_SRC_CC93 0x00dd /* Chorus Send */
|
||||
|
||||
|
||||
/* Generic Destinations */
|
||||
#define CONN_DST_GAIN 0x0001 /* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */
|
||||
#define CONN_DST_KEYNUMBER 0x0005 /* Key Number Generator */
|
||||
|
||||
/* Audio Channel Output Destinations */
|
||||
#define CONN_DST_LEFT 0x0010 /* Left Channel Send */
|
||||
#define CONN_DST_RIGHT 0x0011 /* Right Channel Send */
|
||||
#define CONN_DST_CENTER 0x0012 /* Center Channel Send */
|
||||
#define CONN_DST_LEFTREAR 0x0013 /* Left Rear Channel Send */
|
||||
#define CONN_DST_RIGHTREAR 0x0014 /* Right Rear Channel Send */
|
||||
#define CONN_DST_LFE_CHANNEL 0x0015 /* LFE Channel Send */
|
||||
#define CONN_DST_CHORUS 0x0080 /* Chorus Send */
|
||||
#define CONN_DST_REVERB 0x0081 /* Reverb Send */
|
||||
|
||||
/* Vibrato LFO Destinations */
|
||||
#define CONN_DST_VIB_FREQUENCY 0x0114 /* Vibrato Frequency */
|
||||
#define CONN_DST_VIB_STARTDELAY 0x0115 /* Vibrato Start Delay */
|
||||
|
||||
/* EG1 Destinations */
|
||||
#define CONN_DST_EG1_DELAYTIME 0x020B /* EG1 Delay Time */
|
||||
#define CONN_DST_EG1_HOLDTIME 0x020C /* EG1 Hold Time */
|
||||
#define CONN_DST_EG1_SHUTDOWNTIME 0x020D /* EG1 Shutdown Time */
|
||||
|
||||
|
||||
/* EG2 Destinations */
|
||||
#define CONN_DST_EG2_DELAYTIME 0x030F /* EG2 Delay Time */
|
||||
#define CONN_DST_EG2_HOLDTIME 0x0310 /* EG2 Hold Time */
|
||||
|
||||
|
||||
/* Filter Destinations */
|
||||
#define CONN_DST_FILTER_CUTOFF 0x0500 /* Filter Cutoff Frequency */
|
||||
#define CONN_DST_FILTER_Q 0x0501 /* Filter Resonance */
|
||||
|
||||
|
||||
/* Transforms */
|
||||
#define CONN_TRN_CONVEX 0x0002 /* Convex Transform */
|
||||
#define CONN_TRN_SWITCH 0x0003 /* Switch Transform */
|
||||
|
||||
|
||||
/* Conditional chunk operators */
|
||||
#define DLS_CDL_AND 0x0001 /* X = X & Y */
|
||||
#define DLS_CDL_OR 0x0002 /* X = X | Y */
|
||||
#define DLS_CDL_XOR 0x0003 /* X = X ^ Y */
|
||||
#define DLS_CDL_ADD 0x0004 /* X = X + Y */
|
||||
#define DLS_CDL_SUBTRACT 0x0005 /* X = X - Y */
|
||||
#define DLS_CDL_MULTIPLY 0x0006 /* X = X * Y */
|
||||
#define DLS_CDL_DIVIDE 0x0007 /* X = X / Y */
|
||||
#define DLS_CDL_LOGICAL_AND 0x0008 /* X = X && Y */
|
||||
#define DLS_CDL_LOGICAL_OR 0x0009 /* X = X || Y */
|
||||
#define DLS_CDL_LT 0x000A /* X = (X < Y) */
|
||||
#define DLS_CDL_LE 0x000B /* X = (X <= Y) */
|
||||
#define DLS_CDL_GT 0x000C /* X = (X > Y) */
|
||||
#define DLS_CDL_GE 0x000D /* X = (X >= Y) */
|
||||
#define DLS_CDL_EQ 0x000E /* X = (X == Y) */
|
||||
#define DLS_CDL_NOT 0x000F /* X = !X */
|
||||
#define DLS_CDL_CONST 0x0010 /* 32-bit constant */
|
||||
#define DLS_CDL_QUERY 0x0011 /* 32-bit value returned from query */
|
||||
#define DLS_CDL_QUERYSUPPORTED 0x0012 /* Test to see if query is supported by synth */
|
||||
|
||||
/*
|
||||
Loop and release
|
||||
*/
|
||||
|
||||
#define WLOOP_TYPE_RELEASE 1
|
||||
|
||||
/*
|
||||
WaveLink chunk <wlnk-ck>
|
||||
*/
|
||||
|
||||
#define F_WAVELINK_MULTICHANNEL 0x0002
|
||||
|
||||
|
||||
/*
|
||||
DLSID queries for <cdl-ck>
|
||||
*/
|
||||
|
||||
DEFINE_GUID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
|
||||
DEFINE_GUID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
DEFINE_GUID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
DEFINE_GUID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
|
||||
#endif /* _INC_DLS2 */
|
||||
619
project/jni/timidity/src/instrum.c
Normal file
619
project/jni/timidity/src/instrum.c
Normal file
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.c
|
||||
|
||||
Code to load and unload GUS-compatible instrument patches.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "instrum_dls.h"
|
||||
#include "resample.h"
|
||||
#include "tables.h"
|
||||
|
||||
static void free_instrument(MidInstrument *ip)
|
||||
{
|
||||
MidSample *sp;
|
||||
int i;
|
||||
if (!ip) return;
|
||||
for (i=0; i<ip->samples; i++)
|
||||
{
|
||||
sp=&(ip->sample[i]);
|
||||
free(sp->data);
|
||||
}
|
||||
free(ip->sample);
|
||||
free(ip);
|
||||
}
|
||||
|
||||
static void free_bank(MidSong *song, int dr, int b)
|
||||
{
|
||||
int i;
|
||||
MidToneBank *bank=((dr) ? song->drumset[b] : song->tonebank[b]);
|
||||
for (i=0; i<128; i++)
|
||||
if (bank->instrument[i])
|
||||
{
|
||||
/* Not that this could ever happen, of course */
|
||||
if (bank->instrument[i] != MAGIC_LOAD_INSTRUMENT)
|
||||
free_instrument(bank->instrument[i]);
|
||||
bank->instrument[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
static sint32 convert_envelope_rate(MidSong *song, uint8 rate)
|
||||
{
|
||||
sint32 r;
|
||||
|
||||
r = 3 - ((rate >> 6) & 0x3);
|
||||
r *= 3;
|
||||
r = (sint32) (rate & 0x3f) << r; /* 6.9 fixed point */
|
||||
|
||||
/* 15.15 fixed point. */
|
||||
r = ((r * 44100) / song->rate) * song->control_ratio;
|
||||
|
||||
#ifdef FAST_DECAY
|
||||
return r << 10;
|
||||
#else
|
||||
return r << 9;
|
||||
#endif
|
||||
}
|
||||
|
||||
static sint32 convert_envelope_offset(uint8 offset)
|
||||
{
|
||||
/* This is not too good... Can anyone tell me what these values mean?
|
||||
Are they GUS-style "exponential" volumes? And what does that mean? */
|
||||
|
||||
/* 15.15 fixed point */
|
||||
return offset << (7+15);
|
||||
}
|
||||
|
||||
static sint32 convert_tremolo_sweep(MidSong *song, uint8 sweep)
|
||||
{
|
||||
if (!sweep)
|
||||
return 0;
|
||||
|
||||
return
|
||||
((song->control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
|
||||
(song->rate * sweep);
|
||||
}
|
||||
|
||||
static sint32 convert_vibrato_sweep(MidSong *song, uint8 sweep,
|
||||
sint32 vib_control_ratio)
|
||||
{
|
||||
if (!sweep)
|
||||
return 0;
|
||||
|
||||
return
|
||||
(sint32) (FSCALE((double) (vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT)
|
||||
/ (double)(song->rate * sweep));
|
||||
|
||||
/* this was overflowing with seashore.pat
|
||||
|
||||
((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
|
||||
(song->rate * sweep); */
|
||||
}
|
||||
|
||||
static sint32 convert_tremolo_rate(MidSong *song, uint8 rate)
|
||||
{
|
||||
return
|
||||
((SINE_CYCLE_LENGTH * song->control_ratio * rate) << RATE_SHIFT) /
|
||||
(TREMOLO_RATE_TUNING * song->rate);
|
||||
}
|
||||
|
||||
static sint32 convert_vibrato_rate(MidSong *song, uint8 rate)
|
||||
{
|
||||
/* Return a suitable vibrato_control_ratio value */
|
||||
return
|
||||
(VIBRATO_RATE_TUNING * song->rate) /
|
||||
(rate * 2 * MID_VIBRATO_SAMPLE_INCREMENTS);
|
||||
}
|
||||
|
||||
static void reverse_data(sint16 *sp, sint32 ls, sint32 le)
|
||||
{
|
||||
sint16 s, *ep=sp+le;
|
||||
sp+=ls;
|
||||
le-=ls;
|
||||
le/=2;
|
||||
while (le--)
|
||||
{
|
||||
s=*sp;
|
||||
*sp++=*ep;
|
||||
*ep--=s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If panning or note_to_use != -1, it will be used for all samples,
|
||||
instead of the sample-specific values in the instrument file.
|
||||
|
||||
For note_to_use, any value <0 or >127 will be forced to 0.
|
||||
|
||||
For other parameters, 1 means yes, 0 means no, other values are
|
||||
undefined.
|
||||
|
||||
TODO: do reverse loops right */
|
||||
static MidInstrument *load_instrument(MidSong *song, char *name, int percussion,
|
||||
int panning, int amp, int note_to_use,
|
||||
int strip_loop, int strip_envelope,
|
||||
int strip_tail)
|
||||
{
|
||||
MidInstrument *ip;
|
||||
MidSample *sp;
|
||||
FILE *fp;
|
||||
char tmp[1024];
|
||||
int i,j,noluck=0;
|
||||
static char *patch_ext[] = PATCH_EXT_LIST;
|
||||
|
||||
if (!name) return 0;
|
||||
|
||||
/* Open patch file */
|
||||
if ((fp=open_file(name)) == NULL)
|
||||
{
|
||||
noluck=1;
|
||||
/* Try with various extensions */
|
||||
for (i=0; patch_ext[i]; i++)
|
||||
{
|
||||
if (strlen(name)+strlen(patch_ext[i])<1024)
|
||||
{
|
||||
strcpy(tmp, name);
|
||||
strcat(tmp, patch_ext[i]);
|
||||
if ((fp=open_file(tmp)) != NULL)
|
||||
{
|
||||
noluck=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noluck)
|
||||
{
|
||||
DEBUG_MSG("Instrument `%s' can't be found.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_MSG("Loading instrument %s\n", tmp);
|
||||
|
||||
/* Read some headers and do cursory sanity checks. There are loads
|
||||
of magic offsets. This could be rewritten... */
|
||||
|
||||
if ((239 != fread(tmp, 1, 239, fp)) ||
|
||||
(memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
|
||||
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
||||
differences are */
|
||||
{
|
||||
DEBUG_MSG("%s: not an instrument\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers,
|
||||
0 means 1 */
|
||||
{
|
||||
DEBUG_MSG("Can't handle patches with %d instruments\n", tmp[82]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
||||
{
|
||||
DEBUG_MSG("Can't handle instruments with %d layers\n", tmp[151]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip=safe_malloc(sizeof(MidInstrument));
|
||||
ip->samples = tmp[198];
|
||||
ip->sample = safe_malloc(sizeof(MidSample) * ip->samples);
|
||||
for (i=0; i<ip->samples; i++)
|
||||
{
|
||||
|
||||
uint8 fractions;
|
||||
sint32 tmplong;
|
||||
uint16 tmpshort;
|
||||
uint8 tmpchar;
|
||||
|
||||
#define READ_CHAR(thing) \
|
||||
if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
|
||||
thing = tmpchar;
|
||||
#define READ_SHORT(thing) \
|
||||
if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
|
||||
thing = SWAPLE16(tmpshort);
|
||||
#define READ_LONG(thing) \
|
||||
if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
|
||||
thing = SWAPLE32(tmplong);
|
||||
|
||||
fseek(fp, 7, SEEK_CUR); /* Skip the wave name */
|
||||
|
||||
if (1 != fread(&fractions, 1, 1, fp))
|
||||
{
|
||||
fail:
|
||||
DEBUG_MSG("Error reading sample %d\n", i);
|
||||
for (j=0; j<i; j++)
|
||||
free(ip->sample[j].data);
|
||||
free(ip->sample);
|
||||
free(ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp=&(ip->sample[i]);
|
||||
|
||||
READ_LONG(sp->data_length);
|
||||
READ_LONG(sp->loop_start);
|
||||
READ_LONG(sp->loop_end);
|
||||
READ_SHORT(sp->sample_rate);
|
||||
READ_LONG(sp->low_freq);
|
||||
READ_LONG(sp->high_freq);
|
||||
READ_LONG(sp->root_freq);
|
||||
sp->low_vel = 0;
|
||||
sp->high_vel = 127;
|
||||
fseek(fp, 2, SEEK_CUR); /* Why have a "root frequency" and then
|
||||
* "tuning"?? */
|
||||
|
||||
READ_CHAR(tmp[0]);
|
||||
|
||||
if (panning==-1)
|
||||
sp->panning = (tmp[0] * 8 + 4) & 0x7f;
|
||||
else
|
||||
sp->panning=(uint8)(panning & 0x7F);
|
||||
|
||||
/* envelope, tremolo, and vibrato */
|
||||
if (18 != fread(tmp, 1, 18, fp)) goto fail;
|
||||
|
||||
if (!tmp[13] || !tmp[14])
|
||||
{
|
||||
sp->tremolo_sweep_increment=
|
||||
sp->tremolo_phase_increment=sp->tremolo_depth=0;
|
||||
DEBUG_MSG(" * no tremolo\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->tremolo_sweep_increment=convert_tremolo_sweep(song, tmp[12]);
|
||||
sp->tremolo_phase_increment=convert_tremolo_rate(song, tmp[13]);
|
||||
sp->tremolo_depth=tmp[14];
|
||||
DEBUG_MSG(" * tremolo: sweep %d, phase %d, depth %d\n",
|
||||
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
||||
sp->tremolo_depth);
|
||||
}
|
||||
|
||||
if (!tmp[16] || !tmp[17])
|
||||
{
|
||||
sp->vibrato_sweep_increment=
|
||||
sp->vibrato_control_ratio=sp->vibrato_depth=0;
|
||||
DEBUG_MSG(" * no vibrato\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->vibrato_control_ratio=convert_vibrato_rate(song, tmp[16]);
|
||||
sp->vibrato_sweep_increment=
|
||||
convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
||||
sp->vibrato_depth=tmp[17];
|
||||
DEBUG_MSG(" * vibrato: sweep %d, ctl %d, depth %d\n",
|
||||
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
||||
sp->vibrato_depth);
|
||||
|
||||
}
|
||||
|
||||
READ_CHAR(sp->modes);
|
||||
|
||||
fseek(fp, 40, SEEK_CUR); /* skip the useless scale frequency, scale
|
||||
factor (what's it mean?), and reserved
|
||||
space */
|
||||
|
||||
/* Mark this as a fixed-pitch instrument if such a deed is desired. */
|
||||
if (note_to_use!=-1)
|
||||
sp->note_to_use=(uint8)(note_to_use);
|
||||
else
|
||||
sp->note_to_use=0;
|
||||
|
||||
/* seashore.pat in the Midia patch set has no Sustain. I don't
|
||||
understand why, and fixing it by adding the Sustain flag to
|
||||
all looped patches probably breaks something else. We do it
|
||||
anyway. */
|
||||
|
||||
if (sp->modes & MODES_LOOPING)
|
||||
sp->modes |= MODES_SUSTAIN;
|
||||
|
||||
/* Strip any loops and envelopes we're permitted to */
|
||||
if ((strip_loop==1) &&
|
||||
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING |
|
||||
MODES_PINGPONG | MODES_REVERSE)))
|
||||
{
|
||||
DEBUG_MSG(" - Removing loop and/or sustain\n");
|
||||
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING |
|
||||
MODES_PINGPONG | MODES_REVERSE);
|
||||
}
|
||||
|
||||
if (strip_envelope==1)
|
||||
{
|
||||
if (sp->modes & MODES_ENVELOPE)
|
||||
DEBUG_MSG(" - Removing envelope\n");
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
}
|
||||
else if (strip_envelope != 0)
|
||||
{
|
||||
/* Have to make a guess. */
|
||||
if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||||
{
|
||||
/* No loop? Then what's there to sustain? No envelope needed
|
||||
either... */
|
||||
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
||||
DEBUG_MSG(" - No loop, removing sustain and envelope\n");
|
||||
}
|
||||
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
||||
{
|
||||
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
||||
That's a weird envelope. Take it out. */
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
DEBUG_MSG(" - Weirdness, removing envelope\n");
|
||||
}
|
||||
else if (!(sp->modes & MODES_SUSTAIN))
|
||||
{
|
||||
/* No sustain? Then no envelope. I don't know if this is
|
||||
justified, but patches without sustain usually don't need the
|
||||
envelope either... at least the Gravis ones. They're mostly
|
||||
drums. I think. */
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
DEBUG_MSG(" - No sustain, removing envelope\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (j=0; j<6; j++)
|
||||
{
|
||||
sp->envelope_rate[j]=
|
||||
convert_envelope_rate(song, tmp[j]);
|
||||
sp->envelope_offset[j]=
|
||||
convert_envelope_offset(tmp[6+j]);
|
||||
}
|
||||
|
||||
/* Then read the sample data */
|
||||
sp->data = safe_malloc(sp->data_length);
|
||||
if (1 != fread(sp->data, sp->data_length, 1, fp))
|
||||
goto fail;
|
||||
|
||||
if (!(sp->modes & MODES_16BIT)) /* convert to 16-bit data */
|
||||
{
|
||||
sint32 i=sp->data_length;
|
||||
uint8 *cp=(uint8 *)(sp->data);
|
||||
uint16 *tmp,*new;
|
||||
tmp=new=safe_malloc(sp->data_length*2);
|
||||
while (i--)
|
||||
*tmp++ = (uint16)(*cp++) << 8;
|
||||
cp=(uint8 *)(sp->data);
|
||||
sp->data = (sample_t *)new;
|
||||
free(cp);
|
||||
sp->data_length *= 2;
|
||||
sp->loop_start *= 2;
|
||||
sp->loop_end *= 2;
|
||||
}
|
||||
#ifndef LITTLE_ENDIAN
|
||||
else
|
||||
/* convert to machine byte order */
|
||||
{
|
||||
sint32 i=sp->data_length/2;
|
||||
sint16 *tmp=(sint16 *)sp->data,s;
|
||||
while (i--)
|
||||
{
|
||||
s=SWAPLE16(*tmp);
|
||||
*tmp++=s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
|
||||
{
|
||||
sint32 i=sp->data_length/2;
|
||||
sint16 *tmp=(sint16 *)sp->data;
|
||||
while (i--)
|
||||
*tmp++ ^= 0x8000;
|
||||
}
|
||||
|
||||
/* Reverse reverse loops and pass them off as normal loops */
|
||||
if (sp->modes & MODES_REVERSE)
|
||||
{
|
||||
sint32 t;
|
||||
/* The GUS apparently plays reverse loops by reversing the
|
||||
whole sample. We do the same because the GUS does not SUCK. */
|
||||
|
||||
DEBUG_MSG("Reverse loop in %s\n", name);
|
||||
reverse_data((sint16 *)sp->data, 0, sp->data_length/2);
|
||||
|
||||
t=sp->loop_start;
|
||||
sp->loop_start=sp->data_length - sp->loop_end;
|
||||
sp->loop_end=sp->data_length - t;
|
||||
|
||||
sp->modes &= ~MODES_REVERSE;
|
||||
sp->modes |= MODES_LOOPING; /* just in case */
|
||||
}
|
||||
|
||||
#ifdef ADJUST_SAMPLE_VOLUMES
|
||||
if (amp!=-1)
|
||||
sp->volume=(float)((amp) / 100.0);
|
||||
else
|
||||
{
|
||||
/* Try to determine a volume scaling factor for the sample.
|
||||
This is a very crude adjustment, but things sound more
|
||||
balanced with it. Still, this should be a runtime option. */
|
||||
sint32 i=sp->data_length/2;
|
||||
sint16 maxamp=0,a;
|
||||
sint16 *tmp=(sint16 *)sp->data;
|
||||
while (i--)
|
||||
{
|
||||
a=*tmp++;
|
||||
if (a<0) a=-a;
|
||||
if (a>maxamp)
|
||||
maxamp=a;
|
||||
}
|
||||
sp->volume=(float)(32768.0 / maxamp);
|
||||
DEBUG_MSG(" * volume comp: %f\n", sp->volume);
|
||||
}
|
||||
#else
|
||||
if (amp!=-1)
|
||||
sp->volume=(double)(amp) / 100.0;
|
||||
else
|
||||
sp->volume=1.0;
|
||||
#endif
|
||||
|
||||
sp->data_length /= 2; /* These are in bytes. Convert into samples. */
|
||||
sp->loop_start /= 2;
|
||||
sp->loop_end /= 2;
|
||||
|
||||
/* Then fractional samples */
|
||||
sp->data_length <<= FRACTION_BITS;
|
||||
sp->loop_start <<= FRACTION_BITS;
|
||||
sp->loop_end <<= FRACTION_BITS;
|
||||
|
||||
/* Adjust for fractional loop points. This is a guess. Does anyone
|
||||
know what "fractions" really stands for? */
|
||||
sp->loop_start |=
|
||||
(fractions & 0x0F) << (FRACTION_BITS-4);
|
||||
sp->loop_end |=
|
||||
((fractions>>4) & 0x0F) << (FRACTION_BITS-4);
|
||||
|
||||
/* If this instrument will always be played on the same note,
|
||||
and it's not looped, we can resample it now. */
|
||||
if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
|
||||
pre_resample(song, sp);
|
||||
|
||||
if (strip_tail==1)
|
||||
{
|
||||
/* Let's not really, just say we did. */
|
||||
DEBUG_MSG(" - Stripping tail\n");
|
||||
sp->data_length = sp->loop_end;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return ip;
|
||||
}
|
||||
|
||||
static int fill_bank(MidSong *song, int dr, int b)
|
||||
{
|
||||
int i, errors=0;
|
||||
MidToneBank *bank=((dr) ? song->drumset[b] : song->tonebank[b]);
|
||||
if (!bank)
|
||||
{
|
||||
DEBUG_MSG("Huh. Tried to load instruments in non-existent %s %d\n",
|
||||
(dr) ? "drumset" : "tone bank", b);
|
||||
return 0;
|
||||
}
|
||||
for (i=0; i<128; i++)
|
||||
{
|
||||
if (bank->instrument[i]==MAGIC_LOAD_INSTRUMENT)
|
||||
{
|
||||
bank->instrument[i]=load_instrument_dls(song, dr, b, i);
|
||||
if (bank->instrument[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(bank->tone[i].name))
|
||||
{
|
||||
DEBUG_MSG("No instrument mapped to %s %d, program %d%s\n",
|
||||
(dr)? "drum set" : "tone bank", b, i,
|
||||
(b!=0) ? "" : " - this instrument will not be heard");
|
||||
if (b!=0)
|
||||
{
|
||||
/* Mark the corresponding instrument in the default
|
||||
bank / drumset for loading (if it isn't already) */
|
||||
if (!dr)
|
||||
{
|
||||
if (!(song->tonebank[0]->instrument[i]))
|
||||
song->tonebank[0]->instrument[i] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(song->drumset[0]->instrument[i]))
|
||||
song->drumset[0]->instrument[i] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
}
|
||||
bank->instrument[i] = 0;
|
||||
errors++;
|
||||
}
|
||||
else if (!(bank->instrument[i] =
|
||||
load_instrument(song,
|
||||
bank->tone[i].name,
|
||||
(dr) ? 1 : 0,
|
||||
bank->tone[i].pan,
|
||||
bank->tone[i].amp,
|
||||
(bank->tone[i].note!=-1) ?
|
||||
bank->tone[i].note :
|
||||
((dr) ? i : -1),
|
||||
(bank->tone[i].strip_loop!=-1) ?
|
||||
bank->tone[i].strip_loop :
|
||||
((dr) ? 1 : -1),
|
||||
(bank->tone[i].strip_envelope != -1) ?
|
||||
bank->tone[i].strip_envelope :
|
||||
((dr) ? 1 : -1),
|
||||
bank->tone[i].strip_tail )))
|
||||
{
|
||||
DEBUG_MSG("Couldn't load instrument %s (%s %d, program %d)\n",
|
||||
bank->tone[i].name,
|
||||
(dr)? "drum set" : "tone bank", b, i);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int load_missing_instruments(MidSong *song)
|
||||
{
|
||||
int i=128,errors=0;
|
||||
while (i--)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
errors+=fill_bank(song,0,i);
|
||||
if (song->drumset[i])
|
||||
errors+=fill_bank(song,1,i);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
void free_instruments(MidSong *song)
|
||||
{
|
||||
int i=128;
|
||||
while(i--)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
free_bank(song, 0, i);
|
||||
if (song->drumset[i])
|
||||
free_bank(song, 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
int set_default_instrument(MidSong *song, char *name)
|
||||
{
|
||||
MidInstrument *ip;
|
||||
if (!(ip=load_instrument(song, name, 0, -1, -1, -1, 0, 0, 0)))
|
||||
return -1;
|
||||
song->default_instrument = ip;
|
||||
song->default_program = SPECIAL_PROGRAM;
|
||||
return 0;
|
||||
}
|
||||
41
project/jni/timidity/src/instrum.h
Normal file
41
project/jni/timidity/src/instrum.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.h
|
||||
|
||||
*/
|
||||
|
||||
/* Bits in modes: */
|
||||
#define MODES_16BIT (1<<0)
|
||||
#define MODES_UNSIGNED (1<<1)
|
||||
#define MODES_LOOPING (1<<2)
|
||||
#define MODES_PINGPONG (1<<3)
|
||||
#define MODES_REVERSE (1<<4)
|
||||
#define MODES_SUSTAIN (1<<5)
|
||||
#define MODES_ENVELOPE (1<<6)
|
||||
|
||||
/* A hack to delay instrument loading until after reading the
|
||||
entire MIDI file. */
|
||||
#define MAGIC_LOAD_INSTRUMENT ((MidInstrument *) (-1))
|
||||
|
||||
#define SPECIAL_PROGRAM -1
|
||||
|
||||
extern int load_missing_instruments(MidSong *song);
|
||||
extern void free_instruments(MidSong *song);
|
||||
extern int set_default_instrument(MidSong *song, char *name);
|
||||
1196
project/jni/timidity/src/instrum_dls.c
Normal file
1196
project/jni/timidity/src/instrum_dls.c
Normal file
File diff suppressed because it is too large
Load Diff
24
project/jni/timidity/src/instrum_dls.h
Normal file
24
project/jni/timidity/src/instrum_dls.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.h
|
||||
|
||||
*/
|
||||
|
||||
extern MidInstrument *load_instrument_dls(MidSong *song, int drum, int bank, int instrument);
|
||||
569
project/jni/timidity/src/mix.c
Normal file
569
project/jni/timidity/src/mix.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
Suddenly, you realize that this program is free software; you get
|
||||
an overwhelming urge to redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received another copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
I bet they'll be amazed.
|
||||
|
||||
mix.c */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
#include "mix.h"
|
||||
|
||||
/* Returns 1 if envelope runs out */
|
||||
int recompute_envelope(MidSong *song, int v)
|
||||
{
|
||||
int stage;
|
||||
|
||||
stage = song->voice[v].envelope_stage;
|
||||
|
||||
if (stage>5)
|
||||
{
|
||||
/* Envelope ran out. */
|
||||
song->voice[v].status = VOICE_FREE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
if (song->voice[v].status==VOICE_ON || song->voice[v].status==VOICE_SUSTAINED)
|
||||
{
|
||||
if (stage>2)
|
||||
{
|
||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||
song->voice[v].envelope_increment=0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
song->voice[v].envelope_stage=stage+1;
|
||||
|
||||
if (song->voice[v].envelope_volume==song->voice[v].sample->envelope_offset[stage])
|
||||
return recompute_envelope(song, v);
|
||||
song->voice[v].envelope_target = song->voice[v].sample->envelope_offset[stage];
|
||||
song->voice[v].envelope_increment = song->voice[v].sample->envelope_rate[stage];
|
||||
if (song->voice[v].envelope_target < song->voice[v].envelope_volume)
|
||||
song->voice[v].envelope_increment = -song->voice[v].envelope_increment;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apply_envelope_to_amp(MidSong *song, int v)
|
||||
{
|
||||
float lamp = song->voice[v].left_amp, ramp;
|
||||
sint32 la,ra;
|
||||
if (song->voice[v].panned == PANNED_MYSTERY)
|
||||
{
|
||||
ramp = song->voice[v].right_amp;
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
{
|
||||
lamp *= song->voice[v].tremolo_volume;
|
||||
ramp *= song->voice[v].tremolo_volume;
|
||||
}
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
ramp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
}
|
||||
|
||||
la = (sint32)FSCALE(lamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE)
|
||||
la=MAX_AMP_VALUE;
|
||||
|
||||
ra = (sint32)FSCALE(ramp,AMP_BITS);
|
||||
if (ra>MAX_AMP_VALUE)
|
||||
ra=MAX_AMP_VALUE;
|
||||
|
||||
song->voice[v].left_mix = la;
|
||||
song->voice[v].right_mix = ra;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
lamp *= song->voice[v].tremolo_volume;
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
|
||||
la = (sint32)FSCALE(lamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE)
|
||||
la=MAX_AMP_VALUE;
|
||||
|
||||
song->voice[v].left_mix = la;
|
||||
}
|
||||
}
|
||||
|
||||
static int update_envelope(MidSong *song, int v)
|
||||
{
|
||||
song->voice[v].envelope_volume += song->voice[v].envelope_increment;
|
||||
/* Why is there no ^^ operator?? */
|
||||
if (((song->voice[v].envelope_increment < 0) &&
|
||||
(song->voice[v].envelope_volume <= song->voice[v].envelope_target)) ||
|
||||
((song->voice[v].envelope_increment > 0) &&
|
||||
(song->voice[v].envelope_volume >= song->voice[v].envelope_target)))
|
||||
{
|
||||
song->voice[v].envelope_volume = song->voice[v].envelope_target;
|
||||
if (recompute_envelope(song, v))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_tremolo(MidSong *song, int v)
|
||||
{
|
||||
sint32 depth = song->voice[v].sample->tremolo_depth << 7;
|
||||
|
||||
if (song->voice[v].tremolo_sweep)
|
||||
{
|
||||
/* Update sweep position */
|
||||
|
||||
song->voice[v].tremolo_sweep_position += song->voice[v].tremolo_sweep;
|
||||
if (song->voice[v].tremolo_sweep_position >= (1 << SWEEP_SHIFT))
|
||||
song->voice[v].tremolo_sweep=0; /* Swept to max amplitude */
|
||||
else
|
||||
{
|
||||
/* Need to adjust depth */
|
||||
depth *= song->voice[v].tremolo_sweep_position;
|
||||
depth >>= SWEEP_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
song->voice[v].tremolo_phase += song->voice[v].tremolo_phase_increment;
|
||||
|
||||
/* if (song->voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
|
||||
song->voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT; */
|
||||
|
||||
song->voice[v].tremolo_volume = (float)
|
||||
(1.0 - FSCALENEG((sine(song->voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)
|
||||
* depth * TREMOLO_AMPLITUDE_TUNING,
|
||||
17));
|
||||
|
||||
/* I'm not sure about the +1.0 there -- it makes tremoloed voices'
|
||||
volumes on average the lower the higher the tremolo amplitude. */
|
||||
}
|
||||
|
||||
/* Returns 1 if the note died */
|
||||
static int update_signal(MidSong *song, int v)
|
||||
{
|
||||
if (song->voice[v].envelope_increment && update_envelope(song, v))
|
||||
return 1;
|
||||
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
update_tremolo(song, v);
|
||||
|
||||
apply_envelope_to_amp(song, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MIXATION(a) *lp++ += (a)*s;
|
||||
|
||||
static void mix_mystery_signal(MidSong *song, sample_t *sp, sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
MidVoice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix,
|
||||
right=vp->right_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
right = vp->right_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
right = vp->right_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center_signal(MidSong *song, sample_t *sp, sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
MidVoice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single_signal(MidSong *song, sample_t *sp, sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
MidVoice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono_signal(MidSong *song, sample_t *sp, sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
MidVoice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mystery(MidSong *song, sample_t *sp, sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix,
|
||||
right = song->voice[v].right_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center(MidSong *song, sample_t *sp, sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single(MidSong *song, sample_t *sp, sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono(MidSong *song, sample_t *sp, sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ramp a note out in c samples */
|
||||
static void ramp_out(MidSong *song, sample_t *sp, sint32 *lp, int v, sint32 c)
|
||||
{
|
||||
|
||||
/* should be final_volume_t, but uint8 gives trouble. */
|
||||
sint32 left, right, li, ri;
|
||||
|
||||
sample_t s=0; /* silly warning about uninitialized s */
|
||||
|
||||
/* Fix by James Caldwell */
|
||||
if ( c == 0 ) c = 1;
|
||||
|
||||
left=song->voice[v].left_mix;
|
||||
li=-(left/c);
|
||||
if (!li) li=-1;
|
||||
|
||||
/* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
|
||||
|
||||
if (!(song->encoding & PE_MONO))
|
||||
{
|
||||
if (song->voice[v].panned==PANNED_MYSTERY)
|
||||
{
|
||||
right=song->voice[v].right_mix;
|
||||
ri=-(right/c);
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
left=0;
|
||||
right += ri;
|
||||
if (right<0)
|
||||
right=0;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_CENTER)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_LEFT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_RIGHT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
lp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mono output. */
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************** interface function ******************/
|
||||
|
||||
void mix_voice(MidSong *song, sint32 *buf, int v, sint32 c)
|
||||
{
|
||||
MidVoice *vp = song->voice + v;
|
||||
sample_t *sp;
|
||||
if (vp->status==VOICE_DIE)
|
||||
{
|
||||
if (c>=MAX_DIE_TIME)
|
||||
c=MAX_DIE_TIME;
|
||||
sp=resample_voice(song, v, &c);
|
||||
ramp_out(song, sp, buf, v, c);
|
||||
vp->status=VOICE_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp=resample_voice(song, v, &c);
|
||||
if (song->encoding & PE_MONO)
|
||||
{
|
||||
/* Mono output. */
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mono_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_mono(song, sp, buf, v, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vp->panned == PANNED_MYSTERY)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mystery_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_mystery(song, sp, buf, v, c);
|
||||
}
|
||||
else if (vp->panned == PANNED_CENTER)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_center_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_center(song, sp, buf, v, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's either full left or full right. In either case,
|
||||
every other sample is 0. Just get the offset right: */
|
||||
if (vp->panned == PANNED_RIGHT) buf++;
|
||||
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_single_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_single(song, sp, buf, v, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
project/jni/timidity/src/mix.h
Normal file
27
project/jni/timidity/src/mix.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
In case you haven't heard, this program is free software;
|
||||
you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
mix.h
|
||||
|
||||
*/
|
||||
|
||||
extern void mix_voice(MidSong *song, sint32 *buf, int v, sint32 c);
|
||||
extern int recompute_envelope(MidSong *song, int v);
|
||||
extern void apply_envelope_to_amp(MidSong *song, int v);
|
||||
113
project/jni/timidity/src/options.h
Normal file
113
project/jni/timidity/src/options.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* When a patch file can't be opened, one of these extensions is
|
||||
appended to the filename and the open is tried again.
|
||||
*/
|
||||
#define PATCH_EXT_LIST { ".pat", 0 }
|
||||
|
||||
/* Acoustic Grand Piano seems to be the usual default instrument. */
|
||||
#define DEFAULT_PROGRAM 0
|
||||
|
||||
/* 9 here is MIDI channel 10, which is the standard percussion channel.
|
||||
Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too.
|
||||
On the other hand, some files know that 16 is not a drum channel and
|
||||
try to play music on it. This is now a runtime option, so this isn't
|
||||
a critical choice anymore. */
|
||||
#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))
|
||||
|
||||
/* In percent. */
|
||||
#define DEFAULT_AMPLIFICATION 70
|
||||
|
||||
/* Default polyphony */
|
||||
#define DEFAULT_VOICES 32
|
||||
|
||||
/* 1000 here will give a control ratio of 22:1 with 22 kHz output.
|
||||
Higher CONTROLS_PER_SECOND values allow more accurate rendering
|
||||
of envelopes and tremolo. The cost is CPU time. */
|
||||
#define CONTROLS_PER_SECOND 1000
|
||||
|
||||
/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay
|
||||
faster) and sounds more like a GUS. There is now a command line
|
||||
option to toggle this as well. */
|
||||
#define FAST_DECAY
|
||||
|
||||
/* How many bits to use for the fractional part of sample positions.
|
||||
This affects tonal accuracy. The entire position counter must fit
|
||||
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
||||
a sample is 1048576 samples (2 megabytes in memory). The GUS gets
|
||||
by with just 9 bits and a little help from its friends...
|
||||
"The GUS does not SUCK!!!" -- a happy user :) */
|
||||
#define FRACTION_BITS 12
|
||||
|
||||
/* For some reason the sample volume is always set to maximum in all
|
||||
patch files. Define this for a crude adjustment that may help
|
||||
equalize instrument volumes. */
|
||||
#define ADJUST_SAMPLE_VOLUMES
|
||||
|
||||
/* The number of samples to use for ramping out a dying note. Affects
|
||||
click removal. */
|
||||
#define MAX_DIE_TIME 20
|
||||
|
||||
/**************************************************************************/
|
||||
/* Anything below this shouldn't need to be changed unless you're porting
|
||||
to a new machine with other than 32-bit, big-endian words. */
|
||||
/**************************************************************************/
|
||||
|
||||
/* change FRACTION_BITS above, not these */
|
||||
#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
|
||||
#define FRACTION_MASK (~ INTEGER_MASK)
|
||||
|
||||
/* This is enforced by some computations that must fit in an int */
|
||||
#define MAX_CONTROL_RATIO 255
|
||||
|
||||
#define MAX_AMPLIFICATION 800
|
||||
|
||||
/* The TiMidity configuration file */
|
||||
#define CONFIG_FILE "timidity.cfg"
|
||||
|
||||
/* These affect general volume */
|
||||
#define GUARD_BITS 3
|
||||
#define AMP_BITS (15-GUARD_BITS)
|
||||
|
||||
#define MAX_AMP_VALUE ((1<<(AMP_BITS+1))-1)
|
||||
|
||||
#define FSCALE(a,b) (float)((a) * (double)(1<<(b)))
|
||||
#define FSCALENEG(a,b) (float)((a) * (1.0L / (double)(1<<(b))))
|
||||
|
||||
/* Vibrato and tremolo Choices of the Day */
|
||||
#define SWEEP_TUNING 38
|
||||
#define VIBRATO_AMPLITUDE_TUNING 1.0L
|
||||
#define VIBRATO_RATE_TUNING 38
|
||||
#define TREMOLO_AMPLITUDE_TUNING 1.0L
|
||||
#define TREMOLO_RATE_TUNING 38
|
||||
|
||||
#define SWEEP_SHIFT 16
|
||||
#define RATE_SHIFT 5
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* The path separator (D.M.) */
|
||||
#ifdef WIN32
|
||||
# define PATH_SEP '\\'
|
||||
#else
|
||||
# define PATH_SEP '/'
|
||||
#endif
|
||||
113
project/jni/timidity/src/output.c
Normal file
113
project/jni/timidity/src/output.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
output.c
|
||||
|
||||
Audio output (to file / device) functions.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
|
||||
/*****************************************************************/
|
||||
/* Some functions to convert signed 32-bit data to other formats */
|
||||
|
||||
void s32tos8(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
sint8 *cp=(sint8 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-8-GUARD_BITS);
|
||||
if (l>127) l=127;
|
||||
else if (l<-128) l=-128;
|
||||
*cp++ = (sint8) (l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou8(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
uint8 *cp=(uint8 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-8-GUARD_BITS);
|
||||
if (l>127) l=127;
|
||||
else if (l<-128) l=-128;
|
||||
*cp++ = 0x80 ^ ((uint8) l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tos16(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
sint16 *sp=(sint16 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = (sint16)(l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
uint16 *sp=(uint16 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = 0x8000 ^ (uint16)(l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tos16x(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
sint16 *sp=(sint16 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = XCHG_SHORT((sint16)(l));
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16x(void *dp, sint32 *lp, sint32 c)
|
||||
{
|
||||
uint16 *sp=(uint16 *)(dp);
|
||||
sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = XCHG_SHORT(0x8000 ^ (uint16)(l));
|
||||
}
|
||||
}
|
||||
56
project/jni/timidity/src/output.h
Normal file
56
project/jni/timidity/src/output.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
output.h
|
||||
|
||||
*/
|
||||
|
||||
/* Data format encoding bits */
|
||||
|
||||
#define PE_MONO 0x01 /* versus stereo */
|
||||
#define PE_SIGNED 0x02 /* versus unsigned */
|
||||
#define PE_16BIT 0x04 /* versus 8-bit */
|
||||
|
||||
/* Conversion functions -- These overwrite the sint32 data in *lp with
|
||||
data in another format */
|
||||
|
||||
/* 8-bit signed and unsigned*/
|
||||
extern void s32tos8(void *dp, sint32 *lp, sint32 c);
|
||||
extern void s32tou8(void *dp, sint32 *lp, sint32 c);
|
||||
|
||||
/* 16-bit */
|
||||
extern void s32tos16(void *dp, sint32 *lp, sint32 c);
|
||||
extern void s32tou16(void *dp, sint32 *lp, sint32 c);
|
||||
|
||||
/* byte-exchanged 16-bit */
|
||||
extern void s32tos16x(void *dp, sint32 *lp, sint32 c);
|
||||
extern void s32tou16x(void *dp, sint32 *lp, sint32 c);
|
||||
|
||||
/* little-endian and big-endian specific */
|
||||
#ifdef LITTLE_ENDIAN
|
||||
#define s32tou16l s32tou16
|
||||
#define s32tou16b s32tou16x
|
||||
#define s32tos16l s32tos16
|
||||
#define s32tos16b s32tos16x
|
||||
#else
|
||||
#define s32tou16l s32tou16x
|
||||
#define s32tou16b s32tou16
|
||||
#define s32tos16l s32tos16x
|
||||
#define s32tos16b s32tos16
|
||||
#endif
|
||||
804
project/jni/timidity/src/playmidi.c
Normal file
804
project/jni/timidity/src/playmidi.c
Normal file
@@ -0,0 +1,804 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
playmidi.c -- random stuff in need of rearrangement
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "mix.h"
|
||||
#include "tables.h"
|
||||
|
||||
static void adjust_amplification(MidSong *song)
|
||||
{
|
||||
song->master_volume = (float)(song->amplification) / (float)100.0;
|
||||
}
|
||||
|
||||
static void reset_voices(MidSong *song)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<MID_MAX_VOICES; i++)
|
||||
song->voice[i].status=VOICE_FREE;
|
||||
}
|
||||
|
||||
/* Process the Reset All Controllers event */
|
||||
static void reset_controllers(MidSong *song, int c)
|
||||
{
|
||||
song->channel[c].volume=90; /* Some standard says, although the SCC docs say 0. */
|
||||
song->channel[c].expression=127; /* SCC-1 does this. */
|
||||
song->channel[c].sustain=0;
|
||||
song->channel[c].pitchbend=0x2000;
|
||||
song->channel[c].pitchfactor=0; /* to be computed */
|
||||
}
|
||||
|
||||
static void reset_midi(MidSong *song)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
reset_controllers(song, i);
|
||||
/* The rest of these are unaffected by the Reset All Controllers event */
|
||||
song->channel[i].program=song->default_program;
|
||||
song->channel[i].panning=NO_PANNING;
|
||||
song->channel[i].pitchsens=2;
|
||||
song->channel[i].bank=0; /* tone bank or drum set */
|
||||
}
|
||||
reset_voices(song);
|
||||
}
|
||||
|
||||
static void select_sample(MidSong *song, int v, MidInstrument *ip, int vel)
|
||||
{
|
||||
sint32 f, cdiff, diff;
|
||||
int s,i;
|
||||
MidSample *sp, *closest;
|
||||
|
||||
s=ip->samples;
|
||||
sp=ip->sample;
|
||||
|
||||
if (s==1)
|
||||
{
|
||||
song->voice[v].sample=sp;
|
||||
return;
|
||||
}
|
||||
|
||||
f=song->voice[v].orig_frequency;
|
||||
for (i=0; i<s; i++)
|
||||
{
|
||||
if (sp->low_vel <= vel && sp->high_vel >= vel &&
|
||||
sp->low_freq <= f && sp->high_freq >= f)
|
||||
{
|
||||
song->voice[v].sample=sp;
|
||||
return;
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
|
||||
/*
|
||||
No suitable sample found! We'll select the sample whose root
|
||||
frequency is closest to the one we want. (Actually we should
|
||||
probably convert the low, high, and root frequencies to MIDI note
|
||||
values and compare those.) */
|
||||
|
||||
cdiff=0x7FFFFFFF;
|
||||
closest=sp=ip->sample;
|
||||
for(i=0; i<s; i++)
|
||||
{
|
||||
diff=sp->root_freq - f;
|
||||
if (diff<0) diff=-diff;
|
||||
if (diff<cdiff)
|
||||
{
|
||||
cdiff=diff;
|
||||
closest=sp;
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
song->voice[v].sample=closest;
|
||||
return;
|
||||
}
|
||||
|
||||
static void recompute_freq(MidSong *song, int v)
|
||||
{
|
||||
int
|
||||
sign=(song->voice[v].sample_increment < 0), /* for bidirectional loops */
|
||||
pb=song->channel[song->voice[v].channel].pitchbend;
|
||||
double a;
|
||||
|
||||
if (!song->voice[v].sample->sample_rate)
|
||||
return;
|
||||
|
||||
if (song->voice[v].vibrato_control_ratio)
|
||||
{
|
||||
/* This instrument has vibrato. Invalidate any precomputed
|
||||
sample_increments. */
|
||||
|
||||
int i=MID_VIBRATO_SAMPLE_INCREMENTS;
|
||||
while (i--)
|
||||
song->voice[v].vibrato_sample_increment[i]=0;
|
||||
}
|
||||
|
||||
if (pb==0x2000 || pb<0 || pb>0x3FFF)
|
||||
song->voice[v].frequency = song->voice[v].orig_frequency;
|
||||
else
|
||||
{
|
||||
pb-=0x2000;
|
||||
if (!(song->channel[song->voice[v].channel].pitchfactor))
|
||||
{
|
||||
/* Damn. Somebody bent the pitch. */
|
||||
sint32 i=pb*song->channel[song->voice[v].channel].pitchsens;
|
||||
if (pb<0)
|
||||
i=-i;
|
||||
song->channel[song->voice[v].channel].pitchfactor=
|
||||
(float)(bend_fine[(i>>5) & 0xFF] * bend_coarse[i>>13]);
|
||||
}
|
||||
if (pb>0)
|
||||
song->voice[v].frequency=
|
||||
(sint32)(song->channel[song->voice[v].channel].pitchfactor *
|
||||
(double)(song->voice[v].orig_frequency));
|
||||
else
|
||||
song->voice[v].frequency=
|
||||
(sint32)((double)(song->voice[v].orig_frequency) /
|
||||
song->channel[song->voice[v].channel].pitchfactor);
|
||||
}
|
||||
|
||||
a = FSCALE(((double)(song->voice[v].sample->sample_rate) *
|
||||
(double)(song->voice[v].frequency)) /
|
||||
((double)(song->voice[v].sample->root_freq) *
|
||||
(double)(song->rate)),
|
||||
FRACTION_BITS);
|
||||
|
||||
if (sign)
|
||||
a = -a; /* need to preserve the loop direction */
|
||||
|
||||
song->voice[v].sample_increment = (sint32)(a);
|
||||
}
|
||||
|
||||
static void recompute_amp(MidSong *song, int v)
|
||||
{
|
||||
sint32 tempamp;
|
||||
|
||||
/* TODO: use fscale */
|
||||
|
||||
tempamp= (song->voice[v].velocity *
|
||||
song->channel[song->voice[v].channel].volume *
|
||||
song->channel[song->voice[v].channel].expression); /* 21 bits */
|
||||
|
||||
if (!(song->encoding & PE_MONO))
|
||||
{
|
||||
if (song->voice[v].panning > 60 && song->voice[v].panning < 68)
|
||||
{
|
||||
song->voice[v].panned=PANNED_CENTER;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
21);
|
||||
}
|
||||
else if (song->voice[v].panning<5)
|
||||
{
|
||||
song->voice[v].panned = PANNED_LEFT;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
20);
|
||||
}
|
||||
else if (song->voice[v].panning>123)
|
||||
{
|
||||
song->voice[v].panned = PANNED_RIGHT;
|
||||
|
||||
song->voice[v].left_amp= /* left_amp will be used */
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
20);
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[v].panned = PANNED_MYSTERY;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
27);
|
||||
song->voice[v].right_amp = song->voice[v].left_amp * (song->voice[v].panning);
|
||||
song->voice[v].left_amp *= (float)(127 - song->voice[v].panning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[v].panned = PANNED_CENTER;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
21);
|
||||
}
|
||||
}
|
||||
|
||||
static void start_note(MidSong *song, MidEvent *e, int i)
|
||||
{
|
||||
MidInstrument *ip;
|
||||
int j;
|
||||
|
||||
if (ISDRUMCHANNEL(song, e->channel))
|
||||
{
|
||||
if (!(ip=song->drumset[song->channel[e->channel].bank]->instrument[e->a]))
|
||||
{
|
||||
if (!(ip=song->drumset[0]->instrument[e->a]))
|
||||
return; /* No instrument? Then we can't play. */
|
||||
}
|
||||
if (ip->samples != 1)
|
||||
{
|
||||
DEBUG_MSG("Strange: percussion instrument with %d samples!\n",
|
||||
ip->samples);
|
||||
}
|
||||
|
||||
if (ip->sample->note_to_use) /* Do we have a fixed pitch? */
|
||||
song->voice[i].orig_frequency = freq_table[(int)(ip->sample->note_to_use)];
|
||||
else
|
||||
song->voice[i].orig_frequency = freq_table[e->a & 0x7F];
|
||||
|
||||
/* drums are supposed to have only one sample */
|
||||
song->voice[i].sample = ip->sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (song->channel[e->channel].program == SPECIAL_PROGRAM)
|
||||
ip=song->default_instrument;
|
||||
else if (!(ip=song->tonebank[song->channel[e->channel].bank]->
|
||||
instrument[song->channel[e->channel].program]))
|
||||
{
|
||||
if (!(ip=song->tonebank[0]->instrument[song->channel[e->channel].program]))
|
||||
return; /* No instrument? Then we can't play. */
|
||||
}
|
||||
|
||||
if (ip->sample->note_to_use) /* Fixed-pitch instrument? */
|
||||
song->voice[i].orig_frequency = freq_table[(int)(ip->sample->note_to_use)];
|
||||
else
|
||||
song->voice[i].orig_frequency = freq_table[e->a & 0x7F];
|
||||
select_sample(song, i, ip, e->b);
|
||||
}
|
||||
|
||||
song->voice[i].status = VOICE_ON;
|
||||
song->voice[i].channel = e->channel;
|
||||
song->voice[i].note = e->a;
|
||||
song->voice[i].velocity = e->b;
|
||||
song->voice[i].sample_offset = 0;
|
||||
song->voice[i].sample_increment = 0; /* make sure it isn't negative */
|
||||
|
||||
song->voice[i].tremolo_phase = 0;
|
||||
song->voice[i].tremolo_phase_increment = song->voice[i].sample->tremolo_phase_increment;
|
||||
song->voice[i].tremolo_sweep = song->voice[i].sample->tremolo_sweep_increment;
|
||||
song->voice[i].tremolo_sweep_position = 0;
|
||||
|
||||
song->voice[i].vibrato_sweep = song->voice[i].sample->vibrato_sweep_increment;
|
||||
song->voice[i].vibrato_sweep_position = 0;
|
||||
song->voice[i].vibrato_control_ratio = song->voice[i].sample->vibrato_control_ratio;
|
||||
song->voice[i].vibrato_control_counter = song->voice[i].vibrato_phase = 0;
|
||||
for (j=0; j<MID_VIBRATO_SAMPLE_INCREMENTS; j++)
|
||||
song->voice[i].vibrato_sample_increment[j] = 0;
|
||||
|
||||
if (song->channel[e->channel].panning != NO_PANNING)
|
||||
song->voice[i].panning = song->channel[e->channel].panning;
|
||||
else
|
||||
song->voice[i].panning = song->voice[i].sample->panning;
|
||||
|
||||
recompute_freq(song, i);
|
||||
recompute_amp(song, i);
|
||||
if (song->voice[i].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
/* Ramp up from 0 */
|
||||
song->voice[i].envelope_stage = 0;
|
||||
song->voice[i].envelope_volume = 0;
|
||||
song->voice[i].control_counter = 0;
|
||||
recompute_envelope(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[i].envelope_increment = 0;
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void kill_note(MidSong *song, int i)
|
||||
{
|
||||
song->voice[i].status = VOICE_DIE;
|
||||
}
|
||||
|
||||
/* Only one instance of a note can be playing on a single channel. */
|
||||
static void note_on(MidSong *song)
|
||||
{
|
||||
int i = song->voices, lowest=-1;
|
||||
sint32 lv=0x7FFFFFFF, v;
|
||||
MidEvent *e = song->current_event;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
if (song->voice[i].status == VOICE_FREE)
|
||||
lowest=i; /* Can't get a lower volume than silence */
|
||||
else if (song->voice[i].channel==e->channel &&
|
||||
(song->voice[i].note==e->a || song->channel[song->voice[i].channel].mono))
|
||||
kill_note(song, i);
|
||||
}
|
||||
|
||||
if (lowest != -1)
|
||||
{
|
||||
/* Found a free voice. */
|
||||
start_note(song,e,lowest);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look for the decaying note with the lowest volume */
|
||||
i = song->voices;
|
||||
while (i--)
|
||||
{
|
||||
if ((song->voice[i].status != VOICE_ON) &&
|
||||
(song->voice[i].status != VOICE_DIE))
|
||||
{
|
||||
v = song->voice[i].left_mix;
|
||||
if ((song->voice[i].panned == PANNED_MYSTERY)
|
||||
&& (song->voice[i].right_mix > v))
|
||||
v = song->voice[i].right_mix;
|
||||
if (v<lv)
|
||||
{
|
||||
lv=v;
|
||||
lowest=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lowest != -1)
|
||||
{
|
||||
/* This can still cause a click, but if we had a free voice to
|
||||
spare for ramping down this note, we wouldn't need to kill it
|
||||
in the first place... Still, this needs to be fixed. Perhaps
|
||||
we could use a reserve of voices to play dying notes only. */
|
||||
|
||||
song->cut_notes++;
|
||||
song->voice[lowest].status=VOICE_FREE;
|
||||
start_note(song,e,lowest);
|
||||
}
|
||||
else
|
||||
song->lost_notes++;
|
||||
}
|
||||
|
||||
static void finish_note(MidSong *song, int i)
|
||||
{
|
||||
if (song->voice[i].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
/* We need to get the envelope out of Sustain stage */
|
||||
song->voice[i].envelope_stage = 3;
|
||||
song->voice[i].status = VOICE_OFF;
|
||||
recompute_envelope(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set status to OFF so resample_voice() will let this voice out
|
||||
of its loop, if any. In any case, this voice dies when it
|
||||
hits the end of its data (ofs>=data_length). */
|
||||
song->voice[i].status = VOICE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void note_off(MidSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
MidEvent *e = song->current_event;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == e->channel &&
|
||||
song->voice[i].note == e->a)
|
||||
{
|
||||
if (song->channel[e->channel].sustain)
|
||||
{
|
||||
song->voice[i].status = VOICE_SUSTAINED;
|
||||
}
|
||||
else
|
||||
finish_note(song, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the All Notes Off event */
|
||||
static void all_notes_off(MidSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
DEBUG_MSG("All notes off on channel %d\n", c);
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == c)
|
||||
{
|
||||
if (song->channel[c].sustain)
|
||||
song->voice[i].status = VOICE_SUSTAINED;
|
||||
else
|
||||
finish_note(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the All Sounds Off event */
|
||||
static void all_sounds_off(MidSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].channel == c &&
|
||||
song->voice[i].status != VOICE_FREE &&
|
||||
song->voice[i].status != VOICE_DIE)
|
||||
{
|
||||
kill_note(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_pressure(MidSong *song)
|
||||
{
|
||||
MidEvent *e = song->current_event;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == e->channel &&
|
||||
song->voice[i].note == e->a)
|
||||
{
|
||||
song->voice[i].velocity = e->b;
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_sustain(MidSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_SUSTAINED && song->voice[i].channel == c)
|
||||
finish_note(song, i);
|
||||
}
|
||||
|
||||
static void adjust_pitchbend(MidSong *song)
|
||||
{
|
||||
int c = song->current_event->channel;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status != VOICE_FREE && song->voice[i].channel == c)
|
||||
{
|
||||
recompute_freq(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_volume(MidSong *song)
|
||||
{
|
||||
int c = song->current_event->channel;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].channel == c &&
|
||||
(song->voice[i].status==VOICE_ON || song->voice[i].status==VOICE_SUSTAINED))
|
||||
{
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void seek_forward(MidSong *song, sint32 until_time)
|
||||
{
|
||||
reset_voices(song);
|
||||
while (song->current_event->time < until_time)
|
||||
{
|
||||
switch(song->current_event->type)
|
||||
{
|
||||
/* All notes stay off. Just handle the parameter changes. */
|
||||
|
||||
case ME_PITCH_SENS:
|
||||
song->channel[song->current_event->channel].pitchsens =
|
||||
song->current_event->a;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_PITCHWHEEL:
|
||||
song->channel[song->current_event->channel].pitchbend =
|
||||
song->current_event->a + song->current_event->b * 128;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_MAINVOLUME:
|
||||
song->channel[song->current_event->channel].volume =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_PAN:
|
||||
song->channel[song->current_event->channel].panning =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EXPRESSION:
|
||||
song->channel[song->current_event->channel].expression =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, song->current_event->channel))
|
||||
/* Change drum set */
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
else
|
||||
song->channel[song->current_event->channel].program =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_SUSTAIN:
|
||||
song->channel[song->current_event->channel].sustain =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_RESET_CONTROLLERS:
|
||||
reset_controllers(song, song->current_event->channel);
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EOT:
|
||||
song->current_sample = song->current_event->time;
|
||||
return;
|
||||
}
|
||||
song->current_event++;
|
||||
}
|
||||
/*song->current_sample=song->current_event->time;*/
|
||||
if (song->current_event != song->events)
|
||||
song->current_event--;
|
||||
song->current_sample=until_time;
|
||||
}
|
||||
|
||||
static void skip_to(MidSong *song, sint32 until_time)
|
||||
{
|
||||
if (song->current_sample > until_time)
|
||||
song->current_sample = 0;
|
||||
|
||||
reset_midi(song);
|
||||
song->current_event = song->events;
|
||||
|
||||
if (until_time)
|
||||
seek_forward(song, until_time);
|
||||
}
|
||||
|
||||
static void do_compute_data(MidSong *song, sint32 count)
|
||||
{
|
||||
int i;
|
||||
memset(song->common_buffer, 0,
|
||||
(song->encoding & PE_MONO) ? (count * 4) : (count * 8));
|
||||
for (i = 0; i < song->voices; i++)
|
||||
{
|
||||
if(song->voice[i].status != VOICE_FREE)
|
||||
mix_voice(song, song->common_buffer, i, count);
|
||||
}
|
||||
song->current_sample += count;
|
||||
}
|
||||
|
||||
/* count=0 means flush remaining buffered data to output device, then
|
||||
flush the device itself */
|
||||
static void compute_data(MidSong *song, sint8 **stream, sint32 count)
|
||||
{
|
||||
int channels;
|
||||
|
||||
if ( song->encoding & PE_MONO )
|
||||
channels = 1;
|
||||
else
|
||||
channels = 2;
|
||||
|
||||
while (count)
|
||||
{
|
||||
sint32 block = count;
|
||||
if (block > song->buffer_size)
|
||||
block = song->buffer_size;
|
||||
do_compute_data(song, block);
|
||||
song->write(*stream, song->common_buffer, channels * block);
|
||||
*stream += song->bytes_per_sample * block;
|
||||
count -= block;
|
||||
}
|
||||
}
|
||||
|
||||
void mid_song_start(MidSong *song)
|
||||
{
|
||||
song->playing = 1;
|
||||
adjust_amplification(song);
|
||||
skip_to(song, 0);
|
||||
}
|
||||
|
||||
void mid_song_seek(MidSong *song, uint32 ms)
|
||||
{
|
||||
skip_to(song, (ms * (song->rate / 100)) / 10);
|
||||
}
|
||||
|
||||
uint32 mid_song_get_total_time(MidSong *song)
|
||||
{
|
||||
MidEvent *last_event = &song->events[song->groomed_event_count - 1];
|
||||
/* We want last_event->time * 1000 / song->rate */
|
||||
uint32 retvalue = (last_event->time / song->rate) * 1000;
|
||||
retvalue += (last_event->time % song->rate) * 1000 / song->rate;
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
uint32 mid_song_get_time(MidSong *song)
|
||||
{
|
||||
uint32 retvalue = (song->current_sample / song->rate) * 1000;
|
||||
retvalue += (song->current_sample % song->rate) * 1000 / song->rate;
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
char *mid_song_get_meta(MidSong *song, MidSongMetaId what)
|
||||
{
|
||||
return song->meta_data[what];
|
||||
}
|
||||
|
||||
size_t mid_song_read_wave(MidSong *song, void *ptr, size_t size)
|
||||
{
|
||||
sint32 start_sample, end_sample, samples;
|
||||
|
||||
if (!song->playing)
|
||||
return 0;
|
||||
|
||||
samples = size / song->bytes_per_sample;
|
||||
|
||||
start_sample = song->current_sample;
|
||||
end_sample = song->current_sample+samples;
|
||||
while ( song->current_sample < end_sample ) {
|
||||
/* Handle all events that should happen at this time */
|
||||
while (song->current_event->time <= song->current_sample) {
|
||||
switch(song->current_event->type) {
|
||||
|
||||
/* Effects affecting a single note */
|
||||
|
||||
case ME_NOTEON:
|
||||
if (!(song->current_event->b)) /* Velocity 0? */
|
||||
note_off(song);
|
||||
else
|
||||
note_on(song);
|
||||
break;
|
||||
|
||||
case ME_NOTEOFF:
|
||||
note_off(song);
|
||||
break;
|
||||
|
||||
case ME_KEYPRESSURE:
|
||||
adjust_pressure(song);
|
||||
break;
|
||||
|
||||
/* Effects affecting a single channel */
|
||||
|
||||
case ME_PITCH_SENS:
|
||||
song->channel[song->current_event->channel].pitchsens =
|
||||
song->current_event->a;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_PITCHWHEEL:
|
||||
song->channel[song->current_event->channel].pitchbend =
|
||||
song->current_event->a + song->current_event->b * 128;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
/* Adjust pitch for notes already playing */
|
||||
adjust_pitchbend(song);
|
||||
break;
|
||||
|
||||
case ME_MAINVOLUME:
|
||||
song->channel[song->current_event->channel].volume =
|
||||
song->current_event->a;
|
||||
adjust_volume(song);
|
||||
break;
|
||||
|
||||
case ME_PAN:
|
||||
song->channel[song->current_event->channel].panning =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EXPRESSION:
|
||||
song->channel[song->current_event->channel].expression =
|
||||
song->current_event->a;
|
||||
adjust_volume(song);
|
||||
break;
|
||||
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, song->current_event->channel)) {
|
||||
/* Change drum set */
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
}
|
||||
else
|
||||
song->channel[song->current_event->channel].program =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_SUSTAIN:
|
||||
song->channel[song->current_event->channel].sustain =
|
||||
song->current_event->a;
|
||||
if (!song->current_event->a)
|
||||
drop_sustain(song);
|
||||
break;
|
||||
|
||||
case ME_RESET_CONTROLLERS:
|
||||
reset_controllers(song, song->current_event->channel);
|
||||
break;
|
||||
|
||||
case ME_ALL_NOTES_OFF:
|
||||
all_notes_off(song);
|
||||
break;
|
||||
|
||||
case ME_ALL_SOUNDS_OFF:
|
||||
all_sounds_off(song);
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EOT:
|
||||
/* Give the last notes a couple of seconds to decay */
|
||||
DEBUG_MSG("Playing time: ~%d seconds\n",
|
||||
song->current_sample/song->rate+2);
|
||||
DEBUG_MSG("Notes cut: %d\n", song->cut_notes);
|
||||
DEBUG_MSG("Notes lost totally: %d\n", song->lost_notes);
|
||||
song->playing = 0;
|
||||
return (song->current_sample - start_sample) * song->bytes_per_sample;
|
||||
}
|
||||
song->current_event++;
|
||||
}
|
||||
if (song->current_event->time > end_sample)
|
||||
compute_data(song, (sint8 **)&ptr, end_sample-song->current_sample);
|
||||
else
|
||||
compute_data(song, (sint8 **)&ptr, song->current_event->time-song->current_sample);
|
||||
}
|
||||
return samples * song->bytes_per_sample;
|
||||
}
|
||||
|
||||
void mid_song_set_volume(MidSong *song, int volume)
|
||||
{
|
||||
int i;
|
||||
if (volume > MAX_AMPLIFICATION)
|
||||
song->amplification = MAX_AMPLIFICATION;
|
||||
else
|
||||
if (volume < 0)
|
||||
song->amplification = 0;
|
||||
else
|
||||
song->amplification = volume;
|
||||
adjust_amplification(song);
|
||||
for (i = 0; i < song->voices; i++)
|
||||
if (song->voice[i].status != VOICE_FREE)
|
||||
{
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
64
project/jni/timidity/src/playmidi.h
Normal file
64
project/jni/timidity/src/playmidi.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
playmidi.h
|
||||
|
||||
*/
|
||||
|
||||
/* Midi events */
|
||||
#define ME_NONE 0
|
||||
#define ME_NOTEON 1
|
||||
#define ME_NOTEOFF 2
|
||||
#define ME_KEYPRESSURE 3
|
||||
#define ME_MAINVOLUME 4
|
||||
#define ME_PAN 5
|
||||
#define ME_SUSTAIN 6
|
||||
#define ME_EXPRESSION 7
|
||||
#define ME_PITCHWHEEL 8
|
||||
#define ME_PROGRAM 9
|
||||
#define ME_TEMPO 10
|
||||
#define ME_PITCH_SENS 11
|
||||
|
||||
#define ME_ALL_SOUNDS_OFF 12
|
||||
#define ME_RESET_CONTROLLERS 13
|
||||
#define ME_ALL_NOTES_OFF 14
|
||||
#define ME_TONE_BANK 15
|
||||
|
||||
#define ME_LYRIC 16
|
||||
|
||||
#define ME_EOT 99
|
||||
|
||||
/* Causes the instrument's default panning to be used. */
|
||||
#define NO_PANNING -1
|
||||
|
||||
/* Voice status options: */
|
||||
#define VOICE_FREE 0
|
||||
#define VOICE_ON 1
|
||||
#define VOICE_SUSTAINED 2
|
||||
#define VOICE_OFF 3
|
||||
#define VOICE_DIE 4
|
||||
|
||||
/* Voice panned options: */
|
||||
#define PANNED_MYSTERY 0
|
||||
#define PANNED_LEFT 1
|
||||
#define PANNED_RIGHT 2
|
||||
#define PANNED_CENTER 3
|
||||
/* Anything but PANNED_MYSTERY only uses the left volume */
|
||||
|
||||
#define ISDRUMCHANNEL(s, c) (((s)->drumchannels & (1<<(c))))
|
||||
596
project/jni/timidity/src/readmidi.c
Normal file
596
project/jni/timidity/src/readmidi.c
Normal file
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
|
||||
/* Computes how many (fractional) samples one MIDI delta-time unit contains */
|
||||
static void compute_sample_increment(MidSong *song, sint32 tempo,
|
||||
sint32 divisions)
|
||||
{
|
||||
double a;
|
||||
a = (double) (tempo) * (double) (song->rate) * (65536.0/1000000.0) /
|
||||
(double)(divisions);
|
||||
|
||||
song->sample_correction = (sint32)(a) & 0xFFFF;
|
||||
song->sample_increment = (sint32)(a) >> 16;
|
||||
|
||||
DEBUG_MSG("Samples per delta-t: %d (correction %d)\n",
|
||||
song->sample_increment, song->sample_correction);
|
||||
}
|
||||
|
||||
/* Read variable-length number (7 bits per byte, MSB first) */
|
||||
static sint32 getvl(MidIStream *stream)
|
||||
{
|
||||
sint32 l=0;
|
||||
uint8 c;
|
||||
for (;;)
|
||||
{
|
||||
mid_istream_read(stream, &c, 1, 1);
|
||||
l += (c & 0x7f);
|
||||
if (!(c & 0x80)) return l;
|
||||
l<<=7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a string from the file, followed by a newline. Any non-ASCII
|
||||
or unprintable characters will be converted to periods. */
|
||||
static int read_meta_data(MidIStream *stream, sint32 len, uint8 type, MidSong *song)
|
||||
{
|
||||
char *s=safe_malloc(len+1);
|
||||
MidSongMetaId id;
|
||||
static char *label[] = {
|
||||
"Text event: ", "Text: ", "Copyright: ", "Track name: ",
|
||||
"Instrument: ", "Lyric: ", "Marker: ", "Cue point: "};
|
||||
|
||||
if (len != (sint32) mid_istream_read(stream, s, 1, len))
|
||||
{
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
s[len]='\0';
|
||||
while (len--)
|
||||
{
|
||||
if (((unsigned char)s[len])<32)
|
||||
s[len]='.';
|
||||
}
|
||||
DEBUG_MSG("%s%s\n", label[(type > 7) ? 0 : type], s);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 1: id = MID_SONG_TEXT; break;
|
||||
case 2: id = MID_SONG_COPYRIGHT; break;
|
||||
default: free(s); s = NULL;
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
if (song->meta_data[id])
|
||||
free(song->meta_data[id]);
|
||||
song->meta_data[id] = s;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MIDIEVENT(at,t,ch,pa,pb) \
|
||||
new=safe_malloc(sizeof(MidEventList)); \
|
||||
new->event.time=at; new->event.type=t; new->event.channel=ch; \
|
||||
new->event.a=pa; new->event.b=pb; new->next=0;\
|
||||
return new;
|
||||
|
||||
#define MAGIC_EOT ((MidEventList *)(-1))
|
||||
|
||||
/* Read a MIDI event, returning a freshly allocated element that can
|
||||
be linked to the event list */
|
||||
static MidEventList *read_midi_event(MidIStream *stream, MidSong *song)
|
||||
{
|
||||
static uint8 laststatus, lastchan;
|
||||
static uint8 nrpn=0, rpn_msb[16], rpn_lsb[16]; /* one per channel */
|
||||
uint8 me, type, a,b,c;
|
||||
sint32 len;
|
||||
MidEventList *new;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
song->at += getvl(stream);
|
||||
if (mid_istream_read(stream, &me, 1, 1) != 1)
|
||||
{
|
||||
DEBUG_MSG("read_midi_event: mid_istream_read() failure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(me==0xF0 || me == 0xF7) /* SysEx event */
|
||||
{
|
||||
len=getvl(stream);
|
||||
mid_istream_skip(stream, len);
|
||||
}
|
||||
else if(me==0xFF) /* Meta event */
|
||||
{
|
||||
mid_istream_read(stream, &type, 1, 1);
|
||||
len=getvl(stream);
|
||||
if (type>0 && type<16)
|
||||
{
|
||||
read_meta_data(stream, len, type, song);
|
||||
}
|
||||
else
|
||||
switch(type)
|
||||
{
|
||||
case 0x2F: /* End of Track */
|
||||
return MAGIC_EOT;
|
||||
|
||||
case 0x51: /* Tempo */
|
||||
mid_istream_read(stream, &a, 1, 1);
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
mid_istream_read(stream, &c, 1, 1);
|
||||
MIDIEVENT(song->at, ME_TEMPO, c, a, b);
|
||||
|
||||
default:
|
||||
DEBUG_MSG("(Meta event type 0x%02x, length %d)\n", type, len);
|
||||
mid_istream_skip(stream, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a=me;
|
||||
if (a & 0x80) /* status byte */
|
||||
{
|
||||
lastchan=a & 0x0F;
|
||||
laststatus=(a>>4) & 0x07;
|
||||
mid_istream_read(stream, &a, 1, 1);
|
||||
a &= 0x7F;
|
||||
}
|
||||
switch(laststatus)
|
||||
{
|
||||
case 0: /* Note off */
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_NOTEOFF, lastchan, a,b);
|
||||
|
||||
case 1: /* Note on */
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_NOTEON, lastchan, a,b);
|
||||
|
||||
case 2: /* Key Pressure */
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_KEYPRESSURE, lastchan, a, b);
|
||||
|
||||
case 3: /* Control change */
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
{
|
||||
int control=255;
|
||||
switch(a)
|
||||
{
|
||||
case 7: control=ME_MAINVOLUME; break;
|
||||
case 10: control=ME_PAN; break;
|
||||
case 11: control=ME_EXPRESSION; break;
|
||||
case 64: control=ME_SUSTAIN; break;
|
||||
case 120: control=ME_ALL_SOUNDS_OFF; break;
|
||||
case 121: control=ME_RESET_CONTROLLERS; break;
|
||||
case 123: control=ME_ALL_NOTES_OFF; break;
|
||||
|
||||
/* These should be the SCC-1 tone bank switch
|
||||
commands. I don't know why there are two, or
|
||||
why the latter only allows switching to bank 0.
|
||||
Also, some MIDI files use 0 as some sort of
|
||||
continuous controller. This will cause lots of
|
||||
warnings about undefined tone banks. */
|
||||
case 0: control=ME_TONE_BANK; break;
|
||||
case 32:
|
||||
if (b!=0)
|
||||
DEBUG_MSG("(Strange: tone bank change 0x20%02x)\n", b);
|
||||
else
|
||||
control=ME_TONE_BANK;
|
||||
break;
|
||||
|
||||
case 100: nrpn=0; rpn_msb[lastchan]=b; break;
|
||||
case 101: nrpn=0; rpn_lsb[lastchan]=b; break;
|
||||
case 99: nrpn=1; rpn_msb[lastchan]=b; break;
|
||||
case 98: nrpn=1; rpn_lsb[lastchan]=b; break;
|
||||
|
||||
case 6:
|
||||
if (nrpn)
|
||||
{
|
||||
DEBUG_MSG("(Data entry (MSB) for NRPN %02x,%02x: %d)\n",
|
||||
rpn_msb[lastchan], rpn_lsb[lastchan], b);
|
||||
break;
|
||||
}
|
||||
|
||||
switch((rpn_msb[lastchan]<<8) | rpn_lsb[lastchan])
|
||||
{
|
||||
case 0x0000: /* Pitch bend sensitivity */
|
||||
control=ME_PITCH_SENS;
|
||||
break;
|
||||
|
||||
case 0x7F7F: /* RPN reset */
|
||||
/* reset pitch bend sensitivity to 2 */
|
||||
MIDIEVENT(song->at, ME_PITCH_SENS, lastchan, 2, 0);
|
||||
|
||||
default:
|
||||
DEBUG_MSG("(Data entry (MSB) for RPN %02x,%02x: %d)\n",
|
||||
rpn_msb[lastchan], rpn_lsb[lastchan], b);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_MSG("(Control %d: %d)\n", a, b);
|
||||
break;
|
||||
}
|
||||
if (control != 255)
|
||||
{
|
||||
MIDIEVENT(song->at, control, lastchan, b, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* Program change */
|
||||
a &= 0x7f;
|
||||
MIDIEVENT(song->at, ME_PROGRAM, lastchan, a, 0);
|
||||
|
||||
case 5: /* Channel pressure - NOT IMPLEMENTED */
|
||||
break;
|
||||
|
||||
case 6: /* Pitch wheel */
|
||||
mid_istream_read(stream, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_PITCHWHEEL, lastchan, a, b);
|
||||
|
||||
default:
|
||||
DEBUG_MSG("*** Can't happen: status 0x%02X, channel 0x%02X\n",
|
||||
laststatus, lastchan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
#undef MIDIEVENT
|
||||
|
||||
/* Read a midi track into the linked list, either merging with any previous
|
||||
tracks or appending to them. */
|
||||
static int read_track(MidIStream *stream, MidSong *song, int append)
|
||||
{
|
||||
MidEventList *meep;
|
||||
MidEventList *next, *new;
|
||||
sint32 len;
|
||||
char tmp[4];
|
||||
|
||||
meep = song->evlist;
|
||||
if (append && meep)
|
||||
{
|
||||
/* find the last event in the list */
|
||||
for (; meep->next; meep=meep->next)
|
||||
;
|
||||
song->at = meep->event.time;
|
||||
}
|
||||
else
|
||||
song->at=0;
|
||||
|
||||
/* Check the formalities */
|
||||
|
||||
if (mid_istream_read(stream, tmp, 1, 4) != 4 || mid_istream_read(stream, &len, 4, 1) != 1)
|
||||
{
|
||||
DEBUG_MSG("Can't read track header.\n");
|
||||
return -1;
|
||||
}
|
||||
len=SWAPBE32(len);
|
||||
if (memcmp(tmp, "MTrk", 4))
|
||||
{
|
||||
DEBUG_MSG("Corrupt MIDI file.\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(new=read_midi_event(stream, song))) /* Some kind of error */
|
||||
return -2;
|
||||
|
||||
if (new==MAGIC_EOT) /* End-of-track Hack. */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
next=meep->next;
|
||||
while (next && (next->event.time < new->event.time))
|
||||
{
|
||||
meep=next;
|
||||
next=meep->next;
|
||||
}
|
||||
|
||||
new->next=next;
|
||||
meep->next=new;
|
||||
|
||||
song->event_count++; /* Count the event. (About one?) */
|
||||
meep=new;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the linked event list from memory. */
|
||||
static void free_midi_list(MidSong *song)
|
||||
{
|
||||
MidEventList *meep, *next;
|
||||
if (!(meep = song->evlist)) return;
|
||||
while (meep)
|
||||
{
|
||||
next=meep->next;
|
||||
free(meep);
|
||||
meep=next;
|
||||
}
|
||||
song->evlist=0;
|
||||
}
|
||||
|
||||
/* Allocate an array of MidiEvents and fill it from the linked list of
|
||||
events, marking used instruments for loading. Convert event times to
|
||||
samples: handle tempo changes. Strip unnecessary events from the list.
|
||||
Free the linked list. */
|
||||
static MidEvent *groom_list(MidSong *song, sint32 divisions,sint32 *eventsp,
|
||||
sint32 *samplesp)
|
||||
{
|
||||
MidEvent *groomed_list, *lp;
|
||||
MidEventList *meep;
|
||||
sint32 i, our_event_count, tempo, skip_this_event, new_value;
|
||||
sint32 sample_cum, samples_to_do, at, st, dt, counting_time;
|
||||
|
||||
int current_bank[16], current_set[16], current_program[16];
|
||||
/* Or should each bank have its own current program? */
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
current_bank[i]=0;
|
||||
current_set[i]=0;
|
||||
current_program[i]=song->default_program;
|
||||
}
|
||||
|
||||
tempo=500000;
|
||||
compute_sample_increment(song, tempo, divisions);
|
||||
|
||||
/* This may allocate a bit more than we need */
|
||||
groomed_list=lp=safe_malloc(sizeof(MidEvent) * (song->event_count+1));
|
||||
meep=song->evlist;
|
||||
|
||||
our_event_count=0;
|
||||
st=at=sample_cum=0;
|
||||
counting_time=2; /* We strip any silence before the first NOTE ON. */
|
||||
|
||||
for (i = 0; i < song->event_count; i++)
|
||||
{
|
||||
skip_this_event=0;
|
||||
|
||||
if (meep->event.type==ME_TEMPO)
|
||||
{
|
||||
tempo=
|
||||
meep->event.channel + meep->event.b * 256 + meep->event.a * 65536;
|
||||
compute_sample_increment(song, tempo, divisions);
|
||||
skip_this_event=1;
|
||||
}
|
||||
else switch (meep->event.type)
|
||||
{
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
if (song->drumset[meep->event.a]) /* Is this a defined drumset? */
|
||||
new_value=meep->event.a;
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("Drum set %d is undefined\n", meep->event.a);
|
||||
new_value=meep->event.a=0;
|
||||
}
|
||||
if (current_set[meep->event.channel] != new_value)
|
||||
current_set[meep->event.channel]=new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_value=meep->event.a;
|
||||
if ((current_program[meep->event.channel] != SPECIAL_PROGRAM)
|
||||
&& (current_program[meep->event.channel] != new_value))
|
||||
current_program[meep->event.channel] = new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_NOTEON:
|
||||
if (counting_time)
|
||||
counting_time=1;
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
/* Mark this instrument to be loaded */
|
||||
if (!(song->drumset[current_set[meep->event.channel]]
|
||||
->instrument[meep->event.a]))
|
||||
song->drumset[current_set[meep->event.channel]]
|
||||
->instrument[meep->event.a] = MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_program[meep->event.channel]==SPECIAL_PROGRAM)
|
||||
break;
|
||||
/* Mark this instrument to be loaded */
|
||||
if (!(song->tonebank[current_bank[meep->event.channel]]
|
||||
->instrument[current_program[meep->event.channel]]))
|
||||
song->tonebank[current_bank[meep->event.channel]]
|
||||
->instrument[current_program[meep->event.channel]] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
skip_this_event=1;
|
||||
break;
|
||||
}
|
||||
if (song->tonebank[meep->event.a]) /* Is this a defined tone bank? */
|
||||
new_value=meep->event.a;
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("Tone bank %d is undefined\n", meep->event.a);
|
||||
new_value=meep->event.a=0;
|
||||
}
|
||||
if (current_bank[meep->event.channel]!=new_value)
|
||||
current_bank[meep->event.channel]=new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recompute time in samples*/
|
||||
if ((dt=meep->event.time - at) && !counting_time)
|
||||
{
|
||||
samples_to_do = song->sample_increment * dt;
|
||||
sample_cum += song->sample_correction * dt;
|
||||
if (sample_cum & 0xFFFF0000)
|
||||
{
|
||||
samples_to_do += ((sample_cum >> 16) & 0xFFFF);
|
||||
sample_cum &= 0x0000FFFF;
|
||||
}
|
||||
st += samples_to_do;
|
||||
}
|
||||
else if (counting_time==1) counting_time=0;
|
||||
if (!skip_this_event)
|
||||
{
|
||||
/* Add the event to the list */
|
||||
*lp=meep->event;
|
||||
lp->time=st;
|
||||
lp++;
|
||||
our_event_count++;
|
||||
}
|
||||
at=meep->event.time;
|
||||
meep=meep->next;
|
||||
}
|
||||
/* Add an End-of-Track event */
|
||||
lp->time=st;
|
||||
lp->type=ME_EOT;
|
||||
our_event_count++;
|
||||
free_midi_list(song);
|
||||
|
||||
*eventsp=our_event_count;
|
||||
*samplesp=st;
|
||||
return groomed_list;
|
||||
}
|
||||
|
||||
MidEvent *read_midi_file(MidIStream *stream, MidSong *song, sint32 *count, sint32 *sp)
|
||||
{
|
||||
sint32 len, divisions;
|
||||
sint16 format, tracks, divisions_tmp;
|
||||
int i;
|
||||
char tmp[4];
|
||||
|
||||
song->event_count=0;
|
||||
song->at=0;
|
||||
song->evlist=0;
|
||||
|
||||
if (mid_istream_read(stream, tmp, 1, 4) != 4 || mid_istream_read(stream, &len, 4, 1) != 1)
|
||||
{
|
||||
DEBUG_MSG("Not a MIDI file!\n");
|
||||
return 0;
|
||||
}
|
||||
len=SWAPBE32(len);
|
||||
if (memcmp(tmp, "MThd", 4) || len < 6)
|
||||
{
|
||||
DEBUG_MSG("Not a MIDI file!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mid_istream_read(stream, &format, 2, 1);
|
||||
mid_istream_read(stream, &tracks, 2, 1);
|
||||
mid_istream_read(stream, &divisions_tmp, 2, 1);
|
||||
format=SWAPBE16(format);
|
||||
tracks=SWAPBE16(tracks);
|
||||
divisions_tmp=SWAPBE16(divisions_tmp);
|
||||
|
||||
if (divisions_tmp<0)
|
||||
{
|
||||
/* SMPTE time -- totally untested. Got a MIDI file that uses this? */
|
||||
divisions=
|
||||
(sint32)(-(divisions_tmp/256)) * (sint32)(divisions_tmp & 0xFF);
|
||||
}
|
||||
else divisions=(sint32)(divisions_tmp);
|
||||
|
||||
if (len > 6)
|
||||
{
|
||||
DEBUG_MSG("MIDI file header size %u bytes", len);
|
||||
mid_istream_skip(stream, len-6); /* skip the excess */
|
||||
}
|
||||
if (format<0 || format >2)
|
||||
{
|
||||
DEBUG_MSG("Unknown MIDI file format %d\n", format);
|
||||
return 0;
|
||||
}
|
||||
DEBUG_MSG("Format: %d Tracks: %d Divisions: %d\n",
|
||||
format, tracks, divisions);
|
||||
|
||||
/* Put a do-nothing event first in the list for easier processing */
|
||||
song->evlist=safe_malloc(sizeof(MidEventList));
|
||||
song->evlist->event.time=0;
|
||||
song->evlist->event.type=ME_NONE;
|
||||
song->evlist->next=0;
|
||||
song->event_count++;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case 0:
|
||||
if (read_track(stream, song, 0))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
for (i=0; i<tracks; i++)
|
||||
if (read_track(stream, song, 0))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* We simply play the tracks sequentially */
|
||||
for (i=0; i<tracks; i++)
|
||||
if (read_track(stream, song, 1))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return groom_list(song, divisions, count, sp);
|
||||
}
|
||||
24
project/jni/timidity/src/readmidi.h
Normal file
24
project/jni/timidity/src/readmidi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
readmidi.h
|
||||
|
||||
*/
|
||||
|
||||
extern MidEvent *read_midi_file(MidIStream *stream, MidSong *song, sint32 *count, sint32 *sp);
|
||||
608
project/jni/timidity/src/resample.c
Normal file
608
project/jni/timidity/src/resample.c
Normal file
@@ -0,0 +1,608 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
resample.c
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
|
||||
/*************** resampling with fixed increment *****************/
|
||||
|
||||
static sample_t *rs_plain(MidSong *song, int v, sint32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
sample_t v1, v2;
|
||||
MidVoice
|
||||
*vp=&(song->voice[v]);
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->data_length,
|
||||
count=*countptr;
|
||||
sint32 i;
|
||||
|
||||
if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
|
||||
|
||||
/* Precalc how many times we should go through the loop.
|
||||
NOTE: Assumes that incr > 0 and that ofs <= le */
|
||||
i = (le - ofs) / incr + 1;
|
||||
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
|
||||
if (ofs >= le)
|
||||
{
|
||||
if (ofs == le)
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
vp->status=VOICE_FREE;
|
||||
*countptr-=count+1;
|
||||
}
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_loop(MidSong *song, MidVoice *vp, sint32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
sample_t v1, v2;
|
||||
sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
sint32 i;
|
||||
|
||||
while (count)
|
||||
{
|
||||
if (ofs >= le)
|
||||
/* NOTE: Assumes that ll > incr and that incr > 0. */
|
||||
ofs -= ll;
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = (le - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
}
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_bidir(MidSong *song, MidVoice *vp, sint32 count)
|
||||
{
|
||||
sample_t v1, v2;
|
||||
sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
sint32
|
||||
le2 = le<<1,
|
||||
ls2 = ls<<1,
|
||||
i;
|
||||
/* Play normally until inside the loop region */
|
||||
|
||||
if (ofs <= ls)
|
||||
{
|
||||
/* NOTE: Assumes that incr > 0, which is NOT always the case
|
||||
when doing bidirectional looping. I have yet to see a case
|
||||
where both ofs <= ls AND incr < 0, however. */
|
||||
i = (ls - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
while(count)
|
||||
{
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (ofs>=le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
/*********************** vibrato versions ***************************/
|
||||
|
||||
/* We only need to compute one half of the vibrato sine cycle */
|
||||
static int vib_phase_to_inc_ptr(int phase)
|
||||
{
|
||||
if (phase < MID_VIBRATO_SAMPLE_INCREMENTS/2)
|
||||
return MID_VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
|
||||
else if (phase >= 3*MID_VIBRATO_SAMPLE_INCREMENTS/2)
|
||||
return 5*MID_VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
|
||||
else
|
||||
return phase-MID_VIBRATO_SAMPLE_INCREMENTS/2;
|
||||
}
|
||||
|
||||
static sint32 update_vibrato(MidSong *song, MidVoice *vp, int sign)
|
||||
{
|
||||
sint32 depth;
|
||||
int phase, pb;
|
||||
double a;
|
||||
|
||||
if (vp->vibrato_phase++ >= 2*MID_VIBRATO_SAMPLE_INCREMENTS-1)
|
||||
vp->vibrato_phase=0;
|
||||
phase=vib_phase_to_inc_ptr(vp->vibrato_phase);
|
||||
|
||||
if (vp->vibrato_sample_increment[phase])
|
||||
{
|
||||
if (sign)
|
||||
return -vp->vibrato_sample_increment[phase];
|
||||
else
|
||||
return vp->vibrato_sample_increment[phase];
|
||||
}
|
||||
|
||||
/* Need to compute this sample increment. */
|
||||
|
||||
depth=vp->sample->vibrato_depth<<7;
|
||||
|
||||
if (vp->vibrato_sweep)
|
||||
{
|
||||
/* Need to update sweep */
|
||||
vp->vibrato_sweep_position += vp->vibrato_sweep;
|
||||
if (vp->vibrato_sweep_position >= (1<<SWEEP_SHIFT))
|
||||
vp->vibrato_sweep=0;
|
||||
else
|
||||
{
|
||||
/* Adjust depth */
|
||||
depth *= vp->vibrato_sweep_position;
|
||||
depth >>= SWEEP_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
a = FSCALE(((double)(vp->sample->sample_rate) *
|
||||
(double)(vp->frequency)) /
|
||||
((double)(vp->sample->root_freq) *
|
||||
(double)(song->rate)),
|
||||
FRACTION_BITS);
|
||||
|
||||
pb=(int)((sine(vp->vibrato_phase *
|
||||
(SINE_CYCLE_LENGTH/(2*MID_VIBRATO_SAMPLE_INCREMENTS)))
|
||||
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING));
|
||||
|
||||
if (pb<0)
|
||||
{
|
||||
pb=-pb;
|
||||
a /= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
|
||||
}
|
||||
else
|
||||
a *= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
|
||||
|
||||
/* If the sweep's over, we can store the newly computed sample_increment */
|
||||
if (!vp->vibrato_sweep)
|
||||
vp->vibrato_sample_increment[phase]=(sint32) a;
|
||||
|
||||
if (sign)
|
||||
a = -a; /* need to preserve the loop direction */
|
||||
|
||||
return (sint32) a;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_plain(MidSong *song, int v, sint32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
sample_t v1, v2;
|
||||
MidVoice *vp=&(song->voice[v]);
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
sint32
|
||||
le=vp->sample->data_length,
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
count=*countptr;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
|
||||
/* This has never been tested */
|
||||
|
||||
if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
|
||||
|
||||
while (count--)
|
||||
{
|
||||
if (!cc--)
|
||||
{
|
||||
cc=vp->vibrato_control_ratio;
|
||||
incr=update_vibrato(song, vp, 0);
|
||||
}
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
if (ofs >= le)
|
||||
{
|
||||
if (ofs == le)
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
vp->status=VOICE_FREE;
|
||||
*countptr-=count+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_loop(MidSong *song, MidVoice *vp, sint32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
sample_t v1, v2;
|
||||
sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
sint32 i;
|
||||
int
|
||||
vibflag=0;
|
||||
|
||||
while (count)
|
||||
{
|
||||
/* Hopefully the loop is longer than an increment */
|
||||
if(ofs >= le)
|
||||
ofs -= ll;
|
||||
/* Precalc how many times to go through the loop, taking
|
||||
the vibrato control ratio into account this time. */
|
||||
i = (le - ofs) / incr + 1;
|
||||
if(i > count) i = count;
|
||||
if(i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while(i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if(vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, 0);
|
||||
vibflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_bidir(MidSong *song, MidVoice *vp, sint32 count)
|
||||
{
|
||||
sample_t v1, v2;
|
||||
sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
sint32
|
||||
le2=le<<1,
|
||||
ls2=ls<<1,
|
||||
i;
|
||||
int
|
||||
vibflag = 0;
|
||||
|
||||
/* Play normally until inside the loop region */
|
||||
while (count && (ofs <= ls))
|
||||
{
|
||||
i = (ls - ofs) / incr + 1;
|
||||
if (i > count) i = count;
|
||||
if (i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, 0);
|
||||
vibflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
while (count)
|
||||
{
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
|
||||
if(i > count) i = count;
|
||||
if(i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, (incr < 0));
|
||||
vibflag = 0;
|
||||
}
|
||||
if (ofs >= le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
sample_t *resample_voice(MidSong *song, int v, sint32 *countptr)
|
||||
{
|
||||
sint32 ofs;
|
||||
uint8 modes;
|
||||
MidVoice *vp=&(song->voice[v]);
|
||||
|
||||
if (!(vp->sample->sample_rate))
|
||||
{
|
||||
/* Pre-resampled data -- just update the offset and check if
|
||||
we're out of data. */
|
||||
ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use
|
||||
FRACTION_BITS here... */
|
||||
if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs)
|
||||
{
|
||||
/* Note finished. Free the voice. */
|
||||
vp->status = VOICE_FREE;
|
||||
|
||||
/* Let the caller know how much data we had left */
|
||||
*countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs;
|
||||
}
|
||||
else
|
||||
vp->sample_offset += *countptr << FRACTION_BITS;
|
||||
|
||||
return vp->sample->data+ofs;
|
||||
}
|
||||
|
||||
/* Need to resample. Use the proper function. */
|
||||
modes=vp->sample->modes;
|
||||
|
||||
if (vp->vibrato_control_ratio)
|
||||
{
|
||||
if ((modes & MODES_LOOPING) &&
|
||||
((modes & MODES_ENVELOPE) ||
|
||||
(vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
|
||||
{
|
||||
if (modes & MODES_PINGPONG)
|
||||
return rs_vib_bidir(song, vp, *countptr);
|
||||
else
|
||||
return rs_vib_loop(song, vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_vib_plain(song, v, countptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modes & MODES_LOOPING) &&
|
||||
((modes & MODES_ENVELOPE) ||
|
||||
(vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
|
||||
{
|
||||
if (modes & MODES_PINGPONG)
|
||||
return rs_bidir(song, vp, *countptr);
|
||||
else
|
||||
return rs_loop(song, vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_plain(song, v, countptr);
|
||||
}
|
||||
}
|
||||
|
||||
void pre_resample(MidSong *song, MidSample *sp)
|
||||
{
|
||||
double a, xdiff;
|
||||
sint32 incr, ofs, newlen, count;
|
||||
sint16 *newdata, *dest, *src = (sint16 *) sp->data;
|
||||
sint16 v1, v2, v3, v4, *vptr;
|
||||
#ifdef DEBUG_CHATTER
|
||||
static const char note_name[12][3] =
|
||||
{
|
||||
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
||||
};
|
||||
#endif
|
||||
|
||||
DEBUG_MSG(" * pre-resampling for note %d (%s%d)\n",
|
||||
sp->note_to_use,
|
||||
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
|
||||
|
||||
a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) /
|
||||
((double) (sp->root_freq) * song->rate);
|
||||
newlen = (sint32)(sp->data_length / a);
|
||||
dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1));
|
||||
|
||||
count = (newlen >> FRACTION_BITS) - 1;
|
||||
ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
|
||||
|
||||
if (--count)
|
||||
*dest++ = src[0];
|
||||
|
||||
/* Since we're pre-processing and this doesn't have to be done in
|
||||
real-time, we go ahead and do the full sliding cubic interpolation. */
|
||||
while (--count)
|
||||
{
|
||||
vptr = src + (ofs >> FRACTION_BITS);
|
||||
/*
|
||||
* Electric Fence to the rescue: Accessing *(vptr - 1) is not a
|
||||
* good thing to do when vptr <= src. (TiMidity++ has a similar
|
||||
* safe-guard here.)
|
||||
*/
|
||||
v1 = (vptr > src) ? *(vptr - 1) : 0;
|
||||
v2 = *vptr;
|
||||
v3 = *(vptr + 1);
|
||||
v4 = *(vptr + 2);
|
||||
xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);
|
||||
*dest++ = (sint16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 +
|
||||
xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4))));
|
||||
ofs += incr;
|
||||
}
|
||||
|
||||
if (ofs & FRACTION_MASK)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS) + 1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
}
|
||||
else
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
|
||||
sp->data_length = newlen;
|
||||
sp->loop_start = (sint32)(sp->loop_start / a);
|
||||
sp->loop_end = (sint32)(sp->loop_end / a);
|
||||
free(sp->data);
|
||||
sp->data = (sample_t *) newdata;
|
||||
sp->sample_rate = 0;
|
||||
}
|
||||
24
project/jni/timidity/src/resample.h
Normal file
24
project/jni/timidity/src/resample.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
resample.h
|
||||
*/
|
||||
|
||||
extern sample_t *resample_voice(MidSong *song, int v, sint32 *countptr);
|
||||
extern void pre_resample(MidSong *song, MidSample *sp);
|
||||
188
project/jni/timidity/src/stream.c
Normal file
188
project/jni/timidity/src/stream.c
Normal file
@@ -0,0 +1,188 @@
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
#include "common.h"
|
||||
|
||||
struct _MidIStream
|
||||
{
|
||||
MidIStreamReadFunc read;
|
||||
MidIStreamCloseFunc close;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
typedef struct StdIOContext
|
||||
{
|
||||
FILE *fp;
|
||||
int autoclose;
|
||||
} StdIOContext;
|
||||
|
||||
size_t
|
||||
stdio_istream_read (void *ctx, void *ptr, size_t size, size_t nmemb)
|
||||
{
|
||||
return fread (ptr, size, nmemb, ((StdIOContext *) ctx)->fp);
|
||||
}
|
||||
|
||||
int
|
||||
stdio_istream_close (void *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
if (((StdIOContext *) ctx)->autoclose)
|
||||
ret = fclose (((StdIOContext *) ctx)->fp);
|
||||
free (ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct MemContext
|
||||
{
|
||||
sint8 *base;
|
||||
sint8 *current;
|
||||
sint8 *end;
|
||||
int autofree;
|
||||
} MemContext;
|
||||
|
||||
size_t
|
||||
mem_istream_read (void *ctx, void *ptr, size_t size, size_t nmemb)
|
||||
{
|
||||
MemContext *c;
|
||||
size_t count;
|
||||
|
||||
c = (MemContext *) ctx;
|
||||
count = nmemb;
|
||||
|
||||
if (c->current + count * size > c->end)
|
||||
count = (c->end - c->current) / size;
|
||||
|
||||
memcpy (ptr, c->current, count * size);
|
||||
c->current += count * size;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
mem_istream_close (void *ctx)
|
||||
{
|
||||
if (((MemContext *) ctx)->autofree)
|
||||
free (((MemContext *) ctx)->base);
|
||||
free (ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MidIStream *
|
||||
mid_istream_open_fp (FILE * fp, int autoclose)
|
||||
{
|
||||
StdIOContext *ctx;
|
||||
MidIStream *stream;
|
||||
|
||||
stream = safe_malloc (sizeof (MidIStream));
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx = safe_malloc (sizeof (StdIOContext));
|
||||
if (ctx == NULL)
|
||||
{
|
||||
free (stream);
|
||||
return NULL;
|
||||
}
|
||||
ctx->fp = fp;
|
||||
ctx->autoclose = autoclose;
|
||||
|
||||
stream->ctx = ctx;
|
||||
stream->read = stdio_istream_read;
|
||||
stream->close = stdio_istream_close;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
MidIStream *
|
||||
mid_istream_open_file (const char *file)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen (file, "rb");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
return mid_istream_open_fp (fp, 1);
|
||||
}
|
||||
|
||||
MidIStream *
|
||||
mid_istream_open_mem (void *mem, size_t size, int autofree)
|
||||
{
|
||||
MemContext *ctx;
|
||||
MidIStream *stream;
|
||||
|
||||
stream = safe_malloc (sizeof (MidIStream));
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx = safe_malloc (sizeof (MemContext));
|
||||
if (ctx == NULL)
|
||||
{
|
||||
free (stream);
|
||||
return NULL;
|
||||
}
|
||||
ctx->base = mem;
|
||||
ctx->current = mem;
|
||||
ctx->end = ((sint8 *) mem) + size;
|
||||
ctx->autofree = autofree;
|
||||
|
||||
stream->ctx = ctx;
|
||||
stream->read = mem_istream_read;
|
||||
stream->close = mem_istream_close;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
MidIStream *
|
||||
mid_istream_open_callbacks (MidIStreamReadFunc read,
|
||||
MidIStreamCloseFunc close, void *context)
|
||||
{
|
||||
MidIStream *stream;
|
||||
|
||||
stream = safe_malloc (sizeof (MidIStream));
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
stream->ctx = context;
|
||||
stream->read = read;
|
||||
stream->close = close;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
size_t
|
||||
mid_istream_read (MidIStream * stream, void *ptr, size_t size, size_t nmemb)
|
||||
{
|
||||
return stream->read (stream->ctx, ptr, size, nmemb);
|
||||
}
|
||||
|
||||
void
|
||||
mid_istream_skip (MidIStream * stream, size_t len)
|
||||
{
|
||||
size_t c;
|
||||
char tmp[1024];
|
||||
while (len > 0)
|
||||
{
|
||||
c = len;
|
||||
if (c > 1024)
|
||||
c = 1024;
|
||||
len -= c;
|
||||
if (c != mid_istream_read (stream, tmp, 1, c))
|
||||
{
|
||||
DEBUG_MSG ("mid_istream_skip error\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mid_istream_close (MidIStream * stream)
|
||||
{
|
||||
int ret = stream->close (stream->ctx);
|
||||
free (stream);
|
||||
return ret;
|
||||
}
|
||||
214
project/jni/timidity/src/tables.c
Normal file
214
project/jni/timidity/src/tables.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "tables.h"
|
||||
|
||||
const sint32 freq_table[128]=
|
||||
{
|
||||
8176, 8662, 9177, 9723,
|
||||
10301, 10913, 11562, 12250,
|
||||
12978, 13750, 14568, 15434,
|
||||
|
||||
16352, 17324, 18354, 19445,
|
||||
20602, 21827, 23125, 24500,
|
||||
25957, 27500, 29135, 30868,
|
||||
|
||||
32703, 34648, 36708, 38891,
|
||||
41203, 43654, 46249, 48999,
|
||||
51913, 55000, 58270, 61735,
|
||||
|
||||
65406, 69296, 73416, 77782,
|
||||
82407, 87307, 92499, 97999,
|
||||
103826, 110000, 116541, 123471,
|
||||
|
||||
130813, 138591, 146832, 155563,
|
||||
164814, 174614, 184997, 195998,
|
||||
207652, 220000, 233082, 246942,
|
||||
|
||||
261626, 277183, 293665, 311127,
|
||||
329628, 349228, 369994, 391995,
|
||||
415305, 440000, 466164, 493883,
|
||||
|
||||
523251, 554365, 587330, 622254,
|
||||
659255, 698456, 739989, 783991,
|
||||
830609, 880000, 932328, 987767,
|
||||
|
||||
1046502, 1108731, 1174659, 1244508,
|
||||
1318510, 1396913, 1479978, 1567982,
|
||||
1661219, 1760000, 1864655, 1975533,
|
||||
|
||||
2093005, 2217461, 2349318, 2489016,
|
||||
2637020, 2793826, 2959955, 3135963,
|
||||
3322438, 3520000, 3729310, 3951066,
|
||||
|
||||
4186009, 4434922, 4698636, 4978032,
|
||||
5274041, 5587652, 5919911, 6271927,
|
||||
6644875, 7040000, 7458620, 7902133,
|
||||
|
||||
8372018, 8869844, 9397273, 9956063,
|
||||
10548082, 11175303, 11839822, 12543854
|
||||
};
|
||||
|
||||
/* v=2.^((x/127-1) * 6) */
|
||||
const double vol_table[128] =
|
||||
{
|
||||
0.015625, 0.016145143728351113, 0.016682602624583379, 0.017237953096759438,
|
||||
0.017811790741104401, 0.01840473098076444, 0.019017409725829021, 0.019650484055324921,
|
||||
0.020304632921913132, 0.020980557880044631, 0.021678983838355849, 0.02240065983711079,
|
||||
0.023146359851523596, 0.023916883621822989, 0.024713057510949051, 0.025535735390801884,
|
||||
0.026385799557992876, 0.027264161680080529, 0.028171763773305786, 0.029109579212875332,
|
||||
0.030078613776876421, 0.031079906724942836, 0.032114531912828696, 0.033183598944085631,
|
||||
0.034288254360078256, 0.035429682869614412, 0.036609108619508737, 0.037827796507442342,
|
||||
0.039087053538526394, 0.040388230227024875, 0.041732722044739302, 0.043121970917609151,
|
||||
0.044557466772132896, 0.046040749133268132, 0.047573408775524545, 0.049157089429020417,
|
||||
0.050793489542332405, 0.05248436410402918, 0.054231526524842463, 0.056036850582493913,
|
||||
0.057902272431264008, 0.059829792678457581, 0.061821478529993396, 0.063879466007418645,
|
||||
0.066005962238725971, 0.068203247825430205, 0.070473679288442961, 0.072819691595368496,
|
||||
0.075243800771931268, 0.077748606600335793, 0.080336795407452768, 0.083011142945821612,
|
||||
0.085774517370559328, 0.088629882315368294, 0.091580300070941839, 0.094628934869176312,
|
||||
0.097779056276712184, 0.10103404270144323, 0.1043973850157546, 0.1078726903003755,
|
||||
0.11146368571286204, 0.11517422248485852, 0.11900828005242428, 0.12296997032385605,
|
||||
0.12706354208958254, 0.13129338557886089, 0.13566403716816194, 0.14018018424629392,
|
||||
0.14484667024148207, 0.14966849981579558, 0.15465084423249356, 0.15979904690204472,
|
||||
0.16511862911277009, 0.17061529595225433, 0.17629494242587571, 0.18216365977901747,
|
||||
0.18822774202974024, 0.19449369271892172, 0.20096823188510385, 0.20765830327152621,
|
||||
0.21457108177307616, 0.22171398113114205, 0.2290946618846218, 0.23672103958561411,
|
||||
0.2446012932886038, 0.25274387432224471, 0.26115751535314891, 0.26985123975140174,
|
||||
0.27883437126784744, 0.28811654403352405, 0.29770771289197112, 0.30761816407549192,
|
||||
0.31785852623682015, 0.32843978184802081, 0.33937327897885317, 0.3506707434672246,
|
||||
0.36234429149478936, 0.37440644258117928, 0.38687013301080181, 0.39974872970660535,
|
||||
0.41305604456569134, 0.42680634927214656, 0.44101439060298442, 0.45569540624360722,
|
||||
0.47086514112975281, 0.48653986433345225, 0.50273638651110641, 0.51947207793239625,
|
||||
0.53676488710936021, 0.55463336004561792, 0.57309666012638816, 0.59217458867062556,
|
||||
0.61188760616732485, 0.63225685421876243, 0.65330417821421161, 0.67505215075844849,
|
||||
0.69752409588017272, 0.72074411404630734, 0.74473710800900605, 0.76952880951308478,
|
||||
0.79514580689252357, 0.82161557358563286, 0.84896649759946774, 0.87722791195508854,
|
||||
0.90643012614631979, 0.93660445864574493, 0.96778327049280244, 1
|
||||
};
|
||||
|
||||
const double bend_fine[256] = {
|
||||
1, 1.0002256593050698, 1.0004513695322617, 1.0006771306930664,
|
||||
1.0009029427989777, 1.0011288058614922, 1.0013547198921082, 1.0015806849023274,
|
||||
1.0018067009036538, 1.002032767907594, 1.0022588859256572, 1.0024850549693551,
|
||||
1.0027112750502025, 1.0029375461797159, 1.0031638683694153, 1.0033902416308227,
|
||||
1.0036166659754628, 1.0038431414148634, 1.0040696679605541, 1.0042962456240678,
|
||||
1.0045228744169397, 1.0047495543507072, 1.0049762854369111, 1.0052030676870944,
|
||||
1.0054299011128027, 1.0056567857255843, 1.00588372153699, 1.006110708558573,
|
||||
1.0063377468018897, 1.0065648362784985, 1.0067919769999607, 1.0070191689778405,
|
||||
1.0072464122237039, 1.0074737067491204, 1.0077010525656616, 1.0079284496849015,
|
||||
1.0081558981184175, 1.008383397877789, 1.008610948974598, 1.0088385514204294,
|
||||
1.0090662052268706, 1.0092939104055114, 1.0095216669679448, 1.0097494749257656,
|
||||
1.009977334290572, 1.0102052450739643, 1.0104332072875455, 1.0106612209429215,
|
||||
1.0108892860517005, 1.0111174026254934, 1.0113455706759138, 1.0115737902145781,
|
||||
1.0118020612531047, 1.0120303838031153, 1.0122587578762337, 1.012487183484087,
|
||||
1.0127156606383041, 1.0129441893505169, 1.0131727696323602, 1.0134014014954713,
|
||||
1.0136300849514894, 1.0138588200120575, 1.0140876066888203, 1.0143164449934257,
|
||||
1.0145453349375237, 1.0147742765327674, 1.0150032697908125, 1.0152323147233171,
|
||||
1.015461411341942, 1.0156905596583505, 1.0159197596842091, 1.0161490114311862,
|
||||
1.0163783149109531, 1.0166076701351838, 1.0168370771155553, 1.0170665358637463,
|
||||
1.0172960463914391, 1.0175256087103179, 1.0177552228320703, 1.0179848887683858,
|
||||
1.0182146065309567, 1.0184443761314785, 1.0186741975816487, 1.0189040708931674,
|
||||
1.0191339960777379, 1.0193639731470658, 1.0195940021128593, 1.0198240829868295,
|
||||
1.0200542157806898, 1.0202844005061564, 1.0205146371749483, 1.0207449257987866,
|
||||
1.0209752663893958, 1.0212056589585028, 1.0214361035178368, 1.0216666000791297,
|
||||
1.0218971486541166, 1.0221277492545349, 1.0223584018921241, 1.0225891065786274,
|
||||
1.0228198633257899, 1.0230506721453596, 1.023281533049087, 1.0235124460487257,
|
||||
1.0237434111560313, 1.0239744283827625, 1.0242054977406807, 1.0244366192415495,
|
||||
1.0246677928971357, 1.0248990187192082, 1.025130296719539, 1.0253616269099028,
|
||||
1.0255930093020766, 1.0258244439078401, 1.0260559307389761, 1.0262874698072693,
|
||||
1.0265190611245079, 1.0267507047024822, 1.0269824005529853, 1.027214148687813,
|
||||
1.0274459491187637, 1.0276778018576387, 1.0279097069162415, 1.0281416643063788,
|
||||
1.0283736740398595, 1.0286057361284953, 1.0288378505841009, 1.0290700174184932,
|
||||
1.0293022366434921, 1.0295345082709197, 1.0297668323126017, 1.0299992087803651,
|
||||
1.030231637686041, 1.0304641190414621, 1.0306966528584645, 1.0309292391488862,
|
||||
1.0311618779245688, 1.0313945691973556, 1.0316273129790936, 1.0318601092816313,
|
||||
1.0320929581168212, 1.0323258594965172, 1.0325588134325767, 1.0327918199368598,
|
||||
1.0330248790212284, 1.0332579906975481, 1.0334911549776868, 1.033724371873515,
|
||||
1.0339576413969056, 1.0341909635597348, 1.0344243383738811, 1.0346577658512259,
|
||||
1.034891246003653, 1.0351247788430489, 1.0353583643813031, 1.0355920026303078,
|
||||
1.0358256936019572, 1.0360594373081489, 1.0362932337607829, 1.0365270829717617,
|
||||
1.0367609849529913, 1.0369949397163791, 1.0372289472738365, 1.0374630076372766,
|
||||
1.0376971208186156, 1.0379312868297725, 1.0381655056826686, 1.0383997773892284,
|
||||
1.0386341019613787, 1.0388684794110492, 1.0391029097501721, 1.0393373929906822,
|
||||
1.0395719291445176, 1.0398065182236185, 1.0400411602399278, 1.0402758552053915,
|
||||
1.0405106031319582, 1.0407454040315787, 1.0409802579162071, 1.0412151647977996,
|
||||
1.0414501246883161, 1.0416851375997183, 1.0419202035439705, 1.0421553225330404,
|
||||
1.042390494578898, 1.042625719693516, 1.0428609978888699, 1.043096329176938,
|
||||
1.0433317135697009, 1.0435671510791424, 1.0438026417172486, 1.0440381854960086,
|
||||
1.0442737824274138, 1.044509432523459, 1.044745135796141, 1.0449808922574599,
|
||||
1.0452167019194181, 1.0454525647940205, 1.0456884808932754, 1.0459244502291931,
|
||||
1.0461604728137874, 1.0463965486590741, 1.046632677777072, 1.0468688601798024,
|
||||
1.0471050958792898, 1.047341384887561, 1.0475777272166455, 1.047814122878576,
|
||||
1.048050571885387, 1.0482870742491166, 1.0485236299818055, 1.0487602390954964,
|
||||
1.0489969016022356, 1.0492336175140715, 1.0494703868430555, 1.0497072096012419,
|
||||
1.0499440858006872, 1.0501810154534512, 1.050417998571596, 1.0506550351671864,
|
||||
1.0508921252522903, 1.0511292688389782, 1.0513664659393229, 1.0516037165654004,
|
||||
1.0518410207292894, 1.0520783784430709, 1.0523157897188296, 1.0525532545686513,
|
||||
1.0527907730046264, 1.0530283450388465, 1.0532659706834067, 1.0535036499504049,
|
||||
1.0537413828519411, 1.0539791694001188, 1.0542170096070436, 1.0544549034848243,
|
||||
1.0546928510455722, 1.0549308523014012, 1.0551689072644284, 1.0554070159467728,
|
||||
1.0556451783605572, 1.0558833945179062, 1.0561216644309479, 1.0563599881118126,
|
||||
1.0565983655726334, 1.0568367968255465, 1.0570752818826903, 1.0573138207562065,
|
||||
1.057552413458239, 1.0577910600009348, 1.0580297603964437, 1.058268514656918,
|
||||
1.0585073227945128, 1.0587461848213857, 1.058985100749698, 1.0592240705916123
|
||||
};
|
||||
|
||||
const double bend_coarse[128] = {
|
||||
1, 1.0594630943592953, 1.122462048309373, 1.189207115002721,
|
||||
1.2599210498948732, 1.3348398541700344, 1.4142135623730951, 1.4983070768766815,
|
||||
1.5874010519681994, 1.681792830507429, 1.7817974362806785, 1.8877486253633868,
|
||||
2, 2.1189261887185906, 2.244924096618746, 2.3784142300054421,
|
||||
2.5198420997897464, 2.6696797083400687, 2.8284271247461903, 2.996614153753363,
|
||||
3.1748021039363992, 3.363585661014858, 3.5635948725613571, 3.7754972507267741,
|
||||
4, 4.2378523774371812, 4.4898481932374912, 4.7568284600108841,
|
||||
5.0396841995794928, 5.3393594166801366, 5.6568542494923806, 5.993228307506727,
|
||||
6.3496042078727974, 6.727171322029716, 7.1271897451227151, 7.5509945014535473,
|
||||
8, 8.4757047548743625, 8.9796963864749824, 9.5136569200217682,
|
||||
10.079368399158986, 10.678718833360273, 11.313708498984761, 11.986456615013454,
|
||||
12.699208415745595, 13.454342644059432, 14.25437949024543, 15.101989002907095,
|
||||
16, 16.951409509748721, 17.959392772949972, 19.027313840043536,
|
||||
20.158736798317967, 21.357437666720553, 22.627416997969522, 23.972913230026901,
|
||||
25.398416831491197, 26.908685288118864, 28.508758980490853, 30.203978005814196,
|
||||
32, 33.902819019497443, 35.918785545899944, 38.054627680087073,
|
||||
40.317473596635935, 42.714875333441107, 45.254833995939045, 47.945826460053802,
|
||||
50.796833662982394, 53.817370576237728, 57.017517960981706, 60.407956011628393,
|
||||
64, 67.805638038994886, 71.837571091799887, 76.109255360174146,
|
||||
80.63494719327187, 85.429750666882214, 90.509667991878089, 95.891652920107603,
|
||||
101.59366732596479, 107.63474115247546, 114.03503592196341, 120.81591202325679,
|
||||
128, 135.61127607798977, 143.67514218359977, 152.21851072034829,
|
||||
161.26989438654374, 170.85950133376443, 181.01933598375618, 191.78330584021521,
|
||||
203.18733465192958, 215.26948230495091, 228.07007184392683, 241.63182404651357,
|
||||
256, 271.22255215597971, 287.35028436719938, 304.43702144069658,
|
||||
322.53978877308765, 341.71900266752868, 362.03867196751236, 383.56661168043064,
|
||||
406.37466930385892, 430.53896460990183, 456.14014368785394, 483.26364809302686,
|
||||
512, 542.44510431195943, 574.70056873439876, 608.87404288139317,
|
||||
645.0795775461753, 683.43800533505737, 724.07734393502471, 767.13322336086128,
|
||||
812.74933860771785, 861.07792921980365, 912.28028737570787, 966.52729618605372,
|
||||
1024, 1084.8902086239189, 1149.4011374687975, 1217.7480857627863,
|
||||
1290.1591550923506, 1366.8760106701147, 1448.1546878700494, 1534.2664467217226
|
||||
};
|
||||
30
project/jni/timidity/src/tables.h
Normal file
30
project/jni/timidity/src/tables.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
tables.h
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#define sine(x) (sin((2*PI/1024.0) * (x)))
|
||||
|
||||
#define SINE_CYCLE_LENGTH 1024
|
||||
extern const sint32 freq_table[];
|
||||
extern const double vol_table[];
|
||||
extern const double bend_fine[];
|
||||
extern const double bend_coarse[];
|
||||
606
project/jni/timidity/src/timidity.c
Normal file
606
project/jni/timidity/src/timidity.c
Normal file
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "timidity.h"
|
||||
#include "timidity_internal.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "readmidi.h"
|
||||
#include "output.h"
|
||||
|
||||
#include "tables.h"
|
||||
|
||||
MidToneBank *master_tonebank[128], *master_drumset[128];
|
||||
|
||||
static char def_instr_name[256] = "";
|
||||
|
||||
#define MAXWORDS 10
|
||||
|
||||
/* Quick-and-dirty fgets() replacement. */
|
||||
|
||||
static char *__fgets(char *s, int size, FILE *fp)
|
||||
{
|
||||
int num_read = 0;
|
||||
int newline = 0;
|
||||
|
||||
while (num_read < size && !newline)
|
||||
{
|
||||
if (fread(&s[num_read], 1, 1, fp) != 1)
|
||||
break;
|
||||
|
||||
/* Unlike fgets(), don't store newline. Under Windows/DOS we'll
|
||||
* probably get an extra blank line for every line that's being
|
||||
* read, but that should be ok.
|
||||
*/
|
||||
if (s[num_read] == '\n' || s[num_read] == '\r')
|
||||
{
|
||||
s[num_read] = '\0';
|
||||
newline = 1;
|
||||
}
|
||||
|
||||
num_read++;
|
||||
}
|
||||
|
||||
s[num_read] = '\0';
|
||||
|
||||
return (num_read != 0) ? s : NULL;
|
||||
}
|
||||
|
||||
static int read_config_file(char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
char tmp[1024], *w[MAXWORDS], *cp;
|
||||
MidToneBank *bank=0;
|
||||
int i, j, k, line=0, words;
|
||||
static int rcf_count=0;
|
||||
|
||||
if (rcf_count>50)
|
||||
{
|
||||
DEBUG_MSG("Probable source loop in configuration files\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!(fp=open_file(name)))
|
||||
return -1;
|
||||
|
||||
while (__fgets(tmp, sizeof(tmp), fp))
|
||||
{
|
||||
line++;
|
||||
w[words=0]=strtok(tmp, " \t\240");
|
||||
if (!w[0]) continue;
|
||||
|
||||
/* Originally the TiMidity++ extensions were prefixed like this */
|
||||
if (strcmp(w[0], "#extension") == 0)
|
||||
words = -1;
|
||||
else if (*w[0] == '#')
|
||||
continue;
|
||||
|
||||
while (w[words] && *w[words] != '#' && (words < MAXWORDS))
|
||||
w[++words]=strtok(0," \t\240");
|
||||
|
||||
/*
|
||||
* TiMidity++ adds a number of extensions to the config file format.
|
||||
* Many of them are completely irrelevant to SDL_sound, but at least
|
||||
* we shouldn't choke on them.
|
||||
*
|
||||
* Unfortunately the documentation for these extensions is often quite
|
||||
* vague, gramatically strange or completely absent.
|
||||
*/
|
||||
if (
|
||||
!strcmp(w[0], "comm") /* "comm" program second */
|
||||
|| !strcmp(w[0], "HTTPproxy") /* "HTTPproxy" hostname:port */
|
||||
|| !strcmp(w[0], "FTPproxy") /* "FTPproxy" hostname:port */
|
||||
|| !strcmp(w[0], "mailaddr") /* "mailaddr" your-mail-address */
|
||||
|| !strcmp(w[0], "opt") /* "opt" timidity-options */
|
||||
)
|
||||
{
|
||||
/*
|
||||
* + "comm" sets some kind of comment -- the documentation is too
|
||||
* vague for me to understand at this time.
|
||||
* + "HTTPproxy", "FTPproxy" and "mailaddr" are for reading data
|
||||
* over a network, rather than from the file system.
|
||||
* + "opt" specifies default options for TiMidity++.
|
||||
*
|
||||
* These are all quite useless for our version of TiMidity, so
|
||||
* they can safely remain no-ops.
|
||||
*/
|
||||
} else if (!strcmp(w[0], "timeout")) /* "timeout" program second */
|
||||
{
|
||||
/*
|
||||
* Specifies a timeout value of the program. A number of seconds
|
||||
* before TiMidity kills the note. This may be useful to implement
|
||||
* later, but I don't see any urgent need for it.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"timeout\" in TiMidity config.\n");
|
||||
} else if (!strcmp(w[0], "copydrumset") /* "copydrumset" drumset */
|
||||
|| !strcmp(w[0], "copybank")) /* "copybank" bank */
|
||||
{
|
||||
/*
|
||||
* Copies all the settings of the specified drumset or bank to
|
||||
* the current drumset or bank. May be useful later, but not a
|
||||
* high priority.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"%s\" in TiMidity config.\n", w[0]);
|
||||
} else if (!strcmp(w[0], "undef")) /* "undef" progno */
|
||||
{
|
||||
/*
|
||||
* Undefines the tone "progno" of the current tone bank (or
|
||||
* drum set?). Not a high priority.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"undef\" in TiMidity config.\n");
|
||||
} else if (!strcmp(w[0], "altassign")) /* "altassign" prog1 prog2 ... */
|
||||
{
|
||||
/*
|
||||
* Sets the alternate assign for drum set. Whatever that's
|
||||
* supposed to mean.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"altassign\" in TiMidity config.\n");
|
||||
} else if (!strcmp(w[0], "soundfont")
|
||||
|| !strcmp(w[0], "font"))
|
||||
{
|
||||
/*
|
||||
* I can't find any documentation for these, but I guess they're
|
||||
* an alternative way of loading/unloading instruments.
|
||||
*
|
||||
* "soundfont" sf_file "remove"
|
||||
* "soundfont" sf_file ["order=" order] ["cutoff=" cutoff]
|
||||
* ["reso=" reso] ["amp=" amp]
|
||||
* "font" "exclude" bank preset keynote
|
||||
* "font" "order" order bank preset keynote
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implmement \"%s\" in TiMidity config.\n", w[0]);
|
||||
} else if (!strcmp(w[0], "progbase"))
|
||||
{
|
||||
/*
|
||||
* The documentation for this makes absolutely no sense to me, but
|
||||
* apparently it sets some sort of base offset for tone numbers.
|
||||
* Why anyone would want to do this is beyond me.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"progbase\" in TiMidity config.\n");
|
||||
} else if (!strcmp(w[0], "map")) /* "map" name set1 elem1 set2 elem2 */
|
||||
{
|
||||
/*
|
||||
* This extension is the one we will need to implement, as it is
|
||||
* used by the "eawpats". Unfortunately I cannot find any
|
||||
* documentation whatsoever for it, but it looks like it's used
|
||||
* for remapping one instrument to another somehow.
|
||||
*/
|
||||
DEBUG_MSG("FIXME: Implement \"map\" in TiMidity config.\n");
|
||||
}
|
||||
|
||||
/* Standard TiMidity config */
|
||||
|
||||
else if (!strcmp(w[0], "dir"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: No directory given\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
for (i=1; i<words; i++)
|
||||
add_to_pathlist(w[i]);
|
||||
}
|
||||
else if (!strcmp(w[0], "source"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: No file name given\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
for (i=1; i<words; i++)
|
||||
{
|
||||
rcf_count++;
|
||||
read_config_file(w[i]);
|
||||
rcf_count--;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(w[0], "default"))
|
||||
{
|
||||
if (words != 2)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: Must specify exactly one patch name\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
strncpy(def_instr_name, w[1], 255);
|
||||
def_instr_name[255]='\0';
|
||||
}
|
||||
else if (!strcmp(w[0], "drumset"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: No drum set number given\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[1]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: Drum set must be between 0 and 127\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
if (!master_drumset[i])
|
||||
{
|
||||
master_drumset[i] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(master_drumset[i], 0, sizeof(MidToneBank));
|
||||
master_drumset[i]->tone = safe_malloc(128 * sizeof(MidToneBankElement));
|
||||
memset(master_drumset[i]->tone, 0, 128 * sizeof(MidToneBankElement));
|
||||
}
|
||||
bank=master_drumset[i];
|
||||
}
|
||||
else if (!strcmp(w[0], "bank"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: No bank number given\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[1]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: Tone bank must be between 0 and 127\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
if (!master_tonebank[i])
|
||||
{
|
||||
master_tonebank[i] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(master_tonebank[i], 0, sizeof(MidToneBank));
|
||||
master_tonebank[i]->tone = safe_malloc(128 * sizeof(MidToneBankElement));
|
||||
memset(master_tonebank[i]->tone, 0, 128 * sizeof(MidToneBankElement));
|
||||
}
|
||||
bank=master_tonebank[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: syntax error\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[0]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: Program must be between 0 and 127\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
if (!bank)
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: Must specify tone bank or drum set before assignment\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
if (bank->tone[i].name)
|
||||
free(bank->tone[i].name);
|
||||
strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
|
||||
bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
|
||||
bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
|
||||
bank->tone[i].strip_tail=-1;
|
||||
|
||||
for (j=2; j<words; j++)
|
||||
{
|
||||
if (!(cp=strchr(w[j], '=')))
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: bad patch option %s\n", name, line, w[j]);
|
||||
return -2;
|
||||
}
|
||||
*cp++=0;
|
||||
if (!strcmp(w[j], "amp"))
|
||||
{
|
||||
k=atoi(cp);
|
||||
if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: amplification must be between 0 and %d\n",
|
||||
name, line, MAX_AMPLIFICATION);
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].amp=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "note"))
|
||||
{
|
||||
k=atoi(cp);
|
||||
if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: note must be between 0 and 127\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].note=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "pan"))
|
||||
{
|
||||
if (!strcmp(cp, "center"))
|
||||
k=64;
|
||||
else if (!strcmp(cp, "left"))
|
||||
k=0;
|
||||
else if (!strcmp(cp, "right"))
|
||||
k=127;
|
||||
else
|
||||
k=((atoi(cp)+100) * 100) / 157;
|
||||
if ((k<0 || k>127) || (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: panning must be left, right, center, or between -100 and 100\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].pan=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "keep"))
|
||||
{
|
||||
if (!strcmp(cp, "env"))
|
||||
bank->tone[i].strip_envelope=0;
|
||||
else if (!strcmp(cp, "loop"))
|
||||
bank->tone[i].strip_loop=0;
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: keep must be env or loop\n", name, line);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(w[j], "strip"))
|
||||
{
|
||||
if (!strcmp(cp, "env"))
|
||||
bank->tone[i].strip_envelope=1;
|
||||
else if (!strcmp(cp, "loop"))
|
||||
bank->tone[i].strip_loop=1;
|
||||
else if (!strcmp(cp, "tail"))
|
||||
bank->tone[i].strip_tail=1;
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: strip must be env, loop, or tail\n",
|
||||
name, line);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("%s: line %d: bad patch option %s\n", name, line, w[j]);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mid_init_no_config()
|
||||
{
|
||||
/* Allocate memory for the standard tonebank and drumset */
|
||||
master_tonebank[0] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(master_tonebank[0], 0, sizeof(MidToneBank));
|
||||
master_tonebank[0]->tone = safe_malloc(128 * sizeof(MidToneBankElement));
|
||||
memset(master_tonebank[0]->tone, 0, 128 * sizeof(MidToneBankElement));
|
||||
|
||||
master_drumset[0] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(master_drumset[0], 0, sizeof(MidToneBank));
|
||||
master_drumset[0]->tone = safe_malloc(128 * sizeof(MidToneBankElement));
|
||||
memset(master_drumset[0]->tone, 0, 128 * sizeof(MidToneBankElement));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mid_init(char *config_file)
|
||||
{
|
||||
/* !!! FIXME: This may be ugly, but slightly less so than requiring the
|
||||
* default search path to have only one element. I think.
|
||||
*
|
||||
* We only need to include the likely locations for the config
|
||||
* file itself since that file should contain any other directory
|
||||
* that needs to be added to the search path.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
add_to_pathlist("\\TIMIDITY");
|
||||
#else
|
||||
add_to_pathlist("/usr/local/lib/timidity");
|
||||
add_to_pathlist("/etc");
|
||||
#endif
|
||||
|
||||
mid_init_no_config();
|
||||
|
||||
if (config_file == NULL || *config_file == '\0')
|
||||
config_file = CONFIG_FILE;
|
||||
|
||||
return read_config_file(config_file);
|
||||
}
|
||||
|
||||
MidSong *mid_song_load_dls(MidIStream *stream, MidDLSPatches *patches, MidSongOptions *options)
|
||||
{
|
||||
MidSong *song;
|
||||
int i;
|
||||
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate memory for the song */
|
||||
song = (MidSong *)safe_malloc(sizeof(*song));
|
||||
memset(song, 0, sizeof(*song));
|
||||
song->patches = patches;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (master_tonebank[i])
|
||||
{
|
||||
song->tonebank[i] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(song->tonebank[i], 0, sizeof(MidToneBank));
|
||||
song->tonebank[i]->tone = master_tonebank[i]->tone;
|
||||
}
|
||||
if (master_drumset[i])
|
||||
{
|
||||
song->drumset[i] = safe_malloc(sizeof(MidToneBank));
|
||||
memset(song->drumset[i], 0, sizeof(MidToneBank));
|
||||
song->drumset[i]->tone = master_drumset[i]->tone;
|
||||
}
|
||||
}
|
||||
|
||||
song->amplification = DEFAULT_AMPLIFICATION;
|
||||
song->voices = DEFAULT_VOICES;
|
||||
song->drumchannels = DEFAULT_DRUMCHANNELS;
|
||||
|
||||
song->rate = options->rate;
|
||||
song->encoding = 0;
|
||||
if ((options->format & 0xFF) == 16)
|
||||
song->encoding |= PE_16BIT;
|
||||
if (options->format & 0x8000)
|
||||
song->encoding |= PE_SIGNED;
|
||||
if (options->channels == 1)
|
||||
song->encoding |= PE_MONO;
|
||||
switch (options->format) {
|
||||
case MID_AUDIO_S8:
|
||||
song->write = s32tos8;
|
||||
break;
|
||||
case MID_AUDIO_U8:
|
||||
song->write = s32tou8;
|
||||
break;
|
||||
case MID_AUDIO_S16LSB:
|
||||
song->write = s32tos16l;
|
||||
break;
|
||||
case MID_AUDIO_S16MSB:
|
||||
song->write = s32tos16b;
|
||||
break;
|
||||
case MID_AUDIO_U16LSB:
|
||||
song->write = s32tou16l;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("Unsupported audio format\n");
|
||||
song->write = s32tou16l;
|
||||
break;
|
||||
}
|
||||
|
||||
song->buffer_size = options->buffer_size;
|
||||
song->resample_buffer = safe_malloc(options->buffer_size * sizeof(sample_t));
|
||||
song->common_buffer = safe_malloc(options->buffer_size * 2 * sizeof(sint32));
|
||||
|
||||
song->bytes_per_sample =
|
||||
((song->encoding & PE_MONO) ? 1 : 2)
|
||||
* ((song->encoding & PE_16BIT) ? 2 : 1);
|
||||
|
||||
song->control_ratio = options->rate / CONTROLS_PER_SECOND;
|
||||
if (song->control_ratio < 1)
|
||||
song->control_ratio = 1;
|
||||
else if (song->control_ratio > MAX_CONTROL_RATIO)
|
||||
song->control_ratio = MAX_CONTROL_RATIO;
|
||||
|
||||
song->lost_notes = 0;
|
||||
song->cut_notes = 0;
|
||||
|
||||
song->events = read_midi_file(stream, song, &(song->groomed_event_count),
|
||||
&song->samples);
|
||||
|
||||
/* Make sure everything is okay */
|
||||
if (!song->events) {
|
||||
free(song);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
song->default_instrument = 0;
|
||||
song->default_program = DEFAULT_PROGRAM;
|
||||
|
||||
if (*def_instr_name)
|
||||
set_default_instrument(song, def_instr_name);
|
||||
|
||||
load_missing_instruments(song);
|
||||
|
||||
return(song);
|
||||
}
|
||||
|
||||
MidSong *mid_song_load(MidIStream *stream, MidSongOptions *options)
|
||||
{
|
||||
return mid_song_load_dls(stream, NULL, options);
|
||||
}
|
||||
|
||||
void mid_song_free(MidSong *song)
|
||||
{
|
||||
int i;
|
||||
|
||||
free_instruments(song);
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
free(song->tonebank[i]);
|
||||
if (song->drumset[i])
|
||||
free(song->drumset[i]);
|
||||
}
|
||||
|
||||
free(song->common_buffer);
|
||||
free(song->resample_buffer);
|
||||
free(song->events);
|
||||
|
||||
for (i = 0; i < (sizeof(song->meta_data) / sizeof(song->meta_data[0])); i++)
|
||||
{
|
||||
if (song->meta_data[i])
|
||||
free(song->meta_data[i]);
|
||||
}
|
||||
|
||||
free(song);
|
||||
}
|
||||
|
||||
void mid_exit(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (master_tonebank[i])
|
||||
{
|
||||
MidToneBankElement *e = master_tonebank[i]->tone;
|
||||
if (e != NULL)
|
||||
{
|
||||
for (j = 0; j < 128; j++)
|
||||
{
|
||||
if (e[j].name != NULL)
|
||||
free(e[j].name);
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
free(master_tonebank[i]);
|
||||
}
|
||||
if (master_drumset[i])
|
||||
{
|
||||
MidToneBankElement *e = master_drumset[i]->tone;
|
||||
if (e != NULL)
|
||||
{
|
||||
for (j = 0; j < 128; j++)
|
||||
{
|
||||
if (e[j].name != NULL)
|
||||
free(e[j].name);
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
free(master_drumset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free_pathlist();
|
||||
}
|
||||
206
project/jni/timidity/src/timidity.h.in
Normal file
206
project/jni/timidity/src/timidity.h.in
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
|
||||
libTiMidity -- MIDI to WAVE converter library
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
Copyright (C) 2004 Konstantin Korikov <lostclus@ua.fm>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TIMIDITY_H
|
||||
#define TIMIDITY_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define LIBTIMIDITY_VERSION_MAJOR @LIBTIMIDITY_MAJOR_VERSION@L
|
||||
#define LIBTIMIDITY_VERSION_MINOR @LIBTIMIDITY_MINOR_VERSION@L
|
||||
#define LIBTIMIDITY_PATCHLEVEL @LIBTIMIDITY_MICRO_VERSION@L
|
||||
|
||||
#define LIBTIMIDITY_VERSION \
|
||||
((LIBTIMIDITY_VERSION_MAJOR<<16)| \
|
||||
(LIBTIMIDITY_VERSION_MINOR<< 8)| \
|
||||
(LIBTIMIDITY_PATCHLEVEL))
|
||||
|
||||
/* Audio format flags (defaults to LSB byte order)
|
||||
*/
|
||||
#define MID_AUDIO_U8 0x0008 /* Unsigned 8-bit samples */
|
||||
#define MID_AUDIO_S8 0x8008 /* Signed 8-bit samples */
|
||||
#define MID_AUDIO_U16LSB 0x0010 /* Unsigned 16-bit samples */
|
||||
#define MID_AUDIO_S16LSB 0x8010 /* Signed 16-bit samples */
|
||||
#define MID_AUDIO_U16MSB 0x1010 /* As above, but big-endian byte order */
|
||||
#define MID_AUDIO_S16MSB 0x9010 /* As above, but big-endian byte order */
|
||||
#define MID_AUDIO_U16 MID_AUDIO_U16LSB
|
||||
#define MID_AUDIO_S16 MID_AUDIO_S16LSB
|
||||
|
||||
/* Core Library Types
|
||||
*/
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char sint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short sint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int sint32;
|
||||
|
||||
typedef size_t (*MidIStreamReadFunc) (void *ctx, void *ptr, size_t size,
|
||||
size_t nmemb);
|
||||
typedef int (*MidIStreamCloseFunc) (void *ctx);
|
||||
|
||||
typedef struct _MidIStream MidIStream;
|
||||
typedef struct _MidDLSPatches MidDLSPatches;
|
||||
typedef struct _MidSong MidSong;
|
||||
|
||||
typedef struct _MidSongOptions MidSongOptions;
|
||||
struct _MidSongOptions
|
||||
{
|
||||
sint32 rate; /* DSP frequency -- samples per second */
|
||||
uint16 format; /* Audio data format */
|
||||
uint8 channels; /* Number of channels: 1 mono, 2 stereo */
|
||||
uint16 buffer_size; /* Sample buffer size in samples */
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MID_SONG_TEXT = 0,
|
||||
MID_SONG_COPYRIGHT = 1
|
||||
} MidSongMetaId;
|
||||
|
||||
|
||||
/* Core Library Functions
|
||||
* ======================
|
||||
*/
|
||||
|
||||
/* Initialize the library. If config_file is NULL
|
||||
* search for configuratin file in default directories
|
||||
*/
|
||||
extern int mid_init (char *config_file);
|
||||
|
||||
/* Initialize the library without reading any
|
||||
* configuratin file
|
||||
*/
|
||||
extern int mid_init_no_config (void);
|
||||
|
||||
/* Shutdown the library
|
||||
*/
|
||||
extern void mid_exit (void);
|
||||
|
||||
|
||||
/* Input Stream Functions
|
||||
* ======================
|
||||
*/
|
||||
|
||||
/* Create input stream from a file name
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_file (const char *file);
|
||||
|
||||
/* Create input stream from a file pointer
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_fp (FILE * fp, int autoclose);
|
||||
|
||||
/* Create input stream from memory
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_mem (void *mem, size_t size,
|
||||
int autofree);
|
||||
|
||||
/* Create custom input stream
|
||||
*/
|
||||
extern MidIStream *mid_istream_open_callbacks (MidIStreamReadFunc read,
|
||||
MidIStreamCloseFunc close,
|
||||
void *context);
|
||||
|
||||
/* Read data from input stream
|
||||
*/
|
||||
extern size_t mid_istream_read (MidIStream * stream, void *ptr, size_t size,
|
||||
size_t nmemb);
|
||||
|
||||
/* Skip data from input stream
|
||||
*/
|
||||
extern void mid_istream_skip (MidIStream * stream, size_t len);
|
||||
|
||||
/* Close and destroy input stream
|
||||
*/
|
||||
extern int mid_istream_close (MidIStream * stream);
|
||||
|
||||
|
||||
/* DLS Pathes Functions
|
||||
* ====================
|
||||
*/
|
||||
|
||||
/* Load DLS patches
|
||||
*/
|
||||
extern MidDLSPatches *mid_dlspatches_load (MidIStream * stream);
|
||||
|
||||
/* Destroy DLS patches
|
||||
*/
|
||||
extern void mid_dlspatches_free (MidDLSPatches * patches);
|
||||
|
||||
|
||||
/* MIDI Song Functions
|
||||
* ===================
|
||||
*/
|
||||
|
||||
/* Load MIDI song
|
||||
*/
|
||||
extern MidSong *mid_song_load (MidIStream * stream,
|
||||
MidSongOptions * options);
|
||||
|
||||
/* Load MIDI song with specified DLS pathes
|
||||
*/
|
||||
extern MidSong *mid_song_load_dls (MidIStream * stream,
|
||||
MidDLSPatches * patches,
|
||||
MidSongOptions * options);
|
||||
|
||||
/* Set song amplification value
|
||||
*/
|
||||
extern void mid_song_set_volume (MidSong * song, int volume);
|
||||
|
||||
/* Seek song to the start position and initialize conversion
|
||||
*/
|
||||
extern void mid_song_start (MidSong * song);
|
||||
|
||||
/* Read WAVE data
|
||||
*/
|
||||
extern size_t mid_song_read_wave (MidSong * song, void *ptr, size_t size);
|
||||
|
||||
/* Seek song to specified offset in millseconds
|
||||
*/
|
||||
extern void mid_song_seek (MidSong * song, uint32 ms);
|
||||
|
||||
/* Get total song time in millseconds
|
||||
*/
|
||||
extern uint32 mid_song_get_total_time (MidSong * song);
|
||||
|
||||
/* Get current song time in millseconds
|
||||
*/
|
||||
extern uint32 mid_song_get_time (MidSong * song);
|
||||
|
||||
/* Get song meta data. Return NULL if no meta data found
|
||||
*/
|
||||
extern char *mid_song_get_meta (MidSong * song, MidSongMetaId what);
|
||||
|
||||
/* Destroy song
|
||||
*/
|
||||
extern void mid_song_free (MidSong * song);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* TIMIDITY_H */
|
||||
192
project/jni/timidity/src/timidity_internal.h
Normal file
192
project/jni/timidity/src/timidity_internal.h
Normal file
@@ -0,0 +1,192 @@
|
||||
#ifndef TIMIDITY_INTERNAL_H
|
||||
#define TIMIDITY_INTERNAL_H
|
||||
|
||||
#include "timidity.h"
|
||||
|
||||
#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
|
||||
(defined(__alpha__) || defined(__alpha)) || \
|
||||
defined(__arm__) || \
|
||||
(defined(__mips__) && defined(__MIPSEL__)) || \
|
||||
defined(__SYMBIAN32__) || \
|
||||
defined(__x86_64__) || \
|
||||
defined(__LITTLE_ENDIAN__)
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN
|
||||
#endif
|
||||
#undef BIG_ENDIAN
|
||||
#else
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN
|
||||
#endif
|
||||
#undef LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
/* Instrument files are little-endian, MIDI files big-endian, so we
|
||||
need to do some conversions. */
|
||||
|
||||
#define XCHG_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
|
||||
#ifdef __i486__
|
||||
# define XCHG_LONG(x) \
|
||||
({ sint32 __value; \
|
||||
asm ("bswap %1; movl %1,%0" : "=g" (__value) : "r" (x)); \
|
||||
__value; })
|
||||
#else
|
||||
# define XCHG_LONG(x) ((((x)&0xFF)<<24) | \
|
||||
(((x)&0xFF00)<<8) | \
|
||||
(((x)&0xFF0000)>>8) | \
|
||||
(((x)>>24)&0xFF))
|
||||
#endif
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
#define SWAPLE16(x) x
|
||||
#define SWAPLE32(x) x
|
||||
#define SWAPBE16(x) XCHG_SHORT(x)
|
||||
#define SWAPBE32(x) XCHG_LONG(x)
|
||||
#else
|
||||
#define SWAPBE16(x) x
|
||||
#define SWAPBE32(x) x
|
||||
#define SWAPLE16(x) XCHG_SHORT(x)
|
||||
#define SWAPLE32(x) XCHG_LONG(x)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_MSG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_MSG(...)
|
||||
#endif
|
||||
|
||||
|
||||
#define MID_VIBRATO_SAMPLE_INCREMENTS 32
|
||||
|
||||
/* Maximum polyphony. */
|
||||
#define MID_MAX_VOICES 48
|
||||
|
||||
typedef sint16 sample_t;
|
||||
typedef sint32 final_volume_t;
|
||||
|
||||
typedef struct _MidSample MidSample;
|
||||
struct _MidSample
|
||||
{
|
||||
sint32
|
||||
loop_start, loop_end, data_length,
|
||||
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
|
||||
sint32 envelope_rate[6], envelope_offset[6];
|
||||
float volume;
|
||||
sample_t *data;
|
||||
sint32
|
||||
tremolo_sweep_increment, tremolo_phase_increment,
|
||||
vibrato_sweep_increment, vibrato_control_ratio;
|
||||
uint8 tremolo_depth, vibrato_depth, modes;
|
||||
sint8 panning, note_to_use;
|
||||
};
|
||||
|
||||
typedef struct _MidChannel MidChannel;
|
||||
struct _MidChannel
|
||||
{
|
||||
int bank, program, volume, sustain, panning, pitchbend, expression;
|
||||
int mono; /* one note only on this channel -- not implemented yet */
|
||||
int pitchsens;
|
||||
/* chorus, reverb... Coming soon to a 300-MHz, eight-way superscalar
|
||||
processor near you */
|
||||
float pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||
};
|
||||
|
||||
typedef struct _MidVoice MidVoice;
|
||||
struct _MidVoice
|
||||
{
|
||||
uint8 status, channel, note, velocity;
|
||||
MidSample *sample;
|
||||
sint32
|
||||
orig_frequency, frequency,
|
||||
sample_offset, sample_increment,
|
||||
envelope_volume, envelope_target, envelope_increment,
|
||||
tremolo_sweep, tremolo_sweep_position,
|
||||
tremolo_phase, tremolo_phase_increment,
|
||||
vibrato_sweep, vibrato_sweep_position;
|
||||
|
||||
final_volume_t left_mix, right_mix;
|
||||
|
||||
float left_amp, right_amp, tremolo_volume;
|
||||
sint32 vibrato_sample_increment[MID_VIBRATO_SAMPLE_INCREMENTS];
|
||||
int
|
||||
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
||||
envelope_stage, control_counter, panning, panned;
|
||||
|
||||
};
|
||||
|
||||
typedef struct _MidInstrument MidInstrument;
|
||||
struct _MidInstrument
|
||||
{
|
||||
int samples;
|
||||
MidSample *sample;
|
||||
};
|
||||
|
||||
typedef struct _MidToneBankElement MidToneBankElement;
|
||||
struct _MidToneBankElement
|
||||
{
|
||||
char *name;
|
||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
||||
};
|
||||
|
||||
typedef struct _MidToneBank MidToneBank;
|
||||
struct _MidToneBank
|
||||
{
|
||||
MidToneBankElement *tone;
|
||||
MidInstrument *instrument[128];
|
||||
};
|
||||
|
||||
typedef struct _MidEvent MidEvent;
|
||||
struct _MidEvent
|
||||
{
|
||||
sint32 time;
|
||||
uint8 channel, type, a, b;
|
||||
};
|
||||
|
||||
typedef struct _MidEventList MidEventList;
|
||||
struct _MidEventList
|
||||
{
|
||||
MidEvent event;
|
||||
void *next;
|
||||
};
|
||||
|
||||
struct _MidSong
|
||||
{
|
||||
int playing;
|
||||
sint32 rate;
|
||||
sint32 encoding;
|
||||
int bytes_per_sample;
|
||||
float master_volume;
|
||||
sint32 amplification;
|
||||
MidDLSPatches *patches;
|
||||
MidToneBank *tonebank[128];
|
||||
MidToneBank *drumset[128];
|
||||
MidInstrument *default_instrument;
|
||||
int default_program;
|
||||
void (*write) (void *dp, sint32 * lp, sint32 c);
|
||||
int buffer_size;
|
||||
sample_t *resample_buffer;
|
||||
sint32 *common_buffer;
|
||||
/* These would both fit into 32 bits, but they are often added in
|
||||
large multiples, so it's simpler to have two roomy ints */
|
||||
/* samples per MIDI delta-t */
|
||||
sint32 sample_increment;
|
||||
sint32 sample_correction;
|
||||
MidChannel channel[16];
|
||||
MidVoice voice[MID_MAX_VOICES];
|
||||
int voices;
|
||||
sint32 drumchannels;
|
||||
sint32 control_ratio;
|
||||
sint32 lost_notes;
|
||||
sint32 cut_notes;
|
||||
sint32 samples;
|
||||
MidEvent *events;
|
||||
MidEvent *current_event;
|
||||
MidEventList *evlist;
|
||||
sint32 current_sample;
|
||||
sint32 event_count;
|
||||
sint32 at;
|
||||
sint32 groomed_event_count;
|
||||
char *meta_data[8];
|
||||
};
|
||||
|
||||
#endif /* TIMIDITY_INTERNAL_H */
|
||||
Reference in New Issue
Block a user