mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
This commit is contained in:
parent
01c6dcf6c7
commit
a855d62025
994 changed files with 336924 additions and 15 deletions
458
apps/plugins/sdl/COPYING
Normal file
458
apps/plugins/sdl/COPYING
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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
|
||||
94
apps/plugins/sdl/CREDITS
Normal file
94
apps/plugins/sdl/CREDITS
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
Simple DirectMedia Layer CREDITS
|
||||
Thanks to everyone who made this possible, including:
|
||||
|
||||
* Cliff Matthews, for giving me a reason to start this project. :)
|
||||
-- Executor rocks! *grin*
|
||||
|
||||
* Scott Call, for making a home for SDL on the 'Net... Thanks! :)
|
||||
|
||||
* The Linux Fund, C Magazine, Educational Technology Resources Inc.,
|
||||
Gareth Noyce, Jesse Pavel, Keith Kitchin, Jeremy Horvath, Thomas Nicholson,
|
||||
Hans-Peter Gygax, the Eternal Lands Development Team, Lars Brubaker,
|
||||
and Phoenix Kokido for financial contributions
|
||||
|
||||
* Gaëtan de Menten for writing the PHP and SQL behind the SDL website
|
||||
|
||||
* Tim Jones for the new look of the SDL website
|
||||
|
||||
* Marco Kraus for setting up SDL merchandise
|
||||
|
||||
* Martin Donlon for his work on the SDL Documentation Project
|
||||
|
||||
* Ryan Gordon for helping everybody out and keeping the dream alive. :)
|
||||
|
||||
* IBM R&D Lab for their PS3 SPE video acceleration code
|
||||
|
||||
* Mattias Engdegård, for help with the Solaris port and lots of other help
|
||||
|
||||
* Max Watson, Matt Slot, and Kyle for help with the MacOS Classic port
|
||||
|
||||
* Stan Shebs, for the initial Mac OS X port
|
||||
|
||||
* Eric Wing, Max Horn, and Darrell Walisser for unflagging work on the Mac OS X port
|
||||
|
||||
* Patrick Trainor, Jim Boucher, and Mike Gorchak for the QNX Neutrino port
|
||||
|
||||
* Carsten Griwodz for the AIX port
|
||||
|
||||
* Gabriele Greco, for the Amiga port
|
||||
|
||||
* Patrice Mandin, for the Atari port
|
||||
|
||||
* Hannu Viitala for the EPOC port
|
||||
|
||||
* Marcus Mertama for the S60 port.
|
||||
|
||||
* Peter Valchev for nagging me about the OpenBSD port until I got it right. :)
|
||||
|
||||
* Kent B Mein, for a place to do the IRIX port
|
||||
|
||||
* Ash, for a place to do the OSF/1 Alpha port
|
||||
|
||||
* David Sowsy, for help with the BeOS port
|
||||
|
||||
* Eugenia Loli, for endless work on porting SDL games to BeOS
|
||||
|
||||
* Jon Taylor for the GGI front-end
|
||||
|
||||
* Paulus Esterhazy, for the Visual C++ testing and libraries
|
||||
|
||||
* Brenda Tantzen, for Metrowerks CodeWarrior on MacOS
|
||||
|
||||
* Chris Nentwich, for the Hermes assembly blitters
|
||||
|
||||
* Michael Vance and Jim Kutter for the X11 OpenGL support
|
||||
|
||||
* Stephane Peter, for the AAlib front-end and multi-threaded timer idea.
|
||||
|
||||
* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation
|
||||
|
||||
* Peter Wiklund, for the 1998 winning SDL logo,
|
||||
and Arto Hamara, Steven Wong, and Kent Mein for other logo entries.
|
||||
|
||||
* Arne Claus, for the 2004 winning SDL logo,
|
||||
and Shandy Brown, Jac, Alex Lyman, Mikkel Gjoel, #Guy, Jonas Hartmann,
|
||||
Daniel Liljeberg, Ronald Sowa, DocD, Pekka Jaervinen, Patrick Avella,
|
||||
Erkki Kontilla, Levon Gavalian, Hal Emerich, David Wiktorsson,
|
||||
S. Schury and F. Hufsky, Ciska de Ruyver, Shredweat, Tyler Montbriand,
|
||||
Martin Andersson, Merlyn Wysard, Fernando Ibanez, David Miller,
|
||||
Andre Bommele, lovesby.com, Francisco Camenforte Torres, and David Igreja
|
||||
for other logo entries.
|
||||
|
||||
* Bob Pendleton and David Olofson for being long time contributors to
|
||||
the SDL mailing list.
|
||||
|
||||
* Everybody at Loki Software, Inc. for their great contributions!
|
||||
|
||||
And a big hand to everyone else who gave me appreciation, advice,
|
||||
and suggestions, especially the good folks on the SDL mailing list.
|
||||
|
||||
THANKS! :)
|
||||
|
||||
-- Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
5
apps/plugins/sdl/NOTES
Normal file
5
apps/plugins/sdl/NOTES
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
- SDL sources are mostly untouched, only some minor tweaks to make it build
|
||||
- SDL_image only builds XPM support, edit SDL_config_rockbox.h to change
|
||||
- Only video and "keyboard" drivers are implemented, sound and threading are a WIP
|
||||
- Video may not work under all pixel formats, please tell me if it doesn't!
|
||||
- Ported SDL would conflict with hosted platform's SDL, if present. Worked around by using objcopy --redefine-syms
|
||||
51
apps/plugins/sdl/README
Normal file
51
apps/plugins/sdl/README
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
See NOTES for Rockbox-specific porting notes.
|
||||
The original README is below:
|
||||
|
||||
Simple DirectMedia Layer
|
||||
|
||||
(SDL)
|
||||
|
||||
Version 1.2
|
||||
|
||||
---
|
||||
http://www.libsdl.org/
|
||||
|
||||
This is the Simple DirectMedia Layer, a general API that provides low
|
||||
level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL,
|
||||
and 2D framebuffer across multiple platforms.
|
||||
|
||||
The current version supports Linux, Windows CE/95/98/ME/XP/Vista, BeOS,
|
||||
MacOS Classic, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX,
|
||||
and QNX. The code contains support for Dreamcast, Atari, AIX, OSF/Tru64,
|
||||
RISC OS, SymbianOS, Nintendo DS, and OS/2, but these are not officially
|
||||
supported.
|
||||
|
||||
SDL is written in C, but works with C++ natively, and has bindings to
|
||||
several other languages, including Ada, C#, Eiffel, Erlang, Euphoria,
|
||||
Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP,
|
||||
Pike, Pliant, Python, Ruby, and Smalltalk.
|
||||
|
||||
This library is distributed under GNU LGPL version 2, which can be
|
||||
found in the file "COPYING". This license allows you to use SDL
|
||||
freely in commercial programs as long as you link with the dynamic
|
||||
library.
|
||||
|
||||
The best way to learn how to use SDL is to check out the header files in
|
||||
the "include" subdirectory and the programs in the "test" subdirectory.
|
||||
The header files and test programs are well commented and always up to date.
|
||||
More documentation is available in HTML format in "docs/index.html", and
|
||||
a documentation wiki is available online at:
|
||||
http://www.libsdl.org/cgi/docwiki.cgi
|
||||
|
||||
The test programs in the "test" subdirectory are in the public domain.
|
||||
|
||||
Frequently asked questions are answered online:
|
||||
http://www.libsdl.org/faq.php
|
||||
|
||||
If you need help with the library, or just want to discuss SDL related
|
||||
issues, you can join the developers mailing list:
|
||||
http://www.libsdl.org/mailing-list.php
|
||||
|
||||
Enjoy!
|
||||
Sam Lantinga (slouken@libsdl.org)
|
||||
|
||||
13
apps/plugins/sdl/README-SDL.txt
Normal file
13
apps/plugins/sdl/README-SDL.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
Please distribute this file with the SDL runtime environment:
|
||||
|
||||
The Simple DirectMedia Layer (SDL for short) is a cross-platfrom library
|
||||
designed to make it easy to write multi-media software, such as games and
|
||||
emulators.
|
||||
|
||||
The Simple DirectMedia Layer library source code is available from:
|
||||
http://www.libsdl.org/
|
||||
|
||||
This library is distributed under the terms of the GNU LGPL license:
|
||||
http://www.gnu.org/copyleft/lesser.html
|
||||
|
||||
56
apps/plugins/sdl/README.Porting
Normal file
56
apps/plugins/sdl/README.Porting
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
* Porting To A New Platform
|
||||
|
||||
The first thing you have to do when porting to a new platform, is look at
|
||||
include/SDL_platform.h and create an entry there for your operating system.
|
||||
The standard format is __PLATFORM__, where PLATFORM is the name of the OS.
|
||||
Ideally SDL_platform.h will be able to auto-detect the system it's building
|
||||
on based on C preprocessor symbols.
|
||||
|
||||
There are two basic ways of building SDL at the moment:
|
||||
|
||||
1. The "UNIX" way: ./configure; make; make install
|
||||
|
||||
If you have a GNUish system, then you might try this. Edit configure.in,
|
||||
take a look at the large section labelled:
|
||||
"Set up the configuration based on the target platform!"
|
||||
Add a section for your platform, and then re-run autogen.sh and build!
|
||||
|
||||
2. Using an IDE:
|
||||
|
||||
If you're using an IDE or other non-configure build system, you'll probably
|
||||
want to create a custom SDL_config.h for your platform. Edit SDL_config.h,
|
||||
add a section for your platform, and create a custom SDL_config_{platform}.h,
|
||||
based on SDL_config.h.minimal and SDL_config.h.in
|
||||
|
||||
Add the top level include directory to the header search path, and then add
|
||||
the following sources to the project:
|
||||
src/*.c
|
||||
src/audio/*.c
|
||||
src/cdrom/*.c
|
||||
src/cpuinfo/*.c
|
||||
src/events/*.c
|
||||
src/file/*.c
|
||||
src/joystick/*.c
|
||||
src/stdlib/*.c
|
||||
src/thread/*.c
|
||||
src/timer/*.c
|
||||
src/video/*.c
|
||||
src/audio/disk/*.c
|
||||
src/video/dummy/*.c
|
||||
src/joystick/dummy/*.c
|
||||
src/cdrom/dummy/*.c
|
||||
src/thread/generic/*.c
|
||||
src/timer/dummy/*.c
|
||||
src/loadso/dummy/*.c
|
||||
|
||||
|
||||
Once you have a working library without any drivers, you can go back to each
|
||||
of the major subsystems and start implementing drivers for your platform.
|
||||
|
||||
If you have any questions, don't hesitate to ask on the SDL mailing list:
|
||||
http://www.libsdl.org/mailing-list.php
|
||||
|
||||
Enjoy!
|
||||
Sam Lantinga (slouken@libsdl.org)
|
||||
|
||||
198
apps/plugins/sdl/SDL_image/CHANGES
Normal file
198
apps/plugins/sdl/SDL_image/CHANGES
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
1.2.12:
|
||||
Sam Lantinga - Thu Jan 19 23:18:09 EST 2012
|
||||
* Fixed regression in 1.2.11 loading 8-bit PNG images with libpng
|
||||
|
||||
1.2.11:
|
||||
Sam Lantinga - Sat Jan 14 17:54:38 EST 2012
|
||||
* Fixed loading 8-bit PNG images on Mac OS X
|
||||
Sam Lantinga - Sat Dec 31 09:35:40 EST 2011
|
||||
* SDL_image is now under the zlib license
|
||||
Michael Bonfils - Mon Nov 28 21:46:00 EST 2011
|
||||
* Added WEBP image support
|
||||
Thomas Klausner - Wed Jan 19 19:31:25 PST 2011
|
||||
* Fixed compiling with libpng 1.4
|
||||
Sam Lantinga - Mon Jan 10 12:09:57 2011 -0800
|
||||
* Added Android.mk to build on the Android platform
|
||||
Sam Lantinga - Mon May 10 22:42:53 PDT 2010
|
||||
* Fixed loading HAM6 images with stencil mask
|
||||
Mark Tucker - Fri, 27 Nov 2009 12:38:21 -0500
|
||||
* Fixed bug loading 15 and 16 bit BMP images
|
||||
|
||||
1.2.10:
|
||||
Sam Lantinga - Sat Nov 14 11:22:14 PST 2009
|
||||
* Fixed bug loading multiple images
|
||||
|
||||
1.2.9:
|
||||
Sam Lantinga - Tue Nov 10 00:29:20 PST 2009
|
||||
* Fixed alpha premultiplication on Mac OS X and iPhone OS
|
||||
Sam Lantinga - Sun Nov 8 07:52:11 PST 2009
|
||||
* Fixed checking for IMG_Init() return value in image loaders
|
||||
|
||||
1.2.8:
|
||||
Sam Lantinga - Sun Oct 4 13:12:54 PDT 2009
|
||||
* Added support for uncompressed PCX files
|
||||
Mason Wheeler - 2009-06-10 06:29:45 PDT
|
||||
* Added IMG_Init()/IMG_Quit() to prevent constantly loading and unloading DLLs
|
||||
Couriersud - Mon, 12 Jan 2009 17:21:13 -0800
|
||||
* Added support for ICO and CUR image files
|
||||
Eric Wing - Fri, 2 Jan 2009 02:01:16 -0800
|
||||
* Added ImageIO loading infrastructure for Mac OS X
|
||||
* Added UIImage loading infrastructure for iPhone / iPod Touch
|
||||
|
||||
1.2.7:
|
||||
Sam Lantinga - Sun Nov 2 15:08:27 PST 2008
|
||||
* Fixed buffer overflow in BMP loading code, discovered by j00ru//vx
|
||||
Sam Lantinga - Fri Dec 28 08:34:54 PST 2007
|
||||
* Fixed buffer overflow in GIF loading code, discovered by Michael Skladnikiewicz
|
||||
|
||||
1.2.6:
|
||||
Sam lantinga - Wed Jul 18 00:30:32 PDT 2007
|
||||
* Improved detection of libjpeg, libpng, and libtiff at configure time
|
||||
* PNG and TIFF images are correctly identified even if dynamic libraries
|
||||
to load them aren't available.
|
||||
* Fixed loading of TIFF images using libtiff 3.6
|
||||
Sam Lantinga - Thu Jul 5 07:52:35 2007
|
||||
* Fixed static linking with libjpeg
|
||||
Michael Koch - Tue Feb 13 10:09:17 2007
|
||||
* Fixed crash in IMG_ReadXPMFromArray()
|
||||
|
||||
1.2.5:
|
||||
Maurizio Monge - Sun May 14 13:57:32 PDT 2006
|
||||
* Fixed loading BMP palettes at unusual offsets
|
||||
Sam Lantinga - Thu May 11 21:51:19 PDT 2006
|
||||
* Added support for dynamically loading libjpeg, libpng, and libtiff.
|
||||
Sam Lantinga - Sun Apr 30 01:48:40 PDT 2006
|
||||
* Added gcc-fat.sh for generating Universal binaries on Mac OS X
|
||||
* Updated libtool support to version 1.5.22
|
||||
Sam Lantinga - Sat Feb 4 15:17:44 PST 2006
|
||||
* Added support for XV thumbnail images
|
||||
Gautier Portet - Fri, 19 Mar 2004 17:35:12 +0100
|
||||
* Added support for 32-bit BMP files with alpha
|
||||
|
||||
1.2.4:
|
||||
Pierre G. Richard - Fri, 30 Jul 2004 11:13:11 +0000 (UTC)
|
||||
* Added support for RLE encoded BMP files
|
||||
Marc Le Douarain - Fri, 26 Dec 2003 18:23:42 +0100
|
||||
* Added EHB and HAM mode support to the ILBM loader
|
||||
Sam Lantinga - Wed Nov 19 00:23:44 PST 2003
|
||||
* Updated libtool support for new mingw32 DLL build process
|
||||
Holger Schemel - Mon, 04 Aug 2003 21:50:52 +0200
|
||||
* Fixed crash loading certain PCX images
|
||||
Kyle Davenport - Sat, 19 Apr 2003 17:13:31 -0500
|
||||
* Added .la files to the development RPM, fixing RPM build on RedHat 8
|
||||
|
||||
1.2.3:
|
||||
Ryan C. Gordon - Sat, 8 Feb 2003 09:36:33 -0500
|
||||
* Fixed memory leak with non-seekable SDL_RWops
|
||||
Marc Le Douarain - Sun, 22 Dec 2002 22:59:51 +0100
|
||||
* Added 24-bit support to the ILBM format loader
|
||||
Sam Lantinga - Sun Oct 20 20:55:46 PDT 2002
|
||||
* Added shared library support for MacOS X
|
||||
Pete Shinners - Thu Jun 20 10:05:54 PDT 2002
|
||||
* The JPEG loader can now load EXIF format JPEG images
|
||||
Dag-Erling Smorgrav - Thu May 2 19:09:48 PDT 2002
|
||||
* The XCF loader now ignores invisible layers and channels
|
||||
|
||||
1.2.2:
|
||||
Sam Lantinga - Sat Apr 13 07:49:47 PDT 2002
|
||||
* Updated autogen.sh for new versions of automake
|
||||
* Specify the SDL API calling convention (C by default)
|
||||
Mattias Engdegård - Fri Dec 28 17:54:31 PST 2001
|
||||
* Worked around exit() in the jpeg image library
|
||||
|
||||
1.2.1:
|
||||
Mattias Engdegård - Tue Nov 20 08:08:53 PST 2001
|
||||
* Fixed transparency in the GIF loading code
|
||||
Daniel Morais - Sun Sep 23 16:32:13 PDT 2001
|
||||
* Added support for the IFF (LBM) image format
|
||||
Sam Lantinga - Sun Aug 19 01:51:44 PDT 2001
|
||||
* Added Project Builder projects for building MacOS X framework
|
||||
Mattias Engdegård - Tue Jul 31 04:32:29 PDT 2001
|
||||
* Fixed transparency in 8-bit PNG files
|
||||
Mattias Engdegård - Sat Apr 28 11:30:22 PDT 2001
|
||||
* Added support for loading XPM image data directly
|
||||
Paul Jenner - Sat, 14 Apr 2001 09:20:38 -0700 (PDT)
|
||||
* Added support for building RPM directly from tar archive
|
||||
|
||||
1.2.0:
|
||||
Sam Lantinga - Wed Apr 4 12:42:20 PDT 2001
|
||||
* Synchronized release version with SDL 1.2.0
|
||||
|
||||
1.1.1:
|
||||
Berni - Wed Mar 7 09:18:02 PST 2001
|
||||
* Added initial GIMP XCF support (disabled by default)
|
||||
Mattias Engdegård - Wed Mar 7 09:01:49 PST 2001
|
||||
* Added general PNM (PPM/PGM/PBM) support
|
||||
Mattias Engdegård - Sun Mar 4 14:23:42 PST 2001
|
||||
* Fixed bugs in PPM support, added ASCII PPM support
|
||||
Mattias Engdegård - Fri Mar 2 14:48:09 PST 2001
|
||||
* Cleaned up some compiler warnings
|
||||
Mattias Engdegård - Tue Feb 27 12:44:43 PST 2001
|
||||
* Improved the PCX loading code
|
||||
* Modified showimage to set hardware palette for 8-bit displays
|
||||
Robert Stein - Thu, 22 Feb 2001 14:26:19 -0600
|
||||
* Improved the PPM loading code
|
||||
Sam Lantinga - Tue Jan 30 14:24:06 PST 2001
|
||||
* Modified showimage to accept multiple images on the command line
|
||||
Sam Lantinga - Mon Dec 18 02:49:29 PST 2000
|
||||
* Added a Visual C++ project including JPEG and PNG loading support
|
||||
Mattias Engdegård - Wed Dec 6 10:00:07 PST 2000
|
||||
* Improved the XPM loading code
|
||||
|
||||
1.1.0:
|
||||
Sam Lantinga - Wed Nov 29 00:46:27 PST 2000
|
||||
* Added XPM file format support
|
||||
Supports color, greyscale, and mono XPMs with and without transparency
|
||||
Mattias Engdegård - Thu, 2 Nov 2000 23:23:17 +0100 (MET)
|
||||
* Fixed array overrun when loading an unsupported format
|
||||
* Minor compilation fixes for various platforms
|
||||
|
||||
1.0.10:
|
||||
Mattias Engdegård - Wed Aug 9 20:32:22 MET DST 2000
|
||||
* Removed the alpha flipping, made IMG_InvertAlpha() a noop
|
||||
* Fixed nonexisting PCX alpha support
|
||||
* Some TIFF bugfixes
|
||||
* PNG greyscale images are loaded as 8bpp with a greyscale palette
|
||||
Ray Kelm - Fri, 04 Aug 2000 20:58:00 -0400
|
||||
* Added support for cross-compiling Windows DLL from Linux
|
||||
|
||||
1.0.9:
|
||||
Mattias Engdegård - Sat Jul 1 17:57:37 PDT 2000
|
||||
* PNG loader properly sets the colorkey on 8-bit transparent images
|
||||
Mattias Engdegård - Sat Jul 1 13:24:47 PDT 2000
|
||||
* Fixed a bug in PCX detection
|
||||
* Added support for TGA files
|
||||
* showimage shows a checker background for transparent images
|
||||
|
||||
1.0.8:
|
||||
Mark Baker - Tue May 30 12:20:00 PDT 2000
|
||||
* Added TIFF format loading support
|
||||
|
||||
1.0.7:
|
||||
Mattias Engdegård - Sat May 27 14:18:33 PDT 2000
|
||||
* Added fixes for loading images on big-endian systems
|
||||
|
||||
1.0.6:
|
||||
Sam Lantinga - Sat Apr 29 10:18:32 PDT 2000
|
||||
* showimage puts the name of the image in the title bar caption
|
||||
Sam Lantinga - Sat Apr 29 10:05:58 PDT 2000
|
||||
* Removed pitch check, since PNG already loads to a list of row pointers
|
||||
|
||||
1.0.5:
|
||||
Sam Lantinga - Sun Apr 23 14:41:32 PDT 2000
|
||||
* Added support for GIF transparency
|
||||
Sam Lantinga - Wed Apr 12 14:39:20 PDT 2000
|
||||
* Fixed memory heap crash on NT using PNG images
|
||||
Matt Campbell - Thu, 13 Apr 2000 13:29:17 -0700
|
||||
* Fixed PNG detection on some Linux systems
|
||||
|
||||
1.0.4:
|
||||
Sam Lantinga - Tue Feb 1 13:33:53 PST 2000
|
||||
* Cleaned up for Visual C++
|
||||
* Added Visual C++ project file
|
||||
|
||||
1.0.3:
|
||||
Sam Lantinga - Wed Jan 19 22:10:52 PST 2000
|
||||
* Added CHANGES
|
||||
* Added rpm spec file contributed by Hakan Tandogan
|
||||
* Changed the name of the example program from "show" to "showimage"
|
||||
20
apps/plugins/sdl/SDL_image/COPYING
Normal file
20
apps/plugins/sdl/SDL_image/COPYING
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
214
apps/plugins/sdl/SDL_image/IMG.c
Normal file
214
apps/plugins/sdl/SDL_image/IMG.c
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* A simple library to load images of various formats as SDL surfaces */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/* Table of image detection and loading functions */
|
||||
static struct {
|
||||
char *type;
|
||||
int (SDLCALL *is)(SDL_RWops *src);
|
||||
SDL_Surface *(SDLCALL *load)(SDL_RWops *src);
|
||||
} supported[] = {
|
||||
/* keep magicless formats first */
|
||||
{ "TGA", NULL, IMG_LoadTGA_RW },
|
||||
{ "CUR", IMG_isCUR, IMG_LoadCUR_RW },
|
||||
{ "ICO", IMG_isICO, IMG_LoadICO_RW },
|
||||
{ "BMP", IMG_isBMP, IMG_LoadBMP_RW },
|
||||
{ "GIF", IMG_isGIF, IMG_LoadGIF_RW },
|
||||
{ "JPG", IMG_isJPG, IMG_LoadJPG_RW },
|
||||
{ "LBM", IMG_isLBM, IMG_LoadLBM_RW },
|
||||
{ "PCX", IMG_isPCX, IMG_LoadPCX_RW },
|
||||
{ "PNG", IMG_isPNG, IMG_LoadPNG_RW },
|
||||
{ "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
|
||||
{ "TIF", IMG_isTIF, IMG_LoadTIF_RW },
|
||||
{ "XCF", IMG_isXCF, IMG_LoadXCF_RW },
|
||||
{ "XPM", IMG_isXPM, IMG_LoadXPM_RW },
|
||||
{ "XV", IMG_isXV, IMG_LoadXV_RW },
|
||||
{ "WEBP", IMG_isWEBP, IMG_LoadWEBP_RW },
|
||||
};
|
||||
|
||||
const SDL_version *IMG_Linked_Version(void)
|
||||
{
|
||||
static SDL_version linked_version;
|
||||
SDL_IMAGE_VERSION(&linked_version);
|
||||
return(&linked_version);
|
||||
}
|
||||
|
||||
extern int IMG_InitJPG();
|
||||
extern void IMG_QuitJPG();
|
||||
extern int IMG_InitPNG();
|
||||
extern void IMG_QuitPNG();
|
||||
extern int IMG_InitTIF();
|
||||
extern void IMG_QuitTIF();
|
||||
|
||||
extern int IMG_InitWEBP();
|
||||
extern void IMG_QuitWEBP();
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
int IMG_Init(int flags)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (flags & IMG_INIT_JPG) {
|
||||
if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
|
||||
result |= IMG_INIT_JPG;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_PNG) {
|
||||
if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {
|
||||
result |= IMG_INIT_PNG;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_TIF) {
|
||||
if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) {
|
||||
result |= IMG_INIT_TIF;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_WEBP) {
|
||||
if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) {
|
||||
result |= IMG_INIT_WEBP;
|
||||
}
|
||||
}
|
||||
initialized |= result;
|
||||
|
||||
return (initialized);
|
||||
}
|
||||
|
||||
void IMG_Quit()
|
||||
{
|
||||
if (initialized & IMG_INIT_JPG) {
|
||||
IMG_QuitJPG();
|
||||
}
|
||||
if (initialized & IMG_INIT_PNG) {
|
||||
IMG_QuitPNG();
|
||||
}
|
||||
if (initialized & IMG_INIT_TIF) {
|
||||
IMG_QuitTIF();
|
||||
}
|
||||
if (initialized & IMG_INIT_WEBP) {
|
||||
IMG_QuitWEBP();
|
||||
}
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
/* Load an image from a file */
|
||||
SDL_Surface *IMG_Load(const char *file)
|
||||
{
|
||||
SDL_RWops *src = SDL_RWFromFile(file, "rb");
|
||||
char *ext = strrchr(file, '.');
|
||||
if(ext) {
|
||||
ext++;
|
||||
}
|
||||
if(!src) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
return IMG_LoadTyped_RW(src, 1, ext);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Load an image from an SDL datasource (for compatibility) */
|
||||
SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc)
|
||||
{
|
||||
return IMG_LoadTyped_RW(src, freesrc, NULL);
|
||||
}
|
||||
|
||||
/* Portable case-insensitive string compare function */
|
||||
static int IMG_string_equals(const char *str1, const char *str2)
|
||||
{
|
||||
while ( *str1 && *str2 ) {
|
||||
if ( toupper((unsigned char)*str1) !=
|
||||
toupper((unsigned char)*str2) )
|
||||
break;
|
||||
++str1;
|
||||
++str2;
|
||||
}
|
||||
return (!*str1 && !*str2);
|
||||
}
|
||||
|
||||
/* Load an image from an SDL datasource, optionally specifying the type */
|
||||
SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type)
|
||||
{
|
||||
int i;
|
||||
SDL_Surface *image;
|
||||
|
||||
/* Make sure there is something to do.. */
|
||||
if ( src == NULL ) {
|
||||
IMG_SetError("Passed a NULL data source");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* See whether or not this data source can handle seeking */
|
||||
if ( SDL_RWseek(src, 0, RW_SEEK_CUR) < 0 ) {
|
||||
IMG_SetError("Can't seek in this data source");
|
||||
if(freesrc)
|
||||
SDL_RWclose(src);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Detect the type of image being loaded */
|
||||
image = NULL;
|
||||
for ( i=0; i < ARRAYSIZE(supported); ++i ) {
|
||||
if(supported[i].is) {
|
||||
if(!supported[i].is(src))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* magicless format */
|
||||
if(!type
|
||||
|| !IMG_string_equals(type, supported[i].type))
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_IMGLIB
|
||||
fprintf(stderr, "IMGLIB: Loading image as %s\n",
|
||||
supported[i].type);
|
||||
#endif
|
||||
image = supported[i].load(src);
|
||||
if(freesrc)
|
||||
SDL_RWclose(src);
|
||||
return image;
|
||||
}
|
||||
|
||||
if ( freesrc ) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
IMG_SetError("Unsupported image format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Invert the alpha of a surface for use with OpenGL
|
||||
This function is a no-op and only kept for backwards compatibility.
|
||||
*/
|
||||
int IMG_InvertAlpha(int on)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
848
apps/plugins/sdl/SDL_image/IMG_bmp.c
Normal file
848
apps/plugins/sdl/SDL_image/IMG_bmp.c
Normal file
|
|
@ -0,0 +1,848 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a BMP image file loading framework */
|
||||
/* ICO/CUR file support is here as well since it uses similar internal
|
||||
* representation */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_BMP
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isBMP(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_BMP;
|
||||
char magic[2];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_BMP = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if ( strncmp(magic, "BM", 2) == 0 ) {
|
||||
is_BMP = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_BMP);
|
||||
}
|
||||
|
||||
static int IMG_isICOCUR(SDL_RWops *src, int type)
|
||||
{
|
||||
int start;
|
||||
int is_ICOCUR;
|
||||
|
||||
/* The Win32 ICO file header (14 bytes) */
|
||||
Uint16 bfReserved;
|
||||
Uint16 bfType;
|
||||
Uint16 bfCount;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_ICOCUR = 0;
|
||||
bfReserved = SDL_ReadLE16(src);
|
||||
bfType = SDL_ReadLE16(src);
|
||||
bfCount = SDL_ReadLE16(src);
|
||||
if ((bfReserved == 0) && (bfType == type) && (bfCount != 0))
|
||||
is_ICOCUR = 1;
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
|
||||
return (is_ICOCUR);
|
||||
}
|
||||
|
||||
int IMG_isICO(SDL_RWops *src)
|
||||
{
|
||||
return IMG_isICOCUR(src, 1);
|
||||
}
|
||||
|
||||
int IMG_isCUR(SDL_RWops *src)
|
||||
{
|
||||
return IMG_isICOCUR(src, 2);
|
||||
}
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
/* Compression encodings for BMP files */
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0
|
||||
#define BI_RLE8 1
|
||||
#define BI_RLE4 2
|
||||
#define BI_BITFIELDS 3
|
||||
#endif
|
||||
|
||||
static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
|
||||
{
|
||||
/*
|
||||
| Sets the surface pixels from src. A bmp image is upside down.
|
||||
*/
|
||||
int pitch = surface->pitch;
|
||||
int height = surface->h;
|
||||
Uint8 *start = (Uint8 *)surface->pixels;
|
||||
Uint8 *end = start + (height*pitch);
|
||||
Uint8 *bits = end-pitch, *spot;
|
||||
int ofs = 0;
|
||||
Uint8 ch;
|
||||
Uint8 needsPad;
|
||||
|
||||
#define COPY_PIXEL(x) spot = &bits[ofs++]; if(spot >= start && spot < end) *spot = (x)
|
||||
|
||||
for (;;) {
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
/*
|
||||
| encoded mode starts with a run length, and then a byte
|
||||
| with two colour indexes to alternate between for the run
|
||||
*/
|
||||
if ( ch ) {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
if ( isRle8 ) { /* 256-color bitmap, compressed */
|
||||
do {
|
||||
COPY_PIXEL(pixel);
|
||||
} while (--ch);
|
||||
} else { /* 16-color bitmap, compressed */
|
||||
Uint8 pixel0 = pixel >> 4;
|
||||
Uint8 pixel1 = pixel & 0x0F;
|
||||
for (;;) {
|
||||
COPY_PIXEL(pixel0); /* even count, high nibble */
|
||||
if (!--ch) break;
|
||||
COPY_PIXEL(pixel1); /* odd count, low nibble */
|
||||
if (!--ch) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
| A leading zero is an escape; it may signal the end of the bitmap,
|
||||
| a cursor move, or some absolute data.
|
||||
| zero tag may be absolute mode or an escape
|
||||
*/
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
switch (ch) {
|
||||
case 0: /* end of line */
|
||||
ofs = 0;
|
||||
bits -= pitch; /* go to previous */
|
||||
break;
|
||||
case 1: /* end of bitmap */
|
||||
return 0; /* success! */
|
||||
case 2: /* delta */
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
ofs += ch;
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
bits -= (ch * pitch);
|
||||
break;
|
||||
default: /* no compression */
|
||||
if (isRle8) {
|
||||
needsPad = ( ch & 1 );
|
||||
do {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
COPY_PIXEL(pixel);
|
||||
} while (--ch);
|
||||
} else {
|
||||
needsPad = ( ((ch+1)>>1) & 1 ); /* (ch+1)>>1: bytes size */
|
||||
for (;;) {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
COPY_PIXEL(pixel >> 4);
|
||||
if (!--ch) break;
|
||||
COPY_PIXEL(pixel & 0x0F);
|
||||
if (!--ch) break;
|
||||
}
|
||||
}
|
||||
/* pad at even boundary */
|
||||
if ( needsPad && !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Surface *LoadBMP_RW (SDL_RWops *src, int freesrc)
|
||||
{
|
||||
SDL_bool was_error;
|
||||
long fp_offset;
|
||||
int bmpPitch;
|
||||
int i, pad;
|
||||
SDL_Surface *surface;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Palette *palette;
|
||||
Uint8 *bits;
|
||||
Uint8 *top, *end;
|
||||
SDL_bool topDown;
|
||||
int ExpandBMP;
|
||||
|
||||
/* The Win32 BMP file header (14 bytes) */
|
||||
char magic[2];
|
||||
Uint32 bfSize;
|
||||
Uint16 bfReserved1;
|
||||
Uint16 bfReserved2;
|
||||
Uint32 bfOffBits;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth;
|
||||
Sint32 biHeight;
|
||||
Uint16 biPlanes;
|
||||
Uint16 biBitCount;
|
||||
Uint32 biCompression;
|
||||
Uint32 biSizeImage;
|
||||
Sint32 biXPelsPerMeter;
|
||||
Sint32 biYPelsPerMeter;
|
||||
Uint32 biClrUsed;
|
||||
Uint32 biClrImportant;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
surface = NULL;
|
||||
was_error = SDL_FALSE;
|
||||
if ( src == NULL ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read in the BMP file header */
|
||||
fp_offset = SDL_RWtell(src);
|
||||
SDL_ClearError();
|
||||
if ( SDL_RWread(src, magic, 1, 2) != 2 ) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if ( strncmp(magic, "BM", 2) != 0 ) {
|
||||
IMG_SetError("File is not a Windows BMP file");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
bfSize = SDL_ReadLE32(src);
|
||||
bfReserved1 = SDL_ReadLE16(src);
|
||||
bfReserved2 = SDL_ReadLE16(src);
|
||||
bfOffBits = SDL_ReadLE32(src);
|
||||
|
||||
/* Read the Win32 BITMAPINFOHEADER */
|
||||
biSize = SDL_ReadLE32(src);
|
||||
if ( biSize == 12 ) {
|
||||
biWidth = (Uint32)SDL_ReadLE16(src);
|
||||
biHeight = (Uint32)SDL_ReadLE16(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = BI_RGB;
|
||||
biSizeImage = 0;
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
} else {
|
||||
biWidth = SDL_ReadLE32(src);
|
||||
biHeight = SDL_ReadLE32(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = SDL_ReadLE32(src);
|
||||
biSizeImage = SDL_ReadLE32(src);
|
||||
biXPelsPerMeter = SDL_ReadLE32(src);
|
||||
biYPelsPerMeter = SDL_ReadLE32(src);
|
||||
biClrUsed = SDL_ReadLE32(src);
|
||||
biClrImportant = SDL_ReadLE32(src);
|
||||
}
|
||||
if (biHeight < 0) {
|
||||
topDown = SDL_TRUE;
|
||||
biHeight = -biHeight;
|
||||
} else {
|
||||
topDown = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Check for read error */
|
||||
if ( strcmp(SDL_GetError(), "") != 0 ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
|
||||
switch (biBitCount) {
|
||||
case 1:
|
||||
case 4:
|
||||
ExpandBMP = biBitCount;
|
||||
biBitCount = 8;
|
||||
break;
|
||||
default:
|
||||
ExpandBMP = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* RLE4 and RLE8 BMP compression is supported */
|
||||
Rmask = Gmask = Bmask = Amask = 0;
|
||||
switch (biCompression) {
|
||||
case BI_RGB:
|
||||
/* If there are no masks, use the defaults */
|
||||
if ( bfOffBits == (14+biSize) ) {
|
||||
/* Default values for the BMP format */
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
Rmask = 0x7C00;
|
||||
Gmask = 0x03E0;
|
||||
Bmask = 0x001F;
|
||||
break;
|
||||
case 24:
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
#else
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
#endif
|
||||
break;
|
||||
case 32:
|
||||
Amask = 0xFF000000;
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall through -- read the RGB masks */
|
||||
|
||||
default:
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
Rmask = SDL_ReadLE32(src);
|
||||
Gmask = SDL_ReadLE32(src);
|
||||
Bmask = SDL_ReadLE32(src);
|
||||
break;
|
||||
case 32:
|
||||
Rmask = SDL_ReadLE32(src);
|
||||
Gmask = SDL_ReadLE32(src);
|
||||
Bmask = SDL_ReadLE32(src);
|
||||
Amask = SDL_ReadLE32(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create a compatible surface, note that the colors are RGB ordered */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, Amask);
|
||||
if ( surface == NULL ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the palette, if any */
|
||||
palette = (surface->format)->palette;
|
||||
if ( palette ) {
|
||||
if ( SDL_RWseek(src, fp_offset+14+biSize, RW_SEEK_SET) < 0 ) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
|
||||
| for colorsUsed
|
||||
*/
|
||||
/* if ( biClrUsed == 0 ) { */
|
||||
biClrUsed = 1 << biBitCount;
|
||||
/* } */
|
||||
if ( biSize == 12 ) {
|
||||
for ( i = 0; i < (int)biClrUsed; ++i ) {
|
||||
SDL_RWread(src, &palette->colors[i].b, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1, 1);
|
||||
palette->colors[i].unused = 0;
|
||||
}
|
||||
} else {
|
||||
for ( i = 0; i < (int)biClrUsed; ++i ) {
|
||||
SDL_RWread(src, &palette->colors[i].b, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].unused, 1, 1);
|
||||
}
|
||||
}
|
||||
palette->ncolors = biClrUsed;
|
||||
}
|
||||
|
||||
/* Read the surface pixels. Note that the bmp image is upside down */
|
||||
if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
|
||||
was_error = readRlePixels(surface, src, biCompression == BI_RLE8);
|
||||
if (was_error) IMG_SetError("Error reading from BMP");
|
||||
goto done;
|
||||
}
|
||||
top = (Uint8 *)surface->pixels;
|
||||
end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
|
||||
break;
|
||||
case 4:
|
||||
bmpPitch = (biWidth + 1) >> 1;
|
||||
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
|
||||
break;
|
||||
default:
|
||||
pad = ((surface->pitch%4) ?
|
||||
(4-(surface->pitch%4)) : 0);
|
||||
break;
|
||||
}
|
||||
if ( topDown ) {
|
||||
bits = top;
|
||||
} else {
|
||||
bits = end - surface->pitch;
|
||||
}
|
||||
while ( bits >= top && bits < end ) {
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
case 4: {
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8-ExpandBMP);
|
||||
for ( i=0; i<surface->w; ++i ) {
|
||||
if ( i%(8/ExpandBMP) == 0 ) {
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) {
|
||||
IMG_SetError(
|
||||
"Error reading from BMP");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*(bits+i) = (pixel>>shift);
|
||||
pixel <<= ExpandBMP;
|
||||
} }
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( SDL_RWread(src, bits, 1, surface->pitch)
|
||||
!= surface->pitch ) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
/* Byte-swap the pixels if needed. Note that the 24bpp
|
||||
case has already been taken care of above. */
|
||||
switch(biBitCount) {
|
||||
case 15:
|
||||
case 16: {
|
||||
Uint16 *pix = (Uint16 *)bits;
|
||||
for(i = 0; i < surface->w; i++)
|
||||
pix[i] = SDL_Swap16(pix[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
Uint32 *pix = (Uint32 *)bits;
|
||||
for(i = 0; i < surface->w; i++)
|
||||
pix[i] = SDL_Swap32(pix[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if ( pad ) {
|
||||
Uint8 padbyte;
|
||||
for ( i=0; i<pad; ++i ) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
if ( topDown ) {
|
||||
bits += surface->pitch;
|
||||
} else {
|
||||
bits -= surface->pitch;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if ( was_error ) {
|
||||
if ( src ) {
|
||||
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
|
||||
}
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
surface = NULL;
|
||||
}
|
||||
if ( freesrc && src ) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
static Uint8
|
||||
SDL_Read8(SDL_RWops * src)
|
||||
{
|
||||
Uint8 value;
|
||||
|
||||
SDL_RWread(src, &value, 1, 1);
|
||||
return (value);
|
||||
}
|
||||
|
||||
static SDL_Surface *
|
||||
LoadICOCUR_RW(SDL_RWops * src, int type, int freesrc)
|
||||
{
|
||||
SDL_bool was_error;
|
||||
long fp_offset;
|
||||
int bmpPitch;
|
||||
int i, pad;
|
||||
SDL_Surface *surface;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint8 *bits;
|
||||
int ExpandBMP;
|
||||
int maxCol = 0;
|
||||
int icoOfs = 0;
|
||||
Uint32 palette[256];
|
||||
|
||||
/* The Win32 ICO file header (14 bytes) */
|
||||
Uint16 bfReserved;
|
||||
Uint16 bfType;
|
||||
Uint16 bfCount;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth;
|
||||
Sint32 biHeight;
|
||||
Uint16 biPlanes;
|
||||
Uint16 biBitCount;
|
||||
Uint32 biCompression;
|
||||
Uint32 biSizeImage;
|
||||
Sint32 biXPelsPerMeter;
|
||||
Sint32 biYPelsPerMeter;
|
||||
Uint32 biClrUsed;
|
||||
Uint32 biClrImportant;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
surface = NULL;
|
||||
was_error = SDL_FALSE;
|
||||
if (src == NULL) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read in the ICO file header */
|
||||
fp_offset = SDL_RWtell(src);
|
||||
SDL_ClearError();
|
||||
|
||||
bfReserved = SDL_ReadLE16(src);
|
||||
bfType = SDL_ReadLE16(src);
|
||||
bfCount = SDL_ReadLE16(src);
|
||||
if ((bfReserved != 0) || (bfType != type) || (bfCount == 0)) {
|
||||
IMG_SetError("File is not a Windows %s file", type == 1 ? "ICO" : "CUR");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the Win32 Icon Directory */
|
||||
for (i = 0; i < bfCount; i++) {
|
||||
/* Icon Directory Entries */
|
||||
int bWidth = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
int bHeight = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
int bColorCount = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
Uint8 bReserved = SDL_Read8(src);
|
||||
Uint16 wPlanes = SDL_ReadLE16(src);
|
||||
Uint16 wBitCount = SDL_ReadLE16(src);
|
||||
Uint32 dwBytesInRes = SDL_ReadLE32(src);
|
||||
Uint32 dwImageOffset = SDL_ReadLE32(src);
|
||||
|
||||
if (!bWidth)
|
||||
bWidth = 256;
|
||||
if (!bHeight)
|
||||
bHeight = 256;
|
||||
if (!bColorCount)
|
||||
bColorCount = 256;
|
||||
|
||||
//printf("%dx%d@%d - %08x\n", bWidth, bHeight, bColorCount, dwImageOffset);
|
||||
if (bColorCount > maxCol) {
|
||||
maxCol = bColorCount;
|
||||
icoOfs = dwImageOffset;
|
||||
//printf("marked\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to the DIB Data */
|
||||
if (SDL_RWseek(src, icoOfs, RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the Win32 BITMAPINFOHEADER */
|
||||
biSize = SDL_ReadLE32(src);
|
||||
if (biSize == 40) {
|
||||
biWidth = SDL_ReadLE32(src);
|
||||
biHeight = SDL_ReadLE32(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = SDL_ReadLE32(src);
|
||||
biSizeImage = SDL_ReadLE32(src);
|
||||
biXPelsPerMeter = SDL_ReadLE32(src);
|
||||
biYPelsPerMeter = SDL_ReadLE32(src);
|
||||
biClrUsed = SDL_ReadLE32(src);
|
||||
biClrImportant = SDL_ReadLE32(src);
|
||||
} else {
|
||||
IMG_SetError("Unsupported ICO bitmap format");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check for read error */
|
||||
if (SDL_strcmp(SDL_GetError(), "") != 0) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* We don't support any BMP compression right now */
|
||||
switch (biCompression) {
|
||||
case BI_RGB:
|
||||
/* Default values for the BMP format */
|
||||
switch (biBitCount) {
|
||||
case 1:
|
||||
case 4:
|
||||
ExpandBMP = biBitCount;
|
||||
biBitCount = 8;
|
||||
break;
|
||||
case 8:
|
||||
ExpandBMP = 8;
|
||||
break;
|
||||
case 32:
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
ExpandBMP = 0;
|
||||
break;
|
||||
default:
|
||||
IMG_SetError("ICO file with unsupported bit count");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
IMG_SetError("Compressed ICO files not supported");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create a RGBA surface */
|
||||
biHeight = biHeight >> 1;
|
||||
//printf("%d x %d\n", biWidth, biHeight);
|
||||
surface =
|
||||
SDL_CreateRGBSurface(0, biWidth, biHeight, 32, 0x00FF0000,
|
||||
0x0000FF00, 0x000000FF, 0xFF000000);
|
||||
if (surface == NULL) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the palette, if any */
|
||||
//printf("bc %d bused %d\n", biBitCount, biClrUsed);
|
||||
if (biBitCount <= 8) {
|
||||
if (biClrUsed == 0) {
|
||||
biClrUsed = 1 << biBitCount;
|
||||
}
|
||||
for (i = 0; i < (int) biClrUsed; ++i) {
|
||||
SDL_RWread(src, &palette[i], 4, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the surface pixels. Note that the bmp image is upside down */
|
||||
bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 4:
|
||||
bmpPitch = (biWidth + 1) >> 1;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 8:
|
||||
bmpPitch = biWidth;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
default:
|
||||
bmpPitch = biWidth * 4;
|
||||
pad = 0;
|
||||
break;
|
||||
}
|
||||
while (bits > (Uint8 *) surface->pixels) {
|
||||
bits -= surface->pitch;
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
case 4:
|
||||
case 8:
|
||||
{
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8 - ExpandBMP);
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (i % (8 / ExpandBMP) == 0) {
|
||||
if (!SDL_RWread(src, &pixel, 1, 1)) {
|
||||
IMG_SetError("Error reading from ICO");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*((Uint32 *) bits + i) = (palette[pixel >> shift]);
|
||||
pixel <<= ExpandBMP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (SDL_RWread(src, bits, 1, surface->pitch)
|
||||
!= surface->pitch) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if (pad) {
|
||||
Uint8 padbyte;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Read the mask pixels. Note that the bmp image is upside down */
|
||||
bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
|
||||
ExpandBMP = 1;
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
while (bits > (Uint8 *) surface->pixels) {
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8 - ExpandBMP);
|
||||
|
||||
bits -= surface->pitch;
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (i % (8 / ExpandBMP) == 0) {
|
||||
if (!SDL_RWread(src, &pixel, 1, 1)) {
|
||||
IMG_SetError("Error reading from ICO");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*((Uint32 *) bits + i) |= ((pixel >> shift) ? 0 : 0xFF000000);
|
||||
pixel <<= ExpandBMP;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if (pad) {
|
||||
Uint8 padbyte;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (was_error) {
|
||||
if (src) {
|
||||
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
|
||||
}
|
||||
if (surface) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
surface = NULL;
|
||||
}
|
||||
if (freesrc && src) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
return (surface);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadBMP_RW(src, 0));
|
||||
}
|
||||
|
||||
/* Load a ICO type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadICOCUR_RW(src, 1, 0));
|
||||
}
|
||||
|
||||
/* Load a CUR type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadICOCUR_RW(src, 2, 0));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isBMP(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int IMG_isICO(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int IMG_isCUR(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_BMP */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
625
apps/plugins/sdl/SDL_image/IMG_gif.c
Normal file
625
apps/plugins/sdl/SDL_image/IMG_gif.c
Normal file
|
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a GIF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_GIF
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isGIF(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_GIF;
|
||||
char magic[6];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_GIF = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if ( (strncmp(magic, "GIF", 3) == 0) &&
|
||||
((memcmp(magic + 3, "87a", 3) == 0) ||
|
||||
(memcmp(magic + 3, "89a", 3) == 0)) ) {
|
||||
is_GIF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_GIF);
|
||||
}
|
||||
|
||||
/* Code from here to end of file has been adapted from XPaint: */
|
||||
/* +-------------------------------------------------------------------+ */
|
||||
/* | Copyright 1990, 1991, 1993 David Koblas. | */
|
||||
/* | Copyright 1996 Torsten Martinsen. | */
|
||||
/* | Permission to use, copy, modify, and distribute this software | */
|
||||
/* | and its documentation for any purpose and without fee is hereby | */
|
||||
/* | granted, provided that the above copyright notice appear in all | */
|
||||
/* | copies and that both that copyright notice and this permission | */
|
||||
/* | notice appear in supporting documentation. This software is | */
|
||||
/* | provided "as is" without express or implied warranty. | */
|
||||
/* +-------------------------------------------------------------------+ */
|
||||
|
||||
/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
|
||||
#define USED_BY_SDL
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USED_BY_SDL
|
||||
/* Changes to work with SDL:
|
||||
|
||||
Include SDL header file
|
||||
Use SDL_Surface rather than xpaint Image structure
|
||||
Define SDL versions of RWSetMsg(), ImageNewCmap() and ImageSetCmap()
|
||||
*/
|
||||
#include "SDL.h"
|
||||
|
||||
#define Image SDL_Surface
|
||||
#define RWSetMsg IMG_SetError
|
||||
#define ImageNewCmap(w, h, s) SDL_AllocSurface(SDL_SWSURFACE,w,h,8,0,0,0,0)
|
||||
#define ImageSetCmap(s, i, R, G, B) do { \
|
||||
s->format->palette->colors[i].r = R; \
|
||||
s->format->palette->colors[i].g = G; \
|
||||
s->format->palette->colors[i].b = B; \
|
||||
} while (0)
|
||||
/* * * * * */
|
||||
|
||||
#else
|
||||
|
||||
/* Original XPaint sources */
|
||||
|
||||
#include "image.h"
|
||||
#include "rwTable.h"
|
||||
|
||||
#define SDL_RWops FILE
|
||||
#define SDL_RWclose fclose
|
||||
|
||||
#endif /* USED_BY_SDL */
|
||||
|
||||
|
||||
#define MAXCOLORMAPSIZE 256
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define CM_RED 0
|
||||
#define CM_GREEN 1
|
||||
#define CM_BLUE 2
|
||||
|
||||
#define MAX_LWZ_BITS 12
|
||||
|
||||
#define INTERLACE 0x40
|
||||
#define LOCALCOLORMAP 0x80
|
||||
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
|
||||
|
||||
#define ReadOK(file,buffer,len) SDL_RWread(file, buffer, len, 1)
|
||||
|
||||
#define LM_to_uint(a,b) (((b)<<8)|(a))
|
||||
|
||||
static struct {
|
||||
unsigned int Width;
|
||||
unsigned int Height;
|
||||
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
|
||||
unsigned int BitPixel;
|
||||
unsigned int ColorResolution;
|
||||
unsigned int Background;
|
||||
unsigned int AspectRatio;
|
||||
int GrayScale;
|
||||
} GifScreen;
|
||||
|
||||
static struct {
|
||||
int transparent;
|
||||
int delayTime;
|
||||
int inputFlag;
|
||||
int disposal;
|
||||
} Gif89;
|
||||
|
||||
static int ReadColorMap(SDL_RWops * src, int number,
|
||||
unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag);
|
||||
static int DoExtension(SDL_RWops * src, int label);
|
||||
static int GetDataBlock(SDL_RWops * src, unsigned char *buf);
|
||||
static int GetCode(SDL_RWops * src, int code_size, int flag);
|
||||
static int LWZReadByte(SDL_RWops * src, int flag, int input_code_size);
|
||||
static Image *ReadImage(SDL_RWops * src, int len, int height, int,
|
||||
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
||||
int gray, int interlace, int ignore);
|
||||
|
||||
Image *
|
||||
IMG_LoadGIF_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
unsigned char buf[16];
|
||||
unsigned char c;
|
||||
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
|
||||
int grayScale;
|
||||
int useGlobalColormap;
|
||||
int bitPixel;
|
||||
int imageCount = 0;
|
||||
char version[4];
|
||||
int imageNumber = 1;
|
||||
Image *image = NULL;
|
||||
|
||||
if ( src == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if (!ReadOK(src, buf, 6)) {
|
||||
RWSetMsg("error reading magic number");
|
||||
goto done;
|
||||
}
|
||||
if (strncmp((char *) buf, "GIF", 3) != 0) {
|
||||
RWSetMsg("not a GIF file");
|
||||
goto done;
|
||||
}
|
||||
memcpy(version, (char *) buf + 3, 3);
|
||||
version[3] = '\0';
|
||||
|
||||
if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
|
||||
RWSetMsg("bad version number, not '87a' or '89a'");
|
||||
goto done;
|
||||
}
|
||||
Gif89.transparent = -1;
|
||||
Gif89.delayTime = -1;
|
||||
Gif89.inputFlag = -1;
|
||||
Gif89.disposal = 0;
|
||||
|
||||
if (!ReadOK(src, buf, 7)) {
|
||||
RWSetMsg("failed to read screen descriptor");
|
||||
goto done;
|
||||
}
|
||||
GifScreen.Width = LM_to_uint(buf[0], buf[1]);
|
||||
GifScreen.Height = LM_to_uint(buf[2], buf[3]);
|
||||
GifScreen.BitPixel = 2 << (buf[4] & 0x07);
|
||||
GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
|
||||
GifScreen.Background = buf[5];
|
||||
GifScreen.AspectRatio = buf[6];
|
||||
|
||||
if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
|
||||
if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
|
||||
&GifScreen.GrayScale)) {
|
||||
RWSetMsg("error reading global colormap");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on image data");
|
||||
goto done;
|
||||
}
|
||||
if (c == ';') { /* GIF terminator */
|
||||
if (imageCount < imageNumber) {
|
||||
RWSetMsg("only %d image%s found in file",
|
||||
imageCount, imageCount > 1 ? "s" : "");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (c == '!') { /* Extension */
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on extention function code");
|
||||
goto done;
|
||||
}
|
||||
DoExtension(src, c);
|
||||
continue;
|
||||
}
|
||||
if (c != ',') { /* Not a valid start character */
|
||||
continue;
|
||||
}
|
||||
++imageCount;
|
||||
|
||||
if (!ReadOK(src, buf, 9)) {
|
||||
RWSetMsg("couldn't read left/top/width/height");
|
||||
goto done;
|
||||
}
|
||||
useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
|
||||
|
||||
bitPixel = 1 << ((buf[8] & 0x07) + 1);
|
||||
|
||||
if (!useGlobalColormap) {
|
||||
if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
|
||||
RWSetMsg("error reading local colormap");
|
||||
goto done;
|
||||
}
|
||||
image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
|
||||
LM_to_uint(buf[6], buf[7]),
|
||||
bitPixel, localColorMap, grayScale,
|
||||
BitSet(buf[8], INTERLACE),
|
||||
imageCount != imageNumber);
|
||||
} else {
|
||||
image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
|
||||
LM_to_uint(buf[6], buf[7]),
|
||||
GifScreen.BitPixel, GifScreen.ColorMap,
|
||||
GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
|
||||
imageCount != imageNumber);
|
||||
}
|
||||
} while (image == NULL);
|
||||
|
||||
#ifdef USED_BY_SDL
|
||||
if ( Gif89.transparent >= 0 ) {
|
||||
SDL_SetColorKey(image, SDL_SRCCOLORKEY, Gif89.transparent);
|
||||
}
|
||||
#endif
|
||||
|
||||
done:
|
||||
if ( image == NULL ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
static int
|
||||
ReadColorMap(SDL_RWops *src, int number,
|
||||
unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray)
|
||||
{
|
||||
int i;
|
||||
unsigned char rgb[3];
|
||||
int flag;
|
||||
|
||||
flag = TRUE;
|
||||
|
||||
for (i = 0; i < number; ++i) {
|
||||
if (!ReadOK(src, rgb, sizeof(rgb))) {
|
||||
RWSetMsg("bad colormap");
|
||||
return 1;
|
||||
}
|
||||
buffer[CM_RED][i] = rgb[0];
|
||||
buffer[CM_GREEN][i] = rgb[1];
|
||||
buffer[CM_BLUE][i] = rgb[2];
|
||||
flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (flag)
|
||||
*gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
|
||||
else
|
||||
*gray = PPM_TYPE;
|
||||
#else
|
||||
*gray = 0;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
DoExtension(SDL_RWops *src, int label)
|
||||
{
|
||||
static unsigned char buf[256];
|
||||
char *str;
|
||||
|
||||
switch (label) {
|
||||
case 0x01: /* Plain Text Extension */
|
||||
str = "Plain Text Extension";
|
||||
break;
|
||||
case 0xff: /* Application Extension */
|
||||
str = "Application Extension";
|
||||
break;
|
||||
case 0xfe: /* Comment Extension */
|
||||
str = "Comment Extension";
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
return FALSE;
|
||||
case 0xf9: /* Graphic Control Extension */
|
||||
str = "Graphic Control Extension";
|
||||
(void) GetDataBlock(src, (unsigned char *) buf);
|
||||
Gif89.disposal = (buf[0] >> 2) & 0x7;
|
||||
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
|
||||
Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
|
||||
if ((buf[0] & 0x1) != 0)
|
||||
Gif89.transparent = buf[3];
|
||||
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
return FALSE;
|
||||
default:
|
||||
str = (char *)buf;
|
||||
sprintf(str, "UNKNOWN (0x%02x)", label);
|
||||
break;
|
||||
}
|
||||
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ZeroDataBlock = FALSE;
|
||||
|
||||
static int
|
||||
GetDataBlock(SDL_RWops *src, unsigned char *buf)
|
||||
{
|
||||
unsigned char count;
|
||||
|
||||
if (!ReadOK(src, &count, 1)) {
|
||||
/* pm_message("error in getting DataBlock size" ); */
|
||||
return -1;
|
||||
}
|
||||
ZeroDataBlock = count == 0;
|
||||
|
||||
if ((count != 0) && (!ReadOK(src, buf, count))) {
|
||||
/* pm_message("error in reading DataBlock" ); */
|
||||
return -1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
GetCode(SDL_RWops *src, int code_size, int flag)
|
||||
{
|
||||
static unsigned char buf[280];
|
||||
static int curbit, lastbit, done, last_byte;
|
||||
int i, j, ret;
|
||||
unsigned char count;
|
||||
|
||||
if (flag) {
|
||||
curbit = 0;
|
||||
lastbit = 0;
|
||||
done = FALSE;
|
||||
return 0;
|
||||
}
|
||||
if ((curbit + code_size) >= lastbit) {
|
||||
if (done) {
|
||||
if (curbit >= lastbit)
|
||||
RWSetMsg("ran off the end of my bits");
|
||||
return -1;
|
||||
}
|
||||
buf[0] = buf[last_byte - 2];
|
||||
buf[1] = buf[last_byte - 1];
|
||||
|
||||
if ((count = GetDataBlock(src, &buf[2])) == 0)
|
||||
done = TRUE;
|
||||
|
||||
last_byte = 2 + count;
|
||||
curbit = (curbit - lastbit) + 16;
|
||||
lastbit = (2 + count) * 8;
|
||||
}
|
||||
ret = 0;
|
||||
for (i = curbit, j = 0; j < code_size; ++i, ++j)
|
||||
ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
|
||||
|
||||
curbit += code_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
LWZReadByte(SDL_RWops *src, int flag, int input_code_size)
|
||||
{
|
||||
static int fresh = FALSE;
|
||||
int code, incode;
|
||||
static int code_size, set_code_size;
|
||||
static int max_code, max_code_size;
|
||||
static int firstcode, oldcode;
|
||||
static int clear_code, end_code;
|
||||
static int table[2][(1 << MAX_LWZ_BITS)];
|
||||
static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
|
||||
register int i;
|
||||
|
||||
/* Fixed buffer overflow found by Michael Skladnikiewicz */
|
||||
if (input_code_size > MAX_LWZ_BITS)
|
||||
return -1;
|
||||
|
||||
if (flag) {
|
||||
set_code_size = input_code_size;
|
||||
code_size = set_code_size + 1;
|
||||
clear_code = 1 << set_code_size;
|
||||
end_code = clear_code + 1;
|
||||
max_code_size = 2 * clear_code;
|
||||
max_code = clear_code + 2;
|
||||
|
||||
GetCode(src, 0, TRUE);
|
||||
|
||||
fresh = TRUE;
|
||||
|
||||
for (i = 0; i < clear_code; ++i) {
|
||||
table[0][i] = 0;
|
||||
table[1][i] = i;
|
||||
}
|
||||
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
||||
table[0][i] = table[1][0] = 0;
|
||||
|
||||
sp = stack;
|
||||
|
||||
return 0;
|
||||
} else if (fresh) {
|
||||
fresh = FALSE;
|
||||
do {
|
||||
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
||||
} while (firstcode == clear_code);
|
||||
return firstcode;
|
||||
}
|
||||
if (sp > stack)
|
||||
return *--sp;
|
||||
|
||||
while ((code = GetCode(src, code_size, FALSE)) >= 0) {
|
||||
if (code == clear_code) {
|
||||
for (i = 0; i < clear_code; ++i) {
|
||||
table[0][i] = 0;
|
||||
table[1][i] = i;
|
||||
}
|
||||
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
||||
table[0][i] = table[1][i] = 0;
|
||||
code_size = set_code_size + 1;
|
||||
max_code_size = 2 * clear_code;
|
||||
max_code = clear_code + 2;
|
||||
sp = stack;
|
||||
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
||||
return firstcode;
|
||||
} else if (code == end_code) {
|
||||
int count;
|
||||
unsigned char buf[260];
|
||||
|
||||
if (ZeroDataBlock)
|
||||
return -2;
|
||||
|
||||
while ((count = GetDataBlock(src, buf)) > 0)
|
||||
;
|
||||
|
||||
if (count != 0) {
|
||||
/*
|
||||
* pm_message("missing EOD in data stream (common occurence)");
|
||||
*/
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
incode = code;
|
||||
|
||||
if (code >= max_code) {
|
||||
*sp++ = firstcode;
|
||||
code = oldcode;
|
||||
}
|
||||
while (code >= clear_code) {
|
||||
*sp++ = table[1][code];
|
||||
if (code == table[0][code])
|
||||
RWSetMsg("circular table entry BIG ERROR");
|
||||
code = table[0][code];
|
||||
}
|
||||
|
||||
*sp++ = firstcode = table[1][code];
|
||||
|
||||
if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
|
||||
table[0][code] = oldcode;
|
||||
table[1][code] = firstcode;
|
||||
++max_code;
|
||||
if ((max_code >= max_code_size) &&
|
||||
(max_code_size < (1 << MAX_LWZ_BITS))) {
|
||||
max_code_size *= 2;
|
||||
++code_size;
|
||||
}
|
||||
}
|
||||
oldcode = incode;
|
||||
|
||||
if (sp > stack)
|
||||
return *--sp;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static Image *
|
||||
ReadImage(SDL_RWops * src, int len, int height, int cmapSize,
|
||||
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
||||
int gray, int interlace, int ignore)
|
||||
{
|
||||
Image *image;
|
||||
unsigned char c;
|
||||
int i, v;
|
||||
int xpos = 0, ypos = 0, pass = 0;
|
||||
|
||||
/*
|
||||
** Initialize the compression routines
|
||||
*/
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on image data");
|
||||
return NULL;
|
||||
}
|
||||
if (LWZReadByte(src, TRUE, c) < 0) {
|
||||
RWSetMsg("error reading image");
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
** If this is an "uninteresting picture" ignore it.
|
||||
*/
|
||||
if (ignore) {
|
||||
while (LWZReadByte(src, FALSE, c) >= 0)
|
||||
;
|
||||
return NULL;
|
||||
}
|
||||
image = ImageNewCmap(len, height, cmapSize);
|
||||
|
||||
for (i = 0; i < cmapSize; i++)
|
||||
ImageSetCmap(image, i, cmap[CM_RED][i],
|
||||
cmap[CM_GREEN][i], cmap[CM_BLUE][i]);
|
||||
|
||||
while ((v = LWZReadByte(src, FALSE, c)) >= 0) {
|
||||
#ifdef USED_BY_SDL
|
||||
((Uint8 *)image->pixels)[xpos + ypos * image->pitch] = v;
|
||||
#else
|
||||
image->data[xpos + ypos * len] = v;
|
||||
#endif
|
||||
++xpos;
|
||||
if (xpos == len) {
|
||||
xpos = 0;
|
||||
if (interlace) {
|
||||
switch (pass) {
|
||||
case 0:
|
||||
case 1:
|
||||
ypos += 8;
|
||||
break;
|
||||
case 2:
|
||||
ypos += 4;
|
||||
break;
|
||||
case 3:
|
||||
ypos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ypos >= height) {
|
||||
++pass;
|
||||
switch (pass) {
|
||||
case 1:
|
||||
ypos = 4;
|
||||
break;
|
||||
case 2:
|
||||
ypos = 2;
|
||||
break;
|
||||
case 3:
|
||||
ypos = 1;
|
||||
break;
|
||||
default:
|
||||
goto fini;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
++ypos;
|
||||
}
|
||||
}
|
||||
if (ypos >= height)
|
||||
break;
|
||||
}
|
||||
|
||||
fini:
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isGIF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a GIF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadGIF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_GIF */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
495
apps/plugins/sdl/SDL_image/IMG_jpg.c
Normal file
495
apps/plugins/sdl/SDL_image/IMG_jpg.c
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a JPEG image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_JPG
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
#ifdef JPEG_TRUE /* MinGW version of jpeg-8.x renamed TRUE to JPEG_TRUE etc. */
|
||||
typedef JPEG_boolean boolean;
|
||||
#define TRUE JPEG_TRUE
|
||||
#define FALSE JPEG_FALSE
|
||||
#endif
|
||||
|
||||
/* Define this for fast loading and not as good image quality */
|
||||
/*#define FAST_JPEG*/
|
||||
|
||||
/* Define this for quicker (but less perfect) JPEG identification */
|
||||
#define FAST_IS_JPEG
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
void (*jpeg_calc_output_dimensions) (j_decompress_ptr cinfo);
|
||||
void (*jpeg_CreateDecompress) (j_decompress_ptr cinfo, int version, size_t structsize);
|
||||
void (*jpeg_destroy_decompress) (j_decompress_ptr cinfo);
|
||||
boolean (*jpeg_finish_decompress) (j_decompress_ptr cinfo);
|
||||
int (*jpeg_read_header) (j_decompress_ptr cinfo, boolean require_image);
|
||||
JDIMENSION (*jpeg_read_scanlines) (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines);
|
||||
boolean (*jpeg_resync_to_restart) (j_decompress_ptr cinfo, int desired);
|
||||
boolean (*jpeg_start_decompress) (j_decompress_ptr cinfo);
|
||||
struct jpeg_error_mgr * (*jpeg_std_error) (struct jpeg_error_mgr * err);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_JPG_DYNAMIC
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_JPG_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_calc_output_dimensions =
|
||||
(void (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_calc_output_dimensions");
|
||||
if ( lib.jpeg_calc_output_dimensions == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_CreateDecompress =
|
||||
(void (*) (j_decompress_ptr, int, size_t))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_CreateDecompress");
|
||||
if ( lib.jpeg_CreateDecompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_destroy_decompress =
|
||||
(void (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_destroy_decompress");
|
||||
if ( lib.jpeg_destroy_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_finish_decompress =
|
||||
(boolean (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_finish_decompress");
|
||||
if ( lib.jpeg_finish_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_read_header =
|
||||
(int (*) (j_decompress_ptr, boolean))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_read_header");
|
||||
if ( lib.jpeg_read_header == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_read_scanlines =
|
||||
(JDIMENSION (*) (j_decompress_ptr, JSAMPARRAY, JDIMENSION))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_read_scanlines");
|
||||
if ( lib.jpeg_read_scanlines == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_resync_to_restart =
|
||||
(boolean (*) (j_decompress_ptr, int))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_resync_to_restart");
|
||||
if ( lib.jpeg_resync_to_restart == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_start_decompress =
|
||||
(boolean (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_start_decompress");
|
||||
if ( lib.jpeg_start_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_std_error =
|
||||
(struct jpeg_error_mgr * (*) (struct jpeg_error_mgr *))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_std_error");
|
||||
if ( lib.jpeg_std_error == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.jpeg_calc_output_dimensions = jpeg_calc_output_dimensions;
|
||||
lib.jpeg_CreateDecompress = jpeg_CreateDecompress;
|
||||
lib.jpeg_destroy_decompress = jpeg_destroy_decompress;
|
||||
lib.jpeg_finish_decompress = jpeg_finish_decompress;
|
||||
lib.jpeg_read_header = jpeg_read_header;
|
||||
lib.jpeg_read_scanlines = jpeg_read_scanlines;
|
||||
lib.jpeg_resync_to_restart = jpeg_resync_to_restart;
|
||||
lib.jpeg_start_decompress = jpeg_start_decompress;
|
||||
lib.jpeg_std_error = jpeg_std_error;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_JPG_DYNAMIC */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isJPG(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_JPG;
|
||||
int in_scan;
|
||||
Uint8 magic[4];
|
||||
|
||||
/* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
|
||||
/* Blame me, not Sam, if this doesn't work right. */
|
||||
/* And don't forget to report the problem to the the sdl list too! */
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_JPG = 0;
|
||||
in_scan = 0;
|
||||
if ( SDL_RWread(src, magic, 2, 1) ) {
|
||||
if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
|
||||
is_JPG = 1;
|
||||
while (is_JPG == 1) {
|
||||
if(SDL_RWread(src, magic, 1, 2) != 2) {
|
||||
is_JPG = 0;
|
||||
} else if( (magic[0] != 0xFF) && (in_scan == 0) ) {
|
||||
is_JPG = 0;
|
||||
} else if( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
|
||||
/* Extra padding in JPEG (legal) */
|
||||
/* or this is data and we are scanning */
|
||||
SDL_RWseek(src, -1, RW_SEEK_CUR);
|
||||
} else if(magic[1] == 0xD9) {
|
||||
/* Got to end of good JPEG */
|
||||
break;
|
||||
} else if( (in_scan == 1) && (magic[1] == 0x00) ) {
|
||||
/* This is an encoded 0xFF within the data */
|
||||
} else if( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
|
||||
/* These have nothing else */
|
||||
} else if(SDL_RWread(src, magic+2, 1, 2) != 2) {
|
||||
is_JPG = 0;
|
||||
} else {
|
||||
/* Yes, it's big-endian */
|
||||
Uint32 start;
|
||||
Uint32 size;
|
||||
Uint32 end;
|
||||
start = SDL_RWtell(src);
|
||||
size = (magic[2] << 8) + magic[3];
|
||||
end = SDL_RWseek(src, size-2, RW_SEEK_CUR);
|
||||
if ( end != start + size - 2 ) is_JPG = 0;
|
||||
if ( magic[1] == 0xDA ) {
|
||||
/* Now comes the actual JPEG meat */
|
||||
#ifdef FAST_IS_JPEG
|
||||
/* Ok, I'm convinced. It is a JPEG. */
|
||||
break;
|
||||
#else
|
||||
/* I'm not convinced. Prove it! */
|
||||
in_scan = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_JPG);
|
||||
}
|
||||
|
||||
#define INPUT_BUFFER_SIZE 4096
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub;
|
||||
|
||||
SDL_RWops *ctx;
|
||||
Uint8 buffer[INPUT_BUFFER_SIZE];
|
||||
} my_source_mgr;
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
static void init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* We don't actually need to do anything */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
*/
|
||||
static boolean fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_source_mgr * src = (my_source_mgr *) cinfo->src;
|
||||
int nbytes;
|
||||
|
||||
nbytes = SDL_RWread(src->ctx, src->buffer, 1, INPUT_BUFFER_SIZE);
|
||||
if (nbytes <= 0) {
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (Uint8) 0xFF;
|
||||
src->buffer[1] = (Uint8) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*
|
||||
* Writers of suspendable-input applications must note that skip_input_data
|
||||
* is not granted the right to give a suspension return. If the skip extends
|
||||
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||
* Arranging for additional bytes to be discarded before reloading the input
|
||||
* buffer is the application writer's problem.
|
||||
*/
|
||||
static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_source_mgr * src = (my_source_mgr *) cinfo->src;
|
||||
|
||||
/* Just a dumb implementation for now. Could use fseek() except
|
||||
* it doesn't work on pipes. Not clear that being smart is worth
|
||||
* any trouble anyway --- large skips are infrequent.
|
||||
*/
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) src->pub.fill_input_buffer(cinfo);
|
||||
/* note we assume that fill_input_buffer will never
|
||||
* return FALSE, so suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read.
|
||||
*/
|
||||
static void term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* We don't actually need to do anything */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for input from a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
static void jpeg_SDL_RW_src (j_decompress_ptr cinfo, SDL_RWops *ctx)
|
||||
{
|
||||
my_source_mgr *src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(my_source_mgr));
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
}
|
||||
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = lib.jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = term_source;
|
||||
src->ctx = ctx;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
}
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr errmgr;
|
||||
jmp_buf escape;
|
||||
};
|
||||
|
||||
static void my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
|
||||
longjmp(err->escape, 1);
|
||||
}
|
||||
|
||||
static void output_no_message(j_common_ptr cinfo)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* Load a JPEG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
JSAMPROW rowptr[1];
|
||||
SDL_Surface *volatile surface = NULL;
|
||||
struct my_error_mgr jerr;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_JPG) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a decompression structure and load the JPEG header */
|
||||
cinfo.err = lib.jpeg_std_error(&jerr.errmgr);
|
||||
jerr.errmgr.error_exit = my_error_exit;
|
||||
jerr.errmgr.output_message = output_no_message;
|
||||
if(setjmp(jerr.escape)) {
|
||||
/* If we get here, libjpeg found an error */
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
if ( surface != NULL ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
IMG_SetError("JPEG loading error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lib.jpeg_create_decompress(&cinfo);
|
||||
jpeg_SDL_RW_src(&cinfo, src);
|
||||
lib.jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
if(cinfo.num_components == 4) {
|
||||
/* Set 32-bit Raw output */
|
||||
cinfo.out_color_space = JCS_CMYK;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
lib.jpeg_calc_output_dimensions(&cinfo);
|
||||
|
||||
/* Allocate an output surface to hold the image */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE,
|
||||
cinfo.output_width, cinfo.output_height, 32,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
|
||||
#else
|
||||
0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF);
|
||||
#endif
|
||||
} else {
|
||||
/* Set 24-bit RGB output */
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
#ifdef FAST_JPEG
|
||||
cinfo.scale_num = 1;
|
||||
cinfo.scale_denom = 1;
|
||||
cinfo.dct_method = JDCT_FASTEST;
|
||||
cinfo.do_fancy_upsampling = FALSE;
|
||||
#endif
|
||||
lib.jpeg_calc_output_dimensions(&cinfo);
|
||||
|
||||
/* Allocate an output surface to hold the image */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE,
|
||||
cinfo.output_width, cinfo.output_height, 24,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x0000FF, 0x00FF00, 0xFF0000,
|
||||
#else
|
||||
0xFF0000, 0x00FF00, 0x0000FF,
|
||||
#endif
|
||||
0);
|
||||
}
|
||||
|
||||
if ( surface == NULL ) {
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
IMG_SetError("Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Decompress the image */
|
||||
lib.jpeg_start_decompress(&cinfo);
|
||||
while ( cinfo.output_scanline < cinfo.output_height ) {
|
||||
rowptr[0] = (JSAMPROW)(Uint8 *)surface->pixels +
|
||||
cinfo.output_scanline * surface->pitch;
|
||||
lib.jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
||||
}
|
||||
lib.jpeg_finish_decompress(&cinfo);
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
IMG_SetError("JPEG images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isJPG(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a JPEG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_JPG */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
503
apps/plugins/sdl/SDL_image/IMG_lbm.c
Normal file
503
apps/plugins/sdl/SDL_image/IMG_lbm.c
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a ILBM image file loading framework
|
||||
Load IFF pictures, PBM & ILBM packing methods, with or without stencil
|
||||
Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001.
|
||||
24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati)
|
||||
in December 2002.
|
||||
EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain
|
||||
(http://www.multimania.com/mavati) in December 2003.
|
||||
Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004.
|
||||
Buffer overflow fix in RLE decompression by David Raulo in January 2008.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_LBM
|
||||
|
||||
|
||||
#define MAXCOLORS 256
|
||||
|
||||
/* Structure for an IFF picture ( BMHD = Bitmap Header ) */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint16 w, h; /* width & height of the bitmap in pixels */
|
||||
Sint16 x, y; /* screen coordinates of the bitmap */
|
||||
Uint8 planes; /* number of planes of the bitmap */
|
||||
Uint8 mask; /* mask type ( 0 => no mask ) */
|
||||
Uint8 tcomp; /* compression type */
|
||||
Uint8 pad1; /* dummy value, for padding */
|
||||
Uint16 tcolor; /* transparent color */
|
||||
Uint8 xAspect, /* pixel aspect ratio */
|
||||
yAspect;
|
||||
Sint16 Lpage; /* width of the screen in pixels */
|
||||
Sint16 Hpage; /* height of the screen in pixels */
|
||||
} BMHD;
|
||||
|
||||
int IMG_isLBM( SDL_RWops *src )
|
||||
{
|
||||
int start;
|
||||
int is_LBM;
|
||||
Uint8 magic[4+4+4];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_LBM = 0;
|
||||
if ( SDL_RWread( src, magic, sizeof(magic), 1 ) )
|
||||
{
|
||||
if ( !memcmp( magic, "FORM", 4 ) &&
|
||||
( !memcmp( magic + 8, "PBM ", 4 ) ||
|
||||
!memcmp( magic + 8, "ILBM", 4 ) ) )
|
||||
{
|
||||
is_LBM = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return( is_LBM );
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src )
|
||||
{
|
||||
int start;
|
||||
SDL_Surface *Image;
|
||||
Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk;
|
||||
Uint32 size, bytesloaded, nbcolors;
|
||||
Uint32 i, j, bytesperline, nbplanes, stencil, plane, h;
|
||||
Uint32 remainingbytes;
|
||||
Uint32 width;
|
||||
BMHD bmhd;
|
||||
char *error;
|
||||
Uint8 flagHAM,flagEHB;
|
||||
|
||||
Image = NULL;
|
||||
error = NULL;
|
||||
MiniBuf = NULL;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Should be the size of the file minus 4+4 ( 'FORM'+size ) */
|
||||
if ( !SDL_RWread( src, &size, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk size";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* As size is not used here, no need to swap it */
|
||||
|
||||
if ( memcmp( id, "FORM", 4 ) != 0 )
|
||||
{
|
||||
error="not a IFF file";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
pbm = 0;
|
||||
|
||||
/* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */
|
||||
if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1;
|
||||
else if ( memcmp( id, "ILBM", 4 ) )
|
||||
{
|
||||
error="not a IFF picture";
|
||||
goto done;
|
||||
}
|
||||
|
||||
nbcolors = 0;
|
||||
|
||||
memset( &bmhd, 0, sizeof( BMHD ) );
|
||||
flagHAM = 0;
|
||||
flagEHB = 0;
|
||||
|
||||
while ( memcmp( id, "BODY", 4 ) != 0 )
|
||||
{
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !SDL_RWread( src, &size, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk size";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = 0;
|
||||
|
||||
size = SDL_SwapBE32( size );
|
||||
|
||||
if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */
|
||||
{
|
||||
if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
|
||||
{
|
||||
error="error reading BMHD chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = sizeof( BMHD );
|
||||
|
||||
bmhd.w = SDL_SwapBE16( bmhd.w );
|
||||
bmhd.h = SDL_SwapBE16( bmhd.h );
|
||||
bmhd.x = SDL_SwapBE16( bmhd.x );
|
||||
bmhd.y = SDL_SwapBE16( bmhd.y );
|
||||
bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor );
|
||||
bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage );
|
||||
bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage );
|
||||
}
|
||||
|
||||
if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */
|
||||
{
|
||||
if ( !SDL_RWread( src, &colormap, size, 1 ) )
|
||||
{
|
||||
error="error reading CMAP chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = size;
|
||||
nbcolors = size / 3;
|
||||
}
|
||||
|
||||
if ( !memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */
|
||||
{
|
||||
Uint32 viewmodes;
|
||||
if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) )
|
||||
{
|
||||
error="error reading CAMG chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = size;
|
||||
viewmodes = SDL_SwapBE32( viewmodes );
|
||||
if ( viewmodes & 0x0800 )
|
||||
flagHAM = 1;
|
||||
if ( viewmodes & 0x0080 )
|
||||
flagEHB = 1;
|
||||
}
|
||||
|
||||
if ( memcmp( id, "BODY", 4 ) )
|
||||
{
|
||||
if ( size & 1 ) ++size; /* padding ! */
|
||||
size -= bytesloaded;
|
||||
/* skip the remaining bytes of this chunk */
|
||||
if ( size ) SDL_RWseek( src, size, RW_SEEK_CUR );
|
||||
}
|
||||
}
|
||||
|
||||
/* compute some usefull values, based on the bitmap header */
|
||||
|
||||
width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */
|
||||
|
||||
bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;
|
||||
|
||||
nbplanes = bmhd.planes;
|
||||
|
||||
if ( pbm ) /* File format : 'Packed Bitmap' */
|
||||
{
|
||||
bytesperline *= 8;
|
||||
nbplanes = 1;
|
||||
}
|
||||
|
||||
stencil = (bmhd.mask & 1); /* There is a mask ( 'stencil' ) */
|
||||
|
||||
/* Allocate memory for a temporary buffer ( used for
|
||||
decompression/deinterleaving ) */
|
||||
|
||||
MiniBuf = (void *)malloc( bytesperline * (nbplanes + stencil) );
|
||||
if ( MiniBuf == NULL )
|
||||
{
|
||||
error="no enough memory for temporary buffer";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, (bmhd.planes==24 || flagHAM==1)?24:8, 0, 0, 0, 0 ) ) == NULL )
|
||||
goto done;
|
||||
|
||||
if ( bmhd.mask & 2 ) /* There is a transparent color */
|
||||
SDL_SetColorKey( Image, SDL_SRCCOLORKEY, bmhd.tcolor );
|
||||
|
||||
/* Update palette informations */
|
||||
|
||||
/* There is no palette in 24 bits ILBM file */
|
||||
if ( nbcolors>0 && flagHAM==0 )
|
||||
{
|
||||
/* FIXME: Should this include the stencil? See comment below */
|
||||
int nbrcolorsfinal = 1 << (nbplanes + stencil);
|
||||
ptr = &colormap[0];
|
||||
|
||||
for ( i=0; i<nbcolors; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = *ptr++;
|
||||
Image->format->palette->colors[i].g = *ptr++;
|
||||
Image->format->palette->colors[i].b = *ptr++;
|
||||
}
|
||||
|
||||
/* Amiga EHB mode (Extra-Half-Bright) */
|
||||
/* 6 bitplanes mode with a 32 colors palette */
|
||||
/* The 32 last colors are the same but divided by 2 */
|
||||
/* Some Amiga pictures save 64 colors with 32 last wrong colors, */
|
||||
/* they shouldn't !, and here we overwrite these 32 bad colors. */
|
||||
if ( (nbcolors==32 || flagEHB ) && (1<<bmhd.planes)==64 )
|
||||
{
|
||||
nbcolors = 64;
|
||||
ptr = &colormap[0];
|
||||
for ( i=32; i<64; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = (*ptr++)/2;
|
||||
Image->format->palette->colors[i].g = (*ptr++)/2;
|
||||
Image->format->palette->colors[i].b = (*ptr++)/2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If nbcolors < 2^nbplanes, repeat the colormap */
|
||||
/* This happens when pictures have a stencil mask */
|
||||
if ( nbrcolorsfinal > (1<<bmhd.planes) ) {
|
||||
nbrcolorsfinal = (1<<bmhd.planes);
|
||||
}
|
||||
for ( i=nbcolors; i < (Uint32)nbrcolorsfinal; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = Image->format->palette->colors[i%nbcolors].r;
|
||||
Image->format->palette->colors[i].g = Image->format->palette->colors[i%nbcolors].g;
|
||||
Image->format->palette->colors[i].b = Image->format->palette->colors[i%nbcolors].b;
|
||||
}
|
||||
if ( !pbm )
|
||||
Image->format->palette->ncolors = nbrcolorsfinal;
|
||||
}
|
||||
|
||||
/* Get the bitmap */
|
||||
|
||||
for ( h=0; h < bmhd.h; h++ )
|
||||
{
|
||||
/* uncompress the datas of each planes */
|
||||
|
||||
for ( plane=0; plane < (nbplanes+stencil); plane++ )
|
||||
{
|
||||
ptr = MiniBuf + ( plane * bytesperline );
|
||||
|
||||
remainingbytes = bytesperline;
|
||||
|
||||
if ( bmhd.tcomp == 1 ) /* Datas are compressed */
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( !SDL_RWread( src, &count, 1, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( count & 0x80 )
|
||||
{
|
||||
count ^= 0xFF;
|
||||
count += 2; /* now it */
|
||||
|
||||
if ( ( count > remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
memset( ptr, color, count );
|
||||
}
|
||||
else
|
||||
{
|
||||
++count;
|
||||
|
||||
if ( ( count > remainingbytes ) || !SDL_RWread( src, ptr, count, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ptr += count;
|
||||
remainingbytes -= count;
|
||||
|
||||
} while ( remainingbytes > 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* One line has been read, store it ! */
|
||||
|
||||
ptr = Image->pixels;
|
||||
if ( nbplanes==24 || flagHAM==1 )
|
||||
ptr += h * width * 3;
|
||||
else
|
||||
ptr += h * width;
|
||||
|
||||
if ( pbm ) /* File format : 'Packed Bitmap' */
|
||||
{
|
||||
memcpy( ptr, MiniBuf, width );
|
||||
}
|
||||
else /* We have to un-interlace the bits ! */
|
||||
{
|
||||
if ( nbplanes!=24 && flagHAM==0 )
|
||||
{
|
||||
size = ( width + 7 ) / 8;
|
||||
|
||||
for ( i=0; i < size; i++ )
|
||||
{
|
||||
memset( ptr, 0, 8 );
|
||||
|
||||
for ( plane=0; plane < (nbplanes + stencil); plane++ )
|
||||
{
|
||||
color = *( MiniBuf + i + ( plane * bytesperline ) );
|
||||
msk = 0x80;
|
||||
|
||||
for ( j=0; j<8; j++ )
|
||||
{
|
||||
if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j );
|
||||
else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 );
|
||||
|
||||
msk >>= 1;
|
||||
}
|
||||
}
|
||||
ptr += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Uint32 finalcolor = 0;
|
||||
size = ( width + 7 ) / 8;
|
||||
/* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */
|
||||
/* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */
|
||||
for ( i=0; i<width; i=i+8 )
|
||||
{
|
||||
Uint8 maskBit = 0x80;
|
||||
for ( j=0; j<8; j++ )
|
||||
{
|
||||
Uint32 pixelcolor = 0;
|
||||
Uint32 maskColor = 1;
|
||||
Uint8 dataBody;
|
||||
for ( plane=0; plane < nbplanes; plane++ )
|
||||
{
|
||||
dataBody = MiniBuf[ plane*size+i/8 ];
|
||||
if ( dataBody&maskBit )
|
||||
pixelcolor = pixelcolor | maskColor;
|
||||
maskColor = maskColor<<1;
|
||||
}
|
||||
/* HAM : 12 bits RGB image (4 bits per color component) */
|
||||
/* HAM8 : 18 bits RGB image (6 bits per color component) */
|
||||
if ( flagHAM )
|
||||
{
|
||||
switch( pixelcolor>>(nbplanes-2) )
|
||||
{
|
||||
case 0: /* take direct color from palette */
|
||||
finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16);
|
||||
break;
|
||||
case 1: /* modify only blue component */
|
||||
finalcolor = finalcolor&0x00FFFF;
|
||||
finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes)));
|
||||
break;
|
||||
case 2: /* modify only red component */
|
||||
finalcolor = finalcolor&0xFFFF00;
|
||||
finalcolor = finalcolor | pixelcolor<<(10-nbplanes);
|
||||
break;
|
||||
case 3: /* modify only green component */
|
||||
finalcolor = finalcolor&0xFF00FF;
|
||||
finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finalcolor = pixelcolor;
|
||||
}
|
||||
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
|
||||
{
|
||||
*ptr++ = (Uint8)(finalcolor>>16);
|
||||
*ptr++ = (Uint8)(finalcolor>>8);
|
||||
*ptr++ = (Uint8)(finalcolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = (Uint8)(finalcolor);
|
||||
*ptr++ = (Uint8)(finalcolor>>8);
|
||||
*ptr++ = (Uint8)(finalcolor>>16);
|
||||
}
|
||||
|
||||
maskBit = maskBit>>1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if ( MiniBuf ) free( MiniBuf );
|
||||
|
||||
if ( error )
|
||||
{
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( Image ) {
|
||||
SDL_FreeSurface( Image );
|
||||
Image = NULL;
|
||||
}
|
||||
IMG_SetError( error );
|
||||
}
|
||||
|
||||
return( Image );
|
||||
}
|
||||
|
||||
#else /* LOAD_LBM */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isLBM(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load an IFF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadLBM_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_LBM */
|
||||
276
apps/plugins/sdl/SDL_image/IMG_pcx.c
Normal file
276
apps/plugins/sdl/SDL_image/IMG_pcx.c
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCX file reader:
|
||||
* Supports:
|
||||
* 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
|
||||
* 8 bits/pixel in single-planar format (8 bits/plane/pixel)
|
||||
* 24 bits/pixel in 3-plane format (8 bits/plane/pixel)
|
||||
*
|
||||
* (The <8bpp formats are expanded to 8bpp surfaces)
|
||||
*
|
||||
* Doesn't support:
|
||||
* single-planar packed-pixel formats other than 8bpp
|
||||
* 4-plane 32bpp format with a fourth "intensity" plane
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_PCX
|
||||
|
||||
struct PCXheader {
|
||||
Uint8 Manufacturer;
|
||||
Uint8 Version;
|
||||
Uint8 Encoding;
|
||||
Uint8 BitsPerPixel;
|
||||
Sint16 Xmin, Ymin, Xmax, Ymax;
|
||||
Sint16 HDpi, VDpi;
|
||||
Uint8 Colormap[48];
|
||||
Uint8 Reserved;
|
||||
Uint8 NPlanes;
|
||||
Sint16 BytesPerLine;
|
||||
Sint16 PaletteInfo;
|
||||
Sint16 HscreenSize;
|
||||
Sint16 VscreenSize;
|
||||
Uint8 Filler[54];
|
||||
};
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPCX(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_PCX;
|
||||
const int ZSoft_Manufacturer = 10;
|
||||
const int PC_Paintbrush_Version = 5;
|
||||
const int PCX_Uncompressed_Encoding = 0;
|
||||
const int PCX_RunLength_Encoding = 1;
|
||||
struct PCXheader pcxh;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_PCX = 0;
|
||||
if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
|
||||
if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
|
||||
(pcxh.Version == PC_Paintbrush_Version) &&
|
||||
(pcxh.Encoding == PCX_RunLength_Encoding ||
|
||||
pcxh.Encoding == PCX_Uncompressed_Encoding) ) {
|
||||
is_PCX = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PCX);
|
||||
}
|
||||
|
||||
/* Load a PCX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
struct PCXheader pcxh;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Surface *surface = NULL;
|
||||
int width, height;
|
||||
int y, bpl;
|
||||
Uint8 *row, *buf = NULL;
|
||||
char *error = NULL;
|
||||
int bits, src_bits;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
|
||||
pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
|
||||
pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
|
||||
pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
|
||||
pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
|
||||
|
||||
/* Create the surface of the appropriate type */
|
||||
width = (pcxh.Xmax - pcxh.Xmin) + 1;
|
||||
height = (pcxh.Ymax - pcxh.Ymin) + 1;
|
||||
Rmask = Gmask = Bmask = Amask = 0;
|
||||
src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
|
||||
if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
|
||||
|| (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
|
||||
bits = 8;
|
||||
} else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
|
||||
bits = 24;
|
||||
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
} else {
|
||||
Rmask = 0xFF0000;
|
||||
Gmask = 0x00FF00;
|
||||
Bmask = 0x0000FF;
|
||||
}
|
||||
} else {
|
||||
error = "unsupported PCX format";
|
||||
goto done;
|
||||
}
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
|
||||
bits, Rmask, Gmask, Bmask, Amask);
|
||||
if ( surface == NULL )
|
||||
goto done;
|
||||
|
||||
bpl = pcxh.NPlanes * pcxh.BytesPerLine;
|
||||
if (bpl > surface->pitch) {
|
||||
error = "bytes per line is too large (corrupt?)";
|
||||
}
|
||||
buf = malloc(bpl);
|
||||
row = surface->pixels;
|
||||
for ( y=0; y<surface->h; ++y ) {
|
||||
/* decode a scan line to a temporary buffer first */
|
||||
int i, count = 0;
|
||||
Uint8 ch;
|
||||
Uint8 *dst = (src_bits == 8) ? row : buf;
|
||||
if ( pcxh.Encoding == 0 ) {
|
||||
if(!SDL_RWread(src, dst, bpl, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < bpl; i++) {
|
||||
if(!count) {
|
||||
if(!SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
if( (ch & 0xc0) == 0xc0) {
|
||||
count = ch & 0x3f;
|
||||
if(!SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} else
|
||||
count = 1;
|
||||
}
|
||||
dst[i] = ch;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if(src_bits <= 4) {
|
||||
/* expand planes to 1 byte/pixel */
|
||||
Uint8 *src = buf;
|
||||
int plane;
|
||||
for(plane = 0; plane < pcxh.NPlanes; plane++) {
|
||||
int i, j, x = 0;
|
||||
for(i = 0; i < pcxh.BytesPerLine; i++) {
|
||||
Uint8 byte = *src++;
|
||||
for(j = 7; j >= 0; j--) {
|
||||
unsigned bit = (byte >> j) & 1;
|
||||
/* skip padding bits */
|
||||
if (i * 8 + j >= width)
|
||||
continue;
|
||||
row[x++] |= bit << plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(src_bits == 24) {
|
||||
/* de-interlace planes */
|
||||
Uint8 *src = buf;
|
||||
int plane;
|
||||
for(plane = 0; plane < pcxh.NPlanes; plane++) {
|
||||
int x;
|
||||
dst = row + plane;
|
||||
for(x = 0; x < width; x++) {
|
||||
*dst = *src++;
|
||||
dst += pcxh.NPlanes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
row += surface->pitch;
|
||||
}
|
||||
|
||||
if(bits == 8) {
|
||||
SDL_Color *colors = surface->format->palette->colors;
|
||||
int nc = 1 << src_bits;
|
||||
int i;
|
||||
|
||||
surface->format->palette->ncolors = nc;
|
||||
if(src_bits == 8) {
|
||||
Uint8 ch;
|
||||
/* look for a 256-colour palette */
|
||||
do {
|
||||
if ( !SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} while ( ch != 12 );
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
SDL_RWread(src, &colors[i].r, 1, 1);
|
||||
SDL_RWread(src, &colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &colors[i].b, 1, 1);
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < nc; i++) {
|
||||
colors[i].r = pcxh.Colormap[i * 3];
|
||||
colors[i].g = pcxh.Colormap[i * 3 + 1];
|
||||
colors[i].b = pcxh.Colormap[i * 3 + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
free(buf);
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPCX(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PCX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PCX */
|
||||
584
apps/plugins/sdl/SDL_image/IMG_png.c
Normal file
584
apps/plugins/sdl/SDL_image/IMG_png.c
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a PNG image file loading framework */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_PNG
|
||||
|
||||
/*=============================================================================
|
||||
File: SDL_png.c
|
||||
Purpose: A PNG loader and saver for the SDL library
|
||||
Revision:
|
||||
Created by: Philippe Lavoie (2 November 1998)
|
||||
lavoie@zeus.genie.uottawa.ca
|
||||
Modified by:
|
||||
|
||||
Copyright notice:
|
||||
Copyright (C) 1998 Philippe Lavoie
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Comments: The load and save routine are basically the ones you can find
|
||||
in the example.c file from the libpng distribution.
|
||||
|
||||
Changes:
|
||||
5/17/99 - Modified to use the new SDL data sources - Sam Lantinga
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#ifdef macintosh
|
||||
#define MACOS
|
||||
#endif
|
||||
#include <png.h>
|
||||
|
||||
/* Check for the older version of libpng */
|
||||
#if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR < 4)
|
||||
#define LIBPNG_VERSION_12
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
png_infop (*png_create_info_struct) (png_structp png_ptr);
|
||||
png_structp (*png_create_read_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
|
||||
void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);
|
||||
png_uint_32 (*png_get_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method);
|
||||
png_voidp (*png_get_io_ptr) (png_structp png_ptr);
|
||||
png_byte (*png_get_channels) (png_structp png_ptr, png_infop info_ptr);
|
||||
png_uint_32 (*png_get_PLTE) (png_structp png_ptr, png_infop info_ptr, png_colorp *palette, int *num_palette);
|
||||
png_uint_32 (*png_get_tRNS) (png_structp png_ptr, png_infop info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values);
|
||||
png_uint_32 (*png_get_valid) (png_structp png_ptr, png_infop info_ptr, png_uint_32 flag);
|
||||
void (*png_read_image) (png_structp png_ptr, png_bytepp image);
|
||||
void (*png_read_info) (png_structp png_ptr, png_infop info_ptr);
|
||||
void (*png_read_update_info) (png_structp png_ptr, png_infop info_ptr);
|
||||
void (*png_set_expand) (png_structp png_ptr);
|
||||
void (*png_set_gray_to_rgb) (png_structp png_ptr);
|
||||
void (*png_set_packing) (png_structp png_ptr);
|
||||
void (*png_set_read_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
|
||||
void (*png_set_strip_16) (png_structp png_ptr);
|
||||
int (*png_sig_cmp) (png_bytep sig, png_size_t start, png_size_t num_to_check);
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
jmp_buf* (*png_set_longjmp_fn) (png_structp, png_longjmp_ptr, size_t);
|
||||
#endif
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_PNG_DYNAMIC
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_PNG_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.png_create_info_struct =
|
||||
(png_infop (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_create_info_struct");
|
||||
if ( lib.png_create_info_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_create_read_struct =
|
||||
(png_structp (*) (png_const_charp, png_voidp, png_error_ptr, png_error_ptr))
|
||||
SDL_LoadFunction(lib.handle, "png_create_read_struct");
|
||||
if ( lib.png_create_read_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_destroy_read_struct =
|
||||
(void (*) (png_structpp, png_infopp, png_infopp))
|
||||
SDL_LoadFunction(lib.handle, "png_destroy_read_struct");
|
||||
if ( lib.png_destroy_read_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_IHDR =
|
||||
(png_uint_32 (*) (png_structp, png_infop, png_uint_32 *, png_uint_32 *, int *, int *, int *, int *, int *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_IHDR");
|
||||
if ( lib.png_get_IHDR == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_channels =
|
||||
(png_byte (*) (png_structp, png_infop))
|
||||
SDL_LoadFunction(lib.handle, "png_get_channels");
|
||||
if ( lib.png_get_channels == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_io_ptr =
|
||||
(png_voidp (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_get_io_ptr");
|
||||
if ( lib.png_get_io_ptr == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_PLTE =
|
||||
(png_uint_32 (*) (png_structp, png_infop, png_colorp *, int *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_PLTE");
|
||||
if ( lib.png_get_PLTE == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_tRNS =
|
||||
(png_uint_32 (*) (png_structp, png_infop, png_bytep *, int *, png_color_16p *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_tRNS");
|
||||
if ( lib.png_get_tRNS == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_valid =
|
||||
(png_uint_32 (*) (png_structp, png_infop, png_uint_32))
|
||||
SDL_LoadFunction(lib.handle, "png_get_valid");
|
||||
if ( lib.png_get_valid == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_image =
|
||||
(void (*) (png_structp, png_bytepp))
|
||||
SDL_LoadFunction(lib.handle, "png_read_image");
|
||||
if ( lib.png_read_image == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_info =
|
||||
(void (*) (png_structp, png_infop))
|
||||
SDL_LoadFunction(lib.handle, "png_read_info");
|
||||
if ( lib.png_read_info == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_update_info =
|
||||
(void (*) (png_structp, png_infop))
|
||||
SDL_LoadFunction(lib.handle, "png_read_update_info");
|
||||
if ( lib.png_read_update_info == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_expand =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_expand");
|
||||
if ( lib.png_set_expand == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_gray_to_rgb =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_gray_to_rgb");
|
||||
if ( lib.png_set_gray_to_rgb == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_packing =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_packing");
|
||||
if ( lib.png_set_packing == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_read_fn =
|
||||
(void (*) (png_structp, png_voidp, png_rw_ptr))
|
||||
SDL_LoadFunction(lib.handle, "png_set_read_fn");
|
||||
if ( lib.png_set_read_fn == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_strip_16 =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_strip_16");
|
||||
if ( lib.png_set_strip_16 == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_sig_cmp =
|
||||
(int (*) (png_bytep, png_size_t, png_size_t))
|
||||
SDL_LoadFunction(lib.handle, "png_sig_cmp");
|
||||
if ( lib.png_sig_cmp == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
lib.png_set_longjmp_fn =
|
||||
(jmp_buf * (*) (png_structp, png_longjmp_ptr, size_t))
|
||||
SDL_LoadFunction(lib.handle, "png_set_longjmp_fn");
|
||||
if ( lib.png_set_longjmp_fn == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.png_create_info_struct = png_create_info_struct;
|
||||
lib.png_create_read_struct = png_create_read_struct;
|
||||
lib.png_destroy_read_struct = png_destroy_read_struct;
|
||||
lib.png_get_IHDR = png_get_IHDR;
|
||||
lib.png_get_channels = png_get_channels;
|
||||
lib.png_get_io_ptr = png_get_io_ptr;
|
||||
lib.png_get_PLTE = png_get_PLTE;
|
||||
lib.png_get_tRNS = png_get_tRNS;
|
||||
lib.png_get_valid = png_get_valid;
|
||||
lib.png_read_image = png_read_image;
|
||||
lib.png_read_info = png_read_info;
|
||||
lib.png_read_update_info = png_read_update_info;
|
||||
lib.png_set_expand = png_set_expand;
|
||||
lib.png_set_gray_to_rgb = png_set_gray_to_rgb;
|
||||
lib.png_set_packing = png_set_packing;
|
||||
lib.png_set_read_fn = png_set_read_fn;
|
||||
lib.png_set_strip_16 = png_set_strip_16;
|
||||
lib.png_sig_cmp = png_sig_cmp;
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
lib.png_set_longjmp_fn = png_set_longjmp_fn;
|
||||
#endif
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_PNG_DYNAMIC */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNG(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_PNG;
|
||||
Uint8 magic[4];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_PNG = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( magic[0] == 0x89 &&
|
||||
magic[1] == 'P' &&
|
||||
magic[2] == 'N' &&
|
||||
magic[3] == 'G' ) {
|
||||
is_PNG = 1;
|
||||
}
|
||||
else
|
||||
rb->splashf(HZ, "magic is %4s", magic);
|
||||
}
|
||||
else
|
||||
{
|
||||
rb->splashf(HZ, "read() failed!");
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PNG);
|
||||
}
|
||||
|
||||
/* Load a PNG type image from an SDL datasource */
|
||||
static void png_read_data(png_structp ctx, png_bytep area, png_size_t size)
|
||||
{
|
||||
SDL_RWops *src;
|
||||
|
||||
src = (SDL_RWops *)lib.png_get_io_ptr(ctx);
|
||||
SDL_RWread(src, area, size, 1);
|
||||
}
|
||||
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error;
|
||||
SDL_Surface *volatile surface;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, num_channels;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Palette *palette;
|
||||
png_bytep *volatile row_pointers;
|
||||
int row, i;
|
||||
volatile int ckey = -1;
|
||||
png_color_16 *transv;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_PNG) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the data we will clean up when we're done */
|
||||
error = NULL;
|
||||
png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL;
|
||||
|
||||
/* Create the PNG loading context structure */
|
||||
png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL,NULL,NULL);
|
||||
if (png_ptr == NULL){
|
||||
error = "Couldn't allocate memory for PNG file or incompatible PNG dll";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Allocate/initialize the memory for image information. REQUIRED. */
|
||||
info_ptr = lib.png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
error = "Couldn't create image information for PNG file";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set error handling if you are using setjmp/longjmp method (this is
|
||||
* the normal method of doing things with libpng). REQUIRED unless you
|
||||
* set up your own error handlers in png_create_read_struct() earlier.
|
||||
*/
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
if ( setjmp(*lib.png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))) )
|
||||
#else
|
||||
if ( setjmp(png_ptr->jmpbuf) )
|
||||
#endif
|
||||
{
|
||||
error = "Error reading the PNG file.";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set up the input control */
|
||||
lib.png_set_read_fn(png_ptr, src, png_read_data);
|
||||
|
||||
/* Read PNG header info */
|
||||
lib.png_read_info(png_ptr, info_ptr);
|
||||
lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
||||
&color_type, &interlace_type, NULL, NULL);
|
||||
|
||||
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
|
||||
lib.png_set_strip_16(png_ptr) ;
|
||||
|
||||
/* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
|
||||
* byte into separate bytes (useful for paletted and grayscale images).
|
||||
*/
|
||||
lib.png_set_packing(png_ptr);
|
||||
|
||||
/* scale greyscale values to the range 0..255 */
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY)
|
||||
lib.png_set_expand(png_ptr);
|
||||
|
||||
/* For images with a single "transparent colour", set colour key;
|
||||
if more than one index has transparency, or if partially transparent
|
||||
entries exist, use full alpha channel */
|
||||
if (lib.png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
int num_trans;
|
||||
Uint8 *trans;
|
||||
lib.png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
|
||||
&transv);
|
||||
if(color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
/* Check if all tRNS entries are opaque except one */
|
||||
int i, t = -1;
|
||||
for(i = 0; i < num_trans; i++)
|
||||
if(trans[i] == 0) {
|
||||
if(t >= 0)
|
||||
break;
|
||||
t = i;
|
||||
} else if(trans[i] != 255)
|
||||
break;
|
||||
if(i == num_trans) {
|
||||
/* exactly one transparent index */
|
||||
ckey = t;
|
||||
} else {
|
||||
/* more than one transparent index, or translucency */
|
||||
lib.png_set_expand(png_ptr);
|
||||
}
|
||||
} else
|
||||
ckey = 0; /* actual value will be set later */
|
||||
}
|
||||
|
||||
if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
|
||||
lib.png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
lib.png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
||||
&color_type, &interlace_type, NULL, NULL);
|
||||
|
||||
/* Allocate the SDL surface to hold the image */
|
||||
Rmask = Gmask = Bmask = Amask = 0 ;
|
||||
num_channels = lib.png_get_channels(png_ptr, info_ptr);
|
||||
if ( color_type != PNG_COLOR_TYPE_PALETTE ) {
|
||||
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = (num_channels == 4) ? 0xFF000000 : 0;
|
||||
} else {
|
||||
int s = (num_channels == 4) ? 0 : 8;
|
||||
Rmask = 0xFF000000 >> s;
|
||||
Gmask = 0x00FF0000 >> s;
|
||||
Bmask = 0x0000FF00 >> s;
|
||||
Amask = 0x000000FF >> s;
|
||||
}
|
||||
}
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
|
||||
bit_depth*num_channels, Rmask,Gmask,Bmask,Amask);
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(ckey != -1) {
|
||||
if(color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
/* FIXME: Should these be truncated or shifted down? */
|
||||
ckey = SDL_MapRGB(surface->format,
|
||||
(Uint8)transv->red,
|
||||
(Uint8)transv->green,
|
||||
(Uint8)transv->blue);
|
||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, ckey);
|
||||
}
|
||||
|
||||
/* Create the array of pointers to image data */
|
||||
row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height);
|
||||
if ( (row_pointers == NULL) ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for (row = 0; row < (int)height; row++) {
|
||||
row_pointers[row] = (png_bytep)
|
||||
(Uint8 *)surface->pixels + row*surface->pitch;
|
||||
}
|
||||
|
||||
/* Read the entire image in one go */
|
||||
lib.png_read_image(png_ptr, row_pointers);
|
||||
|
||||
/* and we're done! (png_read_end() can be omitted if no processing of
|
||||
* post-IDAT text/time/etc. is desired)
|
||||
* In some cases it can't read PNG's created by some popular programs (ACDSEE),
|
||||
* we do not want to process comments, so we omit png_read_end
|
||||
|
||||
lib.png_read_end(png_ptr, info_ptr);
|
||||
*/
|
||||
|
||||
/* Load the palette, if any */
|
||||
palette = surface->format->palette;
|
||||
if ( palette ) {
|
||||
int png_num_palette;
|
||||
png_colorp png_palette;
|
||||
lib.png_get_PLTE(png_ptr, info_ptr, &png_palette, &png_num_palette);
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
palette->ncolors = 256;
|
||||
for(i = 0; i < 256; i++) {
|
||||
palette->colors[i].r = i;
|
||||
palette->colors[i].g = i;
|
||||
palette->colors[i].b = i;
|
||||
}
|
||||
} else if (png_num_palette > 0 ) {
|
||||
palette->ncolors = png_num_palette;
|
||||
for( i=0; i<png_num_palette; ++i ) {
|
||||
palette->colors[i].b = png_palette[i].blue;
|
||||
palette->colors[i].g = png_palette[i].green;
|
||||
palette->colors[i].r = png_palette[i].red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done: /* Clean up and return */
|
||||
if ( png_ptr ) {
|
||||
lib.png_destroy_read_struct(&png_ptr,
|
||||
info_ptr ? &info_ptr : (png_infopp)0,
|
||||
(png_infopp)0);
|
||||
}
|
||||
if ( row_pointers ) {
|
||||
free(row_pointers);
|
||||
}
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
IMG_SetError("PNG images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNG(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PNG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PNG */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
258
apps/plugins/sdl/SDL_image/IMG_pnm.c
Normal file
258
apps/plugins/sdl/SDL_image/IMG_pnm.c
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PNM (portable anymap) image loader:
|
||||
*
|
||||
* Supports: PBM, PGM and PPM, ASCII and binary formats
|
||||
* (PBM and PGM are loaded as 8bpp surfaces)
|
||||
* Does not support: maximum component value > 255
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_PNM
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNM(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_PNM;
|
||||
char magic[2];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_PNM = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
/*
|
||||
* PNM magic signatures:
|
||||
* P1 PBM, ascii format
|
||||
* P2 PGM, ascii format
|
||||
* P3 PPM, ascii format
|
||||
* P4 PBM, binary format
|
||||
* P5 PGM, binary format
|
||||
* P6 PPM, binary format
|
||||
* P7 PAM, a general wrapper for PNM data
|
||||
*/
|
||||
if ( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) {
|
||||
is_PNM = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PNM);
|
||||
}
|
||||
|
||||
/* read a non-negative integer from the source. return -1 upon error */
|
||||
static int ReadNumber(SDL_RWops *src)
|
||||
{
|
||||
int number;
|
||||
unsigned char ch;
|
||||
|
||||
/* Initialize return value */
|
||||
number = 0;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
do {
|
||||
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return(0);
|
||||
}
|
||||
/* Eat comments as whitespace */
|
||||
if ( ch == '#' ) { /* Comment is '#' to end of line */
|
||||
do {
|
||||
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return -1;
|
||||
}
|
||||
} while ( (ch != '\r') && (ch != '\n') );
|
||||
}
|
||||
} while ( isspace(ch) );
|
||||
|
||||
/* Add up the number */
|
||||
do {
|
||||
number *= 10;
|
||||
number += ch-'0';
|
||||
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return -1;
|
||||
}
|
||||
} while ( isdigit(ch) );
|
||||
|
||||
return(number);
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
SDL_Surface *surface = NULL;
|
||||
int width, height;
|
||||
int maxval, y, bpl;
|
||||
Uint8 *row;
|
||||
Uint8 *buf = NULL;
|
||||
char *error = NULL;
|
||||
Uint8 magic[2];
|
||||
int ascii;
|
||||
enum { PBM, PGM, PPM, PAM } kind;
|
||||
|
||||
#define ERROR(s) do { error = (s); goto done; } while(0)
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
SDL_RWread(src, magic, 2, 1);
|
||||
kind = magic[1] - '1';
|
||||
ascii = 1;
|
||||
if(kind >= 3) {
|
||||
ascii = 0;
|
||||
kind -= 3;
|
||||
}
|
||||
|
||||
width = ReadNumber(src);
|
||||
height = ReadNumber(src);
|
||||
if(width <= 0 || height <= 0)
|
||||
ERROR("Unable to read image width and height");
|
||||
|
||||
if(kind != PBM) {
|
||||
maxval = ReadNumber(src);
|
||||
if(maxval <= 0 || maxval > 255)
|
||||
ERROR("unsupported PNM format");
|
||||
} else
|
||||
maxval = 255; /* never scale PBMs */
|
||||
|
||||
/* binary PNM allows just a single character of whitespace after
|
||||
the last parameter, and we've already consumed it */
|
||||
|
||||
if(kind == PPM) {
|
||||
/* 24-bit surface in R,G,B byte order */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000,
|
||||
#else
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff,
|
||||
#endif
|
||||
0);
|
||||
} else {
|
||||
/* load PBM/PGM as 8-bit indexed images */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
if ( surface == NULL )
|
||||
ERROR("Out of memory");
|
||||
bpl = width * surface->format->BytesPerPixel;
|
||||
if(kind == PGM) {
|
||||
SDL_Color *c = surface->format->palette->colors;
|
||||
int i;
|
||||
for(i = 0; i < 256; i++)
|
||||
c[i].r = c[i].g = c[i].b = i;
|
||||
surface->format->palette->ncolors = 256;
|
||||
} else if(kind == PBM) {
|
||||
/* for some reason PBM has 1=black, 0=white */
|
||||
SDL_Color *c = surface->format->palette->colors;
|
||||
c[0].r = c[0].g = c[0].b = 255;
|
||||
c[1].r = c[1].g = c[1].b = 0;
|
||||
surface->format->palette->ncolors = 2;
|
||||
bpl = (width + 7) >> 3;
|
||||
buf = malloc(bpl);
|
||||
if(buf == NULL)
|
||||
ERROR("Out of memory");
|
||||
}
|
||||
|
||||
/* Read the image into the surface */
|
||||
row = surface->pixels;
|
||||
for(y = 0; y < height; y++) {
|
||||
if(ascii) {
|
||||
int i;
|
||||
if(kind == PBM) {
|
||||
for(i = 0; i < width; i++) {
|
||||
Uint8 ch;
|
||||
do {
|
||||
if(!SDL_RWread(src, &ch,
|
||||
1, 1))
|
||||
ERROR("file truncated");
|
||||
ch -= '0';
|
||||
} while(ch > 1);
|
||||
row[i] = ch;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < bpl; i++) {
|
||||
int c;
|
||||
c = ReadNumber(src);
|
||||
if(c < 0)
|
||||
ERROR("file truncated");
|
||||
row[i] = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Uint8 *dst = (kind == PBM) ? buf : row;
|
||||
if(!SDL_RWread(src, dst, bpl, 1))
|
||||
ERROR("file truncated");
|
||||
if(kind == PBM) {
|
||||
/* expand bitmap to 8bpp */
|
||||
int i;
|
||||
for(i = 0; i < width; i++) {
|
||||
int bit = 7 - (i & 7);
|
||||
row[i] = (buf[i >> 3] >> bit) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(maxval < 255) {
|
||||
/* scale up to full dynamic range (slow) */
|
||||
int i;
|
||||
for(i = 0; i < bpl; i++)
|
||||
row[i] = row[i] * 255 / maxval;
|
||||
}
|
||||
row += surface->pitch;
|
||||
}
|
||||
done:
|
||||
free(buf);
|
||||
if(error) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNM(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PNM type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PNM */
|
||||
336
apps/plugins/sdl/SDL_image/IMG_tga.c
Normal file
336
apps/plugins/sdl/SDL_image/IMG_tga.c
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a Targa image file loading framework */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_TGA
|
||||
|
||||
/*
|
||||
* A TGA loader for the SDL library
|
||||
* Supports: Reading 8, 15, 16, 24 and 32bpp images, with alpha or colourkey,
|
||||
* uncompressed or RLE encoded.
|
||||
*
|
||||
* 2000-06-10 Mattias Engdegård <f91-men@nada.kth.se>: initial version
|
||||
* 2000-06-26 Mattias Engdegård <f91-men@nada.kth.se>: read greyscale TGAs
|
||||
* 2000-08-09 Mattias Engdegård <f91-men@nada.kth.se>: alpha inversion removed
|
||||
*/
|
||||
|
||||
struct TGAheader {
|
||||
Uint8 infolen; /* length of info field */
|
||||
Uint8 has_cmap; /* 1 if image has colormap, 0 otherwise */
|
||||
Uint8 type;
|
||||
|
||||
Uint8 cmap_start[2]; /* index of first colormap entry */
|
||||
Uint8 cmap_len[2]; /* number of entries in colormap */
|
||||
Uint8 cmap_bits; /* bits per colormap entry */
|
||||
|
||||
Uint8 yorigin[2]; /* image origin (ignored here) */
|
||||
Uint8 xorigin[2];
|
||||
Uint8 width[2]; /* image size */
|
||||
Uint8 height[2];
|
||||
Uint8 pixel_bits; /* bits/pixel */
|
||||
Uint8 flags;
|
||||
};
|
||||
|
||||
enum tga_type {
|
||||
TGA_TYPE_INDEXED = 1,
|
||||
TGA_TYPE_RGB = 2,
|
||||
TGA_TYPE_BW = 3,
|
||||
TGA_TYPE_RLE_INDEXED = 9,
|
||||
TGA_TYPE_RLE_RGB = 10,
|
||||
TGA_TYPE_RLE_BW = 11
|
||||
};
|
||||
|
||||
#define TGA_INTERLEAVE_MASK 0xc0
|
||||
#define TGA_INTERLEAVE_NONE 0x00
|
||||
#define TGA_INTERLEAVE_2WAY 0x40
|
||||
#define TGA_INTERLEAVE_4WAY 0x80
|
||||
|
||||
#define TGA_ORIGIN_MASK 0x30
|
||||
#define TGA_ORIGIN_LEFT 0x00
|
||||
#define TGA_ORIGIN_RIGHT 0x10
|
||||
#define TGA_ORIGIN_LOWER 0x00
|
||||
#define TGA_ORIGIN_UPPER 0x20
|
||||
|
||||
/* read/write unaligned little-endian 16-bit ints */
|
||||
#define LE16(p) ((p)[0] + ((p)[1] << 8))
|
||||
#define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8)
|
||||
|
||||
/* Load a TGA type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
struct TGAheader hdr;
|
||||
int rle = 0;
|
||||
int alpha = 0;
|
||||
int indexed = 0;
|
||||
int grey = 0;
|
||||
int ckey = -1;
|
||||
int ncols, w, h;
|
||||
SDL_Surface *img = NULL;
|
||||
Uint32 rmask, gmask, bmask, amask;
|
||||
Uint8 *dst;
|
||||
int i;
|
||||
int bpp;
|
||||
int lstep;
|
||||
Uint32 pixel;
|
||||
int count, rep;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) {
|
||||
error = "Error reading TGA data";
|
||||
goto error;
|
||||
}
|
||||
ncols = LE16(hdr.cmap_len);
|
||||
switch(hdr.type) {
|
||||
case TGA_TYPE_RLE_INDEXED:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_INDEXED:
|
||||
if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256)
|
||||
goto unsupported;
|
||||
indexed = 1;
|
||||
break;
|
||||
|
||||
case TGA_TYPE_RLE_RGB:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_RGB:
|
||||
indexed = 0;
|
||||
break;
|
||||
|
||||
case TGA_TYPE_RLE_BW:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_BW:
|
||||
if(hdr.pixel_bits != 8)
|
||||
goto unsupported;
|
||||
/* Treat greyscale as 8bpp indexed images */
|
||||
indexed = grey = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
bpp = (hdr.pixel_bits + 7) >> 3;
|
||||
rmask = gmask = bmask = amask = 0;
|
||||
switch(hdr.pixel_bits) {
|
||||
case 8:
|
||||
if(!indexed) {
|
||||
goto unsupported;
|
||||
}
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
/* 15 and 16bpp both seem to use 5 bits/plane. The extra alpha bit
|
||||
is ignored for now. */
|
||||
rmask = 0x7c00;
|
||||
gmask = 0x03e0;
|
||||
bmask = 0x001f;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
alpha = 1;
|
||||
/* fallthrough */
|
||||
case 24:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
||||
int s = alpha ? 0 : 8;
|
||||
amask = 0x000000ff >> s;
|
||||
rmask = 0x0000ff00 >> s;
|
||||
gmask = 0x00ff0000 >> s;
|
||||
bmask = 0xff000000 >> s;
|
||||
} else {
|
||||
amask = alpha ? 0xff000000 : 0;
|
||||
rmask = 0x00ff0000;
|
||||
gmask = 0x0000ff00;
|
||||
bmask = 0x000000ff;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE
|
||||
|| hdr.flags & TGA_ORIGIN_RIGHT) {
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
SDL_RWseek(src, hdr.infolen, RW_SEEK_CUR); /* skip info field */
|
||||
|
||||
w = LE16(hdr.width);
|
||||
h = LE16(hdr.height);
|
||||
img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
|
||||
bpp * 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
if(img == NULL) {
|
||||
error = "Out of memory";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(hdr.has_cmap) {
|
||||
int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3);
|
||||
if(indexed && !grey) {
|
||||
Uint8 *pal = malloc(palsiz), *p = pal;
|
||||
SDL_Color *colors = img->format->palette->colors;
|
||||
img->format->palette->ncolors = ncols;
|
||||
SDL_RWread(src, pal, palsiz, 1);
|
||||
for(i = 0; i < ncols; i++) {
|
||||
switch(hdr.cmap_bits) {
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
Uint16 c = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
colors[i].r = (c >> 7) & 0xf8;
|
||||
colors[i].g = (c >> 2) & 0xf8;
|
||||
colors[i].b = c << 3;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
colors[i].b = *p++;
|
||||
colors[i].g = *p++;
|
||||
colors[i].r = *p++;
|
||||
if(hdr.cmap_bits == 32 && *p++ < 128)
|
||||
ckey = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(pal);
|
||||
if(ckey >= 0)
|
||||
SDL_SetColorKey(img, SDL_SRCCOLORKEY, ckey);
|
||||
} else {
|
||||
/* skip unneeded colormap */
|
||||
SDL_RWseek(src, palsiz, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
if(grey) {
|
||||
SDL_Color *colors = img->format->palette->colors;
|
||||
for(i = 0; i < 256; i++)
|
||||
colors[i].r = colors[i].g = colors[i].b = i;
|
||||
img->format->palette->ncolors = 256;
|
||||
}
|
||||
|
||||
if(hdr.flags & TGA_ORIGIN_UPPER) {
|
||||
lstep = img->pitch;
|
||||
dst = img->pixels;
|
||||
} else {
|
||||
lstep = -img->pitch;
|
||||
dst = (Uint8 *)img->pixels + (h - 1) * img->pitch;
|
||||
}
|
||||
|
||||
/* The RLE decoding code is slightly convoluted since we can't rely on
|
||||
spans not to wrap across scan lines */
|
||||
count = rep = 0;
|
||||
for(i = 0; i < h; i++) {
|
||||
if(rle) {
|
||||
int x = 0;
|
||||
for(;;) {
|
||||
Uint8 c;
|
||||
|
||||
if(count) {
|
||||
int n = count;
|
||||
if(n > w - x)
|
||||
n = w - x;
|
||||
SDL_RWread(src, dst + x * bpp, n * bpp, 1);
|
||||
count -= n;
|
||||
x += n;
|
||||
if(x == w)
|
||||
break;
|
||||
} else if(rep) {
|
||||
int n = rep;
|
||||
if(n > w - x)
|
||||
n = w - x;
|
||||
rep -= n;
|
||||
while(n--) {
|
||||
memcpy(dst + x * bpp, &pixel, bpp);
|
||||
x++;
|
||||
}
|
||||
if(x == w)
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_RWread(src, &c, 1, 1);
|
||||
if(c & 0x80) {
|
||||
SDL_RWread(src, &pixel, bpp, 1);
|
||||
rep = (c & 0x7f) + 1;
|
||||
} else {
|
||||
count = c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
SDL_RWread(src, dst, w * bpp, 1);
|
||||
}
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN && bpp == 2) {
|
||||
/* swap byte order */
|
||||
int x;
|
||||
Uint16 *p = (Uint16 *)dst;
|
||||
for(x = 0; x < w; x++)
|
||||
p[x] = SDL_Swap16(p[x]);
|
||||
}
|
||||
dst += lstep;
|
||||
}
|
||||
return img;
|
||||
|
||||
unsupported:
|
||||
error = "Unsupported TGA format";
|
||||
|
||||
error:
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( img ) {
|
||||
SDL_FreeSurface(img);
|
||||
}
|
||||
IMG_SetError(error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* dummy TGA load routine */
|
||||
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_TGA */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
298
apps/plugins/sdl/SDL_image/IMG_tif.c
Normal file
298
apps/plugins/sdl/SDL_image/IMG_tif.c
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a TIFF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_TIF
|
||||
|
||||
#include <tiffio.h>
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
|
||||
void (*TIFFClose)(TIFF*);
|
||||
int (*TIFFGetField)(TIFF*, ttag_t, ...);
|
||||
int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int);
|
||||
TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_TIF_DYNAMIC
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFClientOpen =
|
||||
(TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
|
||||
SDL_LoadFunction(lib.handle, "TIFFClientOpen");
|
||||
if ( lib.TIFFClientOpen == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFClose =
|
||||
(void (*)(TIFF*))
|
||||
SDL_LoadFunction(lib.handle, "TIFFClose");
|
||||
if ( lib.TIFFClose == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFGetField =
|
||||
(int (*)(TIFF*, ttag_t, ...))
|
||||
SDL_LoadFunction(lib.handle, "TIFFGetField");
|
||||
if ( lib.TIFFGetField == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFReadRGBAImage =
|
||||
(int (*)(TIFF*, uint32, uint32, uint32*, int))
|
||||
SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage");
|
||||
if ( lib.TIFFReadRGBAImage == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFSetErrorHandler =
|
||||
(TIFFErrorHandler (*)(TIFFErrorHandler))
|
||||
SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
|
||||
if ( lib.TIFFSetErrorHandler == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.TIFFClientOpen = TIFFClientOpen;
|
||||
lib.TIFFClose = TIFFClose;
|
||||
lib.TIFFGetField = TIFFGetField;
|
||||
lib.TIFFReadRGBAImage = TIFFReadRGBAImage;
|
||||
lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_TIF_DYNAMIC */
|
||||
|
||||
/*
|
||||
* These are the thunking routine to use the SDL_RWops* routines from
|
||||
* libtiff's internals.
|
||||
*/
|
||||
|
||||
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
|
||||
}
|
||||
|
||||
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
|
||||
{
|
||||
return SDL_RWseek((SDL_RWops*)fd, offset, origin);
|
||||
}
|
||||
|
||||
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
|
||||
}
|
||||
|
||||
static int tiff_close(thandle_t fd)
|
||||
{
|
||||
/*
|
||||
* We don't want libtiff closing our SDL_RWops*, but if it's not given
|
||||
* a routine to try, and if the image isn't a TIFF, it'll segfault.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static toff_t tiff_size(thandle_t fd)
|
||||
{
|
||||
Uint32 save_pos;
|
||||
toff_t size;
|
||||
|
||||
save_pos = SDL_RWtell((SDL_RWops*)fd);
|
||||
SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
|
||||
size = SDL_RWtell((SDL_RWops*)fd);
|
||||
SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
|
||||
return size;
|
||||
}
|
||||
|
||||
int IMG_isTIF(SDL_RWops* src)
|
||||
{
|
||||
int start;
|
||||
int is_TIF;
|
||||
Uint8 magic[4];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_TIF = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( (magic[0] == 'I' &&
|
||||
magic[1] == 'I' &&
|
||||
magic[2] == 0x2a &&
|
||||
magic[3] == 0x00) ||
|
||||
(magic[0] == 'M' &&
|
||||
magic[1] == 'M' &&
|
||||
magic[2] == 0x00 &&
|
||||
magic[3] == 0x2a) ) {
|
||||
is_TIF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_TIF);
|
||||
}
|
||||
|
||||
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
|
||||
{
|
||||
int start;
|
||||
TIFF* tiff;
|
||||
SDL_Surface* surface = NULL;
|
||||
Uint32 img_width, img_height;
|
||||
Uint32 Rmask, Gmask, Bmask, Amask;
|
||||
Uint32 x, y;
|
||||
Uint32 half;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_TIF) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* turn off memory mapped access with the m flag */
|
||||
tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
|
||||
tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
|
||||
if(!tiff)
|
||||
goto error;
|
||||
|
||||
/* Retrieve the dimensions of the image from the TIFF tags */
|
||||
lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
|
||||
lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
|
||||
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = 0xFF000000;
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
if(!surface)
|
||||
goto error;
|
||||
|
||||
if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0))
|
||||
goto error;
|
||||
|
||||
/* libtiff loads the image upside-down, flip it back */
|
||||
half = img_height / 2;
|
||||
for(y = 0; y < half; y++)
|
||||
{
|
||||
Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4;
|
||||
Uint32 *bot = (Uint32 *)surface->pixels
|
||||
+ (img_height - y - 1) * surface->pitch/4;
|
||||
for(x = 0; x < img_width; x++)
|
||||
{
|
||||
Uint32 tmp = top[x];
|
||||
top[x] = bot[x];
|
||||
bot[x] = tmp;
|
||||
}
|
||||
}
|
||||
lib.TIFFClose(tiff);
|
||||
|
||||
return surface;
|
||||
|
||||
error:
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
IMG_SetError("TIFF images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isTIF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a TIFF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_TIF */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
295
apps/plugins/sdl/SDL_image/IMG_webp.c
Normal file
295
apps/plugins/sdl/SDL_image/IMG_webp.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a WEBP image file loading framework */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_WEBP
|
||||
|
||||
/*=============================================================================
|
||||
File: SDL_webp.c
|
||||
Purpose: A WEBP loader for the SDL library
|
||||
Revision:
|
||||
Created by: Michael Bonfils (Murlock) (26 November 2011)
|
||||
murlock42@gmail.com
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#ifdef macintosh
|
||||
#define MACOS
|
||||
#endif
|
||||
#include <webp/decode.h>
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
int/*VP8StatuCode*/ (*webp_get_features_internal) (const uint8_t *data, uint32_t data_size, WebPBitstreamFeatures* const features, int decoder_abi_version);
|
||||
uint8_t* (*webp_decode_rgb_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride);
|
||||
uint8_t* (*webp_decode_rgba_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_WEBP_DYNAMIC
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_WEBP_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.webp_get_features_internal =
|
||||
( int (*) (const uint8_t *, uint32_t, WebPBitstreamFeatures* const, int) )
|
||||
SDL_LoadFunction(lib.handle, "WebPGetFeaturesInternal" );
|
||||
if ( lib.webp_get_features_internal == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lib.webp_decode_rgb_into =
|
||||
( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) )
|
||||
SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" );
|
||||
if ( lib.webp_decode_rgb_into == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lib.webp_decode_rgba_into =
|
||||
( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) )
|
||||
SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" );
|
||||
if ( lib.webp_decode_rgba_into == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.webp_get_features_internal = WebPGetFeaturesInternal;
|
||||
lib.webp_decode_rgb_into = WebPDecodeRGBInto;
|
||||
lib.webp_decode_rgba_into = WebPDecodeRGBAInto;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_WEBP_DYNAMIC */
|
||||
|
||||
static int webp_getinfo( SDL_RWops *src, int *datasize ) {
|
||||
int start;
|
||||
int is_WEBP;
|
||||
int data;
|
||||
Uint8 magic[20];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_WEBP = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( magic[ 0] == 'R' &&
|
||||
magic[ 1] == 'I' &&
|
||||
magic[ 2] == 'F' &&
|
||||
magic[ 3] == 'F' &&
|
||||
magic[ 8] == 'W' &&
|
||||
magic[ 9] == 'E' &&
|
||||
magic[10] == 'B' &&
|
||||
magic[11] == 'P' &&
|
||||
magic[12] == 'V' &&
|
||||
magic[13] == 'P' &&
|
||||
magic[14] == '8' &&
|
||||
magic[15] == ' ' ) {
|
||||
is_WEBP = 1;
|
||||
data = magic[16] | magic[17]<<8 | magic[18]<<16 | magic[19]<<24;
|
||||
if ( datasize )
|
||||
*datasize = data;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_WEBP);
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isWEBP(SDL_RWops *src)
|
||||
{
|
||||
return webp_getinfo( src, NULL );
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *volatile surface = NULL;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
WebPBitstreamFeatures features;
|
||||
int raw_data_size;
|
||||
uint8_t *raw_data;
|
||||
int r;
|
||||
uint8_t *ret;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_WEBP) ) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
raw_data_size = -1;
|
||||
if ( !webp_getinfo( src, &raw_data_size ) ) {
|
||||
error = "Invalid WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
// skip header
|
||||
SDL_RWseek(src, start+20, RW_SEEK_SET );
|
||||
|
||||
raw_data = (uint8_t*) malloc( raw_data_size );
|
||||
if ( raw_data == NULL ) {
|
||||
error = "Failed to allocate enought buffer for WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = SDL_RWread(src, raw_data, 1, raw_data_size );
|
||||
if ( r != raw_data_size ) {
|
||||
error = "Failed to read WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// extract size of picture, not interesting since we don't know about alpha channel
|
||||
int width = -1, height = -1;
|
||||
if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) {
|
||||
printf("WebPGetInfo has failed\n" );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) {
|
||||
error = "WebPGetFeatures has failed";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if it's ok !*/
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = features.has_alpha?0xFF000001:0;
|
||||
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, features.width, features.height,
|
||||
features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask);
|
||||
|
||||
if ( surface == NULL ) {
|
||||
error = "Failed to allocate SDL_Surface";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( features.has_alpha ) {
|
||||
ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h, surface->pitch );
|
||||
} else {
|
||||
ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h, surface->pitch );
|
||||
}
|
||||
|
||||
if ( !ret ) {
|
||||
error = "Failed to decode WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
return surface;
|
||||
|
||||
|
||||
error:
|
||||
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface( surface );
|
||||
}
|
||||
|
||||
if ( raw_data ) {
|
||||
free( raw_data );
|
||||
}
|
||||
|
||||
if ( error ) {
|
||||
IMG_SetError( error );
|
||||
}
|
||||
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
IMG_SetError("WEBP images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isWEBP(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a WEBP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_WEBP */
|
||||
824
apps/plugins/sdl/SDL_image/IMG_xcf.c
Normal file
824
apps/plugins/sdl/SDL_image/IMG_xcf.c
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a XCF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XCF
|
||||
|
||||
#if DEBUG
|
||||
static char prop_names [][30] = {
|
||||
"end",
|
||||
"colormap",
|
||||
"active_layer",
|
||||
"active_channel",
|
||||
"selection",
|
||||
"floating_selection",
|
||||
"opacity",
|
||||
"mode",
|
||||
"visible",
|
||||
"linked",
|
||||
"preserve_transparency",
|
||||
"apply_mask",
|
||||
"edit_mask",
|
||||
"show_mask",
|
||||
"show_masked",
|
||||
"offsets",
|
||||
"color",
|
||||
"compression",
|
||||
"guides",
|
||||
"resolution",
|
||||
"tattoo",
|
||||
"parasites",
|
||||
"unit",
|
||||
"paths",
|
||||
"user_unit"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROP_END = 0,
|
||||
PROP_COLORMAP = 1,
|
||||
PROP_ACTIVE_LAYER = 2,
|
||||
PROP_ACTIVE_CHANNEL = 3,
|
||||
PROP_SELECTION = 4,
|
||||
PROP_FLOATING_SELECTION = 5,
|
||||
PROP_OPACITY = 6,
|
||||
PROP_MODE = 7,
|
||||
PROP_VISIBLE = 8,
|
||||
PROP_LINKED = 9,
|
||||
PROP_PRESERVE_TRANSPARENCY = 10,
|
||||
PROP_APPLY_MASK = 11,
|
||||
PROP_EDIT_MASK = 12,
|
||||
PROP_SHOW_MASK = 13,
|
||||
PROP_SHOW_MASKED = 14,
|
||||
PROP_OFFSETS = 15,
|
||||
PROP_COLOR = 16,
|
||||
PROP_COMPRESSION = 17,
|
||||
PROP_GUIDES = 18,
|
||||
PROP_RESOLUTION = 19,
|
||||
PROP_TATTOO = 20,
|
||||
PROP_PARASITES = 21,
|
||||
PROP_UNIT = 22,
|
||||
PROP_PATHS = 23,
|
||||
PROP_USER_UNIT = 24
|
||||
} xcf_prop_type;
|
||||
|
||||
typedef enum {
|
||||
COMPR_NONE = 0,
|
||||
COMPR_RLE = 1,
|
||||
COMPR_ZLIB = 2,
|
||||
COMPR_FRACTAL = 3
|
||||
} xcf_compr_type;
|
||||
|
||||
typedef enum {
|
||||
IMAGE_RGB = 0,
|
||||
IMAGE_GREYSCALE = 1,
|
||||
IMAGE_INDEXED = 2
|
||||
} xcf_image_type;
|
||||
|
||||
typedef struct {
|
||||
Uint32 id;
|
||||
Uint32 length;
|
||||
union {
|
||||
struct {
|
||||
Uint32 num;
|
||||
char * cmap;
|
||||
} colormap; // 1
|
||||
struct {
|
||||
Uint32 drawable_offset;
|
||||
} floating_selection; // 5
|
||||
Sint32 opacity;
|
||||
Sint32 mode;
|
||||
int visible;
|
||||
int linked;
|
||||
int preserve_transparency;
|
||||
int apply_mask;
|
||||
int show_mask;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} offset;
|
||||
unsigned char color [3];
|
||||
Uint8 compression;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} resolution;
|
||||
struct {
|
||||
char * name;
|
||||
Uint32 flags;
|
||||
Uint32 size;
|
||||
char * data;
|
||||
} parasite;
|
||||
} data;
|
||||
} xcf_prop;
|
||||
|
||||
typedef struct {
|
||||
char sign [14];
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 image_type;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 * layer_file_offsets;
|
||||
Uint32 * channel_file_offsets;
|
||||
|
||||
xcf_compr_type compr;
|
||||
Uint32 cm_num;
|
||||
unsigned char * cm_map;
|
||||
} xcf_header;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 layer_type;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
Uint32 layer_mask_offset;
|
||||
|
||||
Uint32 offset_x;
|
||||
Uint32 offset_y;
|
||||
int visible;
|
||||
} xcf_layer;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
|
||||
Uint32 color;
|
||||
Uint32 opacity;
|
||||
int selection;
|
||||
int visible;
|
||||
} xcf_channel;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Uint32 bpp;
|
||||
|
||||
Uint32 * level_file_offsets;
|
||||
} xcf_hierarchy;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
|
||||
Uint32 * tile_file_offsets;
|
||||
} xcf_level;
|
||||
|
||||
typedef unsigned char * xcf_tile;
|
||||
|
||||
typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XCF;
|
||||
char magic[14];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XCF = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if (strncmp(magic, "gimp xcf ", 9) == 0) {
|
||||
is_XCF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XCF);
|
||||
}
|
||||
|
||||
static char * read_string (SDL_RWops * src) {
|
||||
Uint32 tmp;
|
||||
char * data;
|
||||
|
||||
tmp = SDL_ReadBE32 (src);
|
||||
if (tmp > 0) {
|
||||
data = (char *) malloc (sizeof (char) * tmp);
|
||||
SDL_RWread (src, data, tmp, 1);
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static Uint32 Swap32 (Uint32 v) {
|
||||
return
|
||||
((v & 0x000000FF) << 16)
|
||||
| ((v & 0x0000FF00))
|
||||
| ((v & 0x00FF0000) >> 16)
|
||||
| ((v & 0xFF000000));
|
||||
}
|
||||
|
||||
static void xcf_read_property (SDL_RWops * src, xcf_prop * prop) {
|
||||
prop->id = SDL_ReadBE32 (src);
|
||||
prop->length = SDL_ReadBE32 (src);
|
||||
|
||||
#if DEBUG
|
||||
printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length);
|
||||
#endif
|
||||
|
||||
switch (prop->id) {
|
||||
case PROP_COLORMAP:
|
||||
prop->data.colormap.num = SDL_ReadBE32 (src);
|
||||
prop->data.colormap.cmap = (char *) malloc (sizeof (char) * prop->data.colormap.num * 3);
|
||||
SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1);
|
||||
break;
|
||||
|
||||
case PROP_OFFSETS:
|
||||
prop->data.offset.x = SDL_ReadBE32 (src);
|
||||
prop->data.offset.y = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_OPACITY:
|
||||
prop->data.opacity = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_COMPRESSION:
|
||||
case PROP_COLOR:
|
||||
SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
prop->data.visible = SDL_ReadBE32 (src);
|
||||
break;
|
||||
default:
|
||||
// SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
SDL_RWseek (src, prop->length, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_xcf_header (xcf_header * h) {
|
||||
if (h->cm_num)
|
||||
free (h->cm_map);
|
||||
|
||||
free (h);
|
||||
}
|
||||
|
||||
static xcf_header * read_xcf_header (SDL_RWops * src) {
|
||||
xcf_header * h;
|
||||
xcf_prop prop;
|
||||
|
||||
h = (xcf_header *) malloc (sizeof (xcf_header));
|
||||
SDL_RWread (src, h->sign, 14, 1);
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->image_type = SDL_ReadBE32 (src);
|
||||
|
||||
h->properties = NULL;
|
||||
h->compr = COMPR_NONE;
|
||||
h->cm_num = 0;
|
||||
h->cm_map = NULL;
|
||||
|
||||
// Just read, don't save
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_COMPRESSION)
|
||||
h->compr = prop.data.compression;
|
||||
else if (prop.id == PROP_COLORMAP) {
|
||||
// unused var: int i;
|
||||
|
||||
h->cm_num = prop.data.colormap.num;
|
||||
h->cm_map = (unsigned char *) malloc (sizeof (unsigned char) * 3 * h->cm_num);
|
||||
memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num);
|
||||
free (prop.data.colormap.cmap);
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_layer (xcf_layer * l) {
|
||||
free (l->name);
|
||||
free (l);
|
||||
}
|
||||
|
||||
static xcf_layer * read_xcf_layer (SDL_RWops * src) {
|
||||
xcf_layer * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_layer *) malloc (sizeof (xcf_layer));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
l->layer_type = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_OFFSETS) {
|
||||
l->offset_x = prop.data.offset.x;
|
||||
l->offset_y = prop.data.offset.y;
|
||||
} else if (prop.id == PROP_VISIBLE) {
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
l->layer_mask_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_channel (xcf_channel * c) {
|
||||
free (c->name);
|
||||
free (c);
|
||||
}
|
||||
|
||||
static xcf_channel * read_xcf_channel (SDL_RWops * src) {
|
||||
xcf_channel * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_channel *) malloc (sizeof (xcf_channel));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
l->selection = 0;
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
switch (prop.id) {
|
||||
case PROP_OPACITY:
|
||||
l->opacity = prop.data.opacity << 24;
|
||||
break;
|
||||
case PROP_COLOR:
|
||||
l->color = ((Uint32) prop.data.color[0] << 16)
|
||||
| ((Uint32) prop.data.color[1] << 8)
|
||||
| ((Uint32) prop.data.color[2]);
|
||||
break;
|
||||
case PROP_SELECTION:
|
||||
l->selection = 1;
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_hierarchy (xcf_hierarchy * h) {
|
||||
free (h->level_file_offsets);
|
||||
free (h);
|
||||
}
|
||||
|
||||
static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) {
|
||||
xcf_hierarchy * h;
|
||||
int i;
|
||||
|
||||
h = (xcf_hierarchy *) malloc (sizeof (xcf_hierarchy));
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->bpp = SDL_ReadBE32 (src);
|
||||
|
||||
h->level_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1));
|
||||
h->level_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (h->level_file_offsets [i++]);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_level (xcf_level * l) {
|
||||
free (l->tile_file_offsets);
|
||||
free (l);
|
||||
}
|
||||
|
||||
static xcf_level * read_xcf_level (SDL_RWops * src) {
|
||||
xcf_level * l;
|
||||
int i;
|
||||
|
||||
l = (xcf_level *) malloc (sizeof (xcf_level));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->tile_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1));
|
||||
l->tile_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (l->tile_file_offsets [i++]);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_tile (unsigned char * t) {
|
||||
free (t);
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load;
|
||||
|
||||
load = (unsigned char *) malloc (len); // expect this is okay
|
||||
SDL_RWread (src, load, len, 1);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load, * t, * data, * d;
|
||||
Uint32 reallen;
|
||||
int i, size, count, j, length;
|
||||
unsigned char val;
|
||||
|
||||
t = load = (unsigned char *) malloc (len);
|
||||
reallen = SDL_RWread (src, t, 1, len);
|
||||
|
||||
data = (unsigned char *) malloc (x*y*bpp);
|
||||
for (i = 0; i < bpp; i++) {
|
||||
d = data + i;
|
||||
size = x*y;
|
||||
count = 0;
|
||||
|
||||
while (size > 0) {
|
||||
val = *t++;
|
||||
|
||||
length = val;
|
||||
if (length >= 128) {
|
||||
length = 255 - (length - 1);
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
while (length-- > 0) {
|
||||
*d = *t++;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
length += 1;
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
val = *t++;
|
||||
|
||||
for (j = 0; j < length; j++) {
|
||||
*d = val;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (load);
|
||||
return (data);
|
||||
}
|
||||
|
||||
static Uint32 rgb2grey (Uint32 a) {
|
||||
Uint8 l;
|
||||
l = 0.2990 * ((a && 0x00FF0000) >> 16)
|
||||
+ 0.5870 * ((a && 0x0000FF00) >> 8)
|
||||
+ 0.1140 * ((a && 0x000000FF));
|
||||
|
||||
return (l << 16) | (l << 8) | l;
|
||||
}
|
||||
|
||||
static void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) {
|
||||
Uint32 c = 0;
|
||||
|
||||
switch (itype) {
|
||||
case IMAGE_RGB:
|
||||
case IMAGE_INDEXED:
|
||||
c = opacity | color;
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
c = opacity | rgb2grey (color);
|
||||
break;
|
||||
}
|
||||
SDL_FillRect (surf, NULL, c);
|
||||
}
|
||||
|
||||
static int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) {
|
||||
xcf_hierarchy * hierarchy;
|
||||
xcf_level * level;
|
||||
unsigned char * tile;
|
||||
Uint8 * p8;
|
||||
Uint16 * p16;
|
||||
Uint32 * p;
|
||||
int x, y, tx, ty, ox, oy, i, j;
|
||||
Uint32 *row;
|
||||
|
||||
SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET);
|
||||
hierarchy = read_xcf_hierarchy (src);
|
||||
|
||||
level = NULL;
|
||||
for (i = 0; hierarchy->level_file_offsets [i]; i++) {
|
||||
SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET);
|
||||
level = read_xcf_level (src);
|
||||
|
||||
ty = tx = 0;
|
||||
for (j = 0; level->tile_file_offsets [j]; j++) {
|
||||
SDL_RWseek (src, level->tile_file_offsets [j], RW_SEEK_SET);
|
||||
ox = tx+64 > level->width ? level->width % 64 : 64;
|
||||
oy = ty+64 > level->height ? level->height % 64 : 64;
|
||||
|
||||
if (level->tile_file_offsets [j+1]) {
|
||||
tile = load_tile
|
||||
(src,
|
||||
level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
else {
|
||||
tile = load_tile
|
||||
(src,
|
||||
ox*oy*6,
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
|
||||
p8 = tile;
|
||||
p16 = (Uint16 *) p8;
|
||||
p = (Uint32 *) p8;
|
||||
for (y=ty; y < ty+oy; y++) {
|
||||
row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4);
|
||||
switch (hierarchy->bpp) {
|
||||
case 4:
|
||||
for (x=tx; x < tx+ox; x++)
|
||||
*row++ = Swap32 (*p++);
|
||||
break;
|
||||
case 3:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = 0xFF000000;
|
||||
*row |= ((Uint32) *(p8++) << 16);
|
||||
*row |= ((Uint32) *(p8++) << 8);
|
||||
*row |= ((Uint32) *(p8++) << 0);
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case 2: // Indexed/Greyscale + Alpha
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) (head->cm_map [*p8*3]) << 16);
|
||||
*row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8);
|
||||
*row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) *p8 << 16);
|
||||
*row |= ((Uint32) *p8 << 8);
|
||||
*row |= ((Uint32) *p8++ << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 1: // Indexed/Greyscale
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x = tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| ((Uint32) (head->cm_map [*p8*3]) << 16)
|
||||
| ((Uint32) (head->cm_map [*p8*3+1]) << 8)
|
||||
| ((Uint32) (head->cm_map [*p8*3+2]) << 0);
|
||||
p8++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| (((Uint32) (*p8)) << 16)
|
||||
| (((Uint32) (*p8)) << 8)
|
||||
| (((Uint32) (*p8)) << 0);
|
||||
++p8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
tx += 64;
|
||||
if (tx >= level->width) {
|
||||
tx = 0;
|
||||
ty += 64;
|
||||
}
|
||||
if (ty >= level->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
free_xcf_tile (tile);
|
||||
}
|
||||
free_xcf_level (level);
|
||||
}
|
||||
|
||||
free_xcf_hierarchy (hierarchy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface, *lays;
|
||||
xcf_header * head;
|
||||
xcf_layer * layer;
|
||||
xcf_channel ** channel;
|
||||
int chnls, i, offsets;
|
||||
Uint32 offset, fp;
|
||||
|
||||
unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Initialize the data we will clean up when we're done */
|
||||
surface = NULL;
|
||||
|
||||
head = read_xcf_header (src);
|
||||
|
||||
switch (head->compr) {
|
||||
case COMPR_NONE:
|
||||
load_tile = load_xcf_tile_none;
|
||||
break;
|
||||
case COMPR_RLE:
|
||||
load_tile = load_xcf_tile_rle;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unsupported Compression.\n");
|
||||
free_xcf_header (head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the surface of the appropriate type */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
head->layer_file_offsets = NULL;
|
||||
offsets = 0;
|
||||
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
|
||||
head->layer_file_offsets [offsets] = offset;
|
||||
offsets++;
|
||||
}
|
||||
fp = SDL_RWtell (src);
|
||||
|
||||
lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( lays == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Blit layers backwards, because Gimp saves them highest first
|
||||
for (i = offsets; i > 0; i--) {
|
||||
SDL_Rect rs, rd;
|
||||
SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET);
|
||||
|
||||
layer = read_xcf_layer (src);
|
||||
do_layer_surface (lays, src, head, layer, load_tile);
|
||||
rs.x = 0;
|
||||
rs.y = 0;
|
||||
rs.w = layer->width;
|
||||
rs.h = layer->height;
|
||||
rd.x = layer->offset_x;
|
||||
rd.y = layer->offset_y;
|
||||
rd.w = layer->width;
|
||||
rd.h = layer->height;
|
||||
|
||||
if (layer->visible)
|
||||
SDL_BlitSurface (lays, &rs, surface, &rd);
|
||||
free_xcf_layer (layer);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (lays);
|
||||
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
|
||||
// read channels
|
||||
channel = NULL;
|
||||
chnls = 0;
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1));
|
||||
fp = SDL_RWtell (src);
|
||||
SDL_RWseek (src, offset, RW_SEEK_SET);
|
||||
channel [chnls++] = (read_xcf_channel (src));
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if (chnls) {
|
||||
SDL_Surface * chs;
|
||||
|
||||
chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if (chs == NULL) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < chnls; i++) {
|
||||
// printf ("CNLBLT %i\n", i);
|
||||
if (!channel [i]->selection && channel [i]->visible) {
|
||||
create_channel_surface (chs, head->image_type, channel [i]->color, channel [i]->opacity);
|
||||
SDL_BlitSurface (chs, NULL, surface, NULL);
|
||||
}
|
||||
free_xcf_channel (channel [i]);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (chs);
|
||||
}
|
||||
|
||||
done:
|
||||
free_xcf_header (head);
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XCF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XCF */
|
||||
514
apps/plugins/sdl/SDL_image/IMG_xpm.c
Normal file
514
apps/plugins/sdl/SDL_image/IMG_xpm.c
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XPM (X PixMap) image loader:
|
||||
*
|
||||
* Supports the XPMv3 format, EXCEPT:
|
||||
* - hotspot coordinates are ignored
|
||||
* - only colour ('c') colour symbols are used
|
||||
* - rgb.txt is not used (for portability), so only RGB colours
|
||||
* are recognized (#rrggbb etc) - only a few basic colour names are
|
||||
* handled
|
||||
*
|
||||
* The result is an 8bpp indexed surface if possible, otherwise 32bpp.
|
||||
* The colourkey is correctly set if transparency is used.
|
||||
*
|
||||
* Besides the standard API, also provides
|
||||
*
|
||||
* SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
|
||||
*
|
||||
* that reads the image data from an XPM file included in the C source.
|
||||
*
|
||||
* TODO: include rgb.txt here. The full table (from solaris 2.6) only
|
||||
* requires about 13K in binary form.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XPM
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXPM(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XPM;
|
||||
char magic[9];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XPM = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if ( memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
|
||||
is_XPM = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XPM);
|
||||
}
|
||||
|
||||
/* Hash table to look up colors from pixel strings */
|
||||
#define STARTING_HASH_SIZE 256
|
||||
|
||||
struct hash_entry {
|
||||
char *key;
|
||||
Uint32 color;
|
||||
struct hash_entry *next;
|
||||
};
|
||||
|
||||
struct color_hash {
|
||||
struct hash_entry **table;
|
||||
struct hash_entry *entries; /* array of all entries */
|
||||
struct hash_entry *next_free;
|
||||
int size;
|
||||
int maxnum;
|
||||
};
|
||||
|
||||
static int hash_key(const char *key, int cpp, int size)
|
||||
{
|
||||
int hash;
|
||||
|
||||
hash = 0;
|
||||
while ( cpp-- > 0 ) {
|
||||
hash = hash * 33 + *key++;
|
||||
}
|
||||
return hash & (size - 1);
|
||||
}
|
||||
|
||||
static struct color_hash *create_colorhash(int maxnum)
|
||||
{
|
||||
int bytes, s;
|
||||
struct color_hash *hash;
|
||||
|
||||
/* we know how many entries we need, so we can allocate
|
||||
everything here */
|
||||
hash = malloc(sizeof *hash);
|
||||
if(!hash)
|
||||
return NULL;
|
||||
|
||||
/* use power-of-2 sized hash table for decoding speed */
|
||||
for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
|
||||
;
|
||||
hash->size = s;
|
||||
hash->maxnum = maxnum;
|
||||
bytes = hash->size * sizeof(struct hash_entry **);
|
||||
hash->entries = NULL; /* in case malloc fails */
|
||||
hash->table = malloc(bytes);
|
||||
if(!hash->table)
|
||||
return NULL;
|
||||
memset(hash->table, 0, bytes);
|
||||
hash->entries = malloc(maxnum * sizeof(struct hash_entry));
|
||||
if(!hash->entries) {
|
||||
free(hash->table);
|
||||
return NULL;
|
||||
}
|
||||
hash->next_free = hash->entries;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static int add_colorhash(struct color_hash *hash,
|
||||
char *key, int cpp, Uint32 color)
|
||||
{
|
||||
int index = hash_key(key, cpp, hash->size);
|
||||
struct hash_entry *e = hash->next_free++;
|
||||
e->color = color;
|
||||
e->key = key;
|
||||
e->next = hash->table[index];
|
||||
hash->table[index] = e;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* fast lookup that works if cpp == 1 */
|
||||
#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
|
||||
|
||||
static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
|
||||
{
|
||||
struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
|
||||
while(entry) {
|
||||
if(memcmp(key, entry->key, cpp) == 0)
|
||||
return entry->color;
|
||||
entry = entry->next;
|
||||
}
|
||||
return 0; /* garbage in - garbage out */
|
||||
}
|
||||
|
||||
static void free_colorhash(struct color_hash *hash)
|
||||
{
|
||||
if(hash && hash->table) {
|
||||
free(hash->table);
|
||||
free(hash->entries);
|
||||
free(hash);
|
||||
}
|
||||
}
|
||||
|
||||
/* portable case-insensitive string comparison */
|
||||
static int string_equal(const char *a, const char *b, int n)
|
||||
{
|
||||
while(*a && *b && n) {
|
||||
if(toupper((unsigned char)*a) != toupper((unsigned char)*b))
|
||||
return 0;
|
||||
a++;
|
||||
b++;
|
||||
n--;
|
||||
}
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
#define ARRAYSIZE(a) (int)(sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/*
|
||||
* convert colour spec to RGB (in 0xrrggbb format).
|
||||
* return 1 if successful.
|
||||
*/
|
||||
static int color_to_rgb(char *spec, int speclen, Uint32 *rgb)
|
||||
{
|
||||
/* poor man's rgb.txt */
|
||||
static struct { char *name; Uint32 rgb; } known[] = {
|
||||
{"none", 0xffffffff},
|
||||
{"black", 0x00000000},
|
||||
{"white", 0x00ffffff},
|
||||
{"red", 0x00ff0000},
|
||||
{"green", 0x0000ff00},
|
||||
{"blue", 0x000000ff}
|
||||
};
|
||||
|
||||
if(spec[0] == '#') {
|
||||
char buf[7];
|
||||
switch(speclen) {
|
||||
case 4:
|
||||
buf[0] = buf[1] = spec[1];
|
||||
buf[2] = buf[3] = spec[2];
|
||||
buf[4] = buf[5] = spec[3];
|
||||
break;
|
||||
case 7:
|
||||
memcpy(buf, spec + 1, 6);
|
||||
break;
|
||||
case 13:
|
||||
buf[0] = spec[1];
|
||||
buf[1] = spec[2];
|
||||
buf[2] = spec[5];
|
||||
buf[3] = spec[6];
|
||||
buf[4] = spec[9];
|
||||
buf[5] = spec[10];
|
||||
break;
|
||||
}
|
||||
buf[6] = '\0';
|
||||
*rgb = strtol(buf, NULL, 16);
|
||||
return 1;
|
||||
} else {
|
||||
int i;
|
||||
for(i = 0; i < ARRAYSIZE(known); i++)
|
||||
if(string_equal(known[i].name, spec, speclen)) {
|
||||
*rgb = known[i].rgb;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static char *linebuf;
|
||||
static int buflen;
|
||||
static char *error;
|
||||
|
||||
/*
|
||||
* Read next line from the source.
|
||||
* If len > 0, it's assumed to be at least len chars (for efficiency).
|
||||
* Return NULL and set error upon EOF or parse error.
|
||||
*/
|
||||
static char *get_next_line(char ***lines, SDL_RWops *src, int len)
|
||||
{
|
||||
char *linebufnew;
|
||||
|
||||
if(lines) {
|
||||
return *(*lines)++;
|
||||
} else {
|
||||
char c;
|
||||
int n;
|
||||
do {
|
||||
if(SDL_RWread(src, &c, 1, 1) <= 0) {
|
||||
error = "Premature end of data";
|
||||
return NULL;
|
||||
}
|
||||
} while(c != '"');
|
||||
if(len) {
|
||||
len += 4; /* "\",\n\0" */
|
||||
if(len > buflen){
|
||||
buflen = len;
|
||||
linebufnew = realloc(linebuf, buflen);
|
||||
if(!linebufnew) {
|
||||
free(linebuf);
|
||||
error = "Out of memory";
|
||||
return NULL;
|
||||
}
|
||||
linebuf = linebufnew;
|
||||
}
|
||||
if(SDL_RWread(src, linebuf, len - 1, 1) <= 0) {
|
||||
error = "Premature end of data";
|
||||
return NULL;
|
||||
}
|
||||
n = len - 2;
|
||||
} else {
|
||||
n = 0;
|
||||
do {
|
||||
if(n >= buflen - 1) {
|
||||
if(buflen == 0)
|
||||
buflen = 16;
|
||||
buflen *= 2;
|
||||
linebufnew = realloc(linebuf, buflen);
|
||||
if(!linebufnew) {
|
||||
free(linebuf);
|
||||
error = "Out of memory";
|
||||
return NULL;
|
||||
}
|
||||
linebuf = linebufnew;
|
||||
}
|
||||
if(SDL_RWread(src, linebuf + n, 1, 1) <= 0) {
|
||||
error = "Premature end of data";
|
||||
return NULL;
|
||||
}
|
||||
} while(linebuf[n++] != '"');
|
||||
n--;
|
||||
}
|
||||
linebuf[n] = '\0';
|
||||
return linebuf;
|
||||
}
|
||||
}
|
||||
|
||||
#define SKIPSPACE(p) \
|
||||
do { \
|
||||
while(isspace((unsigned char)*(p))) \
|
||||
++(p); \
|
||||
} while(0)
|
||||
|
||||
#define SKIPNONSPACE(p) \
|
||||
do { \
|
||||
while(!isspace((unsigned char)*(p)) && *p) \
|
||||
++(p); \
|
||||
} while(0)
|
||||
|
||||
/* read XPM from either array or RWops */
|
||||
static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
|
||||
{
|
||||
int start = 0;
|
||||
SDL_Surface *image = NULL;
|
||||
int index;
|
||||
int x, y;
|
||||
int w, h, ncolors, cpp;
|
||||
int indexed;
|
||||
Uint8 *dst;
|
||||
struct color_hash *colors = NULL;
|
||||
SDL_Color *im_colors = NULL;
|
||||
char *keystrings = NULL, *nextkey;
|
||||
char *line;
|
||||
char ***xpmlines = NULL;
|
||||
int pixels_len;
|
||||
|
||||
error = NULL;
|
||||
linebuf = NULL;
|
||||
buflen = 0;
|
||||
|
||||
if ( src )
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if(xpm)
|
||||
xpmlines = &xpm;
|
||||
|
||||
line = get_next_line(xpmlines, src, 0);
|
||||
if(!line)
|
||||
goto done;
|
||||
/*
|
||||
* The header string of an XPMv3 image has the format
|
||||
*
|
||||
* <width> <height> <ncolors> <cpp> [ <hotspot_x> <hotspot_y> ]
|
||||
*
|
||||
* where the hotspot coords are intended for mouse cursors.
|
||||
* Right now we don't use the hotspots but it should be handled
|
||||
* one day.
|
||||
*/
|
||||
if(sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
|
||||
|| w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
|
||||
error = "Invalid format description";
|
||||
goto done;
|
||||
}
|
||||
|
||||
keystrings = malloc(ncolors * cpp);
|
||||
if(!keystrings) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
nextkey = keystrings;
|
||||
|
||||
/* Create the new surface */
|
||||
if(ncolors <= 256) {
|
||||
indexed = 1;
|
||||
image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8,
|
||||
0, 0, 0, 0);
|
||||
im_colors = image->format->palette->colors;
|
||||
image->format->palette->ncolors = ncolors;
|
||||
} else {
|
||||
indexed = 0;
|
||||
image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
|
||||
0xff0000, 0x00ff00, 0x0000ff, 0);
|
||||
}
|
||||
if(!image) {
|
||||
/* Hmm, some SDL error (out of memory?) */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the colors */
|
||||
colors = create_colorhash(ncolors);
|
||||
if (!colors) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for(index = 0; index < ncolors; ++index ) {
|
||||
char *p;
|
||||
line = get_next_line(xpmlines, src, 0);
|
||||
if(!line)
|
||||
goto done;
|
||||
|
||||
p = line + cpp + 1;
|
||||
|
||||
/* parse a colour definition */
|
||||
for(;;) {
|
||||
char nametype;
|
||||
char *colname;
|
||||
Uint32 rgb, pixel;
|
||||
|
||||
SKIPSPACE(p);
|
||||
if(!*p) {
|
||||
error = "colour parse error";
|
||||
goto done;
|
||||
}
|
||||
nametype = *p;
|
||||
SKIPNONSPACE(p);
|
||||
SKIPSPACE(p);
|
||||
colname = p;
|
||||
SKIPNONSPACE(p);
|
||||
if(nametype == 's')
|
||||
continue; /* skip symbolic colour names */
|
||||
|
||||
if(!color_to_rgb(colname, p - colname, &rgb))
|
||||
continue;
|
||||
|
||||
memcpy(nextkey, line, cpp);
|
||||
if(indexed) {
|
||||
SDL_Color *c = im_colors + index;
|
||||
c->r = (Uint8)(rgb >> 16);
|
||||
c->g = (Uint8)(rgb >> 8);
|
||||
c->b = (Uint8)(rgb);
|
||||
pixel = index;
|
||||
} else
|
||||
pixel = rgb;
|
||||
add_colorhash(colors, nextkey, cpp, pixel);
|
||||
nextkey += cpp;
|
||||
if(rgb == 0xffffffff)
|
||||
SDL_SetColorKey(image, SDL_SRCCOLORKEY, pixel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the pixels */
|
||||
pixels_len = w * cpp;
|
||||
dst = image->pixels;
|
||||
for(y = 0; y < h; y++) {
|
||||
line = get_next_line(xpmlines, src, pixels_len);
|
||||
if(indexed) {
|
||||
/* optimization for some common cases */
|
||||
if(cpp == 1)
|
||||
for(x = 0; x < w; x++)
|
||||
dst[x] = (Uint8)QUICK_COLORHASH(colors,
|
||||
line + x);
|
||||
else
|
||||
for(x = 0; x < w; x++)
|
||||
dst[x] = (Uint8)get_colorhash(colors,
|
||||
line + x * cpp,
|
||||
cpp);
|
||||
} else {
|
||||
for (x = 0; x < w; x++)
|
||||
((Uint32*)dst)[x] = get_colorhash(colors,
|
||||
line + x * cpp,
|
||||
cpp);
|
||||
}
|
||||
dst += image->pitch;
|
||||
}
|
||||
|
||||
done:
|
||||
if(error) {
|
||||
if ( src )
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( image ) {
|
||||
SDL_FreeSurface(image);
|
||||
image = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
free(keystrings);
|
||||
free_colorhash(colors);
|
||||
free(linebuf);
|
||||
return(image);
|
||||
}
|
||||
|
||||
/* Load a XPM type image from an RWops datasource */
|
||||
SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
|
||||
{
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
return load_xpm(NULL, src);
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
|
||||
{
|
||||
return load_xpm(xpm, NULL);
|
||||
}
|
||||
|
||||
#else /* not LOAD_XPM */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXPM(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Load a XPM type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* not LOAD_XPM */
|
||||
165
apps/plugins/sdl/SDL_image/IMG_xv.c
Normal file
165
apps/plugins/sdl/SDL_image/IMG_xv.c
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a XV thumbnail image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XV
|
||||
|
||||
static int get_line(SDL_RWops *src, char *line, int size)
|
||||
{
|
||||
while ( size > 0 ) {
|
||||
if ( SDL_RWread(src, line, 1, 1) <= 0 ) {
|
||||
return -1;
|
||||
}
|
||||
if ( *line == '\r' ) {
|
||||
continue;
|
||||
}
|
||||
if ( *line == '\n' ) {
|
||||
*line = '\0';
|
||||
return 0;
|
||||
}
|
||||
++line;
|
||||
--size;
|
||||
}
|
||||
/* Out of space for the line */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_header(SDL_RWops *src, int *w, int *h)
|
||||
{
|
||||
char line[1024];
|
||||
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
|
||||
/* Check the header magic */
|
||||
if ( (get_line(src, line, sizeof(line)) < 0) ||
|
||||
(memcmp(line, "P7 332", 6) != 0) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the header */
|
||||
while ( get_line(src, line, sizeof(line)) == 0 ) {
|
||||
if ( memcmp(line, "#BUILTIN:", 9) == 0 ) {
|
||||
/* Builtin image, no data */
|
||||
break;
|
||||
}
|
||||
if ( memcmp(line, "#END_OF_COMMENTS", 16) == 0 ) {
|
||||
if ( get_line(src, line, sizeof(line)) == 0 ) {
|
||||
sscanf(line, "%d %d", w, h);
|
||||
if ( *w >= 0 && *h >= 0 ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* No image data */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXV(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XV;
|
||||
int w, h;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XV = 0;
|
||||
if ( get_header(src, &w, &h) == 0 ) {
|
||||
is_XV = 1;
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XV);
|
||||
}
|
||||
|
||||
/* Load a XV thumbnail image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface = NULL;
|
||||
int w, h;
|
||||
Uint8 *pixels;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Read the header */
|
||||
if ( get_header(src, &w, &h) < 0 ) {
|
||||
error = "Unsupported image format";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create the 3-3-2 indexed palette surface */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0xe0, 0x1c, 0x03, 0);
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the image data */
|
||||
for ( pixels = (Uint8 *)surface->pixels; h > 0; --h ) {
|
||||
if ( SDL_RWread(src, pixels, w, 1) <= 0 ) {
|
||||
error = "Couldn't read image data";
|
||||
goto done;
|
||||
}
|
||||
pixels += surface->pitch;
|
||||
}
|
||||
|
||||
done:
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXV(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XV */
|
||||
87
apps/plugins/sdl/SDL_image/IMG_xxx.c
Normal file
87
apps/plugins/sdl/SDL_image/IMG_xxx.c
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a generic "format not supported" image framework */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XXX
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXXX(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XXX;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XXX = 0;
|
||||
|
||||
/* Detect the image here */
|
||||
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XXX);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface = NULL;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Load the image here */
|
||||
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXXX(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XXX */
|
||||
40
apps/plugins/sdl/SDL_image/README
Normal file
40
apps/plugins/sdl/SDL_image/README
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
SDL_image 1.2
|
||||
|
||||
The latest version of this library is available from:
|
||||
http://www.libsdl.org/projects/SDL_image/
|
||||
|
||||
This is a simple library to load images of various formats as SDL surfaces.
|
||||
This library supports BMP, PNM (PPM/PGM/PBM), XPM, LBM, PCX, GIF, JPEG, PNG,
|
||||
TGA, and TIFF formats.
|
||||
|
||||
API:
|
||||
#include "SDL_image.h"
|
||||
|
||||
SDL_Surface *IMG_Load(const char *file);
|
||||
or
|
||||
SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc);
|
||||
or
|
||||
SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type);
|
||||
|
||||
where type is a string specifying the format (i.e. "PNG" or "pcx").
|
||||
Note that IMG_Load_RW cannot load TGA images.
|
||||
|
||||
To create a surface from an XPM image included in C source, use:
|
||||
|
||||
SDL_Surface *IMG_ReadXPMFromArray(char **xpm);
|
||||
|
||||
An example program 'showimage' is included, with source in showimage.c
|
||||
|
||||
JPEG support requires the JPEG library: http://www.ijg.org/
|
||||
PNG support requires the PNG library: http://www.libpng.org/pub/png/libpng.html
|
||||
and the Zlib library: http://www.gzip.org/zlib/
|
||||
TIFF support requires the TIFF library: ftp://ftp.sgi.com/graphics/tiff/
|
||||
|
||||
If you have these libraries installed in non-standard places, you can
|
||||
try adding those paths to the configure script, e.g.
|
||||
sh ./configure CPPFLAGS="-I/somewhere/include" LDFLAGS="-L/somewhere/lib"
|
||||
If this works, you may need to add /somewhere/lib to your LD_LIBRARY_PATH
|
||||
so shared library loading works correctly.
|
||||
|
||||
This library is under the zlib License, see the file "COPYING" for details.
|
||||
216
apps/plugins/sdl/SDL_image/showimage.c
Normal file
216
apps/plugins/sdl/SDL_image/showimage.c
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
showimage: A test application for the SDL image loading library.
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
/* #define XPM_INCLUDED and supply picture.xpm to test the XPM inclusion
|
||||
feature */
|
||||
|
||||
#ifdef XPM_INCLUDED
|
||||
#include "picture.xpm"
|
||||
#endif
|
||||
|
||||
/* Draw a Gimpish background pattern to show transparency in the image */
|
||||
static void draw_background(SDL_Surface *screen)
|
||||
{
|
||||
Uint8 *dst = screen->pixels;
|
||||
int x, y;
|
||||
int bpp = screen->format->BytesPerPixel;
|
||||
Uint32 col[2];
|
||||
col[0] = SDL_MapRGB(screen->format, 0x66, 0x66, 0x66);
|
||||
col[1] = SDL_MapRGB(screen->format, 0x99, 0x99, 0x99);
|
||||
for(y = 0; y < screen->h; y++) {
|
||||
for(x = 0; x < screen->w; x++) {
|
||||
/* use an 8x8 checkerboard pattern */
|
||||
Uint32 c = col[((x ^ y) >> 3) & 1];
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
dst[x] = (Uint8)c;
|
||||
break;
|
||||
case 2:
|
||||
((Uint16 *)dst)[x] = (Uint16)c;
|
||||
break;
|
||||
case 3:
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
dst[x * 3] = (Uint8)(c);
|
||||
dst[x * 3 + 1] = (Uint8)(c >> 8);
|
||||
dst[x * 3 + 2] = (Uint8)(c >> 16);
|
||||
#else
|
||||
dst[x * 3] = (Uint8)(c >> 16);
|
||||
dst[x * 3 + 1] = (Uint8)(c >> 8);
|
||||
dst[x * 3 + 2] = (Uint8)(c);
|
||||
#endif
|
||||
break;
|
||||
case 4:
|
||||
((Uint32 *)dst)[x] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dst += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Uint32 flags;
|
||||
SDL_Surface *screen, *image;
|
||||
int i, depth, done;
|
||||
SDL_Event event;
|
||||
#if 0
|
||||
SDL_RWops* rw_ops;
|
||||
#endif
|
||||
|
||||
/* Check command line usage */
|
||||
if ( ! argv[1] ) {
|
||||
fprintf(stderr, "Usage: %s <image_file>\n", argv[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Initialize the SDL library */
|
||||
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
|
||||
return(255);
|
||||
}
|
||||
|
||||
flags = SDL_SWSURFACE;
|
||||
for ( i=1; argv[i]; ++i ) {
|
||||
if ( strcmp(argv[i], "-fullscreen") == 0 ) {
|
||||
SDL_ShowCursor(0);
|
||||
flags |= SDL_FULLSCREEN;
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
rw_ops = SDL_RWFromFile(argv[1], "r");
|
||||
|
||||
fprintf(stderr, "BMP:\t%d\n", IMG_isBMP(rw_ops));
|
||||
fprintf(stderr, "GIF:\t%d\n", IMG_isGIF(rw_ops));
|
||||
fprintf(stderr, "JPG:\t%d\n", IMG_isJPG(rw_ops));
|
||||
fprintf(stderr, "PNG:\t%d\n", IMG_isPNG(rw_ops));
|
||||
fprintf(stderr, "TIF:\t%d\n", IMG_isTIF(rw_ops));
|
||||
/* fprintf(stderr, "TGA:\t%d\n", IMG_isTGA(rw_ops)); */
|
||||
fprintf(stderr, "PCX:\t%d\n", IMG_isPCX(rw_ops));
|
||||
#endif
|
||||
|
||||
/* Open the image file */
|
||||
#ifdef XPM_INCLUDED
|
||||
image = IMG_ReadXPMFromArray(picture_xpm);
|
||||
#else
|
||||
image = IMG_Load(argv[i]);
|
||||
#endif
|
||||
if ( image == NULL ) {
|
||||
fprintf(stderr, "Couldn't load %s: %s\n",
|
||||
argv[i], SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
SDL_WM_SetCaption(argv[i], "showimage");
|
||||
|
||||
/* Create a display for the image */
|
||||
depth = SDL_VideoModeOK(image->w, image->h, 32, flags);
|
||||
/* Use the deepest native mode, except that we emulate 32bpp
|
||||
for viewing non-indexed images on 8bpp screens */
|
||||
if ( depth == 0 ) {
|
||||
if ( image->format->BytesPerPixel > 1 ) {
|
||||
depth = 32;
|
||||
} else {
|
||||
depth = 8;
|
||||
}
|
||||
} else
|
||||
if ( (image->format->BytesPerPixel > 1) && (depth == 8) ) {
|
||||
depth = 32;
|
||||
}
|
||||
if(depth == 8)
|
||||
flags |= SDL_HWPALETTE;
|
||||
screen = SDL_SetVideoMode(image->w, image->h, depth, flags);
|
||||
if ( screen == NULL ) {
|
||||
fprintf(stderr,"Couldn't set %dx%dx%d video mode: %s\n",
|
||||
image->w, image->h, depth, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the palette, if one exists */
|
||||
if ( image->format->palette ) {
|
||||
SDL_SetColors(screen, image->format->palette->colors,
|
||||
0, image->format->palette->ncolors);
|
||||
}
|
||||
|
||||
/* Draw a background pattern if the surface has transparency */
|
||||
if(image->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY))
|
||||
draw_background(screen);
|
||||
|
||||
/* Display the image */
|
||||
SDL_BlitSurface(image, NULL, screen, NULL);
|
||||
SDL_UpdateRect(screen, 0, 0, 0, 0);
|
||||
|
||||
done = 0;
|
||||
while ( ! done ) {
|
||||
if ( SDL_PollEvent(&event) ) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYUP:
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_LEFT:
|
||||
if ( i > 1 ) {
|
||||
i -= 2;
|
||||
done = 1;
|
||||
}
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if ( argv[i+1] ) {
|
||||
done = 1;
|
||||
}
|
||||
break;
|
||||
case SDLK_ESCAPE:
|
||||
case SDLK_q:
|
||||
argv[i+1] = NULL;
|
||||
/* Drop through to done */
|
||||
case SDLK_SPACE:
|
||||
case SDLK_TAB:
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
done = 1;
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
argv[i+1] = NULL;
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
|
||||
/* We're done! */
|
||||
SDL_Quit();
|
||||
return(0);
|
||||
}
|
||||
348
apps/plugins/sdl/SDL_mixer/CHANGES
Normal file
348
apps/plugins/sdl/SDL_mixer/CHANGES
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
1.2.12:
|
||||
Sam Lantinga - Sat Jan 14 22:00:29 2012 -0500
|
||||
* Fixed seek offset with SMPEG (was relative, should be absolute)
|
||||
Sam Lantinga - Fri Jan 13 03:04:27 EST 2012
|
||||
* Fixed memory crash loading Ogg Vorbis files on Windows
|
||||
Sam Lantinga - Thu Jan 05 22:51:54 2012 -0500
|
||||
* Added an Xcode project for iOS
|
||||
Nikos Chantziaras - 2012-01-02 17:37:36 PST
|
||||
* Added Mix_LoadMUSType_RW() so you can tell SDL_mixer what type the music is
|
||||
Sam Lantinga - Sun Jan 01 16:45:58 2012 -0500
|
||||
* Fixed looping native MIDI on Mac OS X and Windows
|
||||
Sam Lantinga - Sun Jan 01 01:00:51 2012 -0500
|
||||
* Added /usr/local/share/timidity to the timidity data path
|
||||
Sam Lantinga - Sat Dec 31 21:26:46 2011 -0500
|
||||
* Fixed timidity loading of some MIDI files
|
||||
Sam Lantinga - Sat Dec 31 19:11:59 EST 2011
|
||||
* Fixed dropping audio in the FLAC audio decoding
|
||||
Sam Lantinga - Sat Dec 31 18:32:05 EST 2011
|
||||
* Fixed memory leak in SDL_LoadMUS()
|
||||
Sam Lantinga - Sat Dec 31 10:22:05 EST 2011
|
||||
* Removed GPL native MIDI code for new licensing
|
||||
Sam Lantinga - Sat Dec 31 10:22:05 EST 2011
|
||||
* SDL_mixer is now under the zlib license
|
||||
Manuel Montezelo - 2011-12-28 11:42:44 PST
|
||||
* Fixed drums playing on MIDI channel 16 with timidity
|
||||
Ryan C. Gordon - Wed Jun 15 03:41:31 2011 -0400
|
||||
* The music-finished hook can start a track immediately
|
||||
James Le Cuirot - Mon Mar 21 16:54:11 PDT 2011
|
||||
* Added support for FluidSynth
|
||||
Egor Suvorov - Tue Jan 18 11:06:47 PST 2011
|
||||
* Added support for native MIDI on Haiku
|
||||
Sam Lantinga - Tue Jan 11 01:29:19 2011 -0800
|
||||
* Added Android.mk to build on the Android platform
|
||||
Jon Atkins - Sat Nov 14 13:00:18 PST 2009
|
||||
* Added support for libmodplug (disabled by default)
|
||||
|
||||
1.2.11:
|
||||
Sam Lantinga - Sat Nov 14 12:38:01 PST 2009
|
||||
* Fixed initialization error and crashes if MikMod library isn't available
|
||||
Sam Lantinga - Sat Nov 14 11:22:14 PST 2009
|
||||
* Fixed bug loading multiple music files
|
||||
|
||||
1.2.10:
|
||||
Sam Lantinga - Sun Nov 8 08:34:48 PST 2009
|
||||
* Added Mix_Init()/Mix_Quit() to prevent constantly loading and unloading DLLs
|
||||
Mike Frysinger - 2009-11-05 09:11:43 PST
|
||||
* Check for fork/vfork on any platform, don't just assume it on UNIX
|
||||
Jon Atkins - Thu Nov 5 00:02:50 2009 UTC
|
||||
* Fixed export of Mix_GetNumChunkDecoders() and Mix_GetNumMusicDecoders()
|
||||
C.W. Betts - 2009-11-02 00:16:21 PST
|
||||
* Use newer MIDI API on Mac OS X 10.5+
|
||||
|
||||
1.2.9:
|
||||
Ryan Gordon - Sun Oct 18 11:42:31 PDT 2009
|
||||
* Updated native MIDI support on Mac OS X for 10.6
|
||||
Ryan Gordon - Sun Oct 11 05:29:55 2009 UTC
|
||||
* Reset channel volumes after a fade out interrupts a fade in.
|
||||
Ryan Gordon - Sun Oct 11 02:59:12 2009 UTC
|
||||
* Fixed crash race condition with position audio functions
|
||||
Ryan Gordon - Sat Oct 10 17:05:45 2009 UTC
|
||||
* Fixed stereo panning in 8-bit mode
|
||||
Sam Lantinga - Sat Oct 10 11:07:15 2009 UTC
|
||||
* Added /usr/share/timidity to the default timidity.cfg locations
|
||||
Sam Lantinga - Sat Oct 3 13:33:36 PDT 2009
|
||||
* MOD support uses libmikmod and is dynamically loaded by default
|
||||
* A patched version of libmikmod is included in libmikmod-3.1.12.zip
|
||||
* The libmikmod patches fix security issues CVE-2007-6720 and CVE-2009-0179.
|
||||
Sam Lantinga - Sat Oct 3 02:49:41 PDT 2009
|
||||
* Added TIMIDITY_CFG environment variable to fully locate timidity.cfg
|
||||
Sam Lantinga - Fri Oct 2 07:15:35 PDT 2009
|
||||
* Implemented seamless looping for music playback
|
||||
Forrest Voight - 2009-06-13 20:31:38 PDT
|
||||
* ID3 files are now recognized as MP3 format
|
||||
Steven Noonan - 2008-05-13 13:31:36 PDT
|
||||
* Fixed native MIDI crash on 64-bit Windows
|
||||
Ryan Gordon - Fri Jun 5 16:07:08 2009 UTC
|
||||
* Added decoder enumeration API:
|
||||
Mix_GetNumChunkDecoders(), Mix_GetChunkDecoder(),
|
||||
Mix_GetNumMusicDecoders(), Mix_GetMusicDecoder()
|
||||
Austen Dicken - Tue Feb 26 23:28:27 PST 2008
|
||||
* Added support for FLAC audio both as chunks and streaming
|
||||
Tilman Sauerbeck - Tue Feb 26 03:44:47 PST 2008
|
||||
* Added support for streaming WAV files with Mix_LoadMUS_RW()
|
||||
Ryan Gordon - Mon Feb 4 17:10:08 UTC 2008
|
||||
* Fixed crash caused by not resetting position_channels
|
||||
|
||||
1.2.8:
|
||||
Sam Lantinga - Wed Jul 18 09:45:54 PDT 2007
|
||||
* Improved detection of Ogg Vorbis and Tremor libraries
|
||||
Ryan Gordon - Sun Jul 15 12:03:54 EDT 2007
|
||||
* Fixed memory leaks in Effects API.
|
||||
David Rose - Sat Jul 14 22:16:09 PDT 2007
|
||||
* Added support for MP3 playback with libmad (for GPL projects only!)
|
||||
Sam Lantinga - Sat Jul 14 21:39:30 PDT 2007
|
||||
* Fixed the final loop of audio samples of a certain size
|
||||
Sam Lantinga - Sat Jul 14 21:05:09 PDT 2007
|
||||
* Fixed opening Ogg Vorbis files using different C runtimes on Windows
|
||||
Philippe Simons - Sat Jul 14 20:33:17 PDT 2007
|
||||
* Added support for Ogg Vorbis playback with Tremor (an integer decoder)
|
||||
Sam Lantinga - Sat Jul 14 07:02:09 PDT 2007
|
||||
* Fixed memory corruption in timidity resampling code
|
||||
Ryan Gordon - Tue Jul 3 10:44:29 2007 UTC
|
||||
* Fixed building SDL_mixer with SDL 1.3 pre-release
|
||||
Ryan Gordon - Tue Feb 13 08:11:54 2007 UTC
|
||||
* Fixed compiling both timidity and native midi in the same build
|
||||
Hans de Goede - Sun Aug 20 23:25:46 2006 UTC
|
||||
* Added volume control to playmus
|
||||
Jonathan Atkins - Thu Aug 10 15:06:40 2006 UTC
|
||||
* Fixed linking with system libmikmod
|
||||
David Ergo - Fri Jun 23 09:07:19 2006 UTC
|
||||
* Corrected no-op conditions in SetDistance(), SetPanning() and SetPosition()
|
||||
* Fixed copy/paste errors in channel amplitudes
|
||||
|
||||
1.2.7:
|
||||
Sam Lantinga - Fri May 12 00:04:32 PDT 2006
|
||||
* Added support for dynamically loading SMPEG library
|
||||
Sam Lantinga - Thu May 11 22:22:43 PDT 2006
|
||||
* Added support for dynamically loading Ogg Vorbis library
|
||||
Sam Lantinga - Sun Apr 30 09:01:44 PDT 2006
|
||||
* Removed automake dependency, to allow Universal binaries on Mac OS X
|
||||
* Added gcc-fat.sh for generating Universal binaries on Mac OS X
|
||||
Sam Lantinga - Sun Apr 30 01:48:40 PDT 2006
|
||||
* Updated libtool support to version 1.5.22
|
||||
Patrice Mandin - Sat Jul 16 16:43:24 UTC 2005
|
||||
* Use SDL_RWops also for native midi mac and win32
|
||||
Patrice Mandin - Sat Jul 9 14:40:09 UTC 2005
|
||||
* Use SDL_RWops also for native midi gpl (todo: mac and win32)
|
||||
Ryan C. Gordon - Sat Jul 9 01:54:03 EDT 2005
|
||||
* Tweaked Mix_Chunk's definition to make predeclaration easier.
|
||||
Patrice Mandin - Mon Jul 4 19:45:40 UTC 2005
|
||||
* Search timidity.cfg also in /etc
|
||||
* Fix memory leaks in timidity player
|
||||
* Use also SDL_RWops to read midifiles for timidity
|
||||
Ryan C. Gordon - Mon Jun 13 18:18:12 EDT 2005
|
||||
* Patch from Eric Wing to fix native midi compiling on MacOS/x86.
|
||||
Sam Lantinga - Wed Dec 22 17:14:32 PST 2004
|
||||
* Disabled support for the system version of libmikmod by default
|
||||
Sam Lantinga - Tue Dec 21 09:51:29 PST 2004
|
||||
* Fixed building mikmod support on UNIX
|
||||
* Always build SDL_RWops music support
|
||||
* Added SDL_RWops support for reading MP3 files
|
||||
|
||||
1.2.6:
|
||||
Jonathan Atkins - Wed, 15 Sep 2004 23:26:42 -0500
|
||||
* Added support for using the system version of libmikmod
|
||||
Martin_Storsjö - Sun, 22 Aug 2004 02:21:14 +0300 (EEST)
|
||||
* Added SDL_RWops support for reading Ogg Vorbis files
|
||||
Greg Lee - Wed, 14 Jul 2004 05:13:14 -1000
|
||||
* Added 4 and 6 channel surround sound output support
|
||||
* Added support for RMID format MIDI files
|
||||
* Improved timidity support (reverb, chorus, Roland & Yamaha sysex dumps, etc.)
|
||||
Sam Lantinga - Wed Nov 19 00:23:44 PST 2003
|
||||
* Updated libtool support for new mingw32 DLL build process
|
||||
Ryan C. Gordon - Sun Nov 9 23:34:47 EST 2003
|
||||
* Patch from Steven Fuller to fix positioning effect on bigendian systems.
|
||||
Laurent Ganter - Mon, 6 Oct 2003 11:51:33 +0200
|
||||
* Fixed bug with MIDI volume in native Windows playback
|
||||
Andre Leiradella - Fri, 30 May 2003 16:12:03 -0300
|
||||
* Added SDL_RWops support for reading MOD files
|
||||
Kyle Davenport - Sat, 19 Apr 2003 17:13:31 -0500
|
||||
* Added .la files to the development RPM, fixing RPM build on RedHat 8
|
||||
|
||||
1.2.5:
|
||||
Darrell Walisser - Tue Mar 4 09:24:01 PST 2003
|
||||
* Worked around MacOS X deadlock between CoreAudio and QuickTime
|
||||
Darrell Walisser - Fri, 14 Feb 2003 20:56:08 -0500
|
||||
* Fixed crash in native midi code with files with more than 32 tracks
|
||||
Marc Le Douarain - Sat, 15 Feb 2003 14:46:41 +0100
|
||||
* Added 8SVX format support to the AIFF loader
|
||||
Sam Lantinga Wed Feb 12 21:03:57 PST 2003
|
||||
* Fixed volume control on WAVE music chunks
|
||||
Ben Nason - Mon, 10 Feb 2003 11:50:27 -0800
|
||||
* Fixed volume control on MOD music chunks
|
||||
Patrice Mandin - Fri, 31 Jan 2003 15:17:30 +0100
|
||||
* Added support for the Atari platform
|
||||
Ryan C. Gordon - Fri Dec 27 10:14:07 EST 2002
|
||||
* Patch from Steven Fuller to fix panning effect with 8-bit sounds.
|
||||
Ryan C. Gordon - Thu Jan 2 12:31:48 EST 2003
|
||||
* Patch from guy on 3DRealms forums to fix native win32 midi volume.
|
||||
Ryan C. Gordon - Wed Oct 30 07:12:06 EST 2002
|
||||
* Small, looping music samples should now be able to fade out correctly.
|
||||
Sam Lantinga - Sun Oct 20 20:52:24 PDT 2002
|
||||
* Added shared library support for MacOS X
|
||||
Pete Shinners - Wed Oct 16 17:10:08 EDT 2002
|
||||
* Correctly report an error when using an unknown filetype
|
||||
Vaclav Slavik - Sun Sep 8 18:57:38 PDT 2002
|
||||
* Added support for loading Ogg Vorbis samples as an audio chunk
|
||||
Martin Storsjö - Tue Jul 16 10:38:12 PDT 2002
|
||||
* Fixed to start playing another sample immediately when one finishes
|
||||
Martin Storsjö - Tue May 28 13:08:29 PDT 2002
|
||||
* Fixed a volume bug when calling Mix_HaltChannel() on unused channel
|
||||
Xavier Wielemans - Wed Jun 12 14:28:14 EDT 2002
|
||||
* Fixed volume reset bug at end of channel fade.
|
||||
Ryan C. Gordon - Wed Jun 26 16:30:59 EDT 2002
|
||||
* Mix_LoadMUS() will now accept an MP3 by file extension, instead of relying
|
||||
entirely on the magic number.
|
||||
|
||||
1.2.4:
|
||||
Sam Lantinga - Mon May 20 09:11:22 PDT 2002
|
||||
* Updated the CodeWarrior project files
|
||||
Sam Lantinga - Sun May 19 13:46:29 PDT 2002
|
||||
* Added a function to query the music format: Mix_GetMusicType()
|
||||
Sam Lantinga - Sat May 18 12:45:16 PDT 2002
|
||||
* Added a function to load audio data from memory: Mix_QuickLoad_RAW()
|
||||
Sam Lantinga - Thu May 16 11:26:46 PDT 2002
|
||||
* Cleaned up threading issues in the music playback code
|
||||
Ryan Gordon - Thu May 2 21:08:48 PDT 2002
|
||||
* Fixed deadlock introduced in the last release
|
||||
|
||||
1.2.3:
|
||||
Sam Lantinga - Sat Apr 13 07:49:47 PDT 2002
|
||||
* Updated autogen.sh for new versions of automake
|
||||
* Specify the SDL API calling convention (C by default)
|
||||
Ryan Gordon - Sat Apr 13 07:33:37 PDT 2002
|
||||
* Fixed recursive audio lock in the mixing function
|
||||
jean-julien Filatriau - Sat Mar 23 18:05:37 PST 2002
|
||||
* Fixed setting invalid volume when querying mixer and music volumes
|
||||
Guillaume Cottenceau - Wed Feb 13 15:43:20 PST 2002
|
||||
* Implemented Ogg Vorbis stream rewinding
|
||||
Peter Kutak - Wed Feb 13 10:26:57 PST 2002
|
||||
* Added native midi support on Linux, using GPL code
|
||||
--enable-music-native-midi-gpl
|
||||
Pete Shinners - Mon Jan 14 11:31:26 PST 2002
|
||||
* Added seek support for MP3 files
|
||||
Ryan Gordon - Mon Jan 14 11:30:44 PST 2002
|
||||
* Sample "finished" callbacks are now always called when a sample is stopped.
|
||||
|
||||
1.2.2:
|
||||
Guillaume Cottenceau - Wed Dec 19 08:59:05 PST 2001
|
||||
* Added an API for seeking in music files (implemented for MOD and Ogg music)
|
||||
Mix_FadeInMusicPos(), Mix_SetMusicPosition()
|
||||
* Exposed the mikmod synchro value for music synchronization
|
||||
Mix_SetSynchroValue(), Mix_GetSynchroValue()
|
||||
|
||||
1.2.1:
|
||||
Yi-Huang Han - Wed Oct 24 21:55:47 PDT 2001
|
||||
* Fixed MOD music volume when looping
|
||||
David Hedbor - Thu Oct 18 10:01:41 PDT 2001
|
||||
* Stop implicit looping, set fade out and other flags on MOD files
|
||||
Sam Lantinga - Tue Oct 16 11:17:12 PDT 2001
|
||||
* The music file type is now determined by extension as well as magic
|
||||
Ryan C. Gordon - Tue Sep 11 12:05:54 PDT 2001
|
||||
* Reworked playwave.c to make it more useful as a mixer testbed
|
||||
* Added a realtime sound effect API to SDL_mixer.h
|
||||
* Added the following standard sound effects:
|
||||
panning, distance attenuation, basic positional audio, stereo reversal
|
||||
* Added API for mixer versioning: Mix_Linked_Version() and MIX_VERSION()
|
||||
Sam Lantinga - Tue Sep 11 11:48:53 PDT 2001
|
||||
* Updated MikMod code to version 3.1.9a
|
||||
Torbjörn Andersson - Tue Sep 11 11:22:29 PDT 2001
|
||||
* Added support for loading AIFF audio chunks
|
||||
Max Horn - Tue Sep 4 20:38:11 PDT 2001
|
||||
* Added native MIDI music support on MacOS and MacOS X
|
||||
Florian Schulze - Sun Aug 19 14:55:37 PDT 2001
|
||||
* Added native MIDI music support on Windows
|
||||
Sam Lantinga - Sun Aug 19 02:20:55 PDT 2001
|
||||
* Added Project Builder projects for building MacOS X framework
|
||||
Darrell Walisser - Sun Aug 19 00:47:22 PDT 2001
|
||||
* Fixed compilation problems with mikmod under MacOS X
|
||||
Torbjörn Andersson - Sun, 19 Aug 2001 16:03:30
|
||||
* Fixed AIFF music playing support
|
||||
Sam Lantinga - Sat Aug 18 04:14:13 PDT 2001
|
||||
* Fixed building Ogg Vorbis support on Windows
|
||||
Ryan C. Gordon - Thu, 7 Jun 2001 13:15:51
|
||||
* Added Mix_ChannelFinished() and Mix_GetChunk()
|
||||
Ryan C. Gordon - Tue, 5 Jun 2001 11:01:51
|
||||
* Added VOC sound file support
|
||||
Guillaume Cottenceau - Thu May 10 11:17:55 PDT 2001
|
||||
* Fixed crashes when API used with audio not initialized
|
||||
Paul Jenner - Sat, 14 Apr 2001 09:20:38 -0700 (PDT)
|
||||
* Added support for building RPM directly from tar archive
|
||||
|
||||
1.2.0:
|
||||
Sam Lantinga - Wed Apr 4 12:42:20 PDT 2001
|
||||
* Synchronized release version with SDL 1.2.0
|
||||
|
||||
1.1.1:
|
||||
John Hall - Tue Jan 2 13:46:54 PST 2001
|
||||
* Added support to playmus for track switching with Ctrl-C
|
||||
* Added support to playmus for multiple command line files
|
||||
|
||||
1.1.0:
|
||||
Sam Lantinga - Wed Nov 29 20:47:13 PST 2000
|
||||
* Package specifically for SDL 1.1 (no real reason API-wise, but for clarity)
|
||||
|
||||
1.0.7:
|
||||
Sam Lantinga - Tue Nov 7 10:22:09 PST 2000
|
||||
* Fixed hang in mikmod re-initialization
|
||||
Stephane Peter - Oct 17 13:07:32 PST 2000
|
||||
* Fixed music fading
|
||||
Ray Kelm - Fri, 04 Aug 2000 20:58:00 -0400
|
||||
* Added support for cross-compiling Windows DLL from Linux
|
||||
|
||||
1.0.6:
|
||||
Sam Lantinga - Sun Jul 2 14:16:44 PDT 2000
|
||||
* Added support for the Ogg Vorbis music format: http://www.vorbis.org/
|
||||
Darrell Walisser - Wed Jun 28 11:59:40 PDT 2000
|
||||
* Added Codewarrior projects for MacOS
|
||||
Sam Lantinga - Mon Jun 26 12:01:11 PDT 2000
|
||||
* Fixed symbol aliasing problem with "channel"
|
||||
Matt - Wed, 12 Apr 2000 15:36:13 -0700
|
||||
* Added SDL_RWops support for mikmod loading (not hooked into music.c yet)
|
||||
|
||||
1.0.5:
|
||||
Paul Furber - Fri Mar 3 14:58:50 PST 2000
|
||||
* Fixed MP3 detection with compilers that use signed char datatypes
|
||||
|
||||
1.0.4:
|
||||
Sam Lantinga - Thu Feb 10 19:42:03 PST 2000
|
||||
* Ported the base mixer and mikmod libraries to MacOS
|
||||
Markus Oberhumer - Wed Feb 2 13:16:17 PST 2000
|
||||
* Fixed problem with short looping sounds
|
||||
Sam Lantinga - Tue Feb 1 13:25:44 PST 2000
|
||||
* Added Visual C++ project file
|
||||
Markus Oberhumer - Tue Feb 1 13:23:11 PST 2000
|
||||
* Cleaned up code for compiling with Visual C++
|
||||
* Don't hang in Mix_HaltMusic() if the music is paused
|
||||
Sam Lantinga - Fri Jan 28 08:54:56 PST 2000
|
||||
* Fixed looping WAVE chunks that are not aligned on sample boundaries
|
||||
|
||||
1.0.3:
|
||||
Sam Lantinga - Mon Jan 17 19:48:09 PST 2000
|
||||
* Changed the name of the library from "mixer" to "SDL_mixer"
|
||||
* Instead of including "mixer.h", include "SDL_mixer.h",
|
||||
* Instead of linking with libmixer.a, link with libSDL_mixer.a
|
||||
|
||||
1.0.2:
|
||||
Sam Lantinga - Fri Jan 14 11:06:56 PST 2000
|
||||
* Made the CHANGELOG entries Y2K compliant. :)
|
||||
MFX - Updated the mikmod support to MikMod 3.1.8
|
||||
MFX - Added Mix_HookMusicFinished() API function
|
||||
|
||||
1.0.1:
|
||||
SOL - Added a post-mixing callback
|
||||
SP - A few music-related bugfixes
|
||||
|
||||
1.0.0:
|
||||
SOL - Added autoconf support
|
||||
SP - Added MP3 support using SMPEG
|
||||
SP - Added fading in/out of music and samples
|
||||
SP - Added dynamic allocation of channels
|
||||
SP - Added channel grouping functions
|
||||
SP - Added expiration delay for samples
|
||||
|
||||
Initial Key:
|
||||
SOL - Sam Lantinga (hercules@lokigames.com)
|
||||
SP - Stephane Peter (megastep@lokigames.com)
|
||||
MFX - Markus Oberhumer (markus.oberhumer@jk.uni-linz.ac.at)
|
||||
20
apps/plugins/sdl/SDL_mixer/COPYING
Normal file
20
apps/plugins/sdl/SDL_mixer/COPYING
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
133
apps/plugins/sdl/SDL_mixer/Makefile.in
Normal file
133
apps/plugins/sdl/SDL_mixer/Makefile.in
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Makefile to build and install the SDL_mixer library
|
||||
|
||||
top_builddir = .
|
||||
srcdir = @srcdir@
|
||||
objects = build
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = $(DESTDIR)@bindir@
|
||||
libdir = $(DESTDIR)@libdir@
|
||||
includedir = $(DESTDIR)@includedir@
|
||||
datarootdir = $(DESTDIR)@datarootdir@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
auxdir = @ac_aux_dir@
|
||||
distpath = $(srcdir)/..
|
||||
distdir = SDL_mixer-@VERSION@
|
||||
distfile = $(distdir).tar.gz
|
||||
|
||||
@SET_MAKE@
|
||||
EXE = @EXE@
|
||||
SHELL = @SHELL@
|
||||
CC = @CC@
|
||||
CXX = g++
|
||||
CFLAGS = @BUILD_CFLAGS@
|
||||
EXTRA_CFLAGS = @EXTRA_CFLAGS@
|
||||
LDFLAGS = @BUILD_LDFLAGS@
|
||||
EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
INSTALL = @INSTALL@
|
||||
AR = @AR@
|
||||
RANLIB = @RANLIB@
|
||||
WINDRES = @WINDRES@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
|
||||
TARGET = libSDL_mixer.la
|
||||
OBJECTS = @OBJECTS@
|
||||
VERSION_OBJECTS = @VERSION_OBJECTS@
|
||||
PLAYWAVE_OBJECTS = @PLAYWAVE_OBJECTS@
|
||||
PLAYMUS_OBJECTS = @PLAYMUS_OBJECTS@
|
||||
|
||||
DIST = Android.mk CHANGES COPYING CWProjects.sea.bin MPWmake.sea.bin Makefile.in SDL_mixer.pc.in README SDL_mixer.h SDL_mixer.qpg.in SDL_mixer.spec SDL_mixer.spec.in VisualC Watcom-OS2.zip Xcode Xcode-iOS acinclude autogen.sh build-scripts configure configure.in dynamic_flac.c dynamic_flac.h dynamic_fluidsynth.c dynamic_fluidsynth.h dynamic_mod.c dynamic_mod.h dynamic_mp3.c dynamic_mp3.h dynamic_ogg.c dynamic_ogg.h effect_position.c effect_stereoreverse.c effects_internal.c effects_internal.h fluidsynth.c fluidsynth.h gcc-fat.sh libmikmod-3.1.12.zip load_aiff.c load_aiff.h load_flac.c load_flac.h load_ogg.c load_ogg.h load_voc.c load_voc.h mixer.c music.c music_cmd.c music_cmd.h music_flac.c music_flac.h music_mad.c music_mad.h music_mod.c music_mod.h music_modplug.c music_modplug.h music_ogg.c music_ogg.h native_midi playmus.c playwave.c timidity wavestream.c wavestream.h version.rc
|
||||
|
||||
LT_AGE = @LT_AGE@
|
||||
LT_CURRENT = @LT_CURRENT@
|
||||
LT_RELEASE = @LT_RELEASE@
|
||||
LT_REVISION = @LT_REVISION@
|
||||
LT_LDFLAGS = -no-undefined -rpath $(libdir) -release $(LT_RELEASE) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
|
||||
all: $(srcdir)/configure Makefile $(objects) $(objects)/$(TARGET) $(objects)/playwave$(EXE) $(objects)/playmus$(EXE)
|
||||
|
||||
$(srcdir)/configure: $(srcdir)/configure.in
|
||||
@echo "Warning, configure.in is out of date"
|
||||
#(cd $(srcdir) && sh autogen.sh && sh configure)
|
||||
@sleep 3
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in
|
||||
$(SHELL) config.status $@
|
||||
|
||||
$(objects):
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $@
|
||||
|
||||
.PHONY: all install install-hdrs install-lib install-bin uninstall uninstall-hdrs uninstall-lib uninstall-bin clean distclean dist
|
||||
|
||||
$(objects)/$(TARGET): $(OBJECTS) $(VERSION_OBJECTS)
|
||||
$(LIBTOOL) --mode=link $(CC) -o $@ $(OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
|
||||
|
||||
$(objects)/playwave$(EXE): $(objects)/playwave.lo $(objects)/$(TARGET)
|
||||
$(LIBTOOL) --mode=link $(CC) -o $@ $(objects)/playwave.lo $(SDL_CFLAGS) $(SDL_LIBS) $(objects)/$(TARGET)
|
||||
|
||||
$(objects)/playmus$(EXE): $(objects)/playmus.lo $(objects)/$(TARGET)
|
||||
$(LIBTOOL) --mode=link $(CC) -o $@ $(objects)/playmus.lo $(SDL_CFLAGS) $(SDL_LIBS) $(objects)/$(TARGET)
|
||||
|
||||
install: all install-hdrs install-lib #install-bin
|
||||
install-hdrs:
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $(includedir)/SDL
|
||||
for src in $(srcdir)/SDL_mixer.h; do \
|
||||
file=`echo $$src | sed -e 's|^.*/||'`; \
|
||||
$(INSTALL) -m 644 $$src $(includedir)/SDL/$$file; \
|
||||
done
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $(libdir)/pkgconfig
|
||||
$(INSTALL) -m 644 SDL_mixer.pc $(libdir)/pkgconfig/
|
||||
install-lib: $(objects) $(objects)/$(TARGET)
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $(libdir)
|
||||
$(LIBTOOL) --mode=install $(INSTALL) $(objects)/$(TARGET) $(libdir)/$(TARGET)
|
||||
install-bin:
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $(bindir)
|
||||
$(LIBTOOL) --mode=install $(INSTALL) -m 755 $(objects)/playwave$(EXE) $(bindir)/playwave$(EXE)
|
||||
$(LIBTOOL) --mode=install $(INSTALL) -m 755 $(objects)/playmus$(EXE) $(bindir)/playmus$(EXE)
|
||||
|
||||
uninstall: uninstall-hdrs uninstall-lib uninstall-bin
|
||||
uninstall-hdrs:
|
||||
for src in $(srcdir)/SDL_mixer.h; do \
|
||||
file=`echo $$src | sed -e 's|^.*/||'`; \
|
||||
rm -f $(includedir)/SDL/$$file; \
|
||||
done
|
||||
-rmdir $(includedir)/SDL
|
||||
rm -f $(libdir)/pkgconfig/SDL_mixer.pc
|
||||
-rmdir $(libdir)/pkgconfig
|
||||
uninstall-lib:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(TARGET)
|
||||
uninstall-bin:
|
||||
rm -f $(bindir)/playwave$(EXE)
|
||||
rm -f $(bindir)/playmus$(EXE)
|
||||
|
||||
clean:
|
||||
rm -rf $(objects)
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -f SDL_mixer.qpg
|
||||
rm -f config.status config.cache config.log libtool
|
||||
rm -f SDL_mixer.pc
|
||||
rm -rf $(srcdir)/autom4te*
|
||||
find $(srcdir) \( \
|
||||
-name '*~' -o \
|
||||
-name '*.bak' -o \
|
||||
-name '*.old' -o \
|
||||
-name '*.rej' -o \
|
||||
-name '*.orig' -o \
|
||||
-name '.#*' \) \
|
||||
-exec rm -f {} \;
|
||||
|
||||
dist $(distfile):
|
||||
$(SHELL) $(auxdir)/mkinstalldirs $(distdir)
|
||||
tar cf - $(DIST) | (cd $(distdir); tar xf -)
|
||||
rm -rf `find $(distdir) -name .svn`
|
||||
rm -f `find $(distdir) -name '.#*'`
|
||||
tar cvf - $(distdir) | gzip --best >$(distfile)
|
||||
rm -rf $(distdir)
|
||||
|
||||
rpm: $(distfile)
|
||||
rpmbuild -ta $?
|
||||
43
apps/plugins/sdl/SDL_mixer/README
Normal file
43
apps/plugins/sdl/SDL_mixer/README
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
SDL_mixer 1.2
|
||||
|
||||
The latest version of this library is available from:
|
||||
http://www.libsdl.org/projects/SDL_mixer/
|
||||
|
||||
Due to popular demand, here is a simple multi-channel audio mixer.
|
||||
It supports 8 channels of 16 bit stereo audio, plus a single channel
|
||||
of music, mixed by the popular MikMod MOD, Timidity MIDI and SMPEG MP3
|
||||
libraries.
|
||||
|
||||
See the header file SDL_mixer.h and the examples playwave.c and playmus.c
|
||||
for documentation on this mixer library.
|
||||
|
||||
The mixer can currently load Microsoft WAVE files and Creative Labs VOC
|
||||
files as audio samples, and can load MIDI files via Timidity and the
|
||||
following music formats via MikMod: .MOD .S3M .IT .XM. It can load
|
||||
Ogg Vorbis streams as music if built with Ogg Vorbis or Tremor libraries,
|
||||
and finally it can load MP3 music using the SMPEG or libmad libraries.
|
||||
|
||||
Tremor decoding is disabled by default; you can enable it by passing
|
||||
--enable-music-ogg-tremor
|
||||
to configure, or by defining OGG_MUSIC and OGG_USE_TREMOR.
|
||||
|
||||
libmad decoding is disabled by default; you can enable it by passing
|
||||
--enable-music-mp3-mad
|
||||
to configure, or by defining MP3_MAD_MUSIC
|
||||
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
WARNING: The license for libmad is GPL, which means that in order to
|
||||
use it your application must also be GPL!
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The process of mixing MIDI files to wave output is very CPU intensive,
|
||||
so if playing regular WAVE files sound great, but playing MIDI files
|
||||
sound choppy, try using 8-bit audio, mono audio, or lower frequencies.
|
||||
|
||||
To play MIDI files, you'll need to get a complete set of GUS patches
|
||||
from:
|
||||
http://www.libsdl.org/projects/mixer/timidity/timidity.tar.gz
|
||||
and unpack them in /usr/local/lib under UNIX, and C:\ under Win32.
|
||||
|
||||
This library is under the zlib license, see the file "COPYING" for details.
|
||||
|
||||
177
apps/plugins/sdl/SDL_mixer/dynamic_flac.c
Normal file
177
apps/plugins/sdl/SDL_mixer/dynamic_flac.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Implementation of the dynamic loading functionality for libFLAC.
|
||||
~ Austen Dicken (admin@cvpcs.org)
|
||||
*/
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
#include "dynamic_flac.h"
|
||||
|
||||
flac_loader flac = {
|
||||
0, NULL
|
||||
};
|
||||
|
||||
#ifdef FLAC_DYNAMIC
|
||||
int Mix_InitFLAC()
|
||||
{
|
||||
if ( flac.loaded == 0 ) {
|
||||
flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
|
||||
if ( flac.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_new =
|
||||
(FLAC__StreamDecoder *(*)())
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_new");
|
||||
if ( flac.FLAC__stream_decoder_new == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_delete =
|
||||
(void (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_delete");
|
||||
if ( flac.FLAC__stream_decoder_delete == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_init_stream =
|
||||
(FLAC__StreamDecoderInitStatus (*)(
|
||||
FLAC__StreamDecoder *,
|
||||
FLAC__StreamDecoderReadCallback,
|
||||
FLAC__StreamDecoderSeekCallback,
|
||||
FLAC__StreamDecoderTellCallback,
|
||||
FLAC__StreamDecoderLengthCallback,
|
||||
FLAC__StreamDecoderEofCallback,
|
||||
FLAC__StreamDecoderWriteCallback,
|
||||
FLAC__StreamDecoderMetadataCallback,
|
||||
FLAC__StreamDecoderErrorCallback,
|
||||
void *))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_init_stream");
|
||||
if ( flac.FLAC__stream_decoder_init_stream == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_finish =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_finish");
|
||||
if ( flac.FLAC__stream_decoder_finish == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_flush =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_flush");
|
||||
if ( flac.FLAC__stream_decoder_flush == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_process_single =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle,
|
||||
"FLAC__stream_decoder_process_single");
|
||||
if ( flac.FLAC__stream_decoder_process_single == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_process_until_end_of_metadata =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle,
|
||||
"FLAC__stream_decoder_process_until_end_of_metadata");
|
||||
if ( flac.FLAC__stream_decoder_process_until_end_of_metadata == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_process_until_end_of_stream =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *))
|
||||
SDL_LoadFunction(flac.handle,
|
||||
"FLAC__stream_decoder_process_until_end_of_stream");
|
||||
if ( flac.FLAC__stream_decoder_process_until_end_of_stream == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_seek_absolute =
|
||||
(FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_seek_absolute");
|
||||
if ( flac.FLAC__stream_decoder_seek_absolute == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
flac.FLAC__stream_decoder_get_state =
|
||||
(FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
|
||||
SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_get_state");
|
||||
if ( flac.FLAC__stream_decoder_get_state == NULL ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++flac.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitFLAC()
|
||||
{
|
||||
if ( flac.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( flac.loaded == 1 ) {
|
||||
SDL_UnloadObject(flac.handle);
|
||||
}
|
||||
--flac.loaded;
|
||||
}
|
||||
#else
|
||||
int Mix_InitFLAC()
|
||||
{
|
||||
if ( flac.loaded == 0 ) {
|
||||
flac.FLAC__stream_decoder_new = FLAC__stream_decoder_new;
|
||||
flac.FLAC__stream_decoder_delete = FLAC__stream_decoder_delete;
|
||||
flac.FLAC__stream_decoder_init_stream =
|
||||
FLAC__stream_decoder_init_stream;
|
||||
flac.FLAC__stream_decoder_finish = FLAC__stream_decoder_finish;
|
||||
flac.FLAC__stream_decoder_flush = FLAC__stream_decoder_flush;
|
||||
flac.FLAC__stream_decoder_process_single =
|
||||
FLAC__stream_decoder_process_single;
|
||||
flac.FLAC__stream_decoder_process_until_end_of_metadata =
|
||||
FLAC__stream_decoder_process_until_end_of_metadata;
|
||||
flac.FLAC__stream_decoder_process_until_end_of_stream =
|
||||
FLAC__stream_decoder_process_until_end_of_stream;
|
||||
flac.FLAC__stream_decoder_seek_absolute =
|
||||
FLAC__stream_decoder_seek_absolute;
|
||||
flac.FLAC__stream_decoder_get_state =
|
||||
FLAC__stream_decoder_get_state;
|
||||
}
|
||||
++flac.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitFLAC()
|
||||
{
|
||||
if ( flac.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( flac.loaded == 1 ) {
|
||||
}
|
||||
--flac.loaded;
|
||||
}
|
||||
#endif /* FLAC_DYNAMIC */
|
||||
|
||||
#endif /* FLAC_MUSIC */
|
||||
66
apps/plugins/sdl/SDL_mixer/dynamic_flac.h
Normal file
66
apps/plugins/sdl/SDL_mixer/dynamic_flac.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
The following file defines all of the functions/objects used to dynamically
|
||||
link to the libFLAC library.
|
||||
~ Austen Dicken (admin@cvpcs.org)
|
||||
*/
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
||||
typedef struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
FLAC__StreamDecoder *(*FLAC__stream_decoder_new)();
|
||||
void (*FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
|
||||
FLAC__StreamDecoderInitStatus (*FLAC__stream_decoder_init_stream)(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderReadCallback read_callback,
|
||||
FLAC__StreamDecoderSeekCallback seek_callback,
|
||||
FLAC__StreamDecoderTellCallback tell_callback,
|
||||
FLAC__StreamDecoderLengthCallback length_callback,
|
||||
FLAC__StreamDecoderEofCallback eof_callback,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data);
|
||||
FLAC__bool (*FLAC__stream_decoder_finish)(FLAC__StreamDecoder *decoder);
|
||||
FLAC__bool (*FLAC__stream_decoder_flush)(FLAC__StreamDecoder *decoder);
|
||||
FLAC__bool (*FLAC__stream_decoder_process_single)(
|
||||
FLAC__StreamDecoder *decoder);
|
||||
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_metadata)(
|
||||
FLAC__StreamDecoder *decoder);
|
||||
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_stream)(
|
||||
FLAC__StreamDecoder *decoder);
|
||||
FLAC__bool (*FLAC__stream_decoder_seek_absolute)(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 sample);
|
||||
FLAC__StreamDecoderState (*FLAC__stream_decoder_get_state)(
|
||||
const FLAC__StreamDecoder *decoder);
|
||||
} flac_loader;
|
||||
|
||||
extern flac_loader flac;
|
||||
|
||||
#endif /* FLAC_MUSIC */
|
||||
|
||||
extern int Mix_InitFLAC();
|
||||
extern void Mix_QuitFLAC();
|
||||
87
apps/plugins/sdl/SDL_mixer/dynamic_fluidsynth.c
Normal file
87
apps/plugins/sdl/SDL_mixer/dynamic_fluidsynth.c
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
James Le Cuirot
|
||||
chewi@aura-online.co.uk
|
||||
*/
|
||||
|
||||
#ifdef USE_FLUIDSYNTH_MIDI
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "dynamic_fluidsynth.h"
|
||||
|
||||
fluidsynth_loader fluidsynth = {
|
||||
0, NULL
|
||||
};
|
||||
|
||||
#ifdef FLUIDSYNTH_DYNAMIC
|
||||
#define FLUIDSYNTH_LOADER(FUNC, SIG) \
|
||||
fluidsynth.FUNC = (SIG) SDL_LoadFunction(fluidsynth.handle, #FUNC); \
|
||||
if (fluidsynth.FUNC == NULL) { SDL_UnloadObject(fluidsynth.handle); return -1; }
|
||||
#else
|
||||
#define FLUIDSYNTH_LOADER(FUNC, SIG) \
|
||||
fluidsynth.FUNC = FUNC;
|
||||
#endif
|
||||
|
||||
int Mix_InitFluidSynth()
|
||||
{
|
||||
if ( fluidsynth.loaded == 0 ) {
|
||||
#ifdef FLUIDSYNTH_DYNAMIC
|
||||
fluidsynth.handle = SDL_LoadObject(FLUIDSYNTH_DYNAMIC);
|
||||
if ( fluidsynth.handle == NULL ) return -1;
|
||||
#endif
|
||||
|
||||
FLUIDSYNTH_LOADER(delete_fluid_player, int (*)(fluid_player_t*));
|
||||
FLUIDSYNTH_LOADER(delete_fluid_settings, void (*)(fluid_settings_t*));
|
||||
FLUIDSYNTH_LOADER(delete_fluid_synth, int (*)(fluid_synth_t*));
|
||||
FLUIDSYNTH_LOADER(fluid_player_add, int (*)(fluid_player_t*, const char*));
|
||||
FLUIDSYNTH_LOADER(fluid_player_add_mem, int (*)(fluid_player_t*, const void*, size_t));
|
||||
FLUIDSYNTH_LOADER(fluid_player_get_status, int (*)(fluid_player_t*));
|
||||
FLUIDSYNTH_LOADER(fluid_player_play, int (*)(fluid_player_t*));
|
||||
FLUIDSYNTH_LOADER(fluid_player_set_loop, int (*)(fluid_player_t*, int));
|
||||
FLUIDSYNTH_LOADER(fluid_player_stop, int (*)(fluid_player_t*));
|
||||
FLUIDSYNTH_LOADER(fluid_settings_setnum, int (*)(fluid_settings_t*, const char*, double));
|
||||
FLUIDSYNTH_LOADER(fluid_synth_get_settings, fluid_settings_t* (*)(fluid_synth_t*));
|
||||
FLUIDSYNTH_LOADER(fluid_synth_set_gain, void (*)(fluid_synth_t*, float));
|
||||
FLUIDSYNTH_LOADER(fluid_synth_sfload, int(*)(fluid_synth_t*, const char*, int));
|
||||
FLUIDSYNTH_LOADER(fluid_synth_write_s16, int(*)(fluid_synth_t*, int, void*, int, int, void*, int, int));
|
||||
FLUIDSYNTH_LOADER(new_fluid_player, fluid_player_t* (*)(fluid_synth_t*));
|
||||
FLUIDSYNTH_LOADER(new_fluid_settings, fluid_settings_t* (*)(void));
|
||||
FLUIDSYNTH_LOADER(new_fluid_synth, fluid_synth_t* (*)(fluid_settings_t*));
|
||||
}
|
||||
++fluidsynth.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mix_QuitFluidSynth()
|
||||
{
|
||||
if ( fluidsynth.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( fluidsynth.loaded == 1 ) {
|
||||
#ifdef FLUIDSYNTH_DYNAMIC
|
||||
SDL_UnloadObject(fluidsynth.handle);
|
||||
#endif
|
||||
}
|
||||
--fluidsynth.loaded;
|
||||
}
|
||||
|
||||
#endif /* USE_FLUIDSYNTH_MIDI */
|
||||
57
apps/plugins/sdl/SDL_mixer/dynamic_fluidsynth.h
Normal file
57
apps/plugins/sdl/SDL_mixer/dynamic_fluidsynth.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
James Le Cuirot
|
||||
chewi@aura-online.co.uk
|
||||
*/
|
||||
|
||||
#ifdef USE_FLUIDSYNTH_MIDI
|
||||
|
||||
#include <fluidsynth.h>
|
||||
|
||||
typedef struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
|
||||
int (*delete_fluid_player)(fluid_player_t*);
|
||||
void (*delete_fluid_settings)(fluid_settings_t*);
|
||||
int (*delete_fluid_synth)(fluid_synth_t*);
|
||||
int (*fluid_player_add)(fluid_player_t*, const char*);
|
||||
int (*fluid_player_add_mem)(fluid_player_t*, const void*, size_t);
|
||||
int (*fluid_player_get_status)(fluid_player_t*);
|
||||
int (*fluid_player_play)(fluid_player_t*);
|
||||
int (*fluid_player_set_loop)(fluid_player_t*, int);
|
||||
int (*fluid_player_stop)(fluid_player_t*);
|
||||
int (*fluid_settings_setnum)(fluid_settings_t*, const char*, double);
|
||||
fluid_settings_t* (*fluid_synth_get_settings)(fluid_synth_t*);
|
||||
void (*fluid_synth_set_gain)(fluid_synth_t*, float);
|
||||
int (*fluid_synth_sfload)(fluid_synth_t*, const char*, int);
|
||||
int (*fluid_synth_write_s16)(fluid_synth_t*, int, void*, int, int, void*, int, int);
|
||||
fluid_player_t* (*new_fluid_player)(fluid_synth_t*);
|
||||
fluid_settings_t* (*new_fluid_settings)(void);
|
||||
fluid_synth_t* (*new_fluid_synth)(fluid_settings_t*);
|
||||
} fluidsynth_loader;
|
||||
|
||||
extern fluidsynth_loader fluidsynth;
|
||||
|
||||
#endif /* USE_FLUIDSYNTH_MIDI */
|
||||
|
||||
extern int Mix_InitFluidSynth();
|
||||
extern void Mix_QuitFluidSynth();
|
||||
275
apps/plugins/sdl/SDL_mixer/dynamic_mod.c
Normal file
275
apps/plugins/sdl/SDL_mixer/dynamic_mod.c
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MOD_MUSIC
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
#include "dynamic_mod.h"
|
||||
|
||||
mikmod_loader mikmod = {
|
||||
0, NULL
|
||||
};
|
||||
|
||||
#ifdef MOD_DYNAMIC
|
||||
int Mix_InitMOD()
|
||||
{
|
||||
if ( mikmod.loaded == 0 ) {
|
||||
mikmod.handle = SDL_LoadObject(MOD_DYNAMIC);
|
||||
if ( mikmod.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_Exit =
|
||||
(void (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_Exit");
|
||||
if ( mikmod.MikMod_Exit == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_InfoDriver =
|
||||
(CHAR* (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_InfoDriver");
|
||||
if ( mikmod.MikMod_InfoDriver == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_InfoLoader =
|
||||
(CHAR* (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_InfoLoader");
|
||||
if ( mikmod.MikMod_InfoLoader == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_Init =
|
||||
(BOOL (*)(CHAR*))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_Init");
|
||||
if ( mikmod.MikMod_Init == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_RegisterAllLoaders =
|
||||
(void (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_RegisterAllLoaders");
|
||||
if ( mikmod.MikMod_RegisterAllLoaders == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_RegisterDriver =
|
||||
(void (*)(struct MDRIVER*))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_RegisterDriver");
|
||||
if ( mikmod.MikMod_RegisterDriver == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_errno =
|
||||
(int*)
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_errno");
|
||||
if ( mikmod.MikMod_errno == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.MikMod_strerror =
|
||||
(char* (*)(int))
|
||||
SDL_LoadFunction(mikmod.handle, "MikMod_strerror");
|
||||
if ( mikmod.MikMod_strerror == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_Active =
|
||||
(BOOL (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_Active");
|
||||
if ( mikmod.Player_Active == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_Free =
|
||||
(void (*)(MODULE*))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_Free");
|
||||
if ( mikmod.Player_Free == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_LoadGeneric =
|
||||
(MODULE* (*)(MREADER*,int,BOOL))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_LoadGeneric");
|
||||
if ( mikmod.Player_LoadGeneric == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_SetPosition =
|
||||
(void (*)(UWORD))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_SetPosition");
|
||||
if ( mikmod.Player_SetPosition == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_SetVolume =
|
||||
(void (*)(SWORD))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_SetVolume");
|
||||
if ( mikmod.Player_SetVolume == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_Start =
|
||||
(void (*)(MODULE*))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_Start");
|
||||
if ( mikmod.Player_Start == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.Player_Stop =
|
||||
(void (*)(void))
|
||||
SDL_LoadFunction(mikmod.handle, "Player_Stop");
|
||||
if ( mikmod.Player_Stop == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.VC_WriteBytes =
|
||||
(ULONG (*)(SBYTE*,ULONG))
|
||||
SDL_LoadFunction(mikmod.handle, "VC_WriteBytes");
|
||||
if ( mikmod.VC_WriteBytes == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.drv_nos =
|
||||
(MDRIVER*)
|
||||
SDL_LoadFunction(mikmod.handle, "drv_nos");
|
||||
if ( mikmod.drv_nos == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_device =
|
||||
(UWORD*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_device");
|
||||
if ( mikmod.md_device == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_mixfreq =
|
||||
(UWORD*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_mixfreq");
|
||||
if ( mikmod.md_mixfreq == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_mode =
|
||||
(UWORD*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_mode");
|
||||
if ( mikmod.md_mode == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_musicvolume =
|
||||
(UBYTE*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_musicvolume");
|
||||
if ( mikmod.md_musicvolume == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_pansep =
|
||||
(UBYTE*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_pansep");
|
||||
if ( mikmod.md_pansep == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_reverb =
|
||||
(UBYTE*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_reverb");
|
||||
if ( mikmod.md_reverb == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_sndfxvolume =
|
||||
(UBYTE*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_sndfxvolume");
|
||||
if ( mikmod.md_sndfxvolume == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
mikmod.md_volume =
|
||||
(UBYTE*)
|
||||
SDL_LoadFunction(mikmod.handle, "md_volume");
|
||||
if ( mikmod.md_volume == NULL ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++mikmod.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitMOD()
|
||||
{
|
||||
if ( mikmod.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( mikmod.loaded == 1 ) {
|
||||
SDL_UnloadObject(mikmod.handle);
|
||||
}
|
||||
--mikmod.loaded;
|
||||
}
|
||||
#else
|
||||
int Mix_InitMOD()
|
||||
{
|
||||
if ( mikmod.loaded == 0 ) {
|
||||
mikmod.MikMod_Exit = MikMod_Exit;
|
||||
mikmod.MikMod_InfoDriver = MikMod_InfoDriver;
|
||||
mikmod.MikMod_InfoLoader = MikMod_InfoLoader;
|
||||
mikmod.MikMod_Init = MikMod_Init;
|
||||
mikmod.MikMod_RegisterAllLoaders = MikMod_RegisterAllLoaders;
|
||||
mikmod.MikMod_RegisterDriver = MikMod_RegisterDriver;
|
||||
mikmod.MikMod_errno = &MikMod_errno;
|
||||
mikmod.MikMod_strerror = MikMod_strerror;
|
||||
mikmod.Player_Active = Player_Active;
|
||||
mikmod.Player_Free = Player_Free;
|
||||
mikmod.Player_LoadGeneric = Player_LoadGeneric;
|
||||
mikmod.Player_SetPosition = Player_SetPosition;
|
||||
mikmod.Player_SetVolume = Player_SetVolume;
|
||||
mikmod.Player_Start = Player_Start;
|
||||
mikmod.Player_Stop = Player_Stop;
|
||||
mikmod.VC_WriteBytes = VC_WriteBytes;
|
||||
mikmod.drv_nos = &drv_nos;
|
||||
mikmod.md_device = &md_device;
|
||||
mikmod.md_mixfreq = &md_mixfreq;
|
||||
mikmod.md_mode = &md_mode;
|
||||
mikmod.md_musicvolume = &md_musicvolume;
|
||||
mikmod.md_pansep = &md_pansep;
|
||||
mikmod.md_reverb = &md_reverb;
|
||||
mikmod.md_sndfxvolume = &md_sndfxvolume;
|
||||
mikmod.md_volume = &md_volume;
|
||||
}
|
||||
++mikmod.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitMOD()
|
||||
{
|
||||
if ( mikmod.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( mikmod.loaded == 1 ) {
|
||||
}
|
||||
--mikmod.loaded;
|
||||
}
|
||||
#endif /* MOD_DYNAMIC */
|
||||
|
||||
#endif /* MOD_MUSIC */
|
||||
62
apps/plugins/sdl/SDL_mixer/dynamic_mod.h
Normal file
62
apps/plugins/sdl/SDL_mixer/dynamic_mod.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MOD_MUSIC
|
||||
|
||||
#include "mikmod.h"
|
||||
|
||||
typedef struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
|
||||
void (*MikMod_Exit)(void);
|
||||
CHAR* (*MikMod_InfoDriver)(void);
|
||||
CHAR* (*MikMod_InfoLoader)(void);
|
||||
BOOL (*MikMod_Init)(CHAR*);
|
||||
void (*MikMod_RegisterAllLoaders)(void);
|
||||
void (*MikMod_RegisterDriver)(struct MDRIVER*);
|
||||
int* MikMod_errno;
|
||||
char* (*MikMod_strerror)(int);
|
||||
BOOL (*Player_Active)(void);
|
||||
void (*Player_Free)(MODULE*);
|
||||
MODULE* (*Player_LoadGeneric)(MREADER*,int,BOOL);
|
||||
void (*Player_SetPosition)(UWORD);
|
||||
void (*Player_SetVolume)(SWORD);
|
||||
void (*Player_Start)(MODULE*);
|
||||
void (*Player_Stop)(void);
|
||||
ULONG (*VC_WriteBytes)(SBYTE*,ULONG);
|
||||
struct MDRIVER* drv_nos;
|
||||
UWORD* md_device;
|
||||
UWORD* md_mixfreq;
|
||||
UWORD* md_mode;
|
||||
UBYTE* md_musicvolume;
|
||||
UBYTE* md_pansep;
|
||||
UBYTE* md_reverb;
|
||||
UBYTE* md_sndfxvolume;
|
||||
UBYTE* md_volume;
|
||||
} mikmod_loader;
|
||||
|
||||
extern mikmod_loader mikmod;
|
||||
|
||||
#endif /* MOD_MUSIC */
|
||||
|
||||
extern int Mix_InitMOD();
|
||||
extern void Mix_QuitMOD();
|
||||
171
apps/plugins/sdl/SDL_mixer/dynamic_mp3.c
Normal file
171
apps/plugins/sdl/SDL_mixer/dynamic_mp3.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MP3_MUSIC
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
#include "dynamic_mp3.h"
|
||||
|
||||
smpeg_loader smpeg = {
|
||||
0, NULL
|
||||
};
|
||||
|
||||
#ifdef MP3_DYNAMIC
|
||||
int Mix_InitMP3()
|
||||
{
|
||||
if ( smpeg.loaded == 0 ) {
|
||||
smpeg.handle = SDL_LoadObject(MP3_DYNAMIC);
|
||||
if ( smpeg.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_actualSpec =
|
||||
(void (*)( SMPEG *, SDL_AudioSpec * ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_actualSpec");
|
||||
if ( smpeg.SMPEG_actualSpec == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_delete =
|
||||
(void (*)( SMPEG* ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_delete");
|
||||
if ( smpeg.SMPEG_delete == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_enableaudio =
|
||||
(void (*)( SMPEG*, int ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_enableaudio");
|
||||
if ( smpeg.SMPEG_enableaudio == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_enablevideo =
|
||||
(void (*)( SMPEG*, int ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_enablevideo");
|
||||
if ( smpeg.SMPEG_enablevideo == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_new_rwops =
|
||||
(SMPEG* (*)(SDL_RWops *, SMPEG_Info*, int))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_new_rwops");
|
||||
if ( smpeg.SMPEG_new_rwops == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_play =
|
||||
(void (*)( SMPEG* ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_play");
|
||||
if ( smpeg.SMPEG_play == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_playAudio =
|
||||
(int (*)( SMPEG *, Uint8 *, int ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_playAudio");
|
||||
if ( smpeg.SMPEG_playAudio == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_rewind =
|
||||
(void (*)( SMPEG* ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_rewind");
|
||||
if ( smpeg.SMPEG_rewind == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_setvolume =
|
||||
(void (*)( SMPEG*, int ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_setvolume");
|
||||
if ( smpeg.SMPEG_setvolume == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_skip =
|
||||
(void (*)( SMPEG*, float ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_skip");
|
||||
if ( smpeg.SMPEG_skip == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_status =
|
||||
(SMPEGstatus (*)( SMPEG* ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_status");
|
||||
if ( smpeg.SMPEG_status == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
smpeg.SMPEG_stop =
|
||||
(void (*)( SMPEG* ))
|
||||
SDL_LoadFunction(smpeg.handle, "SMPEG_stop");
|
||||
if ( smpeg.SMPEG_stop == NULL ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++smpeg.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitMP3()
|
||||
{
|
||||
if ( smpeg.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( smpeg.loaded == 1 ) {
|
||||
SDL_UnloadObject(smpeg.handle);
|
||||
}
|
||||
--smpeg.loaded;
|
||||
}
|
||||
#else
|
||||
int Mix_InitMP3()
|
||||
{
|
||||
if ( smpeg.loaded == 0 ) {
|
||||
smpeg.SMPEG_actualSpec = SMPEG_actualSpec;
|
||||
smpeg.SMPEG_delete = SMPEG_delete;
|
||||
smpeg.SMPEG_enableaudio = SMPEG_enableaudio;
|
||||
smpeg.SMPEG_enablevideo = SMPEG_enablevideo;
|
||||
smpeg.SMPEG_new_rwops = SMPEG_new_rwops;
|
||||
smpeg.SMPEG_play = SMPEG_play;
|
||||
smpeg.SMPEG_playAudio = SMPEG_playAudio;
|
||||
smpeg.SMPEG_rewind = SMPEG_rewind;
|
||||
smpeg.SMPEG_setvolume = SMPEG_setvolume;
|
||||
smpeg.SMPEG_skip = SMPEG_skip;
|
||||
smpeg.SMPEG_status = SMPEG_status;
|
||||
smpeg.SMPEG_stop = SMPEG_stop;
|
||||
}
|
||||
++smpeg.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitMP3()
|
||||
{
|
||||
if ( smpeg.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( smpeg.loaded == 1 ) {
|
||||
}
|
||||
--smpeg.loaded;
|
||||
}
|
||||
#endif /* MP3_DYNAMIC */
|
||||
|
||||
#endif /* MP3_MUSIC */
|
||||
47
apps/plugins/sdl/SDL_mixer/dynamic_mp3.h
Normal file
47
apps/plugins/sdl/SDL_mixer/dynamic_mp3.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MP3_MUSIC
|
||||
#include "smpeg.h"
|
||||
|
||||
typedef struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
void (*SMPEG_actualSpec)( SMPEG *mpeg, SDL_AudioSpec *spec );
|
||||
void (*SMPEG_delete)( SMPEG* mpeg );
|
||||
void (*SMPEG_enableaudio)( SMPEG* mpeg, int enable );
|
||||
void (*SMPEG_enablevideo)( SMPEG* mpeg, int enable );
|
||||
SMPEG* (*SMPEG_new_rwops)(SDL_RWops *src, SMPEG_Info* info, int sdl_audio);
|
||||
void (*SMPEG_play)( SMPEG* mpeg );
|
||||
int (*SMPEG_playAudio)( SMPEG *mpeg, Uint8 *stream, int len );
|
||||
void (*SMPEG_rewind)( SMPEG* mpeg );
|
||||
void (*SMPEG_setvolume)( SMPEG* mpeg, int volume );
|
||||
void (*SMPEG_skip)( SMPEG* mpeg, float seconds );
|
||||
SMPEGstatus (*SMPEG_status)( SMPEG* mpeg );
|
||||
void (*SMPEG_stop)( SMPEG* mpeg );
|
||||
} smpeg_loader;
|
||||
|
||||
extern smpeg_loader smpeg;
|
||||
|
||||
#endif /* MUSIC_MP3 */
|
||||
|
||||
extern int Mix_InitMP3();
|
||||
extern void Mix_QuitMP3();
|
||||
131
apps/plugins/sdl/SDL_mixer/dynamic_ogg.c
Normal file
131
apps/plugins/sdl/SDL_mixer/dynamic_ogg.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
#include "dynamic_ogg.h"
|
||||
|
||||
vorbis_loader vorbis = {
|
||||
0, NULL
|
||||
};
|
||||
|
||||
#ifdef OGG_DYNAMIC
|
||||
int Mix_InitOgg()
|
||||
{
|
||||
if ( vorbis.loaded == 0 ) {
|
||||
vorbis.handle = SDL_LoadObject(OGG_DYNAMIC);
|
||||
if ( vorbis.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_clear =
|
||||
(int (*)(OggVorbis_File *))
|
||||
SDL_LoadFunction(vorbis.handle, "ov_clear");
|
||||
if ( vorbis.ov_clear == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_info =
|
||||
(vorbis_info *(*)(OggVorbis_File *,int))
|
||||
SDL_LoadFunction(vorbis.handle, "ov_info");
|
||||
if ( vorbis.ov_info == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_open_callbacks =
|
||||
(int (*)(void *, OggVorbis_File *, char *, long, ov_callbacks))
|
||||
SDL_LoadFunction(vorbis.handle, "ov_open_callbacks");
|
||||
if ( vorbis.ov_open_callbacks == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_pcm_total =
|
||||
(ogg_int64_t (*)(OggVorbis_File *,int))
|
||||
SDL_LoadFunction(vorbis.handle, "ov_pcm_total");
|
||||
if ( vorbis.ov_pcm_total == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_read =
|
||||
#ifdef OGG_USE_TREMOR
|
||||
(long (*)(OggVorbis_File *,char *,int,int *))
|
||||
#else
|
||||
(long (*)(OggVorbis_File *,char *,int,int,int,int,int *))
|
||||
#endif
|
||||
SDL_LoadFunction(vorbis.handle, "ov_read");
|
||||
if ( vorbis.ov_read == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
vorbis.ov_time_seek =
|
||||
#ifdef OGG_USE_TREMOR
|
||||
(long (*)(OggVorbis_File *,ogg_int64_t))
|
||||
#else
|
||||
(int (*)(OggVorbis_File *,double))
|
||||
#endif
|
||||
SDL_LoadFunction(vorbis.handle, "ov_time_seek");
|
||||
if ( vorbis.ov_time_seek == NULL ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++vorbis.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitOgg()
|
||||
{
|
||||
if ( vorbis.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( vorbis.loaded == 1 ) {
|
||||
SDL_UnloadObject(vorbis.handle);
|
||||
}
|
||||
--vorbis.loaded;
|
||||
}
|
||||
#else
|
||||
int Mix_InitOgg()
|
||||
{
|
||||
if ( vorbis.loaded == 0 ) {
|
||||
vorbis.ov_clear = ov_clear;
|
||||
vorbis.ov_info = ov_info;
|
||||
vorbis.ov_open_callbacks = ov_open_callbacks;
|
||||
vorbis.ov_pcm_total = ov_pcm_total;
|
||||
vorbis.ov_read = ov_read;
|
||||
vorbis.ov_time_seek = ov_time_seek;
|
||||
}
|
||||
++vorbis.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Mix_QuitOgg()
|
||||
{
|
||||
if ( vorbis.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( vorbis.loaded == 1 ) {
|
||||
}
|
||||
--vorbis.loaded;
|
||||
}
|
||||
#endif /* OGG_DYNAMIC */
|
||||
|
||||
#endif /* OGG_MUSIC */
|
||||
53
apps/plugins/sdl/SDL_mixer/dynamic_ogg.h
Normal file
53
apps/plugins/sdl/SDL_mixer/dynamic_ogg.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
#ifdef OGG_USE_TREMOR
|
||||
#include <tremor/ivorbisfile.h>
|
||||
#else
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
int (*ov_clear)(OggVorbis_File *vf);
|
||||
vorbis_info *(*ov_info)(OggVorbis_File *vf,int link);
|
||||
int (*ov_open_callbacks)(void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks);
|
||||
ogg_int64_t (*ov_pcm_total)(OggVorbis_File *vf,int i);
|
||||
#ifdef OGG_USE_TREMOR
|
||||
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int *bitstream);
|
||||
#else
|
||||
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream);
|
||||
#endif
|
||||
#ifdef OGG_USE_TREMOR
|
||||
int (*ov_time_seek)(OggVorbis_File *vf,ogg_int64_t pos);
|
||||
#else
|
||||
int (*ov_time_seek)(OggVorbis_File *vf,double pos);
|
||||
#endif
|
||||
} vorbis_loader;
|
||||
|
||||
extern vorbis_loader vorbis;
|
||||
|
||||
#endif /* OGG_MUSIC */
|
||||
|
||||
extern int Mix_InitOgg();
|
||||
extern void Mix_QuitOgg();
|
||||
1615
apps/plugins/sdl/SDL_mixer/effect_position.c
Normal file
1615
apps/plugins/sdl/SDL_mixer/effect_position.c
Normal file
File diff suppressed because it is too large
Load diff
117
apps/plugins/sdl/SDL_mixer/effect_stereoreverse.c
Normal file
117
apps/plugins/sdl/SDL_mixer/effect_stereoreverse.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This file by Ryan C. Gordon (icculus@icculus.org)
|
||||
|
||||
These are some internally supported special effects that use SDL_mixer's
|
||||
effect callback API. They are meant for speed over quality. :)
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#define __MIX_INTERNAL_EFFECT__
|
||||
#include "effects_internal.h"
|
||||
|
||||
/* profile code:
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
struct timeval tv1;
|
||||
struct timeval tv2;
|
||||
|
||||
gettimeofday(&tv1, NULL);
|
||||
|
||||
... do your thing here ...
|
||||
|
||||
gettimeofday(&tv2, NULL);
|
||||
printf("%ld\n", tv2.tv_usec - tv1.tv_usec);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Stereo reversal effect...this one's pretty straightforward...
|
||||
*/
|
||||
|
||||
static void _Eff_reversestereo16(int chan, void *stream, int len, void *udata)
|
||||
{
|
||||
/* 16 bits * 2 channels. */
|
||||
Uint32 *ptr = (Uint32 *) stream;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i += sizeof (Uint32), ptr++) {
|
||||
*ptr = (((*ptr) & 0xFFFF0000) >> 16) | (((*ptr) & 0x0000FFFF) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _Eff_reversestereo8(int chan, void *stream, int len, void *udata)
|
||||
{
|
||||
/* 8 bits * 2 channels. */
|
||||
Uint32 *ptr = (Uint32 *) stream;
|
||||
int i;
|
||||
|
||||
/* get the last two bytes if len is not divisible by four... */
|
||||
if (len % sizeof (Uint32) != 0) {
|
||||
Uint16 *p = (Uint16 *) (((Uint8 *) stream) + (len - 2));
|
||||
*p = (Uint16)((((*p) & 0xFF00) >> 8) | (((*ptr) & 0x00FF) << 8));
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += sizeof (Uint32), ptr++) {
|
||||
*ptr = (((*ptr) & 0x0000FF00) >> 8) | (((*ptr) & 0x000000FF) << 8) |
|
||||
(((*ptr) & 0xFF000000) >> 8) | (((*ptr) & 0x00FF0000) << 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Mix_SetReverseStereo(int channel, int flip)
|
||||
{
|
||||
Mix_EffectFunc_t f = NULL;
|
||||
int channels;
|
||||
Uint16 format;
|
||||
|
||||
Mix_QuerySpec(NULL, &format, &channels);
|
||||
|
||||
if (channels == 2) {
|
||||
if ((format & 0xFF) == 16)
|
||||
f = _Eff_reversestereo16;
|
||||
else if ((format & 0xFF) == 8)
|
||||
f = _Eff_reversestereo8;
|
||||
else {
|
||||
Mix_SetError("Unsupported audio format");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!flip) {
|
||||
return(Mix_UnregisterEffect(channel, f));
|
||||
} else {
|
||||
return(Mix_RegisterEffect(channel, f, NULL, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* end of effect_stereoreverse.c ... */
|
||||
|
||||
121
apps/plugins/sdl/SDL_mixer/effects_internal.c
Normal file
121
apps/plugins/sdl/SDL_mixer/effects_internal.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This file by Ryan C. Gordon (icculus@icculus.org)
|
||||
|
||||
These are some helper functions for the internal mixer special effects.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
/* ------ These are used internally only. Don't touch. ------ */
|
||||
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#define __MIX_INTERNAL_EFFECT__
|
||||
#include "effects_internal.h"
|
||||
|
||||
/* Should we favor speed over memory usage and/or quality of output? */
|
||||
int _Mix_effects_max_speed = 0;
|
||||
|
||||
|
||||
void _Mix_InitEffects(void)
|
||||
{
|
||||
_Mix_effects_max_speed = (SDL_getenv(MIX_EFFECTSMAXSPEED) != NULL);
|
||||
}
|
||||
|
||||
void _Mix_DeinitEffects(void)
|
||||
{
|
||||
_Eff_PositionDeinit();
|
||||
}
|
||||
|
||||
|
||||
void *_Eff_volume_table = NULL;
|
||||
|
||||
|
||||
/* Build the volume table for Uint8-format samples.
|
||||
*
|
||||
* Each column of the table is a possible sample, while each row of the
|
||||
* table is a volume. Volume is a Uint8, where 0 is silence and 255 is full
|
||||
* volume. So _Eff_volume_table[128][mysample] would be the value of
|
||||
* mysample, at half volume.
|
||||
*/
|
||||
void *_Eff_build_volume_table_u8(void)
|
||||
{
|
||||
int volume;
|
||||
int sample;
|
||||
Uint8 *rc;
|
||||
|
||||
if (!_Mix_effects_max_speed) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (!_Eff_volume_table) {
|
||||
rc = SDL_malloc(256 * 256);
|
||||
if (rc) {
|
||||
_Eff_volume_table = (void *) rc;
|
||||
for (volume = 0; volume < 256; volume++) {
|
||||
for (sample = -128; sample < 128; sample ++) {
|
||||
*rc = (Uint8)(((float) sample) * ((float) volume / 255.0))
|
||||
+ 128;
|
||||
rc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(_Eff_volume_table);
|
||||
}
|
||||
|
||||
|
||||
/* Build the volume table for Sint8-format samples.
|
||||
*
|
||||
* Each column of the table is a possible sample, while each row of the
|
||||
* table is a volume. Volume is a Uint8, where 0 is silence and 255 is full
|
||||
* volume. So _Eff_volume_table[128][mysample+128] would be the value of
|
||||
* mysample, at half volume.
|
||||
*/
|
||||
void *_Eff_build_volume_table_s8(void)
|
||||
{
|
||||
int volume;
|
||||
int sample;
|
||||
Sint8 *rc;
|
||||
|
||||
if (!_Eff_volume_table) {
|
||||
rc = SDL_malloc(256 * 256);
|
||||
if (rc) {
|
||||
_Eff_volume_table = (void *) rc;
|
||||
for (volume = 0; volume < 256; volume++) {
|
||||
for (sample = -128; sample < 128; sample ++) {
|
||||
*rc = (Sint8)(((float) sample) * ((float) volume / 255.0));
|
||||
rc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(_Eff_volume_table);
|
||||
}
|
||||
|
||||
|
||||
/* end of effects.c ... */
|
||||
|
||||
60
apps/plugins/sdl/SDL_mixer/effects_internal.h
Normal file
60
apps/plugins/sdl/SDL_mixer/effects_internal.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef _INCLUDE_EFFECTS_INTERNAL_H_
|
||||
#define _INCLUDE_EFFECTS_INTERNAL_H_
|
||||
|
||||
#ifndef __MIX_INTERNAL_EFFECT__
|
||||
#error You should not include this file or use these functions.
|
||||
#endif
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int _Mix_effects_max_speed;
|
||||
extern void *_Eff_volume_table;
|
||||
void *_Eff_build_volume_table_u8(void);
|
||||
void *_Eff_build_volume_table_s8(void);
|
||||
|
||||
void _Mix_InitEffects(void);
|
||||
void _Mix_DeinitEffects(void);
|
||||
void _Eff_PositionDeinit(void);
|
||||
|
||||
int _Mix_RegisterEffect_locked(int channel, Mix_EffectFunc_t f,
|
||||
Mix_EffectDone_t d, void *arg);
|
||||
int _Mix_UnregisterEffect_locked(int channel, Mix_EffectFunc_t f);
|
||||
int _Mix_UnregisterAllEffects_locked(int channel);
|
||||
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
219
apps/plugins/sdl/SDL_mixer/fluidsynth.c
Normal file
219
apps/plugins/sdl/SDL_mixer/fluidsynth.c
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
James Le Cuirot
|
||||
chewi@aura-online.co.uk
|
||||
*/
|
||||
|
||||
#ifdef USE_FLUIDSYNTH_MIDI
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "fluidsynth.h"
|
||||
|
||||
static Uint16 format;
|
||||
static Uint8 channels;
|
||||
static int freq;
|
||||
|
||||
int fluidsynth_check_soundfont(const char *path, void *data)
|
||||
{
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if (file) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
} else {
|
||||
Mix_SetError("Failed to access the SoundFont %s", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int fluidsynth_load_soundfont(const char *path, void *data)
|
||||
{
|
||||
/* If this fails, it's too late to try Timidity so pray that at least one works. */
|
||||
fluidsynth.fluid_synth_sfload((fluid_synth_t*) data, path, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fluidsynth_init(SDL_AudioSpec *mixer)
|
||||
{
|
||||
if (!Mix_EachSoundFont(fluidsynth_check_soundfont, NULL))
|
||||
return -1;
|
||||
|
||||
format = mixer->format;
|
||||
channels = mixer->channels;
|
||||
freq = mixer->freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FluidSynthMidiSong *fluidsynth_loadsong_common(int (*function)(FluidSynthMidiSong*, void*), void *data)
|
||||
{
|
||||
FluidSynthMidiSong *song;
|
||||
fluid_settings_t *settings = NULL;
|
||||
|
||||
if (!Mix_Init(MIX_INIT_FLUIDSYNTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((song = SDL_malloc(sizeof(FluidSynthMidiSong)))) {
|
||||
memset(song, 0, sizeof(FluidSynthMidiSong));
|
||||
|
||||
if (SDL_BuildAudioCVT(&song->convert, AUDIO_S16, 2, freq, format, channels, freq) >= 0) {
|
||||
if ((settings = fluidsynth.new_fluid_settings())) {
|
||||
fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) freq);
|
||||
|
||||
if ((song->synth = fluidsynth.new_fluid_synth(settings))) {
|
||||
if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) song->synth)) {
|
||||
if ((song->player = fluidsynth.new_fluid_player(song->synth))) {
|
||||
if (function(song, data)) return song;
|
||||
fluidsynth.delete_fluid_player(song->player);
|
||||
} else {
|
||||
Mix_SetError("Failed to create FluidSynth player");
|
||||
}
|
||||
}
|
||||
fluidsynth.delete_fluid_synth(song->synth);
|
||||
} else {
|
||||
Mix_SetError("Failed to create FluidSynth synthesizer");
|
||||
}
|
||||
fluidsynth.delete_fluid_settings(settings);
|
||||
} else {
|
||||
Mix_SetError("Failed to create FluidSynth settings");
|
||||
}
|
||||
} else {
|
||||
Mix_SetError("Failed to set up audio conversion");
|
||||
}
|
||||
SDL_free(song);
|
||||
} else {
|
||||
Mix_SetError("Insufficient memory for song");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fluidsynth_loadsong_RW_internal(FluidSynthMidiSong *song, void *data)
|
||||
{
|
||||
off_t offset;
|
||||
size_t size;
|
||||
char *buffer;
|
||||
SDL_RWops *rw = (SDL_RWops*) data;
|
||||
|
||||
offset = SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_END);
|
||||
size = SDL_RWtell(rw) - offset;
|
||||
SDL_RWseek(rw, offset, RW_SEEK_SET);
|
||||
|
||||
if ((buffer = (char*) SDL_malloc(size))) {
|
||||
if(SDL_RWread(rw, buffer, size, 1) == 1) {
|
||||
if (fluidsynth.fluid_player_add_mem(song->player, buffer, size) == FLUID_OK) {
|
||||
return 1;
|
||||
} else {
|
||||
Mix_SetError("FluidSynth failed to load in-memory song");
|
||||
}
|
||||
} else {
|
||||
Mix_SetError("Failed to read in-memory song");
|
||||
}
|
||||
SDL_free(buffer);
|
||||
} else {
|
||||
Mix_SetError("Insufficient memory for song");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
FluidSynthMidiSong *song;
|
||||
|
||||
song = fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) rw);
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return song;
|
||||
}
|
||||
|
||||
void fluidsynth_freesong(FluidSynthMidiSong *song)
|
||||
{
|
||||
if (!song) return;
|
||||
fluidsynth.delete_fluid_player(song->player);
|
||||
fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(song->synth));
|
||||
fluidsynth.delete_fluid_synth(song->synth);
|
||||
SDL_free(song);
|
||||
}
|
||||
|
||||
void fluidsynth_start(FluidSynthMidiSong *song)
|
||||
{
|
||||
fluidsynth.fluid_player_set_loop(song->player, 1);
|
||||
fluidsynth.fluid_player_play(song->player);
|
||||
}
|
||||
|
||||
void fluidsynth_stop(FluidSynthMidiSong *song)
|
||||
{
|
||||
fluidsynth.fluid_player_stop(song->player);
|
||||
}
|
||||
|
||||
int fluidsynth_active(FluidSynthMidiSong *song)
|
||||
{
|
||||
return fluidsynth.fluid_player_get_status(song->player) == FLUID_PLAYER_PLAYING ? 1 : 0;
|
||||
}
|
||||
|
||||
void fluidsynth_setvolume(FluidSynthMidiSong *song, int volume)
|
||||
{
|
||||
/* FluidSynth's default is 0.2. Make 0.8 the maximum. */
|
||||
fluidsynth.fluid_synth_set_gain(song->synth, (float) (volume * 0.00625));
|
||||
}
|
||||
|
||||
int fluidsynth_playsome(FluidSynthMidiSong *song, void *dest, int dest_len)
|
||||
{
|
||||
int result = -1;
|
||||
int frames = dest_len / channels / ((format & 0xFF) / 8);
|
||||
int src_len = frames * 4; /* 16-bit stereo */
|
||||
void *src = dest;
|
||||
|
||||
if (dest_len < src_len) {
|
||||
if (!(src = SDL_malloc(src_len))) {
|
||||
Mix_SetError("Insufficient memory for audio conversion");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (fluidsynth.fluid_synth_write_s16(song->synth, frames, src, 0, 2, src, 1, 2) != FLUID_OK) {
|
||||
Mix_SetError("Error generating FluidSynth audio");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
song->convert.buf = src;
|
||||
song->convert.len = src_len;
|
||||
|
||||
if (SDL_ConvertAudio(&song->convert) < 0) {
|
||||
Mix_SetError("Error during audio conversion");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (src != dest)
|
||||
memcpy(dest, src, dest_len);
|
||||
|
||||
result = 0;
|
||||
|
||||
finish:
|
||||
if (src != dest)
|
||||
SDL_free(src);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* USE_FLUIDSYNTH_MIDI */
|
||||
51
apps/plugins/sdl/SDL_mixer/fluidsynth.h
Normal file
51
apps/plugins/sdl/SDL_mixer/fluidsynth.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
James Le Cuirot
|
||||
chewi@aura-online.co.uk
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_H_
|
||||
#define _FLUIDSYNTH_H_
|
||||
|
||||
#ifdef USE_FLUIDSYNTH_MIDI
|
||||
|
||||
#include "dynamic_fluidsynth.h"
|
||||
#include <SDL_rwops.h>
|
||||
#include <SDL_audio.h>
|
||||
|
||||
typedef struct {
|
||||
SDL_AudioCVT convert;
|
||||
fluid_synth_t *synth;
|
||||
fluid_player_t* player;
|
||||
} FluidSynthMidiSong;
|
||||
|
||||
int fluidsynth_init(SDL_AudioSpec *mixer);
|
||||
FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw, int freerw);
|
||||
void fluidsynth_freesong(FluidSynthMidiSong *song);
|
||||
void fluidsynth_start(FluidSynthMidiSong *song);
|
||||
void fluidsynth_stop(FluidSynthMidiSong *song);
|
||||
int fluidsynth_active(FluidSynthMidiSong *song);
|
||||
void fluidsynth_setvolume(FluidSynthMidiSong *song, int volume);
|
||||
int fluidsynth_playsome(FluidSynthMidiSong *song, void *stream, int len);
|
||||
|
||||
#endif /* USE_FLUIDSYNTH_MIDI */
|
||||
|
||||
#endif /* _FLUIDSYNTH_H_ */
|
||||
247
apps/plugins/sdl/SDL_mixer/load_aiff.c
Normal file
247
apps/plugins/sdl/SDL_mixer/load_aiff.c
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode an AIFF file into a waveform.
|
||||
It's pretty straightforward once you get going. The only
|
||||
externally-callable function is Mix_LoadAIFF_RW(), which is meant to
|
||||
act as identically to SDL_LoadWAV_RW() as possible.
|
||||
|
||||
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
|
||||
8SVX file support added by Marc Le Douarain (mavati@club-internet.fr)
|
||||
in december 2002.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_mixer.h"
|
||||
#include "load_aiff.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Define values for AIFF (IFF audio) format */
|
||||
/*********************************************/
|
||||
#define FORM 0x4d524f46 /* "FORM" */
|
||||
|
||||
#define AIFF 0x46464941 /* "AIFF" */
|
||||
#define SSND 0x444e5353 /* "SSND" */
|
||||
#define COMM 0x4d4d4f43 /* "COMM" */
|
||||
|
||||
#define _8SVX 0x58565338 /* "8SVX" */
|
||||
#define VHDR 0x52444856 /* "VHDR" */
|
||||
#define BODY 0x59444F42 /* "BODY" */
|
||||
|
||||
/* This function was taken from libsndfile. I don't pretend to fully
|
||||
* understand it.
|
||||
*/
|
||||
|
||||
static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
|
||||
{
|
||||
/* Is the frequency outside of what we can represent with Uint32? */
|
||||
if ( (sanebuf[0] & 0x80) || (sanebuf[0] <= 0x3F) || (sanebuf[0] > 0x40)
|
||||
|| (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
|
||||
return 0;
|
||||
|
||||
return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
|
||||
| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
|
||||
}
|
||||
|
||||
/* This function is based on SDL_LoadWAV_RW(). */
|
||||
|
||||
SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
{
|
||||
int was_error;
|
||||
int found_SSND;
|
||||
int found_COMM;
|
||||
int found_VHDR;
|
||||
int found_BODY;
|
||||
long start = 0;
|
||||
|
||||
Uint32 chunk_type;
|
||||
Uint32 chunk_length;
|
||||
long next_chunk;
|
||||
|
||||
/* AIFF magic header */
|
||||
Uint32 FORMchunk;
|
||||
Uint32 AIFFmagic;
|
||||
|
||||
/* SSND chunk */
|
||||
Uint32 offset;
|
||||
Uint32 blocksize;
|
||||
|
||||
/* COMM format chunk */
|
||||
Uint16 channels = 0;
|
||||
Uint32 numsamples = 0;
|
||||
Uint16 samplesize = 0;
|
||||
Uint8 sane_freq[10];
|
||||
Uint32 frequency = 0;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
was_error = 0;
|
||||
if ( src == NULL ) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
FORMchunk = SDL_ReadLE32(src);
|
||||
chunk_length = SDL_ReadBE32(src);
|
||||
if ( chunk_length == AIFF ) { /* The FORMchunk has already been read */
|
||||
AIFFmagic = chunk_length;
|
||||
chunk_length = FORMchunk;
|
||||
FORMchunk = FORM;
|
||||
} else {
|
||||
AIFFmagic = SDL_ReadLE32(src);
|
||||
}
|
||||
if ( (FORMchunk != FORM) || ( (AIFFmagic != AIFF) && (AIFFmagic != _8SVX) ) ) {
|
||||
SDL_SetError("Unrecognized file type (not AIFF nor 8SVX)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* TODO: Better santity-checking. */
|
||||
|
||||
found_SSND = 0;
|
||||
found_COMM = 0;
|
||||
found_VHDR = 0;
|
||||
found_BODY = 0;
|
||||
|
||||
do {
|
||||
chunk_type = SDL_ReadLE32(src);
|
||||
chunk_length = SDL_ReadBE32(src);
|
||||
next_chunk = SDL_RWtell(src) + chunk_length;
|
||||
/* Paranoia to avoid infinite loops */
|
||||
if (chunk_length == 0)
|
||||
break;
|
||||
|
||||
switch (chunk_type) {
|
||||
case SSND:
|
||||
found_SSND = 1;
|
||||
offset = SDL_ReadBE32(src);
|
||||
blocksize = SDL_ReadBE32(src);
|
||||
start = SDL_RWtell(src) + offset;
|
||||
break;
|
||||
|
||||
case COMM:
|
||||
found_COMM = 1;
|
||||
channels = SDL_ReadBE16(src);
|
||||
numsamples = SDL_ReadBE32(src);
|
||||
samplesize = SDL_ReadBE16(src);
|
||||
SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
|
||||
frequency = SANE_to_Uint32(sane_freq);
|
||||
if (frequency == 0) {
|
||||
SDL_SetError("Bad AIFF sample frequency");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case VHDR:
|
||||
found_VHDR = 1;
|
||||
SDL_ReadBE32(src);
|
||||
SDL_ReadBE32(src);
|
||||
SDL_ReadBE32(src);
|
||||
frequency = SDL_ReadBE16(src);
|
||||
channels = 1;
|
||||
samplesize = 8;
|
||||
break;
|
||||
|
||||
case BODY:
|
||||
found_BODY = 1;
|
||||
numsamples = chunk_length;
|
||||
start = SDL_RWtell(src);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* a 0 pad byte can be stored for any odd-length chunk */
|
||||
if (chunk_length&1)
|
||||
next_chunk++;
|
||||
} while ( ( ( (AIFFmagic == AIFF) && ( !found_SSND || !found_COMM ) )
|
||||
|| ( (AIFFmagic == _8SVX ) && ( !found_VHDR || !found_BODY ) ) )
|
||||
&& SDL_RWseek(src, next_chunk, RW_SEEK_SET) != 1 );
|
||||
|
||||
if ( (AIFFmagic == AIFF) && !found_SSND ) {
|
||||
SDL_SetError("Bad AIFF (no SSND chunk)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( (AIFFmagic == AIFF) && !found_COMM ) {
|
||||
SDL_SetError("Bad AIFF (no COMM chunk)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( (AIFFmagic == _8SVX) && !found_VHDR ) {
|
||||
SDL_SetError("Bad 8SVX (no VHDR chunk)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( (AIFFmagic == _8SVX) && !found_BODY ) {
|
||||
SDL_SetError("Bad 8SVX (no BODY chunk)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Decode the audio data format */
|
||||
memset(spec, 0, sizeof(*spec));
|
||||
spec->freq = frequency;
|
||||
switch (samplesize) {
|
||||
case 8:
|
||||
spec->format = AUDIO_S8;
|
||||
break;
|
||||
case 16:
|
||||
spec->format = AUDIO_S16MSB;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported AIFF samplesize");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
spec->channels = (Uint8) channels;
|
||||
spec->samples = 4096; /* Good default buffer size */
|
||||
|
||||
*audio_len = channels * numsamples * (samplesize / 8);
|
||||
*audio_buf = (Uint8 *)SDL_malloc(*audio_len);
|
||||
if ( *audio_buf == NULL ) {
|
||||
SDL_SetError("Out of memory");
|
||||
return(NULL);
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( SDL_RWread(src, *audio_buf, *audio_len, 1) != 1 ) {
|
||||
SDL_SetError("Unable to read audio data");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Don't return a buffer that isn't a multiple of samplesize */
|
||||
*audio_len &= ~((samplesize / 8) - 1);
|
||||
|
||||
done:
|
||||
if ( freesrc && src ) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
if ( was_error ) {
|
||||
spec = NULL;
|
||||
}
|
||||
return(spec);
|
||||
}
|
||||
|
||||
31
apps/plugins/sdl/SDL_mixer/load_aiff.h
Normal file
31
apps/plugins/sdl/SDL_mixer/load_aiff.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2009 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
This is the source needed to decode an AIFF file into a waveform.
|
||||
It's pretty straightforward once you get going. The only
|
||||
externally-callable function is Mix_LoadAIFF_RW(), which is meant to
|
||||
act as identically to SDL_LoadWAV_RW() as possible.
|
||||
|
||||
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
|
||||
338
apps/plugins/sdl/SDL_mixer/load_flac.c
Normal file
338
apps/plugins/sdl/SDL_mixer/load_flac.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode a FLAC into a waveform.
|
||||
~ Austen Dicken (admin@cvpcs.org).
|
||||
*/
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "dynamic_flac.h"
|
||||
#include "load_flac.h"
|
||||
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
||||
typedef struct {
|
||||
SDL_RWops* sdl_src;
|
||||
SDL_AudioSpec* sdl_spec;
|
||||
Uint8** sdl_audio_buf;
|
||||
Uint32* sdl_audio_len;
|
||||
int sdl_audio_read;
|
||||
FLAC__uint64 flac_total_samples;
|
||||
unsigned flac_bps;
|
||||
} FLAC_SDL_Data;
|
||||
|
||||
static FLAC__StreamDecoderReadStatus flac_read_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__byte buffer[],
|
||||
size_t *bytes,
|
||||
void *client_data)
|
||||
{
|
||||
// make sure there is something to be reading
|
||||
if (*bytes > 0) {
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
|
||||
*bytes = SDL_RWread (data->sdl_src, buffer, sizeof (FLAC__byte),
|
||||
*bytes);
|
||||
|
||||
if(*bytes < 0) { // error in read
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
else if(*bytes == 0) { // no data was read (EOF)
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
else { // data was read, continue
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderSeekStatus flac_seek_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 absolute_byte_offset,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
|
||||
if (SDL_RWseek (data->sdl_src, absolute_byte_offset, RW_SEEK_SET) < 0) {
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderTellStatus flac_tell_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 *absolute_byte_offset,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->sdl_src);
|
||||
|
||||
if (pos < 0) {
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
*absolute_byte_offset = (FLAC__uint64)pos;
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderLengthStatus flac_length_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 *stream_length,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->sdl_src);
|
||||
int length = SDL_RWseek (data->sdl_src, 0, RW_SEEK_END);
|
||||
|
||||
if (SDL_RWseek (data->sdl_src, pos, RW_SEEK_SET) != pos || length < 0) {
|
||||
/* there was an error attempting to return the stream to the original
|
||||
* position, or the length was invalid. */
|
||||
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
*stream_length = (FLAC__uint64)length;
|
||||
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__bool flac_eof_load_cb(const FLAC__StreamDecoder *decoder,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->sdl_src);
|
||||
int end = SDL_RWseek (data->sdl_src, 0, RW_SEEK_END);
|
||||
|
||||
// was the original position equal to the end (a.k.a. the seek didn't move)?
|
||||
if (pos == end) {
|
||||
// must be EOF
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// not EOF, return to the original position
|
||||
SDL_RWseek (data->sdl_src, pos, RW_SEEK_SET);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus flac_write_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__Frame *frame,
|
||||
const FLAC__int32 *const buffer[],
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
size_t i;
|
||||
Uint8 *buf;
|
||||
|
||||
if (data->flac_total_samples == 0) {
|
||||
SDL_SetError ("Given FLAC file does not specify its sample count.");
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
if (data->sdl_spec->channels != 2 || data->flac_bps != 16) {
|
||||
SDL_SetError ("Current FLAC support is only for 16 bit Stereo files.");
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
// check if it is the first audio frame so we can initialize the output
|
||||
// buffer
|
||||
if (frame->header.number.sample_number == 0) {
|
||||
*(data->sdl_audio_len) = data->sdl_spec->size;
|
||||
data->sdl_audio_read = 0;
|
||||
*(data->sdl_audio_buf) = SDL_malloc (*(data->sdl_audio_len));
|
||||
|
||||
if (*(data->sdl_audio_buf) == NULL) {
|
||||
SDL_SetError
|
||||
("Unable to allocate memory to store the FLAC stream.");
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
buf = *(data->sdl_audio_buf);
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++) {
|
||||
FLAC__int16 i16;
|
||||
FLAC__uint16 ui16;
|
||||
|
||||
i16 = (FLAC__int16)buffer[0][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*(buf + (data->sdl_audio_read++)) = (char)(ui16);
|
||||
*(buf + (data->sdl_audio_read++)) = (char)(ui16 >> 8);
|
||||
|
||||
i16 = (FLAC__int16)buffer[1][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*(buf + (data->sdl_audio_read++)) = (char)(ui16);
|
||||
*(buf + (data->sdl_audio_read++)) = (char)(ui16 >> 8);
|
||||
}
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void flac_metadata_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__StreamMetadata *metadata,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data;
|
||||
FLAC__uint64 total_samples;
|
||||
unsigned bps;
|
||||
|
||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
// save the metadata right now for use later on
|
||||
*(data->sdl_audio_buf) = NULL;
|
||||
*(data->sdl_audio_len) = 0;
|
||||
memset (data->sdl_spec, '\0', sizeof (SDL_AudioSpec));
|
||||
|
||||
data->sdl_spec->format = AUDIO_S16;
|
||||
data->sdl_spec->freq = (int)(metadata->data.stream_info.sample_rate);
|
||||
data->sdl_spec->channels = (Uint8)(metadata->data.stream_info.channels);
|
||||
data->sdl_spec->samples = 8192; /* buffer size */
|
||||
|
||||
total_samples = metadata->data.stream_info.total_samples;
|
||||
bps = metadata->data.stream_info.bits_per_sample;
|
||||
|
||||
data->sdl_spec->size = total_samples * data->sdl_spec->channels *
|
||||
(bps / 8);
|
||||
data->flac_total_samples = total_samples;
|
||||
data->flac_bps = bps;
|
||||
}
|
||||
}
|
||||
|
||||
static void flac_error_load_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
void *client_data)
|
||||
{
|
||||
// print an SDL error based on the error status
|
||||
switch (status) {
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
|
||||
SDL_SetError ("Error processing the FLAC file [LOST_SYNC].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
|
||||
SDL_SetError ("Error processing the FLAC file [BAD_HEADER].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
|
||||
SDL_SetError ("Error processing the FLAC file [CRC_MISMATCH].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
|
||||
SDL_SetError ("Error processing the FLAC file [UNPARSEABLE].");
|
||||
break;
|
||||
default:
|
||||
SDL_SetError ("Error processing the FLAC file [UNKNOWN].");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
{
|
||||
FLAC__StreamDecoder *decoder = 0;
|
||||
FLAC__StreamDecoderInitStatus init_status;
|
||||
int was_error = 1;
|
||||
int was_init = 0;
|
||||
Uint32 samplesize;
|
||||
|
||||
// create the client data passing information
|
||||
FLAC_SDL_Data* client_data;
|
||||
client_data = (FLAC_SDL_Data *)SDL_malloc (sizeof (FLAC_SDL_Data));
|
||||
|
||||
if ((!src) || (!audio_buf) || (!audio_len)) /* sanity checks. */
|
||||
goto done;
|
||||
|
||||
if (!Mix_Init(MIX_INIT_FLAC))
|
||||
goto done;
|
||||
|
||||
if ((decoder = flac.FLAC__stream_decoder_new ()) == NULL) {
|
||||
SDL_SetError ("Unable to allocate FLAC decoder.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
init_status = flac.FLAC__stream_decoder_init_stream (decoder,
|
||||
flac_read_load_cb, flac_seek_load_cb,
|
||||
flac_tell_load_cb, flac_length_load_cb,
|
||||
flac_eof_load_cb, flac_write_load_cb,
|
||||
flac_metadata_load_cb, flac_error_load_cb,
|
||||
client_data);
|
||||
|
||||
if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
|
||||
SDL_SetError ("Unable to initialize FLAC stream decoder.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
was_init = 1;
|
||||
|
||||
client_data->sdl_src = src;
|
||||
client_data->sdl_spec = spec;
|
||||
client_data->sdl_audio_buf = audio_buf;
|
||||
client_data->sdl_audio_len = audio_len;
|
||||
|
||||
if (!flac.FLAC__stream_decoder_process_until_end_of_stream (decoder)) {
|
||||
SDL_SetError ("Unable to process FLAC file.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
was_error = 0;
|
||||
|
||||
/* Don't return a buffer that isn't a multiple of samplesize */
|
||||
samplesize = ((spec->format & 0xFF) / 8) * spec->channels;
|
||||
*audio_len &= ~(samplesize - 1);
|
||||
|
||||
done:
|
||||
if (was_init && decoder) {
|
||||
flac.FLAC__stream_decoder_finish (decoder);
|
||||
}
|
||||
|
||||
if (decoder) {
|
||||
flac.FLAC__stream_decoder_delete (decoder);
|
||||
}
|
||||
|
||||
if (src) {
|
||||
if (freesrc)
|
||||
SDL_RWclose (src);
|
||||
else
|
||||
SDL_RWseek (src, 0, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if (was_error)
|
||||
spec = NULL;
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
#endif // FLAC_MUSIC
|
||||
31
apps/plugins/sdl/SDL_mixer/load_flac.h
Normal file
31
apps/plugins/sdl/SDL_mixer/load_flac.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode a FLAC into a waveform.
|
||||
~ Austen Dicken (admin@cvpcs.org).
|
||||
*/
|
||||
|
||||
/* $Id: $ */
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
|
||||
#endif
|
||||
159
apps/plugins/sdl/SDL_mixer/load_ogg.c
Normal file
159
apps/plugins/sdl/SDL_mixer/load_ogg.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode an Ogg Vorbis into a waveform.
|
||||
This file by Vaclav Slavik (vaclav.slavik@matfyz.cz).
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "dynamic_ogg.h"
|
||||
#include "load_ogg.h"
|
||||
|
||||
static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
|
||||
}
|
||||
|
||||
static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence);
|
||||
}
|
||||
|
||||
static int sdl_close_func_freesrc(void *datasource)
|
||||
{
|
||||
return SDL_RWclose((SDL_RWops*)datasource);
|
||||
}
|
||||
|
||||
static int sdl_close_func_nofreesrc(void *datasource)
|
||||
{
|
||||
return SDL_RWseek((SDL_RWops*)datasource, 0, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
static long sdl_tell_func(void *datasource)
|
||||
{
|
||||
return SDL_RWtell((SDL_RWops*)datasource);
|
||||
}
|
||||
|
||||
|
||||
/* don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
{
|
||||
OggVorbis_File vf;
|
||||
ov_callbacks callbacks;
|
||||
vorbis_info *info;
|
||||
Uint8 *buf;
|
||||
int bitstream = -1;
|
||||
long samplesize;
|
||||
long samples;
|
||||
int read, to_read;
|
||||
int must_close = 1;
|
||||
int was_error = 1;
|
||||
|
||||
if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */
|
||||
goto done;
|
||||
|
||||
if ( !Mix_Init(MIX_INIT_OGG) )
|
||||
goto done;
|
||||
|
||||
callbacks.read_func = sdl_read_func;
|
||||
callbacks.seek_func = sdl_seek_func;
|
||||
callbacks.tell_func = sdl_tell_func;
|
||||
callbacks.close_func = freesrc ?
|
||||
sdl_close_func_freesrc : sdl_close_func_nofreesrc;
|
||||
|
||||
if (vorbis.ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0)
|
||||
{
|
||||
SDL_SetError("OGG bitstream is not valid Vorbis stream!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
must_close = 0;
|
||||
|
||||
info = vorbis.ov_info(&vf, -1);
|
||||
|
||||
*audio_buf = NULL;
|
||||
*audio_len = 0;
|
||||
memset(spec, '\0', sizeof (SDL_AudioSpec));
|
||||
|
||||
spec->format = AUDIO_S16;
|
||||
spec->channels = info->channels;
|
||||
spec->freq = info->rate;
|
||||
spec->samples = 4096; /* buffer size */
|
||||
|
||||
samples = (long)vorbis.ov_pcm_total(&vf, -1);
|
||||
|
||||
*audio_len = spec->size = samples * spec->channels * 2;
|
||||
*audio_buf = SDL_malloc(*audio_len);
|
||||
if (*audio_buf == NULL)
|
||||
goto done;
|
||||
|
||||
buf = *audio_buf;
|
||||
to_read = *audio_len;
|
||||
#ifdef OGG_USE_TREMOR
|
||||
for (read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream);
|
||||
read > 0;
|
||||
read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream))
|
||||
#else
|
||||
for (read = vorbis.ov_read(&vf, (char *)buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream);
|
||||
read > 0;
|
||||
read = vorbis.ov_read(&vf, (char *)buf, to_read, 0, 2, 1, &bitstream))
|
||||
#endif
|
||||
{
|
||||
if (read == OV_HOLE || read == OV_EBADLINK)
|
||||
break; /* error */
|
||||
|
||||
to_read -= read;
|
||||
buf += read;
|
||||
}
|
||||
|
||||
vorbis.ov_clear(&vf);
|
||||
was_error = 0;
|
||||
|
||||
/* Don't return a buffer that isn't a multiple of samplesize */
|
||||
samplesize = ((spec->format & 0xFF)/8)*spec->channels;
|
||||
*audio_len &= ~(samplesize-1);
|
||||
|
||||
done:
|
||||
if (src && must_close)
|
||||
{
|
||||
if (freesrc)
|
||||
SDL_RWclose(src);
|
||||
else
|
||||
SDL_RWseek(src, 0, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if ( was_error )
|
||||
spec = NULL;
|
||||
|
||||
return(spec);
|
||||
} /* Mix_LoadOGG_RW */
|
||||
|
||||
/* end of load_ogg.c ... */
|
||||
|
||||
#endif
|
||||
31
apps/plugins/sdl/SDL_mixer/load_ogg.h
Normal file
31
apps/plugins/sdl/SDL_mixer/load_ogg.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode an Ogg Vorbis into a waveform.
|
||||
This file by Vaclav Slavik (vaclav.slavik@matfyz.cz).
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
|
||||
#endif
|
||||
458
apps/plugins/sdl/SDL_mixer/load_voc.c
Normal file
458
apps/plugins/sdl/SDL_mixer/load_voc.c
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode a Creative Labs VOC file into a
|
||||
waveform. It's pretty straightforward once you get going. The only
|
||||
externally-callable function is Mix_LoadVOC_RW(), which is meant to
|
||||
act as identically to SDL_LoadWAV_RW() as possible.
|
||||
|
||||
This file by Ryan C. Gordon (icculus@icculus.org).
|
||||
|
||||
Heavily borrowed from sox v12.17.1's voc.c.
|
||||
(http://www.freshmeat.net/projects/sox/)
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "load_voc.h"
|
||||
|
||||
/* Private data for VOC file */
|
||||
typedef struct vocstuff {
|
||||
Uint32 rest; /* bytes remaining in current block */
|
||||
Uint32 rate; /* rate code (byte) of this chunk */
|
||||
int silent; /* sound or silence? */
|
||||
Uint32 srate; /* rate code (byte) of silence */
|
||||
Uint32 blockseek; /* start of current output block */
|
||||
Uint32 samples; /* number of samples output */
|
||||
Uint32 size; /* word length of data */
|
||||
Uint8 channels; /* number of sound channels */
|
||||
int has_extended; /* Has an extended block been read? */
|
||||
} vs_t;
|
||||
|
||||
/* Size field */
|
||||
/* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
|
||||
#define ST_SIZE_BYTE 1
|
||||
#define ST_SIZE_8BIT 1
|
||||
#define ST_SIZE_WORD 2
|
||||
#define ST_SIZE_16BIT 2
|
||||
#define ST_SIZE_DWORD 4
|
||||
#define ST_SIZE_32BIT 4
|
||||
#define ST_SIZE_FLOAT 5
|
||||
#define ST_SIZE_DOUBLE 6
|
||||
#define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */
|
||||
|
||||
/* Style field */
|
||||
#define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */
|
||||
#define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */
|
||||
#define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */
|
||||
#define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */
|
||||
#define ST_ENCODING_ADPCM 5 /* Compressed PCM */
|
||||
#define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */
|
||||
#define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */
|
||||
|
||||
#define VOC_TERM 0
|
||||
#define VOC_DATA 1
|
||||
#define VOC_CONT 2
|
||||
#define VOC_SILENCE 3
|
||||
#define VOC_MARKER 4
|
||||
#define VOC_TEXT 5
|
||||
#define VOC_LOOP 6
|
||||
#define VOC_LOOPEND 7
|
||||
#define VOC_EXTENDED 8
|
||||
#define VOC_DATA_16 9
|
||||
|
||||
|
||||
static int voc_check_header(SDL_RWops *src)
|
||||
{
|
||||
/* VOC magic header */
|
||||
Uint8 signature[20]; /* "Creative Voice File\032" */
|
||||
Uint16 datablockofs;
|
||||
|
||||
SDL_RWseek(src, 0, RW_SEEK_SET);
|
||||
|
||||
if (SDL_RWread(src, signature, sizeof (signature), 1) != 1)
|
||||
return(0);
|
||||
|
||||
if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) {
|
||||
SDL_SetError("Unrecognized file type (not VOC)");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* get the offset where the first datablock is located */
|
||||
if (SDL_RWread(src, &datablockofs, sizeof (Uint16), 1) != 1)
|
||||
return(0);
|
||||
|
||||
datablockofs = SDL_SwapLE16(datablockofs);
|
||||
|
||||
if (SDL_RWseek(src, datablockofs, RW_SEEK_SET) != datablockofs)
|
||||
return(0);
|
||||
|
||||
return(1); /* success! */
|
||||
} /* voc_check_header */
|
||||
|
||||
|
||||
/* Read next block header, save info, leave position at start of data */
|
||||
static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
|
||||
{
|
||||
Uint8 bits24[3];
|
||||
Uint8 uc, block;
|
||||
Uint32 sblen;
|
||||
Uint16 new_rate_short;
|
||||
Uint32 new_rate_long;
|
||||
Uint8 trash[6];
|
||||
Uint16 period;
|
||||
unsigned int i;
|
||||
|
||||
v->silent = 0;
|
||||
while (v->rest == 0)
|
||||
{
|
||||
if (SDL_RWread(src, &block, sizeof (block), 1) != 1)
|
||||
return 1; /* assume that's the end of the file. */
|
||||
|
||||
if (block == VOC_TERM)
|
||||
return 1;
|
||||
|
||||
if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1)
|
||||
return 1; /* assume that's the end of the file. */
|
||||
|
||||
/* Size is an 24-bit value. Ugh. */
|
||||
sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) );
|
||||
|
||||
switch(block)
|
||||
{
|
||||
case VOC_DATA:
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
|
||||
/* When DATA block preceeded by an EXTENDED */
|
||||
/* block, the DATA blocks rate value is invalid */
|
||||
if (!v->has_extended)
|
||||
{
|
||||
if (uc == 0)
|
||||
{
|
||||
SDL_SetError("VOC Sample rate is zero?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((v->rate != -1) && (uc != v->rate))
|
||||
{
|
||||
SDL_SetError("VOC sample rate codes differ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
v->rate = uc;
|
||||
spec->freq = (Uint16)(1000000.0/(256 - v->rate));
|
||||
v->channels = 1;
|
||||
}
|
||||
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
|
||||
if (uc != 0)
|
||||
{
|
||||
SDL_SetError("VOC decoder only interprets 8-bit data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
v->has_extended = 0;
|
||||
v->rest = sblen - 2;
|
||||
v->size = ST_SIZE_BYTE;
|
||||
return 1;
|
||||
|
||||
case VOC_DATA_16:
|
||||
if (SDL_RWread(src, &new_rate_long, sizeof (new_rate_long), 1) != 1)
|
||||
return 0;
|
||||
new_rate_long = SDL_SwapLE32(new_rate_long);
|
||||
if (new_rate_long == 0)
|
||||
{
|
||||
SDL_SetError("VOC Sample rate is zero?");
|
||||
return 0;
|
||||
}
|
||||
if ((v->rate != -1) && (new_rate_long != v->rate))
|
||||
{
|
||||
SDL_SetError("VOC sample rate codes differ");
|
||||
return 0;
|
||||
}
|
||||
v->rate = new_rate_long;
|
||||
spec->freq = new_rate_long;
|
||||
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
|
||||
switch (uc)
|
||||
{
|
||||
case 8: v->size = ST_SIZE_BYTE; break;
|
||||
case 16: v->size = ST_SIZE_WORD; break;
|
||||
default:
|
||||
SDL_SetError("VOC with unknown data size");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SDL_RWread(src, &v->channels, sizeof (Uint8), 1) != 1)
|
||||
return 0;
|
||||
|
||||
if (SDL_RWread(src, trash, sizeof (Uint8), 6) != 6)
|
||||
return 0;
|
||||
|
||||
v->rest = sblen - 12;
|
||||
return 1;
|
||||
|
||||
case VOC_CONT:
|
||||
v->rest = sblen;
|
||||
return 1;
|
||||
|
||||
case VOC_SILENCE:
|
||||
if (SDL_RWread(src, &period, sizeof (period), 1) != 1)
|
||||
return 0;
|
||||
period = SDL_SwapLE16(period);
|
||||
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
if (uc == 0)
|
||||
{
|
||||
SDL_SetError("VOC silence sample rate is zero");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some silence-packed files have gratuitously
|
||||
* different sample rate codes in silence.
|
||||
* Adjust period.
|
||||
*/
|
||||
if ((v->rate != -1) && (uc != v->rate))
|
||||
period = (Uint16)((period * (256 - uc))/(256 - v->rate));
|
||||
else
|
||||
v->rate = uc;
|
||||
v->rest = period;
|
||||
v->silent = 1;
|
||||
return 1;
|
||||
|
||||
case VOC_LOOP:
|
||||
case VOC_LOOPEND:
|
||||
for(i = 0; i < sblen; i++) /* skip repeat loops. */
|
||||
{
|
||||
if (SDL_RWread(src, trash, sizeof (Uint8), 1) != 1)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case VOC_EXTENDED:
|
||||
/* An Extended block is followed by a data block */
|
||||
/* Set this byte so we know to use the rate */
|
||||
/* value from the extended block and not the */
|
||||
/* data block. */
|
||||
v->has_extended = 1;
|
||||
if (SDL_RWread(src, &new_rate_short, sizeof (new_rate_short), 1) != 1)
|
||||
return 0;
|
||||
new_rate_short = SDL_SwapLE16(new_rate_short);
|
||||
if (new_rate_short == 0)
|
||||
{
|
||||
SDL_SetError("VOC sample rate is zero");
|
||||
return 0;
|
||||
}
|
||||
if ((v->rate != -1) && (new_rate_short != v->rate))
|
||||
{
|
||||
SDL_SetError("VOC sample rate codes differ");
|
||||
return 0;
|
||||
}
|
||||
v->rate = new_rate_short;
|
||||
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
|
||||
if (uc != 0)
|
||||
{
|
||||
SDL_SetError("VOC decoder only interprets 8-bit data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
|
||||
return 0;
|
||||
|
||||
if (uc)
|
||||
spec->channels = 2; /* Stereo */
|
||||
/* Needed number of channels before finishing
|
||||
compute for rate */
|
||||
spec->freq = (256000000L/(65536L - v->rate))/spec->channels;
|
||||
/* An extended block must be followed by a data */
|
||||
/* block to be valid so loop back to top so it */
|
||||
/* can be grabed. */
|
||||
continue;
|
||||
|
||||
case VOC_MARKER:
|
||||
if (SDL_RWread(src, trash, sizeof (Uint8), 2) != 2)
|
||||
return 0;
|
||||
|
||||
/* Falling! Falling! */
|
||||
|
||||
default: /* text block or other krapola. */
|
||||
for(i = 0; i < sblen; i++)
|
||||
{
|
||||
if (SDL_RWread(src, &trash, sizeof (Uint8), 1) != 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (block == VOC_TEXT)
|
||||
continue; /* get next block */
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int voc_read(SDL_RWops *src, vs_t *v, Uint8 *buf, SDL_AudioSpec *spec)
|
||||
{
|
||||
int done = 0;
|
||||
Uint8 silence = 0x80;
|
||||
|
||||
if (v->rest == 0)
|
||||
{
|
||||
if (!voc_get_block(src, v, spec))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (v->rest == 0)
|
||||
return 0;
|
||||
|
||||
if (v->silent)
|
||||
{
|
||||
if (v->size == ST_SIZE_WORD)
|
||||
silence = 0x00;
|
||||
|
||||
/* Fill in silence */
|
||||
memset(buf, silence, v->rest);
|
||||
done = v->rest;
|
||||
v->rest = 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
done = SDL_RWread(src, buf, 1, v->rest);
|
||||
v->rest -= done;
|
||||
if (v->size == ST_SIZE_WORD)
|
||||
{
|
||||
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
Uint16 *samples = (Uint16 *)buf;
|
||||
for (; v->rest > 0; v->rest -= 2)
|
||||
{
|
||||
*samples = SDL_SwapLE16(*samples);
|
||||
samples++;
|
||||
}
|
||||
#endif
|
||||
done >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
} /* voc_read */
|
||||
|
||||
|
||||
/* don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
{
|
||||
vs_t v;
|
||||
int was_error = 1;
|
||||
int samplesize;
|
||||
Uint8 *fillptr;
|
||||
void *ptr;
|
||||
|
||||
if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */
|
||||
goto done;
|
||||
|
||||
if ( !voc_check_header(src) )
|
||||
goto done;
|
||||
|
||||
v.rate = -1;
|
||||
v.rest = 0;
|
||||
v.has_extended = 0;
|
||||
*audio_buf = NULL;
|
||||
*audio_len = 0;
|
||||
memset(spec, '\0', sizeof (SDL_AudioSpec));
|
||||
|
||||
if (!voc_get_block(src, &v, spec))
|
||||
goto done;
|
||||
|
||||
if (v.rate == -1)
|
||||
{
|
||||
SDL_SetError("VOC data had no sound!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
spec->format = ((v.size == ST_SIZE_WORD) ? AUDIO_S16 : AUDIO_U8);
|
||||
if (spec->channels == 0)
|
||||
spec->channels = v.channels;
|
||||
|
||||
*audio_len = v.rest;
|
||||
*audio_buf = SDL_malloc(v.rest);
|
||||
if (*audio_buf == NULL)
|
||||
goto done;
|
||||
|
||||
fillptr = *audio_buf;
|
||||
|
||||
while (voc_read(src, &v, fillptr, spec) > 0)
|
||||
{
|
||||
if (!voc_get_block(src, &v, spec))
|
||||
goto done;
|
||||
|
||||
*audio_len += v.rest;
|
||||
ptr = SDL_realloc(*audio_buf, *audio_len);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
SDL_free(*audio_buf);
|
||||
*audio_buf = NULL;
|
||||
*audio_len = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*audio_buf = ptr;
|
||||
fillptr = ((Uint8 *) ptr) + (*audio_len - v.rest);
|
||||
}
|
||||
|
||||
spec->samples = (Uint16)(*audio_len / v.size);
|
||||
|
||||
was_error = 0; /* success, baby! */
|
||||
|
||||
/* Don't return a buffer that isn't a multiple of samplesize */
|
||||
samplesize = ((spec->format & 0xFF)/8)*spec->channels;
|
||||
*audio_len &= ~(samplesize-1);
|
||||
|
||||
done:
|
||||
if (src)
|
||||
{
|
||||
if (freesrc)
|
||||
SDL_RWclose(src);
|
||||
else
|
||||
SDL_RWseek(src, 0, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if ( was_error )
|
||||
spec = NULL;
|
||||
|
||||
return(spec);
|
||||
} /* Mix_LoadVOC_RW */
|
||||
|
||||
/* end of load_voc.c ... */
|
||||
36
apps/plugins/sdl/SDL_mixer/load_voc.h
Normal file
36
apps/plugins/sdl/SDL_mixer/load_voc.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This is the source needed to decode a Creative Labs VOC file into a
|
||||
waveform. It's pretty straightforward once you get going. The only
|
||||
externally-callable function is Mix_LoadVOC_RW(), which is meant to
|
||||
act as identically to SDL_LoadWAV_RW() as possible.
|
||||
|
||||
This file by Ryan C. Gordon (icculus@icculus.org).
|
||||
|
||||
Heavily borrowed from sox v12.17.1's voc.c.
|
||||
(http://www.freshmeat.net/projects/sox/)
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
|
||||
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
|
||||
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
|
||||
1484
apps/plugins/sdl/SDL_mixer/mixer.c
Normal file
1484
apps/plugins/sdl/SDL_mixer/mixer.c
Normal file
File diff suppressed because it is too large
Load diff
1599
apps/plugins/sdl/SDL_mixer/music.c
Normal file
1599
apps/plugins/sdl/SDL_mixer/music.c
Normal file
File diff suppressed because it is too large
Load diff
241
apps/plugins/sdl/SDL_mixer/music_cmd.c
Normal file
241
apps/plugins/sdl/SDL_mixer/music_cmd.c
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This file supports an external command for playing music */
|
||||
|
||||
#ifdef CMD_MUSIC
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "music_cmd.h"
|
||||
|
||||
/* Unimplemented */
|
||||
void MusicCMD_SetVolume(int volume)
|
||||
{
|
||||
Mix_SetError("No way to modify external player volume");
|
||||
}
|
||||
|
||||
/* Load a music stream from the given file */
|
||||
MusicCMD *MusicCMD_LoadSong(const char *cmd, const char *file)
|
||||
{
|
||||
MusicCMD *music;
|
||||
|
||||
/* Allocate and fill the music structure */
|
||||
music = (MusicCMD *)SDL_malloc(sizeof *music);
|
||||
if ( music == NULL ) {
|
||||
Mix_SetError("Out of memory");
|
||||
return(NULL);
|
||||
}
|
||||
strncpy(music->file, file, (sizeof music->file)-1);
|
||||
music->file[(sizeof music->file)-1] = '\0';
|
||||
strncpy(music->cmd, cmd, (sizeof music->cmd)-1);
|
||||
music->cmd[(sizeof music->cmd)-1] = '\0';
|
||||
music->pid = 0;
|
||||
|
||||
/* We're done */
|
||||
return(music);
|
||||
}
|
||||
|
||||
/* Parse a command line buffer into arguments */
|
||||
static int ParseCommandLine(char *cmdline, char **argv)
|
||||
{
|
||||
char *bufp;
|
||||
int argc;
|
||||
|
||||
argc = 0;
|
||||
for ( bufp = cmdline; *bufp; ) {
|
||||
/* Skip leading whitespace */
|
||||
while ( isspace(*bufp) ) {
|
||||
++bufp;
|
||||
}
|
||||
/* Skip over argument */
|
||||
if ( *bufp == '"' ) {
|
||||
++bufp;
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
argv[argc] = bufp;
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
/* Skip over word */
|
||||
while ( *bufp && (*bufp != '"') ) {
|
||||
++bufp;
|
||||
}
|
||||
} else {
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
argv[argc] = bufp;
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
/* Skip over word */
|
||||
while ( *bufp && ! isspace(*bufp) ) {
|
||||
++bufp;
|
||||
}
|
||||
}
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
*bufp = '\0';
|
||||
}
|
||||
++bufp;
|
||||
}
|
||||
}
|
||||
if ( argv ) {
|
||||
argv[argc] = NULL;
|
||||
}
|
||||
return(argc);
|
||||
}
|
||||
|
||||
static char **parse_args(char *command, char *last_arg)
|
||||
{
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
/* Parse the command line */
|
||||
argc = ParseCommandLine(command, NULL);
|
||||
if ( last_arg ) {
|
||||
++argc;
|
||||
}
|
||||
argv = (char **)SDL_malloc((argc+1)*(sizeof *argv));
|
||||
if ( argv == NULL ) {
|
||||
return(NULL);
|
||||
}
|
||||
argc = ParseCommandLine(command, argv);
|
||||
|
||||
/* Add last command line argument */
|
||||
if ( last_arg ) {
|
||||
argv[argc++] = last_arg;
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
/* We're ready! */
|
||||
return(argv);
|
||||
}
|
||||
|
||||
/* Start playback of a given music stream */
|
||||
void MusicCMD_Start(MusicCMD *music)
|
||||
{
|
||||
#ifdef HAVE_FORK
|
||||
music->pid = fork();
|
||||
#else
|
||||
music->pid = vfork();
|
||||
#endif
|
||||
switch(music->pid) {
|
||||
/* Failed fork() system call */
|
||||
case -1:
|
||||
Mix_SetError("fork() failed");
|
||||
return;
|
||||
|
||||
/* Child process - executes here */
|
||||
case 0: {
|
||||
char command[PATH_MAX];
|
||||
char **argv;
|
||||
|
||||
/* Unblock signals in case we're called from a thread */
|
||||
{
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
}
|
||||
|
||||
/* Execute the command */
|
||||
strcpy(command, music->cmd);
|
||||
argv = parse_args(command, music->file);
|
||||
if ( argv != NULL ) {
|
||||
execvp(argv[0], argv);
|
||||
}
|
||||
|
||||
/* exec() failed */
|
||||
perror(argv[0]);
|
||||
_exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Parent process - executes here */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop playback of a stream previously started with MusicCMD_Start() */
|
||||
void MusicCMD_Stop(MusicCMD *music)
|
||||
{
|
||||
int status;
|
||||
|
||||
if ( music->pid > 0 ) {
|
||||
while ( kill(music->pid, 0) == 0 ) {
|
||||
kill(music->pid, SIGTERM);
|
||||
sleep(1);
|
||||
waitpid(music->pid, &status, WNOHANG);
|
||||
}
|
||||
music->pid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pause playback of a given music stream */
|
||||
void MusicCMD_Pause(MusicCMD *music)
|
||||
{
|
||||
if ( music->pid > 0 ) {
|
||||
kill(music->pid, SIGSTOP);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume playback of a given music stream */
|
||||
void MusicCMD_Resume(MusicCMD *music)
|
||||
{
|
||||
if ( music->pid > 0 ) {
|
||||
kill(music->pid, SIGCONT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the given music stream */
|
||||
void MusicCMD_FreeSong(MusicCMD *music)
|
||||
{
|
||||
SDL_free(music);
|
||||
}
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int MusicCMD_Active(MusicCMD *music)
|
||||
{
|
||||
int status;
|
||||
int active;
|
||||
|
||||
active = 0;
|
||||
if ( music->pid > 0 ) {
|
||||
waitpid(music->pid, &status, WNOHANG);
|
||||
if ( kill(music->pid, 0) == 0 ) {
|
||||
active = 1;
|
||||
}
|
||||
}
|
||||
return(active);
|
||||
}
|
||||
|
||||
#endif /* CMD_MUSIC */
|
||||
62
apps/plugins/sdl/SDL_mixer/music_cmd.h
Normal file
62
apps/plugins/sdl/SDL_mixer/music_cmd.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This file supports an external command for playing music */
|
||||
|
||||
#ifdef CMD_MUSIC
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__linux__) && defined(__arm__)
|
||||
# include <linux/limits.h>
|
||||
#endif
|
||||
typedef struct {
|
||||
char file[PATH_MAX];
|
||||
char cmd[PATH_MAX];
|
||||
pid_t pid;
|
||||
} MusicCMD;
|
||||
|
||||
/* Unimplemented */
|
||||
extern void MusicCMD_SetVolume(int volume);
|
||||
|
||||
/* Load a music stream from the given file */
|
||||
extern MusicCMD *MusicCMD_LoadSong(const char *cmd, const char *file);
|
||||
|
||||
/* Start playback of a given music stream */
|
||||
extern void MusicCMD_Start(MusicCMD *music);
|
||||
|
||||
/* Stop playback of a stream previously started with MusicCMD_Start() */
|
||||
extern void MusicCMD_Stop(MusicCMD *music);
|
||||
|
||||
/* Pause playback of a given music stream */
|
||||
extern void MusicCMD_Pause(MusicCMD *music);
|
||||
|
||||
/* Resume playback of a given music stream */
|
||||
extern void MusicCMD_Resume(MusicCMD *music);
|
||||
|
||||
/* Close the given music stream */
|
||||
extern void MusicCMD_FreeSong(MusicCMD *music);
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
extern int MusicCMD_Active(MusicCMD *music);
|
||||
|
||||
#endif /* CMD_MUSIC */
|
||||
593
apps/plugins/sdl/SDL_mixer/music_flac.c
Normal file
593
apps/plugins/sdl/SDL_mixer/music_flac.c
Normal file
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
This file is used to support SDL_LoadMUS playback of FLAC files.
|
||||
~ Austen Dicken (admin@cvpcs.org)
|
||||
*/
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "dynamic_flac.h"
|
||||
#include "music_flac.h"
|
||||
|
||||
/* This is the format of the audio mixer data */
|
||||
static SDL_AudioSpec mixer;
|
||||
|
||||
/* Initialize the FLAC player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
int FLAC_init(SDL_AudioSpec *mixerfmt)
|
||||
{
|
||||
mixer = *mixerfmt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Set the volume for an FLAC stream */
|
||||
void FLAC_setvolume(FLAC_music *music, int volume)
|
||||
{
|
||||
music->volume = volume;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderReadStatus flac_read_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__byte buffer[],
|
||||
size_t *bytes,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_music *data = (FLAC_music*)client_data;
|
||||
|
||||
// make sure there is something to be reading
|
||||
if (*bytes > 0) {
|
||||
*bytes = SDL_RWread (data->rwops, buffer, sizeof (FLAC__byte), *bytes);
|
||||
|
||||
if (*bytes < 0) { // error in read
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
else if (*bytes == 0 ) { // no data was read (EOF)
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
else { // data was read, continue
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderSeekStatus flac_seek_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 absolute_byte_offset,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_music *data = (FLAC_music*)client_data;
|
||||
|
||||
if (SDL_RWseek (data->rwops, absolute_byte_offset, RW_SEEK_SET) < 0) {
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderTellStatus flac_tell_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 *absolute_byte_offset,
|
||||
void *client_data )
|
||||
{
|
||||
FLAC_music *data = (FLAC_music*)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->rwops);
|
||||
|
||||
if (pos < 0) {
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
*absolute_byte_offset = (FLAC__uint64)pos;
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderLengthStatus flac_length_music_cb (
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 *stream_length,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_music *data = (FLAC_music*)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->rwops);
|
||||
int length = SDL_RWseek (data->rwops, 0, RW_SEEK_END);
|
||||
|
||||
if (SDL_RWseek (data->rwops, pos, RW_SEEK_SET) != pos || length < 0) {
|
||||
/* there was an error attempting to return the stream to the original
|
||||
* position, or the length was invalid. */
|
||||
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
*stream_length = (FLAC__uint64)length;
|
||||
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__bool flac_eof_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
void *client_data )
|
||||
{
|
||||
FLAC_music *data = (FLAC_music*)client_data;
|
||||
|
||||
int pos = SDL_RWtell (data->rwops);
|
||||
int end = SDL_RWseek (data->rwops, 0, RW_SEEK_END);
|
||||
|
||||
// was the original position equal to the end (a.k.a. the seek didn't move)?
|
||||
if (pos == end) {
|
||||
// must be EOF
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// not EOF, return to the original position
|
||||
SDL_RWseek (data->rwops, pos, RW_SEEK_SET);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus flac_write_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__Frame *frame,
|
||||
const FLAC__int32 *const buffer[],
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_music *data = (FLAC_music *)client_data;
|
||||
size_t i;
|
||||
|
||||
if (data->flac_data.total_samples == 0) {
|
||||
SDL_SetError ("Given FLAC file does not specify its sample count.");
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
if (data->flac_data.channels != 2 ||
|
||||
data->flac_data.bits_per_sample != 16) {
|
||||
SDL_SetError("Current FLAC support is only for 16 bit Stereo files.");
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++) {
|
||||
FLAC__int16 i16;
|
||||
FLAC__uint16 ui16;
|
||||
|
||||
// make sure we still have at least two bytes that can be read (one for
|
||||
// each channel)
|
||||
if (data->flac_data.max_to_read >= 4) {
|
||||
// does the data block exist?
|
||||
if (!data->flac_data.data) {
|
||||
data->flac_data.data_len = data->flac_data.max_to_read;
|
||||
data->flac_data.data_read = 0;
|
||||
|
||||
// create it
|
||||
data->flac_data.data =
|
||||
(char *)SDL_malloc (data->flac_data.data_len);
|
||||
|
||||
if (!data->flac_data.data) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
i16 = (FLAC__int16)buffer[0][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*((data->flac_data.data) + (data->flac_data.data_read++)) =
|
||||
(char)(ui16);
|
||||
*((data->flac_data.data) + (data->flac_data.data_read++)) =
|
||||
(char)(ui16 >> 8);
|
||||
|
||||
i16 = (FLAC__int16)buffer[1][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*((data->flac_data.data) + (data->flac_data.data_read++)) =
|
||||
(char)(ui16);
|
||||
*((data->flac_data.data) + (data->flac_data.data_read++)) =
|
||||
(char)(ui16 >> 8);
|
||||
|
||||
data->flac_data.max_to_read -= 4;
|
||||
|
||||
if (data->flac_data.max_to_read < 4) {
|
||||
// we need to set this so that the read halts from the
|
||||
// FLAC_getsome function.
|
||||
data->flac_data.max_to_read = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we need to write to the overflow
|
||||
if (!data->flac_data.overflow) {
|
||||
data->flac_data.overflow_len =
|
||||
4 * (frame->header.blocksize - i);
|
||||
data->flac_data.overflow_read = 0;
|
||||
|
||||
// make it big enough for the rest of the block
|
||||
data->flac_data.overflow =
|
||||
(char *)SDL_malloc (data->flac_data.overflow_len);
|
||||
|
||||
if (!data->flac_data.overflow) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
i16 = (FLAC__int16)buffer[0][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
|
||||
(char)(ui16);
|
||||
*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
|
||||
(char)(ui16 >> 8);
|
||||
|
||||
i16 = (FLAC__int16)buffer[1][i];
|
||||
ui16 = (FLAC__uint16)i16;
|
||||
|
||||
*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
|
||||
(char)(ui16);
|
||||
*((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
|
||||
(char)(ui16 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void flac_metadata_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__StreamMetadata *metadata,
|
||||
void *client_data)
|
||||
{
|
||||
FLAC_music *data = (FLAC_music *)client_data;
|
||||
|
||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
data->flac_data.sample_rate = metadata->data.stream_info.sample_rate;
|
||||
data->flac_data.channels = metadata->data.stream_info.channels;
|
||||
data->flac_data.total_samples =
|
||||
metadata->data.stream_info.total_samples;
|
||||
data->flac_data.bits_per_sample =
|
||||
metadata->data.stream_info.bits_per_sample;
|
||||
data->flac_data.sample_size = data->flac_data.channels *
|
||||
((data->flac_data.bits_per_sample) / 8);
|
||||
}
|
||||
}
|
||||
|
||||
static void flac_error_music_cb(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
void *client_data)
|
||||
{
|
||||
// print an SDL error based on the error status
|
||||
switch (status) {
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
|
||||
SDL_SetError ("Error processing the FLAC file [LOST_SYNC].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
|
||||
SDL_SetError ("Error processing the FLAC file [BAD_HEADER].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
|
||||
SDL_SetError ("Error processing the FLAC file [CRC_MISMATCH].");
|
||||
break;
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
|
||||
SDL_SetError ("Error processing the FLAC file [UNPARSEABLE].");
|
||||
break;
|
||||
default:
|
||||
SDL_SetError ("Error processing the FLAC file [UNKNOWN].");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an FLAC stream from an SDL_RWops object */
|
||||
FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
FLAC_music *music;
|
||||
int init_stage = 0;
|
||||
int was_error = 1;
|
||||
|
||||
if (!Mix_Init(MIX_INIT_FLAC)) {
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
music = (FLAC_music *)SDL_malloc ( sizeof (*music));
|
||||
if (music) {
|
||||
/* Initialize the music structure */
|
||||
memset (music, 0, (sizeof (*music)));
|
||||
FLAC_stop (music);
|
||||
FLAC_setvolume (music, MIX_MAX_VOLUME);
|
||||
music->section = -1;
|
||||
music->rwops = rw;
|
||||
music->freerw = freerw;
|
||||
music->flac_data.max_to_read = 0;
|
||||
music->flac_data.overflow = NULL;
|
||||
music->flac_data.overflow_len = 0;
|
||||
music->flac_data.overflow_read = 0;
|
||||
music->flac_data.data = NULL;
|
||||
music->flac_data.data_len = 0;
|
||||
music->flac_data.data_read = 0;
|
||||
|
||||
init_stage++; // stage 1!
|
||||
|
||||
music->flac_decoder = flac.FLAC__stream_decoder_new ();
|
||||
|
||||
if (music->flac_decoder != NULL) {
|
||||
init_stage++; // stage 2!
|
||||
|
||||
if (flac.FLAC__stream_decoder_init_stream(
|
||||
music->flac_decoder,
|
||||
flac_read_music_cb, flac_seek_music_cb,
|
||||
flac_tell_music_cb, flac_length_music_cb,
|
||||
flac_eof_music_cb, flac_write_music_cb,
|
||||
flac_metadata_music_cb, flac_error_music_cb,
|
||||
music) == FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
|
||||
init_stage++; // stage 3!
|
||||
|
||||
if (flac.FLAC__stream_decoder_process_until_end_of_metadata
|
||||
(music->flac_decoder)) {
|
||||
was_error = 0;
|
||||
} else {
|
||||
SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("FLAC__stream_decoder_init_stream() failed");
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("FLAC__stream_decoder_new() failed");
|
||||
}
|
||||
|
||||
if (was_error) {
|
||||
switch (init_stage) {
|
||||
case 3:
|
||||
flac.FLAC__stream_decoder_finish( music->flac_decoder );
|
||||
case 2:
|
||||
flac.FLAC__stream_decoder_delete( music->flac_decoder );
|
||||
case 1:
|
||||
case 0:
|
||||
SDL_free(music);
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return music;
|
||||
}
|
||||
|
||||
/* Start playback of a given FLAC stream */
|
||||
void FLAC_play(FLAC_music *music)
|
||||
{
|
||||
music->playing = 1;
|
||||
}
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int FLAC_playing(FLAC_music *music)
|
||||
{
|
||||
return(music->playing);
|
||||
}
|
||||
|
||||
/* Read some FLAC stream data and convert it for output */
|
||||
static void FLAC_getsome(FLAC_music *music)
|
||||
{
|
||||
SDL_AudioCVT *cvt;
|
||||
|
||||
/* GET AUDIO WAVE DATA */
|
||||
// set the max number of characters to read
|
||||
music->flac_data.max_to_read = 8192;
|
||||
music->flac_data.data_len = music->flac_data.max_to_read;
|
||||
music->flac_data.data_read = 0;
|
||||
if (!music->flac_data.data) {
|
||||
music->flac_data.data = (char *)SDL_malloc (music->flac_data.data_len);
|
||||
}
|
||||
|
||||
// we have data to read
|
||||
while(music->flac_data.max_to_read > 0) {
|
||||
// first check if there is data in the overflow from before
|
||||
if (music->flac_data.overflow) {
|
||||
size_t overflow_len = music->flac_data.overflow_read;
|
||||
|
||||
if (overflow_len > music->flac_data.max_to_read) {
|
||||
size_t overflow_extra_len = overflow_len -
|
||||
music->flac_data.max_to_read;
|
||||
|
||||
memcpy (music->flac_data.data+music->flac_data.data_read,
|
||||
music->flac_data.overflow, music->flac_data.max_to_read);
|
||||
music->flac_data.data_read += music->flac_data.max_to_read;
|
||||
memcpy (music->flac_data.overflow,
|
||||
music->flac_data.overflow + music->flac_data.max_to_read,
|
||||
overflow_extra_len);
|
||||
music->flac_data.overflow_len = overflow_extra_len;
|
||||
music->flac_data.overflow_read = overflow_extra_len;
|
||||
music->flac_data.max_to_read = 0;
|
||||
}
|
||||
else {
|
||||
memcpy (music->flac_data.data+music->flac_data.data_read,
|
||||
music->flac_data.overflow, overflow_len);
|
||||
music->flac_data.data_read += overflow_len;
|
||||
free (music->flac_data.overflow);
|
||||
music->flac_data.overflow = NULL;
|
||||
music->flac_data.overflow_len = 0;
|
||||
music->flac_data.overflow_read = 0;
|
||||
music->flac_data.max_to_read -= overflow_len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!flac.FLAC__stream_decoder_process_single (
|
||||
music->flac_decoder)) {
|
||||
music->flac_data.max_to_read = 0;
|
||||
}
|
||||
|
||||
if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
|
||||
== FLAC__STREAM_DECODER_END_OF_STREAM) {
|
||||
music->flac_data.max_to_read = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (music->flac_data.data_read <= 0) {
|
||||
if (music->flac_data.data_read == 0) {
|
||||
music->playing = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
cvt = &music->cvt;
|
||||
if (music->section < 0) {
|
||||
|
||||
SDL_BuildAudioCVT (cvt, AUDIO_S16, (Uint8)music->flac_data.channels,
|
||||
(int)music->flac_data.sample_rate, mixer.format,
|
||||
mixer.channels, mixer.freq);
|
||||
if (cvt->buf) {
|
||||
free (cvt->buf);
|
||||
}
|
||||
cvt->buf = (Uint8 *)SDL_malloc (music->flac_data.data_len * cvt->len_mult);
|
||||
music->section = 0;
|
||||
}
|
||||
if (cvt->buf) {
|
||||
memcpy (cvt->buf, music->flac_data.data, music->flac_data.data_read);
|
||||
if (cvt->needed) {
|
||||
cvt->len = music->flac_data.data_read;
|
||||
SDL_ConvertAudio (cvt);
|
||||
}
|
||||
else {
|
||||
cvt->len_cvt = music->flac_data.data_read;
|
||||
}
|
||||
music->len_available = music->cvt.len_cvt;
|
||||
music->snd_available = music->cvt.buf;
|
||||
}
|
||||
else {
|
||||
SDL_SetError ("Out of memory");
|
||||
music->playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Play some of a stream previously started with FLAC_play() */
|
||||
int FLAC_playAudio(FLAC_music *music, Uint8 *snd, int len)
|
||||
{
|
||||
int mixable;
|
||||
|
||||
while ((len > 0) && music->playing) {
|
||||
if (!music->len_available) {
|
||||
FLAC_getsome (music);
|
||||
}
|
||||
mixable = len;
|
||||
if (mixable > music->len_available) {
|
||||
mixable = music->len_available;
|
||||
}
|
||||
if (music->volume == MIX_MAX_VOLUME) {
|
||||
memcpy (snd, music->snd_available, mixable);
|
||||
}
|
||||
else {
|
||||
SDL_MixAudio (snd, music->snd_available, mixable, music->volume);
|
||||
}
|
||||
music->len_available -= mixable;
|
||||
music->snd_available += mixable;
|
||||
len -= mixable;
|
||||
snd += mixable;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Stop playback of a stream previously started with FLAC_play() */
|
||||
void FLAC_stop(FLAC_music *music)
|
||||
{
|
||||
music->playing = 0;
|
||||
}
|
||||
|
||||
/* Close the given FLAC_music object */
|
||||
void FLAC_delete(FLAC_music *music)
|
||||
{
|
||||
if (music) {
|
||||
if (music->flac_decoder) {
|
||||
flac.FLAC__stream_decoder_finish (music->flac_decoder);
|
||||
flac.FLAC__stream_decoder_delete (music->flac_decoder);
|
||||
}
|
||||
|
||||
if (music->flac_data.data) {
|
||||
free (music->flac_data.data);
|
||||
}
|
||||
|
||||
if (music->flac_data.overflow) {
|
||||
free (music->flac_data.overflow);
|
||||
}
|
||||
|
||||
if (music->cvt.buf) {
|
||||
free (music->cvt.buf);
|
||||
}
|
||||
|
||||
if (music->freerw) {
|
||||
SDL_RWclose(music->rwops);
|
||||
}
|
||||
free (music);
|
||||
}
|
||||
}
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
void FLAC_jump_to_time(FLAC_music *music, double time)
|
||||
{
|
||||
if (music) {
|
||||
if (music->flac_decoder) {
|
||||
double seek_sample = music->flac_data.sample_rate * time;
|
||||
|
||||
// clear data if it has data
|
||||
if (music->flac_data.data) {
|
||||
free (music->flac_data.data);
|
||||
music->flac_data.data = NULL;
|
||||
}
|
||||
|
||||
// clear overflow if it has data
|
||||
if (music->flac_data.overflow) {
|
||||
free (music->flac_data.overflow);
|
||||
music->flac_data.overflow = NULL;
|
||||
}
|
||||
|
||||
if (!flac.FLAC__stream_decoder_seek_absolute (music->flac_decoder,
|
||||
(FLAC__uint64)seek_sample)) {
|
||||
if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
|
||||
== FLAC__STREAM_DECODER_SEEK_ERROR) {
|
||||
flac.FLAC__stream_decoder_flush (music->flac_decoder);
|
||||
}
|
||||
|
||||
SDL_SetError
|
||||
("Seeking of FLAC stream failed: libFLAC seek failed.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_SetError
|
||||
("Seeking of FLAC stream failed: FLAC decoder was NULL.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_SetError ("Seeking of FLAC stream failed: music was NULL.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FLAC_MUSIC */
|
||||
90
apps/plugins/sdl/SDL_mixer/music_flac.h
Normal file
90
apps/plugins/sdl/SDL_mixer/music_flac.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Header to handle loading FLAC music files in SDL.
|
||||
~ Austen Dicken (admin@cvpcs.org)
|
||||
*/
|
||||
|
||||
/* $Id: $ */
|
||||
|
||||
#ifdef FLAC_MUSIC
|
||||
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
||||
typedef struct {
|
||||
FLAC__uint64 sample_size;
|
||||
unsigned sample_rate;
|
||||
unsigned channels;
|
||||
unsigned bits_per_sample;
|
||||
FLAC__uint64 total_samples;
|
||||
|
||||
// the following are used to handle the callback nature of the writer
|
||||
int max_to_read;
|
||||
char *data; // pointer to beginning of data array
|
||||
int data_len; // size of data array
|
||||
int data_read; // amount of data array used
|
||||
char *overflow; // pointer to beginning of overflow array
|
||||
int overflow_len; // size of overflow array
|
||||
int overflow_read; // amount of overflow array used
|
||||
} FLAC_Data;
|
||||
|
||||
typedef struct {
|
||||
int playing;
|
||||
int volume;
|
||||
int section;
|
||||
FLAC__StreamDecoder *flac_decoder;
|
||||
FLAC_Data flac_data;
|
||||
SDL_RWops *rwops;
|
||||
int freerw;
|
||||
SDL_AudioCVT cvt;
|
||||
int len_available;
|
||||
Uint8 *snd_available;
|
||||
} FLAC_music;
|
||||
|
||||
/* Initialize the FLAC player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
extern int FLAC_init(SDL_AudioSpec *mixer);
|
||||
|
||||
/* Set the volume for a FLAC stream */
|
||||
extern void FLAC_setvolume(FLAC_music *music, int volume);
|
||||
|
||||
/* Load an FLAC stream from an SDL_RWops object */
|
||||
extern FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw);
|
||||
|
||||
/* Start playback of a given FLAC stream */
|
||||
extern void FLAC_play(FLAC_music *music);
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
extern int FLAC_playing(FLAC_music *music);
|
||||
|
||||
/* Play some of a stream previously started with FLAC_play() */
|
||||
extern int FLAC_playAudio(FLAC_music *music, Uint8 *stream, int len);
|
||||
|
||||
/* Stop playback of a stream previously started with FLAC_play() */
|
||||
extern void FLAC_stop(FLAC_music *music);
|
||||
|
||||
/* Close the given FLAC stream */
|
||||
extern void FLAC_delete(FLAC_music *music);
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
extern void FLAC_jump_to_time(FLAC_music *music, double time);
|
||||
|
||||
#endif /* FLAC_MUSIC */
|
||||
325
apps/plugins/sdl/SDL_mixer/music_mad.c
Normal file
325
apps/plugins/sdl/SDL_mixer/music_mad.c
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MP3_MAD_MUSIC
|
||||
|
||||
#include "music_mad.h"
|
||||
|
||||
mad_data *
|
||||
mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw)
|
||||
{
|
||||
mad_data *mp3_mad;
|
||||
|
||||
mp3_mad = (mad_data *)SDL_malloc(sizeof(mad_data));
|
||||
if (mp3_mad) {
|
||||
mp3_mad->rw = rw;
|
||||
mp3_mad->freerw = freerw;
|
||||
mad_stream_init(&mp3_mad->stream);
|
||||
mad_frame_init(&mp3_mad->frame);
|
||||
mad_synth_init(&mp3_mad->synth);
|
||||
mp3_mad->frames_read = 0;
|
||||
mad_timer_reset(&mp3_mad->next_frame_start);
|
||||
mp3_mad->volume = MIX_MAX_VOLUME;
|
||||
mp3_mad->status = 0;
|
||||
mp3_mad->output_begin = 0;
|
||||
mp3_mad->output_end = 0;
|
||||
mp3_mad->mixer = *mixer;
|
||||
}
|
||||
return mp3_mad;
|
||||
}
|
||||
|
||||
void
|
||||
mad_closeFile(mad_data *mp3_mad)
|
||||
{
|
||||
mad_stream_finish(&mp3_mad->stream);
|
||||
mad_frame_finish(&mp3_mad->frame);
|
||||
mad_synth_finish(&mp3_mad->synth);
|
||||
|
||||
if (mp3_mad->freerw) {
|
||||
SDL_RWclose(mp3_mad->rw);
|
||||
}
|
||||
SDL_free(mp3_mad);
|
||||
}
|
||||
|
||||
/* Starts the playback. */
|
||||
void
|
||||
mad_start(mad_data *mp3_mad) {
|
||||
mp3_mad->status |= MS_playing;
|
||||
}
|
||||
|
||||
/* Stops the playback. */
|
||||
void
|
||||
mad_stop(mad_data *mp3_mad) {
|
||||
mp3_mad->status &= ~MS_playing;
|
||||
}
|
||||
|
||||
/* Returns true if the playing is engaged, false otherwise. */
|
||||
int
|
||||
mad_isPlaying(mad_data *mp3_mad) {
|
||||
return ((mp3_mad->status & MS_playing) != 0);
|
||||
}
|
||||
|
||||
/* Reads the next frame from the file. Returns true on success or
|
||||
false on failure. */
|
||||
static int
|
||||
read_next_frame(mad_data *mp3_mad) {
|
||||
if (mp3_mad->stream.buffer == NULL ||
|
||||
mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
|
||||
size_t read_size;
|
||||
size_t remaining;
|
||||
unsigned char *read_start;
|
||||
|
||||
/* There might be some bytes in the buffer left over from last
|
||||
time. If so, move them down and read more bytes following
|
||||
them. */
|
||||
if (mp3_mad->stream.next_frame != NULL) {
|
||||
remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
|
||||
memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
|
||||
read_start = mp3_mad->input_buffer + remaining;
|
||||
read_size = MAD_INPUT_BUFFER_SIZE - remaining;
|
||||
|
||||
} else {
|
||||
read_size = MAD_INPUT_BUFFER_SIZE;
|
||||
read_start = mp3_mad->input_buffer;
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
/* Now read additional bytes from the input file. */
|
||||
read_size = SDL_RWread(mp3_mad->rw, read_start, 1, read_size);
|
||||
|
||||
if (read_size <= 0) {
|
||||
if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
|
||||
if (read_size == 0) {
|
||||
mp3_mad->status |= MS_input_eof;
|
||||
} else {
|
||||
mp3_mad->status |= MS_input_error;
|
||||
}
|
||||
|
||||
/* At the end of the file, we must stuff MAD_BUFFER_GUARD
|
||||
number of 0 bytes. */
|
||||
memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
|
||||
read_size += MAD_BUFFER_GUARD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now feed those bytes into the libmad stream. */
|
||||
mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
|
||||
read_size + remaining);
|
||||
mp3_mad->stream.error = MAD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Now ask libmad to extract a frame from the data we just put in
|
||||
its buffer. */
|
||||
if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
|
||||
if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
|
||||
return 0;
|
||||
|
||||
} else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
mp3_mad->status |= MS_decode_error;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mp3_mad->frames_read++;
|
||||
mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Scale a MAD sample to 16 bits for output. */
|
||||
static signed int
|
||||
scale(mad_fixed_t sample) {
|
||||
/* round */
|
||||
sample += (1L << (MAD_F_FRACBITS - 16));
|
||||
|
||||
/* clip */
|
||||
if (sample >= MAD_F_ONE)
|
||||
sample = MAD_F_ONE - 1;
|
||||
else if (sample < -MAD_F_ONE)
|
||||
sample = -MAD_F_ONE;
|
||||
|
||||
/* quantize */
|
||||
return sample >> (MAD_F_FRACBITS + 1 - 16);
|
||||
}
|
||||
|
||||
/* Once the frame has been read, copies its samples into the output
|
||||
buffer. */
|
||||
static void
|
||||
decode_frame(mad_data *mp3_mad) {
|
||||
struct mad_pcm *pcm;
|
||||
unsigned int nchannels, nsamples;
|
||||
mad_fixed_t const *left_ch, *right_ch;
|
||||
unsigned char *out;
|
||||
int ret;
|
||||
|
||||
mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
|
||||
pcm = &mp3_mad->synth.pcm;
|
||||
out = mp3_mad->output_buffer + mp3_mad->output_end;
|
||||
|
||||
if ((mp3_mad->status & MS_cvt_decoded) == 0) {
|
||||
mp3_mad->status |= MS_cvt_decoded;
|
||||
|
||||
/* The first frame determines some key properties of the stream.
|
||||
In particular, it tells us enough to set up the convert
|
||||
structure now. */
|
||||
SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels, mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);
|
||||
}
|
||||
|
||||
/* pcm->samplerate contains the sampling frequency */
|
||||
|
||||
nchannels = pcm->channels;
|
||||
nsamples = pcm->length;
|
||||
left_ch = pcm->samples[0];
|
||||
right_ch = pcm->samples[1];
|
||||
|
||||
while (nsamples--) {
|
||||
signed int sample;
|
||||
|
||||
/* output sample(s) in 16-bit signed little-endian PCM */
|
||||
|
||||
sample = scale(*left_ch++);
|
||||
*out++ = ((sample >> 0) & 0xff);
|
||||
*out++ = ((sample >> 8) & 0xff);
|
||||
|
||||
if (nchannels == 2) {
|
||||
sample = scale(*right_ch++);
|
||||
*out++ = ((sample >> 0) & 0xff);
|
||||
*out++ = ((sample >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
mp3_mad->output_end = out - mp3_mad->output_buffer;
|
||||
/*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
|
||||
}
|
||||
|
||||
int
|
||||
mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len) {
|
||||
int bytes_remaining;
|
||||
int num_bytes;
|
||||
Uint8 *out;
|
||||
|
||||
if ((mp3_mad->status & MS_playing) == 0) {
|
||||
/* We're not supposed to be playing, so send silence instead. */
|
||||
memset(stream, 0, len);
|
||||
return;
|
||||
}
|
||||
|
||||
out = stream;
|
||||
bytes_remaining = len;
|
||||
while (bytes_remaining > 0) {
|
||||
if (mp3_mad->output_end == mp3_mad->output_begin) {
|
||||
/* We need to get a new frame. */
|
||||
mp3_mad->output_begin = 0;
|
||||
mp3_mad->output_end = 0;
|
||||
if (!read_next_frame(mp3_mad)) {
|
||||
if ((mp3_mad->status & MS_error_flags) != 0) {
|
||||
/* Couldn't read a frame; either an error condition or
|
||||
end-of-file. Stop. */
|
||||
memset(out, 0, bytes_remaining);
|
||||
mp3_mad->status &= ~MS_playing;
|
||||
return bytes_remaining;
|
||||
}
|
||||
} else {
|
||||
decode_frame(mp3_mad);
|
||||
|
||||
/* Now convert the frame data to the appropriate format for
|
||||
output. */
|
||||
mp3_mad->cvt.buf = mp3_mad->output_buffer;
|
||||
mp3_mad->cvt.len = mp3_mad->output_end;
|
||||
|
||||
mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
|
||||
/*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
|
||||
SDL_ConvertAudio(&mp3_mad->cvt);
|
||||
}
|
||||
}
|
||||
|
||||
num_bytes = mp3_mad->output_end - mp3_mad->output_begin;
|
||||
if (bytes_remaining < num_bytes) {
|
||||
num_bytes = bytes_remaining;
|
||||
}
|
||||
|
||||
if (mp3_mad->volume == MIX_MAX_VOLUME) {
|
||||
memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
|
||||
} else {
|
||||
SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
|
||||
num_bytes, mp3_mad->volume);
|
||||
}
|
||||
out += num_bytes;
|
||||
mp3_mad->output_begin += num_bytes;
|
||||
bytes_remaining -= num_bytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mad_seek(mad_data *mp3_mad, double position) {
|
||||
mad_timer_t target;
|
||||
int int_part;
|
||||
|
||||
int_part = (int)position;
|
||||
mad_timer_set(&target, int_part,
|
||||
(int)((position - int_part) * 1000000), 1000000);
|
||||
|
||||
if (mad_timer_compare(mp3_mad->next_frame_start, target) > 0) {
|
||||
/* In order to seek backwards in a VBR file, we have to rewind and
|
||||
start again from the beginning. This isn't necessary if the
|
||||
file happens to be CBR, of course; in that case we could seek
|
||||
directly to the frame we want. But I leave that little
|
||||
optimization for the future developer who discovers she really
|
||||
needs it. */
|
||||
mp3_mad->frames_read = 0;
|
||||
mad_timer_reset(&mp3_mad->next_frame_start);
|
||||
mp3_mad->status &= ~MS_error_flags;
|
||||
mp3_mad->output_begin = 0;
|
||||
mp3_mad->output_end = 0;
|
||||
|
||||
SDL_RWseek(mp3_mad->rw, 0, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
/* Now we have to skip frames until we come to the right one.
|
||||
Again, only truly necessary if the file is VBR. */
|
||||
while (mad_timer_compare(mp3_mad->next_frame_start, target) < 0) {
|
||||
if (!read_next_frame(mp3_mad)) {
|
||||
if ((mp3_mad->status & MS_error_flags) != 0) {
|
||||
/* Couldn't read a frame; either an error condition or
|
||||
end-of-file. Stop. */
|
||||
mp3_mad->status &= ~MS_playing;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we are, at the beginning of the frame that contains the
|
||||
target time. Ehh, I say that's close enough. If we wanted to,
|
||||
we could get more precise by decoding the frame now and counting
|
||||
the appropriate number of samples out of it. */
|
||||
}
|
||||
|
||||
void
|
||||
mad_setVolume(mad_data *mp3_mad, int volume) {
|
||||
mp3_mad->volume = volume;
|
||||
}
|
||||
|
||||
|
||||
#endif /* MP3_MAD_MUSIC */
|
||||
72
apps/plugins/sdl/SDL_mixer/music_mad.h
Normal file
72
apps/plugins/sdl/SDL_mixer/music_mad.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef MP3_MAD_MUSIC
|
||||
|
||||
#include "mad.h"
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#define MAD_INPUT_BUFFER_SIZE (5*8192)
|
||||
#define MAD_OUTPUT_BUFFER_SIZE 8192
|
||||
|
||||
enum {
|
||||
MS_input_eof = 0x0001,
|
||||
MS_input_error = 0x0001,
|
||||
MS_decode_eof = 0x0002,
|
||||
MS_decode_error = 0x0004,
|
||||
MS_error_flags = 0x000f,
|
||||
|
||||
MS_playing = 0x0100,
|
||||
MS_cvt_decoded = 0x0200,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
SDL_RWops *rw;
|
||||
int freerw;
|
||||
struct mad_stream stream;
|
||||
struct mad_frame frame;
|
||||
struct mad_synth synth;
|
||||
int frames_read;
|
||||
mad_timer_t next_frame_start;
|
||||
int volume;
|
||||
int status;
|
||||
int output_begin, output_end;
|
||||
SDL_AudioSpec mixer;
|
||||
SDL_AudioCVT cvt;
|
||||
|
||||
unsigned char input_buffer[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
|
||||
unsigned char output_buffer[MAD_OUTPUT_BUFFER_SIZE];
|
||||
} mad_data;
|
||||
|
||||
mad_data *mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw);
|
||||
void mad_closeFile(mad_data *mp3_mad);
|
||||
|
||||
void mad_start(mad_data *mp3_mad);
|
||||
void mad_stop(mad_data *mp3_mad);
|
||||
int mad_isPlaying(mad_data *mp3_mad);
|
||||
|
||||
int mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len);
|
||||
void mad_seek(mad_data *mp3_mad, double position);
|
||||
void mad_setVolume(mad_data *mp3_mad, int volume);
|
||||
|
||||
#endif
|
||||
346
apps/plugins/sdl/SDL_mixer/music_mod.c
Normal file
346
apps/plugins/sdl/SDL_mixer/music_mod.c
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id: music_mod.c 4211 2008-12-08 00:27:32Z slouken $ */
|
||||
|
||||
#ifdef MOD_MUSIC
|
||||
|
||||
/* This file supports MOD tracker music streams */
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "dynamic_mod.h"
|
||||
#include "music_mod.h"
|
||||
|
||||
#include "mikmod.h"
|
||||
|
||||
#define SDL_SURROUND
|
||||
#ifdef SDL_SURROUND
|
||||
#define MAX_OUTPUT_CHANNELS 6
|
||||
#else
|
||||
#define MAX_OUTPUT_CHANNELS 2
|
||||
#endif
|
||||
|
||||
/* Reference for converting mikmod output to 4/6 channels */
|
||||
static int current_output_channels;
|
||||
static Uint16 current_output_format;
|
||||
|
||||
static int music_swap8;
|
||||
static int music_swap16;
|
||||
|
||||
/* Initialize the MOD player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
int MOD_init(SDL_AudioSpec *mixerfmt)
|
||||
{
|
||||
CHAR *list;
|
||||
|
||||
if ( !Mix_Init(MIX_INIT_MOD) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the MikMod music format */
|
||||
music_swap8 = 0;
|
||||
music_swap16 = 0;
|
||||
switch (mixerfmt->format) {
|
||||
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S8: {
|
||||
if ( mixerfmt->format == AUDIO_S8 ) {
|
||||
music_swap8 = 1;
|
||||
}
|
||||
*mikmod.md_mode = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
case AUDIO_S16MSB: {
|
||||
/* See if we need to correct MikMod mixing */
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
if ( mixerfmt->format == AUDIO_S16MSB ) {
|
||||
#else
|
||||
if ( mixerfmt->format == AUDIO_S16LSB ) {
|
||||
#endif
|
||||
music_swap16 = 1;
|
||||
}
|
||||
*mikmod.md_mode = DMODE_16BITS;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
Mix_SetError("Unknown hardware audio format");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
current_output_channels = mixerfmt->channels;
|
||||
current_output_format = mixerfmt->format;
|
||||
if ( mixerfmt->channels > 1 ) {
|
||||
if ( mixerfmt->channels > MAX_OUTPUT_CHANNELS ) {
|
||||
Mix_SetError("Hardware uses more channels than mixerfmt");
|
||||
return -1;
|
||||
}
|
||||
*mikmod.md_mode |= DMODE_STEREO;
|
||||
}
|
||||
*mikmod.md_mixfreq = mixerfmt->freq;
|
||||
*mikmod.md_device = 0;
|
||||
*mikmod.md_volume = 96;
|
||||
*mikmod.md_musicvolume = 128;
|
||||
*mikmod.md_sndfxvolume = 128;
|
||||
*mikmod.md_pansep = 128;
|
||||
*mikmod.md_reverb = 0;
|
||||
*mikmod.md_mode |= DMODE_HQMIXER|DMODE_SOFT_MUSIC|DMODE_SURROUND;
|
||||
|
||||
list = mikmod.MikMod_InfoDriver();
|
||||
if ( list )
|
||||
free(list);
|
||||
else
|
||||
mikmod.MikMod_RegisterDriver(mikmod.drv_nos);
|
||||
|
||||
list = mikmod.MikMod_InfoLoader();
|
||||
if ( list )
|
||||
free(list);
|
||||
else
|
||||
mikmod.MikMod_RegisterAllLoaders();
|
||||
|
||||
if ( mikmod.MikMod_Init(NULL) ) {
|
||||
Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Uninitialize the music players */
|
||||
void MOD_exit(void)
|
||||
{
|
||||
if (mikmod.MikMod_Exit) {
|
||||
mikmod.MikMod_Exit();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the volume for a MOD stream */
|
||||
void MOD_setvolume(MODULE *music, int volume)
|
||||
{
|
||||
mikmod.Player_SetVolume((SWORD)volume);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MREADER mr;
|
||||
long offset;
|
||||
long eof;
|
||||
SDL_RWops *rw;
|
||||
} LMM_MREADER;
|
||||
|
||||
BOOL LMM_Seek(struct MREADER *mr,long to,int dir)
|
||||
{
|
||||
LMM_MREADER* lmmmr = (LMM_MREADER*)mr;
|
||||
if ( dir == SEEK_SET ) {
|
||||
to += lmmmr->offset;
|
||||
}
|
||||
return (SDL_RWseek(lmmmr->rw, to, dir) < lmmmr->offset);
|
||||
}
|
||||
long LMM_Tell(struct MREADER *mr)
|
||||
{
|
||||
LMM_MREADER* lmmmr = (LMM_MREADER*)mr;
|
||||
return SDL_RWtell(lmmmr->rw) - lmmmr->offset;
|
||||
}
|
||||
BOOL LMM_Read(struct MREADER *mr,void *buf,size_t sz)
|
||||
{
|
||||
LMM_MREADER* lmmmr = (LMM_MREADER*)mr;
|
||||
return SDL_RWread(lmmmr->rw, buf, sz, 1);
|
||||
}
|
||||
int LMM_Get(struct MREADER *mr)
|
||||
{
|
||||
unsigned char c;
|
||||
LMM_MREADER* lmmmr = (LMM_MREADER*)mr;
|
||||
if ( SDL_RWread(lmmmr->rw, &c, 1, 1) ) {
|
||||
return c;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
BOOL LMM_Eof(struct MREADER *mr)
|
||||
{
|
||||
long offset;
|
||||
LMM_MREADER* lmmmr = (LMM_MREADER*)mr;
|
||||
offset = LMM_Tell(mr);
|
||||
return offset >= lmmmr->eof;
|
||||
}
|
||||
MODULE *MikMod_LoadSongRW(SDL_RWops *rw, int maxchan)
|
||||
{
|
||||
LMM_MREADER lmmmr = {
|
||||
{ LMM_Seek, LMM_Tell, LMM_Read, LMM_Get, LMM_Eof },
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
lmmmr.offset = SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_END);
|
||||
lmmmr.eof = SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, lmmmr.offset, RW_SEEK_SET);
|
||||
lmmmr.rw = rw;
|
||||
return mikmod.Player_LoadGeneric((MREADER*)&lmmmr, maxchan, 0);
|
||||
}
|
||||
|
||||
/* Load a MOD stream from an SDL_RWops object */
|
||||
MODULE *MOD_new_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
MODULE *module;
|
||||
|
||||
/* Make sure the mikmod library is loaded */
|
||||
if ( !Mix_Init(MIX_INIT_MOD) ) {
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module = MikMod_LoadSongRW(rw,64);
|
||||
if (!module) {
|
||||
Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno));
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Stop implicit looping, fade out and other flags. */
|
||||
module->extspd = 1;
|
||||
module->panflag = 1;
|
||||
module->wrap = 0;
|
||||
module->loop = 0;
|
||||
#if 0 /* Don't set fade out by default - unfortunately there's no real way
|
||||
to query the status of the song or set trigger actions. Hum. */
|
||||
module->fadeout = 1;
|
||||
#endif
|
||||
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
/* Start playback of a given MOD stream */
|
||||
void MOD_play(MODULE *music)
|
||||
{
|
||||
mikmod.Player_Start(music);
|
||||
}
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int MOD_playing(MODULE *music)
|
||||
{
|
||||
return mikmod.Player_Active();
|
||||
}
|
||||
|
||||
/* Play some of a stream previously started with MOD_play() */
|
||||
int MOD_playAudio(MODULE *music, Uint8 *stream, int len)
|
||||
{
|
||||
if (current_output_channels > 2) {
|
||||
int small_len = 2 * len / current_output_channels;
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
mikmod.VC_WriteBytes((SBYTE *)stream, small_len);
|
||||
/* and extend to len by copying channels */
|
||||
src = stream + small_len;
|
||||
dst = stream + len;
|
||||
|
||||
switch (current_output_format & 0xFF) {
|
||||
case 8:
|
||||
for ( i=small_len/2; i; --i ) {
|
||||
src -= 2;
|
||||
dst -= current_output_channels;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
dst[3] = src[1];
|
||||
if (current_output_channels == 6) {
|
||||
dst[4] = src[0];
|
||||
dst[5] = src[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
for ( i=small_len/4; i; --i ) {
|
||||
src -= 4;
|
||||
dst -= 2 * current_output_channels;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
dst[4] = src[0];
|
||||
dst[5] = src[1];
|
||||
dst[6] = src[2];
|
||||
dst[7] = src[3];
|
||||
if (current_output_channels == 6) {
|
||||
dst[8] = src[0];
|
||||
dst[9] = src[1];
|
||||
dst[10] = src[2];
|
||||
dst[11] = src[3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mikmod.VC_WriteBytes((SBYTE *)stream, len);
|
||||
}
|
||||
if ( music_swap8 ) {
|
||||
Uint8 *dst;
|
||||
int i;
|
||||
|
||||
dst = stream;
|
||||
for ( i=len; i; --i ) {
|
||||
*dst++ ^= 0x80;
|
||||
}
|
||||
} else
|
||||
if ( music_swap16 ) {
|
||||
Uint8 *dst, tmp;
|
||||
int i;
|
||||
|
||||
dst = stream;
|
||||
for ( i=(len/2); i; --i ) {
|
||||
tmp = dst[0];
|
||||
dst[0] = dst[1];
|
||||
dst[1] = tmp;
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stop playback of a stream previously started with MOD_play() */
|
||||
void MOD_stop(MODULE *music)
|
||||
{
|
||||
mikmod.Player_Stop();
|
||||
}
|
||||
|
||||
/* Close the given MOD stream */
|
||||
void MOD_delete(MODULE *music)
|
||||
{
|
||||
mikmod.Player_Free(music);
|
||||
}
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
void MOD_jump_to_time(MODULE *music, double time)
|
||||
{
|
||||
mikmod.Player_SetPosition((UWORD)time);
|
||||
}
|
||||
|
||||
#endif /* MOD_MUSIC */
|
||||
62
apps/plugins/sdl/SDL_mixer/music_mod.h
Normal file
62
apps/plugins/sdl/SDL_mixer/music_mod.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id: music_mod.h 4211 2008-12-08 00:27:32Z slouken $ */
|
||||
|
||||
#ifdef MOD_MUSIC
|
||||
|
||||
/* This file supports MOD tracker music streams */
|
||||
|
||||
struct MODULE;
|
||||
|
||||
/* Initialize the Ogg Vorbis player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
extern int MOD_init(SDL_AudioSpec *mixer);
|
||||
|
||||
/* Uninitialize the music players */
|
||||
extern void MOD_exit(void);
|
||||
|
||||
/* Set the volume for a MOD stream */
|
||||
extern void MOD_setvolume(struct MODULE *music, int volume);
|
||||
|
||||
/* Load a MOD stream from an SDL_RWops object */
|
||||
extern struct MODULE *MOD_new_RW(SDL_RWops *rw, int freerw);
|
||||
|
||||
/* Start playback of a given MOD stream */
|
||||
extern void MOD_play(struct MODULE *music);
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
extern int MOD_playing(struct MODULE *music);
|
||||
|
||||
/* Play some of a stream previously started with MOD_play() */
|
||||
extern int MOD_playAudio(struct MODULE *music, Uint8 *stream, int len);
|
||||
|
||||
/* Stop playback of a stream previously started with MOD_play() */
|
||||
extern void MOD_stop(struct MODULE *music);
|
||||
|
||||
/* Close the given MOD stream */
|
||||
extern void MOD_delete(struct MODULE *music);
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
extern void MOD_jump_to_time(struct MODULE *music, double time);
|
||||
|
||||
#endif /* MOD_MUSIC */
|
||||
239
apps/plugins/sdl/SDL_mixer/music_modplug.c
Normal file
239
apps/plugins/sdl/SDL_mixer/music_modplug.c
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
#ifdef MODPLUG_MUSIC
|
||||
|
||||
#include "music_modplug.h"
|
||||
|
||||
static int current_output_channels=0;
|
||||
static int music_swap8=0;
|
||||
static int music_swap16=0;
|
||||
static ModPlug_Settings settings;
|
||||
|
||||
int modplug_init(SDL_AudioSpec *spec)
|
||||
{
|
||||
ModPlug_GetSettings(&settings);
|
||||
settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING;
|
||||
current_output_channels=spec->channels;
|
||||
settings.mChannels=spec->channels>1?2:1;
|
||||
settings.mBits=spec->format&0xFF;
|
||||
|
||||
music_swap8 = 0;
|
||||
music_swap16 = 0;
|
||||
|
||||
switch(spec->format)
|
||||
{
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S8: {
|
||||
if ( spec->format == AUDIO_S8 ) {
|
||||
music_swap8 = 1;
|
||||
}
|
||||
settings.mBits=8;
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
case AUDIO_S16MSB: {
|
||||
/* See if we need to correct MikMod mixing */
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
if ( spec->format == AUDIO_S16MSB ) {
|
||||
#else
|
||||
if ( spec->format == AUDIO_S16LSB ) {
|
||||
#endif
|
||||
music_swap16 = 1;
|
||||
}
|
||||
settings.mBits=16;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
Mix_SetError("Unknown hardware audio format");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
settings.mFrequency=spec->freq; /*TODO: limit to 11025, 22050, or 44100 ? */
|
||||
settings.mResamplingMode=MODPLUG_RESAMPLE_FIR;
|
||||
settings.mReverbDepth=0;
|
||||
settings.mReverbDelay=100;
|
||||
settings.mBassAmount=0;
|
||||
settings.mBassRange=50;
|
||||
settings.mSurroundDepth=0;
|
||||
settings.mSurroundDelay=10;
|
||||
settings.mLoopCount=0;
|
||||
ModPlug_SetSettings(&settings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Uninitialize the music players */
|
||||
void modplug_exit()
|
||||
{
|
||||
}
|
||||
|
||||
/* Set the volume for a modplug stream */
|
||||
void modplug_setvolume(modplug_data *music, int volume)
|
||||
{
|
||||
ModPlug_SetMasterVolume(music->file, volume*4);
|
||||
}
|
||||
|
||||
/* Load a modplug stream from an SDL_RWops object */
|
||||
modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
modplug_data *music=NULL;
|
||||
long offset,sz;
|
||||
char *buf=NULL;
|
||||
|
||||
offset = SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_END);
|
||||
sz = SDL_RWtell(rw)-offset;
|
||||
SDL_RWseek(rw, offset, RW_SEEK_SET);
|
||||
buf=(char*)SDL_malloc(sz);
|
||||
if(buf)
|
||||
{
|
||||
if(SDL_RWread(rw, buf, sz, 1)==1)
|
||||
{
|
||||
music=(modplug_data*)SDL_malloc(sizeof(modplug_data));
|
||||
if (music)
|
||||
{
|
||||
music->playing=0;
|
||||
music->file=ModPlug_Load(buf,sz);
|
||||
if(!music->file)
|
||||
{
|
||||
SDL_free(music);
|
||||
music=NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
}
|
||||
SDL_free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return music;
|
||||
}
|
||||
|
||||
/* Start playback of a given modplug stream */
|
||||
void modplug_play(modplug_data *music)
|
||||
{
|
||||
ModPlug_Seek(music->file,0);
|
||||
music->playing=1;
|
||||
}
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int modplug_playing(modplug_data *music)
|
||||
{
|
||||
return music && music->playing;
|
||||
}
|
||||
|
||||
/* Play some of a stream previously started with modplug_play() */
|
||||
int modplug_playAudio(modplug_data *music, Uint8 *stream, int len)
|
||||
{
|
||||
if (current_output_channels > 2) {
|
||||
int small_len = 2 * len / current_output_channels;
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
i=ModPlug_Read(music->file, stream, small_len);
|
||||
if(i<small_len)
|
||||
{
|
||||
memset(stream+i,0,small_len-i);
|
||||
music->playing=0;
|
||||
}
|
||||
/* and extend to len by copying channels */
|
||||
src = stream + small_len;
|
||||
dst = stream + len;
|
||||
|
||||
switch (settings.mBits) {
|
||||
case 8:
|
||||
for ( i=small_len/2; i; --i ) {
|
||||
src -= 2;
|
||||
dst -= current_output_channels;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
dst[3] = src[1];
|
||||
if (current_output_channels == 6) {
|
||||
dst[4] = src[0];
|
||||
dst[5] = src[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
for ( i=small_len/4; i; --i ) {
|
||||
src -= 4;
|
||||
dst -= 2 * current_output_channels;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
dst[4] = src[0];
|
||||
dst[5] = src[1];
|
||||
dst[6] = src[2];
|
||||
dst[7] = src[3];
|
||||
if (current_output_channels == 6) {
|
||||
dst[8] = src[0];
|
||||
dst[9] = src[1];
|
||||
dst[10] = src[2];
|
||||
dst[11] = src[3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int i=ModPlug_Read(music->file, stream, len);
|
||||
if(i<len)
|
||||
{
|
||||
memset(stream+i,0,len-i);
|
||||
music->playing=0;
|
||||
}
|
||||
}
|
||||
if ( music_swap8 ) {
|
||||
Uint8 *dst;
|
||||
int i;
|
||||
|
||||
dst = stream;
|
||||
for ( i=len; i; --i ) {
|
||||
*dst++ ^= 0x80;
|
||||
}
|
||||
} else
|
||||
if ( music_swap16 ) {
|
||||
Uint8 *dst, tmp;
|
||||
int i;
|
||||
|
||||
dst = stream;
|
||||
for ( i=(len/2); i; --i ) {
|
||||
tmp = dst[0];
|
||||
dst[0] = dst[1];
|
||||
dst[1] = tmp;
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stop playback of a stream previously started with modplug_play() */
|
||||
void modplug_stop(modplug_data *music)
|
||||
{
|
||||
music->playing=0;
|
||||
}
|
||||
|
||||
/* Close the given modplug stream */
|
||||
void modplug_delete(modplug_data *music)
|
||||
{
|
||||
ModPlug_Unload(music->file);
|
||||
SDL_free(music);
|
||||
}
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
void modplug_jump_to_time(modplug_data *music, double time)
|
||||
{
|
||||
ModPlug_Seek(music->file,(int)(time*1000));
|
||||
}
|
||||
|
||||
#endif
|
||||
42
apps/plugins/sdl/SDL_mixer/music_modplug.h
Normal file
42
apps/plugins/sdl/SDL_mixer/music_modplug.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifdef MODPLUG_MUSIC
|
||||
|
||||
#include "modplug.h"
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
typedef struct {
|
||||
ModPlugFile *file;
|
||||
int playing;
|
||||
} modplug_data;
|
||||
|
||||
int modplug_init(SDL_AudioSpec *mixer);
|
||||
|
||||
/* Uninitialize the music players */
|
||||
void modplug_exit(void);
|
||||
|
||||
/* Set the volume for a modplug stream */
|
||||
void modplug_setvolume(modplug_data *music, int volume);
|
||||
|
||||
/* Load a modplug stream from an SDL_RWops object */
|
||||
modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw);
|
||||
|
||||
/* Start playback of a given modplug stream */
|
||||
void modplug_play(modplug_data *music);
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int modplug_playing(modplug_data *music);
|
||||
|
||||
/* Play some of a stream previously started with modplug_play() */
|
||||
int modplug_playAudio(modplug_data *music, Uint8 *stream, int len);
|
||||
|
||||
/* Stop playback of a stream previously started with modplug_play() */
|
||||
void modplug_stop(modplug_data *music);
|
||||
|
||||
/* Close the given modplug stream */
|
||||
void modplug_delete(modplug_data *music);
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
void modplug_jump_to_time(modplug_data *music, double time);
|
||||
|
||||
#endif
|
||||
230
apps/plugins/sdl/SDL_mixer/music_ogg.c
Normal file
230
apps/plugins/sdl/SDL_mixer/music_ogg.c
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
|
||||
/* This file supports Ogg Vorbis music streams */
|
||||
|
||||
#include "SDL_mixer.h"
|
||||
#include "dynamic_ogg.h"
|
||||
#include "music_ogg.h"
|
||||
|
||||
/* This is the format of the audio mixer data */
|
||||
static SDL_AudioSpec mixer;
|
||||
|
||||
/* Initialize the Ogg Vorbis player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
int OGG_init(SDL_AudioSpec *mixerfmt)
|
||||
{
|
||||
mixer = *mixerfmt;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Set the volume for an OGG stream */
|
||||
void OGG_setvolume(OGG_music *music, int volume)
|
||||
{
|
||||
music->volume = volume;
|
||||
}
|
||||
|
||||
static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
|
||||
}
|
||||
|
||||
static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence);
|
||||
}
|
||||
|
||||
static long sdl_tell_func(void *datasource)
|
||||
{
|
||||
return SDL_RWtell((SDL_RWops*)datasource);
|
||||
}
|
||||
|
||||
/* Load an OGG stream from an SDL_RWops object */
|
||||
OGG_music *OGG_new_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
OGG_music *music;
|
||||
ov_callbacks callbacks;
|
||||
|
||||
if ( !Mix_Init(MIX_INIT_OGG) ) {
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
SDL_memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.read_func = sdl_read_func;
|
||||
callbacks.seek_func = sdl_seek_func;
|
||||
callbacks.tell_func = sdl_tell_func;
|
||||
|
||||
music = (OGG_music *)SDL_malloc(sizeof *music);
|
||||
if ( music ) {
|
||||
/* Initialize the music structure */
|
||||
memset(music, 0, (sizeof *music));
|
||||
music->rw = rw;
|
||||
music->freerw = freerw;
|
||||
OGG_stop(music);
|
||||
OGG_setvolume(music, MIX_MAX_VOLUME);
|
||||
music->section = -1;
|
||||
|
||||
if ( vorbis.ov_open_callbacks(rw, &music->vf, NULL, 0, callbacks) < 0 ) {
|
||||
SDL_free(music);
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
SDL_SetError("Not an Ogg Vorbis audio stream");
|
||||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
if ( freerw ) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
SDL_OutOfMemory();
|
||||
return(NULL);
|
||||
}
|
||||
return(music);
|
||||
}
|
||||
|
||||
/* Start playback of a given OGG stream */
|
||||
void OGG_play(OGG_music *music)
|
||||
{
|
||||
music->playing = 1;
|
||||
}
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
int OGG_playing(OGG_music *music)
|
||||
{
|
||||
return(music->playing);
|
||||
}
|
||||
|
||||
/* Read some Ogg stream data and convert it for output */
|
||||
static void OGG_getsome(OGG_music *music)
|
||||
{
|
||||
int section;
|
||||
int len;
|
||||
char data[4096];
|
||||
SDL_AudioCVT *cvt;
|
||||
|
||||
#ifdef OGG_USE_TREMOR
|
||||
len = vorbis.ov_read(&music->vf, data, sizeof(data), §ion);
|
||||
#else
|
||||
len = vorbis.ov_read(&music->vf, data, sizeof(data), 0, 2, 1, §ion);
|
||||
#endif
|
||||
if ( len <= 0 ) {
|
||||
if ( len == 0 ) {
|
||||
music->playing = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
cvt = &music->cvt;
|
||||
if ( section != music->section ) {
|
||||
vorbis_info *vi;
|
||||
|
||||
vi = vorbis.ov_info(&music->vf, -1);
|
||||
SDL_BuildAudioCVT(cvt, AUDIO_S16, vi->channels, vi->rate,
|
||||
mixer.format,mixer.channels,mixer.freq);
|
||||
if ( cvt->buf ) {
|
||||
SDL_free(cvt->buf);
|
||||
}
|
||||
cvt->buf = (Uint8 *)SDL_malloc(sizeof(data)*cvt->len_mult);
|
||||
music->section = section;
|
||||
}
|
||||
if ( cvt->buf ) {
|
||||
memcpy(cvt->buf, data, len);
|
||||
if ( cvt->needed ) {
|
||||
cvt->len = len;
|
||||
SDL_ConvertAudio(cvt);
|
||||
} else {
|
||||
cvt->len_cvt = len;
|
||||
}
|
||||
music->len_available = music->cvt.len_cvt;
|
||||
music->snd_available = music->cvt.buf;
|
||||
} else {
|
||||
SDL_SetError("Out of memory");
|
||||
music->playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Play some of a stream previously started with OGG_play() */
|
||||
int OGG_playAudio(OGG_music *music, Uint8 *snd, int len)
|
||||
{
|
||||
int mixable;
|
||||
|
||||
while ( (len > 0) && music->playing ) {
|
||||
if ( ! music->len_available ) {
|
||||
OGG_getsome(music);
|
||||
}
|
||||
mixable = len;
|
||||
if ( mixable > music->len_available ) {
|
||||
mixable = music->len_available;
|
||||
}
|
||||
if ( music->volume == MIX_MAX_VOLUME ) {
|
||||
memcpy(snd, music->snd_available, mixable);
|
||||
} else {
|
||||
SDL_MixAudio(snd, music->snd_available, mixable,
|
||||
music->volume);
|
||||
}
|
||||
music->len_available -= mixable;
|
||||
music->snd_available += mixable;
|
||||
len -= mixable;
|
||||
snd += mixable;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Stop playback of a stream previously started with OGG_play() */
|
||||
void OGG_stop(OGG_music *music)
|
||||
{
|
||||
music->playing = 0;
|
||||
}
|
||||
|
||||
/* Close the given OGG stream */
|
||||
void OGG_delete(OGG_music *music)
|
||||
{
|
||||
if ( music ) {
|
||||
if ( music->cvt.buf ) {
|
||||
SDL_free(music->cvt.buf);
|
||||
}
|
||||
if ( music->freerw ) {
|
||||
SDL_RWclose(music->rw);
|
||||
}
|
||||
vorbis.ov_clear(&music->vf);
|
||||
SDL_free(music);
|
||||
}
|
||||
}
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
void OGG_jump_to_time(OGG_music *music, double time)
|
||||
{
|
||||
#ifdef OGG_USE_TREMOR
|
||||
vorbis.ov_time_seek( &music->vf, (ogg_int64_t)time );
|
||||
#else
|
||||
vorbis.ov_time_seek( &music->vf, time );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* OGG_MUSIC */
|
||||
75
apps/plugins/sdl/SDL_mixer/music_ogg.h
Normal file
75
apps/plugins/sdl/SDL_mixer/music_ogg.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef OGG_MUSIC
|
||||
|
||||
/* This file supports Ogg Vorbis music streams */
|
||||
|
||||
#ifdef OGG_USE_TREMOR
|
||||
#include <tremor/ivorbisfile.h>
|
||||
#else
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
SDL_RWops *rw;
|
||||
int freerw;
|
||||
int playing;
|
||||
int volume;
|
||||
OggVorbis_File vf;
|
||||
int section;
|
||||
SDL_AudioCVT cvt;
|
||||
int len_available;
|
||||
Uint8 *snd_available;
|
||||
} OGG_music;
|
||||
|
||||
/* Initialize the Ogg Vorbis player, with the given mixer settings
|
||||
This function returns 0, or -1 if there was an error.
|
||||
*/
|
||||
extern int OGG_init(SDL_AudioSpec *mixer);
|
||||
|
||||
/* Set the volume for an OGG stream */
|
||||
extern void OGG_setvolume(OGG_music *music, int volume);
|
||||
|
||||
/* Load an OGG stream from an SDL_RWops object */
|
||||
extern OGG_music *OGG_new_RW(SDL_RWops *rw, int freerw);
|
||||
|
||||
/* Start playback of a given OGG stream */
|
||||
extern void OGG_play(OGG_music *music);
|
||||
|
||||
/* Return non-zero if a stream is currently playing */
|
||||
extern int OGG_playing(OGG_music *music);
|
||||
|
||||
/* Play some of a stream previously started with OGG_play() */
|
||||
extern int OGG_playAudio(OGG_music *music, Uint8 *stream, int len);
|
||||
|
||||
/* Stop playback of a stream previously started with OGG_play() */
|
||||
extern void OGG_stop(OGG_music *music);
|
||||
|
||||
/* Close the given OGG stream */
|
||||
extern void OGG_delete(OGG_music *music);
|
||||
|
||||
/* Jump (seek) to a given position (time is in seconds) */
|
||||
extern void OGG_jump_to_time(OGG_music *music, double time);
|
||||
|
||||
#endif /* OGG_MUSIC */
|
||||
38
apps/plugins/sdl/SDL_mixer/native_midi/native_midi.h
Normal file
38
apps/plugins/sdl/SDL_mixer/native_midi/native_midi.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
native_midi: Hardware Midi support for the SDL_mixer library
|
||||
Copyright (C) 2000 Florian 'Proff' Schulze <florian.proff.schulze@gmx.net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef _NATIVE_MIDI_H_
|
||||
#define _NATIVE_MIDI_H_
|
||||
|
||||
#include <SDL_rwops.h>
|
||||
|
||||
typedef struct _NativeMidiSong NativeMidiSong;
|
||||
|
||||
int native_midi_detect();
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw);
|
||||
void native_midi_freesong(NativeMidiSong *song);
|
||||
void native_midi_start(NativeMidiSong *song, int loops);
|
||||
void native_midi_stop();
|
||||
int native_midi_active();
|
||||
void native_midi_setvolume(int volume);
|
||||
const char *native_midi_error(void);
|
||||
|
||||
#endif /* _NATIVE_MIDI_H_ */
|
||||
409
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_common.c
Normal file
409
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_common.c
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
native_midi: Hardware Midi support for the SDL_mixer library
|
||||
Copyright (C) 2000,2001 Florian 'Proff' Schulze <florian.proff.schulze@gmx.net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "native_midi_common.h"
|
||||
|
||||
#include "../SDL_mixer.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/* The maximum number of midi tracks that we can handle
|
||||
#define MIDI_TRACKS 32 */
|
||||
|
||||
|
||||
/* A single midi track as read from the midi file */
|
||||
typedef struct
|
||||
{
|
||||
Uint8 *data; /* MIDI message stream */
|
||||
int len; /* length of the track data */
|
||||
} MIDITrack;
|
||||
|
||||
/* A midi file, stripped down to the absolute minimum - divison & track data */
|
||||
typedef struct
|
||||
{
|
||||
int division; /* number of pulses per quarter note (ppqn) */
|
||||
int nTracks; /* number of tracks */
|
||||
MIDITrack *track; /* tracks */
|
||||
} MIDIFile;
|
||||
|
||||
|
||||
/* Some macros that help us stay endianess-independant */
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#define BE_SHORT(x) (x)
|
||||
#define BE_LONG(x) (x)
|
||||
#else
|
||||
#define BE_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
|
||||
#define BE_LONG(x) ((((x)&0x0000FF)<<24) | \
|
||||
(((x)&0x00FF00)<<8) | \
|
||||
(((x)&0xFF0000)>>8) | \
|
||||
(((x)>>24)&0xFF))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Get Variable Length Quantity */
|
||||
static int GetVLQ(MIDITrack *track, int *currentPos)
|
||||
{
|
||||
int l = 0;
|
||||
Uint8 c;
|
||||
while(1)
|
||||
{
|
||||
c = track->data[*currentPos];
|
||||
(*currentPos)++;
|
||||
l += (c & 0x7f);
|
||||
if (!(c & 0x80))
|
||||
return l;
|
||||
l <<= 7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a single MIDIEvent */
|
||||
static MIDIEvent *CreateEvent(Uint32 time, Uint8 event, Uint8 a, Uint8 b)
|
||||
{
|
||||
MIDIEvent *newEvent;
|
||||
|
||||
newEvent = calloc(1, sizeof(MIDIEvent));
|
||||
|
||||
if (newEvent)
|
||||
{
|
||||
newEvent->time = time;
|
||||
newEvent->status = event;
|
||||
newEvent->data[0] = a;
|
||||
newEvent->data[1] = b;
|
||||
}
|
||||
else
|
||||
Mix_SetError("Out of memory");
|
||||
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
/* Convert a single midi track to a list of MIDIEvents */
|
||||
static MIDIEvent *MIDITracktoStream(MIDITrack *track)
|
||||
{
|
||||
Uint32 atime = 0;
|
||||
Uint32 len = 0;
|
||||
Uint8 event,type,a,b;
|
||||
Uint8 laststatus = 0;
|
||||
Uint8 lastchan = 0;
|
||||
int currentPos = 0;
|
||||
int end = 0;
|
||||
MIDIEvent *head = CreateEvent(0,0,0,0); /* dummy event to make handling the list easier */
|
||||
MIDIEvent *currentEvent = head;
|
||||
|
||||
while (!end)
|
||||
{
|
||||
if (currentPos >= track->len)
|
||||
break; /* End of data stream reached */
|
||||
|
||||
atime += GetVLQ(track, ¤tPos);
|
||||
event = track->data[currentPos++];
|
||||
|
||||
/* Handle SysEx seperatly */
|
||||
if (((event>>4) & 0x0F) == MIDI_STATUS_SYSEX)
|
||||
{
|
||||
if (event == 0xFF)
|
||||
{
|
||||
type = track->data[currentPos];
|
||||
currentPos++;
|
||||
switch(type)
|
||||
{
|
||||
case 0x2f: /* End of data marker */
|
||||
end = 1;
|
||||
case 0x51: /* Tempo change */
|
||||
/*
|
||||
a=track->data[currentPos];
|
||||
b=track->data[currentPos+1];
|
||||
c=track->data[currentPos+2];
|
||||
AddEvent(song, atime, MEVT_TEMPO, c, b, a);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
type = 0;
|
||||
|
||||
len = GetVLQ(track, ¤tPos);
|
||||
|
||||
/* Create an event and attach the extra data, if any */
|
||||
currentEvent->next = CreateEvent(atime, event, type, 0);
|
||||
currentEvent = currentEvent->next;
|
||||
if (NULL == currentEvent)
|
||||
{
|
||||
FreeMIDIEventList(head);
|
||||
return NULL;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
currentEvent->extraLen = len;
|
||||
currentEvent->extraData = malloc(len);
|
||||
memcpy(currentEvent->extraData, &(track->data[currentPos]), len);
|
||||
currentPos += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a = event;
|
||||
if (a & 0x80) /* It's a status byte */
|
||||
{
|
||||
/* Extract channel and status information */
|
||||
lastchan = a & 0x0F;
|
||||
laststatus = (a>>4) & 0x0F;
|
||||
|
||||
/* Read the next byte which should always be a data byte */
|
||||
a = track->data[currentPos++] & 0x7F;
|
||||
}
|
||||
switch(laststatus)
|
||||
{
|
||||
case MIDI_STATUS_NOTE_OFF:
|
||||
case MIDI_STATUS_NOTE_ON: /* Note on */
|
||||
case MIDI_STATUS_AFTERTOUCH: /* Key Pressure */
|
||||
case MIDI_STATUS_CONTROLLER: /* Control change */
|
||||
case MIDI_STATUS_PITCH_WHEEL: /* Pitch wheel */
|
||||
b = track->data[currentPos++] & 0x7F;
|
||||
currentEvent->next = CreateEvent(atime, (Uint8)((laststatus<<4)+lastchan), a, b);
|
||||
currentEvent = currentEvent->next;
|
||||
if (NULL == currentEvent)
|
||||
{
|
||||
FreeMIDIEventList(head);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIDI_STATUS_PROG_CHANGE: /* Program change */
|
||||
case MIDI_STATUS_PRESSURE: /* Channel pressure */
|
||||
a &= 0x7f;
|
||||
currentEvent->next = CreateEvent(atime, (Uint8)((laststatus<<4)+lastchan), a, 0);
|
||||
currentEvent = currentEvent->next;
|
||||
if (NULL == currentEvent)
|
||||
{
|
||||
FreeMIDIEventList(head);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Sysex already handled above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentEvent = head->next;
|
||||
free(head); /* release the dummy head event */
|
||||
return currentEvent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a midi song, consisting of up to 32 tracks, to a list of MIDIEvents.
|
||||
* To do so, first convert the tracks seperatly, then interweave the resulting
|
||||
* MIDIEvent-Lists to one big list.
|
||||
*/
|
||||
static MIDIEvent *MIDItoStream(MIDIFile *mididata)
|
||||
{
|
||||
MIDIEvent **track;
|
||||
MIDIEvent *head = CreateEvent(0,0,0,0); /* dummy event to make handling the list easier */
|
||||
MIDIEvent *currentEvent = head;
|
||||
int trackID;
|
||||
|
||||
if (NULL == head)
|
||||
return NULL;
|
||||
|
||||
track = (MIDIEvent**) calloc(1, sizeof(MIDIEvent*) * mididata->nTracks);
|
||||
if (NULL == head)
|
||||
return NULL;
|
||||
|
||||
/* First, convert all tracks to MIDIEvent lists */
|
||||
for (trackID = 0; trackID < mididata->nTracks; trackID++)
|
||||
track[trackID] = MIDITracktoStream(&mididata->track[trackID]);
|
||||
|
||||
/* Now, merge the lists. */
|
||||
/* TODO */
|
||||
while(1)
|
||||
{
|
||||
Uint32 lowestTime = INT_MAX;
|
||||
int currentTrackID = -1;
|
||||
|
||||
/* Find the next event */
|
||||
for (trackID = 0; trackID < mididata->nTracks; trackID++)
|
||||
{
|
||||
if (track[trackID] && (track[trackID]->time < lowestTime))
|
||||
{
|
||||
currentTrackID = trackID;
|
||||
lowestTime = track[currentTrackID]->time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we processes all events */
|
||||
if (currentTrackID == -1)
|
||||
break;
|
||||
|
||||
currentEvent->next = track[currentTrackID];
|
||||
track[currentTrackID] = track[currentTrackID]->next;
|
||||
|
||||
currentEvent = currentEvent->next;
|
||||
|
||||
|
||||
lowestTime = 0;
|
||||
}
|
||||
|
||||
/* Make sure the list is properly terminated */
|
||||
currentEvent->next = 0;
|
||||
|
||||
currentEvent = head->next;
|
||||
free(track);
|
||||
free(head); /* release the dummy head event */
|
||||
return currentEvent;
|
||||
}
|
||||
|
||||
static int ReadMIDIFile(MIDIFile *mididata, SDL_RWops *rw)
|
||||
{
|
||||
int i = 0;
|
||||
Uint32 ID;
|
||||
Uint32 size;
|
||||
Uint16 format;
|
||||
Uint16 tracks;
|
||||
Uint16 division;
|
||||
|
||||
if (!mididata)
|
||||
return 0;
|
||||
if (!rw)
|
||||
return 0;
|
||||
|
||||
/* Make sure this is really a MIDI file */
|
||||
SDL_RWread(rw, &ID, 1, 4);
|
||||
if (BE_LONG(ID) != 'MThd')
|
||||
return 0;
|
||||
|
||||
/* Header size must be 6 */
|
||||
SDL_RWread(rw, &size, 1, 4);
|
||||
size = BE_LONG(size);
|
||||
if (size != 6)
|
||||
return 0;
|
||||
|
||||
/* We only support format 0 and 1, but not 2 */
|
||||
SDL_RWread(rw, &format, 1, 2);
|
||||
format = BE_SHORT(format);
|
||||
if (format != 0 && format != 1)
|
||||
return 0;
|
||||
|
||||
SDL_RWread(rw, &tracks, 1, 2);
|
||||
tracks = BE_SHORT(tracks);
|
||||
mididata->nTracks = tracks;
|
||||
|
||||
/* Allocate tracks */
|
||||
mididata->track = (MIDITrack*) calloc(1, sizeof(MIDITrack) * mididata->nTracks);
|
||||
if (NULL == mididata->track)
|
||||
{
|
||||
Mix_SetError("Out of memory");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Retrieve the PPQN value, needed for playback */
|
||||
SDL_RWread(rw, &division, 1, 2);
|
||||
mididata->division = BE_SHORT(division);
|
||||
|
||||
|
||||
for (i=0; i<tracks; i++)
|
||||
{
|
||||
SDL_RWread(rw, &ID, 1, 4); /* We might want to verify this is MTrk... */
|
||||
SDL_RWread(rw, &size, 1, 4);
|
||||
size = BE_LONG(size);
|
||||
mididata->track[i].len = size;
|
||||
mididata->track[i].data = malloc(size);
|
||||
if (NULL == mididata->track[i].data)
|
||||
{
|
||||
Mix_SetError("Out of memory");
|
||||
goto bail;
|
||||
}
|
||||
SDL_RWread(rw, mididata->track[i].data, 1, size);
|
||||
}
|
||||
return 1;
|
||||
|
||||
bail:
|
||||
for(;i >= 0; i--)
|
||||
{
|
||||
if (mididata->track[i].data)
|
||||
free(mididata->track[i].data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIDIEvent *CreateMIDIEventList(SDL_RWops *rw, Uint16 *division)
|
||||
{
|
||||
MIDIFile *mididata = NULL;
|
||||
MIDIEvent *eventList;
|
||||
int trackID;
|
||||
|
||||
mididata = calloc(1, sizeof(MIDIFile));
|
||||
if (!mididata)
|
||||
return NULL;
|
||||
|
||||
/* Open the file */
|
||||
if ( rw != NULL )
|
||||
{
|
||||
/* Read in the data */
|
||||
if ( ! ReadMIDIFile(mididata, rw))
|
||||
{
|
||||
free(mididata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(mididata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (division)
|
||||
*division = mididata->division;
|
||||
|
||||
eventList = MIDItoStream(mididata);
|
||||
|
||||
for(trackID = 0; trackID < mididata->nTracks; trackID++)
|
||||
{
|
||||
if (mididata->track[trackID].data)
|
||||
free(mididata->track[trackID].data);
|
||||
}
|
||||
free(mididata->track);
|
||||
free(mididata);
|
||||
|
||||
return eventList;
|
||||
}
|
||||
|
||||
void FreeMIDIEventList(MIDIEvent *head)
|
||||
{
|
||||
MIDIEvent *cur, *next;
|
||||
|
||||
cur = head;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
next = cur->next;
|
||||
if (cur->extraData)
|
||||
free (cur->extraData);
|
||||
free (cur);
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
63
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_common.h
Normal file
63
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_common.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
native_midi: Hardware Midi support for the SDL_mixer library
|
||||
Copyright (C) 2000,2001 Florian 'Proff' Schulze <florian.proff.schulze@gmx.net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef _NATIVE_MIDI_COMMON_H_
|
||||
#define _NATIVE_MIDI_COMMON_H_
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
/* Midi Status Bytes */
|
||||
#define MIDI_STATUS_NOTE_OFF 0x8
|
||||
#define MIDI_STATUS_NOTE_ON 0x9
|
||||
#define MIDI_STATUS_AFTERTOUCH 0xA
|
||||
#define MIDI_STATUS_CONTROLLER 0xB
|
||||
#define MIDI_STATUS_PROG_CHANGE 0xC
|
||||
#define MIDI_STATUS_PRESSURE 0xD
|
||||
#define MIDI_STATUS_PITCH_WHEEL 0xE
|
||||
#define MIDI_STATUS_SYSEX 0xF
|
||||
|
||||
/* We store the midi events in a linked list; this way it is
|
||||
easy to shuffle the tracks together later on; and we are
|
||||
flexible in the size of each elemnt.
|
||||
*/
|
||||
typedef struct MIDIEvent
|
||||
{
|
||||
Uint32 time; /* Time at which this midi events occurs */
|
||||
Uint8 status; /* Status byte */
|
||||
Uint8 data[2]; /* 1 or 2 bytes additional data for most events */
|
||||
|
||||
Uint32 extraLen; /* For some SysEx events, we need additional storage */
|
||||
Uint8 *extraData;
|
||||
|
||||
struct MIDIEvent *next;
|
||||
} MIDIEvent;
|
||||
|
||||
|
||||
/* Load a midifile to memory, converting it to a list of MIDIEvents.
|
||||
This function returns a linked lists of MIDIEvents, 0 if an error occured.
|
||||
*/
|
||||
MIDIEvent *CreateMIDIEventList(SDL_RWops *rw, Uint16 *division);
|
||||
|
||||
/* Release a MIDIEvent list after usage. */
|
||||
void FreeMIDIEventList(MIDIEvent *head);
|
||||
|
||||
|
||||
#endif /* _NATIVE_MIDI_COMMON_H_ */
|
||||
281
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_haiku.cpp
Normal file
281
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_haiku.cpp
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
native_midi_haiku: Native Midi support on Haiku for the SDL_mixer library
|
||||
Copyright (C) 2010 Egor Suvorov <egor_suvorov@mail.ru>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <MidiStore.h>
|
||||
#include <MidiDefs.h>
|
||||
#include <MidiSynthFile.h>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
extern "C" {
|
||||
#include "native_midi.h"
|
||||
#include "native_midi_common.h"
|
||||
}
|
||||
|
||||
bool compareMIDIEvent(const MIDIEvent &a, const MIDIEvent &b)
|
||||
{
|
||||
return a.time < b.time;
|
||||
}
|
||||
|
||||
class MidiEventsStore : public BMidi
|
||||
{
|
||||
public:
|
||||
MidiEventsStore()
|
||||
{
|
||||
fPlaying = false;
|
||||
fLoops = 0;
|
||||
}
|
||||
virtual status_t Import(SDL_RWops *rw)
|
||||
{
|
||||
fEvs = CreateMIDIEventList(rw, &fDivision);
|
||||
if (!fEvs) {
|
||||
return B_BAD_MIDI_DATA;
|
||||
}
|
||||
fTotal = 0;
|
||||
for (MIDIEvent *x = fEvs; x; x = x->next) fTotal++;
|
||||
fPos = fTotal;
|
||||
|
||||
sort_events();
|
||||
return B_OK;
|
||||
}
|
||||
virtual void Run()
|
||||
{
|
||||
fPlaying = true;
|
||||
fPos = 0;
|
||||
MIDIEvent *ev = fEvs;
|
||||
|
||||
uint32 startTime = B_NOW;
|
||||
while (KeepRunning())
|
||||
{
|
||||
if (!ev) {
|
||||
if (fLoops && fEvs) {
|
||||
--fLoops;
|
||||
fPos = 0;
|
||||
ev = fEvs;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
SprayEvent(ev, ev->time + startTime);
|
||||
ev = ev->next;
|
||||
fPos++;
|
||||
}
|
||||
fPos = fTotal;
|
||||
fPlaying = false;
|
||||
}
|
||||
virtual ~MidiEventsStore()
|
||||
{
|
||||
if (!fEvs) return;
|
||||
FreeMIDIEventList(fEvs);
|
||||
fEvs = 0;
|
||||
}
|
||||
|
||||
bool IsPlaying()
|
||||
{
|
||||
return fPlaying;
|
||||
}
|
||||
|
||||
void SetLoops(int loops)
|
||||
{
|
||||
fLoops = loops;
|
||||
}
|
||||
|
||||
protected:
|
||||
MIDIEvent *fEvs;
|
||||
Uint16 fDivision;
|
||||
|
||||
int fPos, fTotal;
|
||||
int fLoops;
|
||||
bool fPlaying;
|
||||
|
||||
void SprayEvent(MIDIEvent *ev, uint32 time)
|
||||
{
|
||||
switch (ev->status & 0xF0)
|
||||
{
|
||||
case B_NOTE_OFF:
|
||||
SprayNoteOff((ev->status & 0x0F) + 1, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case B_NOTE_ON:
|
||||
SprayNoteOn((ev->status & 0x0F) + 1, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case B_KEY_PRESSURE:
|
||||
SprayKeyPressure((ev->status & 0x0F) + 1, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case B_CONTROL_CHANGE:
|
||||
SprayControlChange((ev->status & 0x0F) + 1, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case B_PROGRAM_CHANGE:
|
||||
SprayProgramChange((ev->status & 0x0F) + 1, ev->data[0], time);
|
||||
break;
|
||||
case B_CHANNEL_PRESSURE:
|
||||
SprayChannelPressure((ev->status & 0x0F) + 1, ev->data[0], time);
|
||||
break;
|
||||
case B_PITCH_BEND:
|
||||
SprayPitchBend((ev->status & 0x0F) + 1, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case 0xF:
|
||||
switch (ev->status)
|
||||
{
|
||||
case B_SYS_EX_START:
|
||||
SpraySystemExclusive(ev->extraData, ev->extraLen, time);
|
||||
break;
|
||||
case B_MIDI_TIME_CODE:
|
||||
case B_SONG_POSITION:
|
||||
case B_SONG_SELECT:
|
||||
case B_CABLE_MESSAGE:
|
||||
case B_TUNE_REQUEST:
|
||||
case B_SYS_EX_END:
|
||||
SpraySystemCommon(ev->status, ev->data[0], ev->data[1], time);
|
||||
break;
|
||||
case B_TIMING_CLOCK:
|
||||
case B_START:
|
||||
case B_STOP:
|
||||
case B_CONTINUE:
|
||||
case B_ACTIVE_SENSING:
|
||||
SpraySystemRealTime(ev->status, time);
|
||||
break;
|
||||
case B_SYSTEM_RESET:
|
||||
if (ev->data[0] == 0x51 && ev->data[1] == 0x03)
|
||||
{
|
||||
assert(ev->extraLen == 3);
|
||||
int val = (ev->extraData[0] << 16) | (ev->extraData[1] << 8) | ev->extraData[2];
|
||||
int tempo = 60000000 / val;
|
||||
SprayTempoChange(tempo, time);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpraySystemRealTime(ev->status, time);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sort_events()
|
||||
{
|
||||
MIDIEvent *items = new MIDIEvent[fTotal];
|
||||
MIDIEvent *x = fEvs;
|
||||
for (int i = 0; i < fTotal; i++)
|
||||
{
|
||||
memcpy(items + i, x, sizeof(MIDIEvent));
|
||||
x = x->next;
|
||||
}
|
||||
std::sort(items, items + fTotal, compareMIDIEvent);
|
||||
|
||||
x = fEvs;
|
||||
for (int i = 0; i < fTotal; i++)
|
||||
{
|
||||
MIDIEvent *ne = x->next;
|
||||
memcpy(x, items + i, sizeof(MIDIEvent));
|
||||
x->next = ne;
|
||||
x = ne;
|
||||
}
|
||||
|
||||
for (x = fEvs; x && x->next; x = x->next)
|
||||
assert(x->time <= x->next->time);
|
||||
|
||||
delete[] items;
|
||||
}
|
||||
};
|
||||
|
||||
BMidiSynth synth;
|
||||
struct _NativeMidiSong {
|
||||
MidiEventsStore *store;
|
||||
} *currentSong = NULL;
|
||||
|
||||
char lasterr[1024];
|
||||
|
||||
int native_midi_detect()
|
||||
{
|
||||
status_t res = synth.EnableInput(true, false);
|
||||
return res == B_OK;
|
||||
}
|
||||
|
||||
void native_midi_setvolume(int volume)
|
||||
{
|
||||
if (volume < 0) volume = 0;
|
||||
if (volume > 128) volume = 128;
|
||||
synth.SetVolume(volume / 128.0);
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
NativeMidiSong *song = new NativeMidiSong;
|
||||
song->store = new MidiEventsStore;
|
||||
status_t res = song->store->Import(rw);
|
||||
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
if (res != B_OK)
|
||||
{
|
||||
snprintf(lasterr, sizeof lasterr, "Cannot Import() midi file: status_t=%d", res);
|
||||
delete song->store;
|
||||
delete song;
|
||||
return NULL;
|
||||
}
|
||||
return song;
|
||||
}
|
||||
|
||||
void native_midi_freesong(NativeMidiSong *song)
|
||||
{
|
||||
if (song == NULL) return;
|
||||
song->store->Stop();
|
||||
song->store->Disconnect(&synth);
|
||||
if (currentSong == song)
|
||||
{
|
||||
currentSong = NULL;
|
||||
}
|
||||
delete song->store;
|
||||
delete song; song = 0;
|
||||
}
|
||||
void native_midi_start(NativeMidiSong *song, int loops)
|
||||
{
|
||||
native_midi_stop();
|
||||
song->store->Connect(&synth);
|
||||
song->store->SetLoops(loops);
|
||||
song->store->Start();
|
||||
currentSong = song;
|
||||
}
|
||||
void native_midi_stop()
|
||||
{
|
||||
if (currentSong == NULL) return;
|
||||
currentSong->store->Stop();
|
||||
currentSong->store->Disconnect(&synth);
|
||||
while (currentSong->store->IsPlaying())
|
||||
usleep(1000);
|
||||
currentSong = NULL;
|
||||
}
|
||||
int native_midi_active()
|
||||
{
|
||||
if (currentSong == NULL) return 0;
|
||||
return currentSong->store->IsPlaying();
|
||||
}
|
||||
|
||||
const char* native_midi_error(void)
|
||||
{
|
||||
return lasterr;
|
||||
}
|
||||
|
||||
#endif /* __HAIKU__ */
|
||||
644
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_mac.c
Normal file
644
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_mac.c
Normal file
|
|
@ -0,0 +1,644 @@
|
|||
/*
|
||||
native_midi_mac: Native Midi support on MacOS for the SDL_mixer library
|
||||
Copyright (C) 2001 Max Horn <max@quendi.de>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#if __MACOS__ /*|| __MACOSX__ */
|
||||
|
||||
#include "native_midi.h"
|
||||
#include "native_midi_common.h"
|
||||
|
||||
#if __MACOSX__
|
||||
#include <QuickTime/QuickTimeMusic.h>
|
||||
#else
|
||||
#include <QuickTimeMusic.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Native Midi song */
|
||||
struct _NativeMidiSong
|
||||
{
|
||||
Uint32 *tuneSequence;
|
||||
Uint32 *tuneHeader;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* number of (32-bit) long words in a note request event */
|
||||
kNoteRequestEventLength = ((sizeof(NoteRequest)/sizeof(long)) + 2),
|
||||
|
||||
/* number of (32-bit) long words in a marker event */
|
||||
kMarkerEventLength = 1,
|
||||
|
||||
/* number of (32-bit) long words in a general event, minus its data */
|
||||
kGeneralEventLength = 2
|
||||
};
|
||||
|
||||
#define ERROR_BUF_SIZE 256
|
||||
#define BUFFER_INCREMENT 5000
|
||||
|
||||
#define REST_IF_NECESSARY() do {\
|
||||
int timeDiff = eventPos->time - lastEventTime; \
|
||||
if(timeDiff) \
|
||||
{ \
|
||||
timeDiff = (int)(timeDiff*tick); \
|
||||
qtma_StuffRestEvent(*tunePos, timeDiff); \
|
||||
tunePos++; \
|
||||
lastEventTime = eventPos->time; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
static Uint32 *BuildTuneSequence(MIDIEvent *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int *numParts);
|
||||
static Uint32 *BuildTuneHeader(int part_poly_max[32], int part_to_inst[32], int numParts);
|
||||
|
||||
/* The global TunePlayer instance */
|
||||
static TunePlayer gTunePlayer = NULL;
|
||||
static int gInstaceCount = 0;
|
||||
static Uint32 *gCurrentTuneSequence = NULL;
|
||||
static char gErrorBuffer[ERROR_BUF_SIZE] = "";
|
||||
|
||||
|
||||
/* Check whether QuickTime is available */
|
||||
int native_midi_detect()
|
||||
{
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
NativeMidiSong *song = NULL;
|
||||
MIDIEvent *evntlist = NULL;
|
||||
int part_to_inst[32];
|
||||
int part_poly_max[32];
|
||||
int numParts = 0;
|
||||
Uint16 ppqn;
|
||||
|
||||
/* Init the arrays */
|
||||
memset(part_poly_max,0,sizeof(part_poly_max));
|
||||
memset(part_to_inst,-1,sizeof(part_to_inst));
|
||||
|
||||
/* Attempt to load the midi file */
|
||||
evntlist = CreateMIDIEventList(rw, &ppqn);
|
||||
if (!evntlist)
|
||||
goto bail;
|
||||
|
||||
/* Allocate memory for the song struct */
|
||||
song = malloc(sizeof(NativeMidiSong));
|
||||
if (!song)
|
||||
goto bail;
|
||||
|
||||
/* Build a tune sequence from the event list */
|
||||
song->tuneSequence = BuildTuneSequence(evntlist, ppqn, part_poly_max, part_to_inst, &numParts);
|
||||
if(!song->tuneSequence)
|
||||
goto bail;
|
||||
|
||||
/* Now build a tune header from the data we collect above, create
|
||||
all parts as needed and assign them the correct instrument.
|
||||
*/
|
||||
song->tuneHeader = BuildTuneHeader(part_poly_max, part_to_inst, numParts);
|
||||
if(!song->tuneHeader)
|
||||
goto bail;
|
||||
|
||||
/* Increment the instance count */
|
||||
gInstaceCount++;
|
||||
if (gTunePlayer == NULL)
|
||||
gTunePlayer = OpenDefaultComponent(kTunePlayerComponentType, 0);
|
||||
|
||||
/* Finally, free the event list */
|
||||
FreeMIDIEventList(evntlist);
|
||||
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return song;
|
||||
|
||||
bail:
|
||||
if (evntlist)
|
||||
FreeMIDIEventList(evntlist);
|
||||
|
||||
if (song)
|
||||
{
|
||||
if(song->tuneSequence)
|
||||
free(song->tuneSequence);
|
||||
|
||||
if(song->tuneHeader)
|
||||
DisposePtr((Ptr)song->tuneHeader);
|
||||
|
||||
free(song);
|
||||
}
|
||||
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void native_midi_freesong(NativeMidiSong *song)
|
||||
{
|
||||
if(!song || !song->tuneSequence)
|
||||
return;
|
||||
|
||||
/* If this is the currently playing song, stop it now */
|
||||
if (song->tuneSequence == gCurrentTuneSequence)
|
||||
native_midi_stop();
|
||||
|
||||
/* Finally, free the data storage */
|
||||
free(song->tuneSequence);
|
||||
DisposePtr((Ptr)song->tuneHeader);
|
||||
free(song);
|
||||
|
||||
/* Increment the instance count */
|
||||
gInstaceCount--;
|
||||
if ((gTunePlayer != NULL) && (gInstaceCount == 0))
|
||||
{
|
||||
CloseComponent(gTunePlayer);
|
||||
gTunePlayer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void native_midi_start(NativeMidiSong *song, int loops)
|
||||
{
|
||||
UInt32 queueFlags = 0;
|
||||
ComponentResult tpError;
|
||||
|
||||
assert (gTunePlayer != NULL);
|
||||
|
||||
/* FIXME: is this code even used anymore? */
|
||||
assert (loops == 0);
|
||||
|
||||
SDL_PauseAudio(1);
|
||||
SDL_UnlockAudio();
|
||||
|
||||
/* First, stop the currently playing music */
|
||||
native_midi_stop();
|
||||
|
||||
/* Set up the queue flags */
|
||||
queueFlags = kTuneStartNow;
|
||||
|
||||
/* Set the time scale (units per second), we want milliseconds */
|
||||
tpError = TuneSetTimeScale(gTunePlayer, 1000);
|
||||
if (tpError != noErr)
|
||||
{
|
||||
strncpy (gErrorBuffer, "MIDI error during TuneSetTimeScale", ERROR_BUF_SIZE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set the header, to tell what instruments are used */
|
||||
tpError = TuneSetHeader(gTunePlayer, (UInt32 *)song->tuneHeader);
|
||||
if (tpError != noErr)
|
||||
{
|
||||
strncpy (gErrorBuffer, "MIDI error during TuneSetHeader", ERROR_BUF_SIZE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Have it allocate whatever resources are needed */
|
||||
tpError = TunePreroll(gTunePlayer);
|
||||
if (tpError != noErr)
|
||||
{
|
||||
strncpy (gErrorBuffer, "MIDI error during TunePreroll", ERROR_BUF_SIZE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* We want to play at normal volume */
|
||||
tpError = TuneSetVolume(gTunePlayer, 0x00010000);
|
||||
if (tpError != noErr)
|
||||
{
|
||||
strncpy (gErrorBuffer, "MIDI error during TuneSetVolume", ERROR_BUF_SIZE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Finally, start playing the full song */
|
||||
gCurrentTuneSequence = song->tuneSequence;
|
||||
tpError = TuneQueue(gTunePlayer, (UInt32 *)song->tuneSequence, 0x00010000, 0, 0xFFFFFFFF, queueFlags, NULL, 0);
|
||||
if (tpError != noErr)
|
||||
{
|
||||
strncpy (gErrorBuffer, "MIDI error during TuneQueue", ERROR_BUF_SIZE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
SDL_LockAudio();
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
void native_midi_stop()
|
||||
{
|
||||
if (gTunePlayer == NULL)
|
||||
return;
|
||||
|
||||
/* Stop music */
|
||||
TuneStop(gTunePlayer, 0);
|
||||
|
||||
/* Deallocate all instruments */
|
||||
TuneUnroll(gTunePlayer);
|
||||
}
|
||||
|
||||
int native_midi_active()
|
||||
{
|
||||
if (gTunePlayer != NULL)
|
||||
{
|
||||
TuneStatus ts;
|
||||
|
||||
TuneGetStatus(gTunePlayer,&ts);
|
||||
return ts.queueTime != 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void native_midi_setvolume(int volume)
|
||||
{
|
||||
if (gTunePlayer == NULL)
|
||||
return;
|
||||
|
||||
/* QTMA olume may range from 0.0 to 1.0 (in 16.16 fixed point encoding) */
|
||||
TuneSetVolume(gTunePlayer, (0x00010000 * volume)/SDL_MIX_MAXVOLUME);
|
||||
}
|
||||
|
||||
const char *native_midi_error(void)
|
||||
{
|
||||
return gErrorBuffer;
|
||||
}
|
||||
|
||||
Uint32 *BuildTuneSequence(MIDIEvent *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int *numParts)
|
||||
{
|
||||
int part_poly[32];
|
||||
int channel_to_part[16];
|
||||
|
||||
int channel_pan[16];
|
||||
int channel_vol[16];
|
||||
int channel_pitch_bend[16];
|
||||
|
||||
int lastEventTime = 0;
|
||||
int tempo = 500000;
|
||||
double Ippqn = 1.0 / (1000*ppqn);
|
||||
double tick = tempo * Ippqn;
|
||||
MIDIEvent *eventPos = evntlist;
|
||||
MIDIEvent *noteOffPos;
|
||||
Uint32 *tunePos, *endPos;
|
||||
Uint32 *tuneSequence;
|
||||
size_t tuneSize;
|
||||
|
||||
/* allocate space for the tune header */
|
||||
tuneSize = 5000;
|
||||
tuneSequence = (Uint32 *)malloc(tuneSize * sizeof(Uint32));
|
||||
if (tuneSequence == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Set starting position in our tune memory */
|
||||
tunePos = tuneSequence;
|
||||
endPos = tuneSequence + tuneSize;
|
||||
|
||||
/* Initialise the arrays */
|
||||
memset(part_poly,0,sizeof(part_poly));
|
||||
|
||||
memset(channel_to_part,-1,sizeof(channel_to_part));
|
||||
memset(channel_pan,-1,sizeof(channel_pan));
|
||||
memset(channel_vol,-1,sizeof(channel_vol));
|
||||
memset(channel_pitch_bend,-1,sizeof(channel_pitch_bend));
|
||||
|
||||
*numParts = 0;
|
||||
|
||||
/*
|
||||
* Now the major work - iterate over all GM events,
|
||||
* and turn them into QuickTime Music format.
|
||||
* At the same time, calculate the max. polyphony for each part,
|
||||
* and also the part->instrument mapping.
|
||||
*/
|
||||
while(eventPos)
|
||||
{
|
||||
int status = (eventPos->status&0xF0)>>4;
|
||||
int channel = eventPos->status&0x0F;
|
||||
int part = channel_to_part[channel];
|
||||
int velocity, pitch;
|
||||
int value, controller;
|
||||
int bend;
|
||||
int newInst;
|
||||
|
||||
/* Check if we are running low on space... */
|
||||
if((tunePos+16) > endPos)
|
||||
{
|
||||
/* Resize our data storage. */
|
||||
Uint32 *oldTuneSequence = tuneSequence;
|
||||
|
||||
tuneSize += BUFFER_INCREMENT;
|
||||
tuneSequence = (Uint32 *)realloc(tuneSequence, tuneSize * sizeof(Uint32));
|
||||
if(oldTuneSequence != tuneSequence)
|
||||
tunePos += tuneSequence - oldTuneSequence;
|
||||
endPos = tuneSequence + tuneSize;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case MIDI_STATUS_NOTE_OFF:
|
||||
assert(part>=0 && part<=31);
|
||||
|
||||
/* Keep track of the polyphony of the current part */
|
||||
part_poly[part]--;
|
||||
break;
|
||||
case MIDI_STATUS_NOTE_ON:
|
||||
if (part < 0)
|
||||
{
|
||||
/* If no part is specified yet, we default to the first instrument, which
|
||||
is piano (or the first drum kit if we are on the drum channel)
|
||||
*/
|
||||
int newInst;
|
||||
|
||||
if (channel == 9)
|
||||
newInst = kFirstDrumkit + 1; /* the first drum kit is the "no drum" kit! */
|
||||
else
|
||||
newInst = kFirstGMInstrument;
|
||||
part = channel_to_part[channel] = *numParts;
|
||||
part_to_inst[(*numParts)++] = newInst;
|
||||
}
|
||||
/* TODO - add support for more than 32 parts using eXtended QTMA events */
|
||||
assert(part<=31);
|
||||
|
||||
/* Decode pitch & velocity */
|
||||
pitch = eventPos->data[0];
|
||||
velocity = eventPos->data[1];
|
||||
|
||||
if (velocity == 0)
|
||||
{
|
||||
/* was a NOTE OFF in disguise, so we decrement the polyphony */
|
||||
part_poly[part]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep track of the polyphony of the current part */
|
||||
int foo = ++part_poly[part];
|
||||
if (part_poly_max[part] < foo)
|
||||
part_poly_max[part] = foo;
|
||||
|
||||
/* Now scan forward to find the matching NOTE OFF event */
|
||||
for(noteOffPos = eventPos; noteOffPos; noteOffPos = noteOffPos->next)
|
||||
{
|
||||
if ((noteOffPos->status&0xF0)>>4 == MIDI_STATUS_NOTE_OFF
|
||||
&& channel == (eventPos->status&0x0F)
|
||||
&& pitch == noteOffPos->data[0])
|
||||
break;
|
||||
/* NOTE ON with velocity == 0 is the same as a NOTE OFF */
|
||||
if ((noteOffPos->status&0xF0)>>4 == MIDI_STATUS_NOTE_ON
|
||||
&& channel == (eventPos->status&0x0F)
|
||||
&& pitch == noteOffPos->data[0]
|
||||
&& 0 == noteOffPos->data[1])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Did we find a note off? Should always be the case, but who knows... */
|
||||
if (noteOffPos)
|
||||
{
|
||||
/* We found a NOTE OFF, now calculate the note duration */
|
||||
int duration = (int)((noteOffPos->time - eventPos->time)*tick);
|
||||
|
||||
REST_IF_NECESSARY();
|
||||
/* Now we need to check if we get along with a normal Note Event, or if we need an extended one... */
|
||||
if (duration < 2048 && pitch>=32 && pitch<=95 && velocity>=0 && velocity<=127)
|
||||
{
|
||||
qtma_StuffNoteEvent(*tunePos, part, pitch, velocity, duration);
|
||||
tunePos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
qtma_StuffXNoteEvent(*tunePos, *(tunePos+1), part, pitch, velocity, duration);
|
||||
tunePos+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MIDI_STATUS_AFTERTOUCH:
|
||||
/* NYI - use kControllerAfterTouch. But how are the parameters to be mapped? */
|
||||
break;
|
||||
case MIDI_STATUS_CONTROLLER:
|
||||
controller = eventPos->data[0];
|
||||
value = eventPos->data[1];
|
||||
|
||||
switch(controller)
|
||||
{
|
||||
case 0: /* bank change - igore for now */
|
||||
break;
|
||||
case kControllerVolume:
|
||||
if(channel_vol[channel] != value<<8)
|
||||
{
|
||||
channel_vol[channel] = value<<8;
|
||||
if(part>=0 && part<=31)
|
||||
{
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerVolume, channel_vol[channel]);
|
||||
tunePos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kControllerPan:
|
||||
if(channel_pan[channel] != (value << 1) + 256)
|
||||
{
|
||||
channel_pan[channel] = (value << 1) + 256;
|
||||
if(part>=0 && part<=31)
|
||||
{
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerPan, channel_pan[channel]);
|
||||
tunePos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* No other controllers implemented yet */;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case MIDI_STATUS_PROG_CHANGE:
|
||||
/* Instrument changed */
|
||||
newInst = eventPos->data[0];
|
||||
|
||||
/* Channel 9 (the 10th channel) is different, it indicates a drum kit */
|
||||
if (channel == 9)
|
||||
newInst += kFirstDrumkit;
|
||||
else
|
||||
newInst += kFirstGMInstrument;
|
||||
/* Only if the instrument for this channel *really* changed, add a new part. */
|
||||
if(newInst != part_to_inst[part])
|
||||
{
|
||||
/* TODO maybe make use of kGeneralEventPartChange here,
|
||||
to help QT reuse note channels?
|
||||
*/
|
||||
part = channel_to_part[channel] = *numParts;
|
||||
part_to_inst[(*numParts)++] = newInst;
|
||||
|
||||
if(channel_vol[channel] >= 0)
|
||||
{
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerVolume, channel_vol[channel]);
|
||||
tunePos++;
|
||||
}
|
||||
if(channel_pan[channel] >= 0)
|
||||
{
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerPan, channel_pan[channel]);
|
||||
tunePos++;
|
||||
}
|
||||
if(channel_pitch_bend[channel] >= 0)
|
||||
{
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerPitchBend, channel_pitch_bend[channel]);
|
||||
tunePos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MIDI_STATUS_PRESSURE:
|
||||
/* NYI */
|
||||
break;
|
||||
case MIDI_STATUS_PITCH_WHEEL:
|
||||
/* In the midi spec, 0x2000 = center, 0x0000 = - 2 semitones, 0x3FFF = +2 semitones
|
||||
but for QTMA, we specify it as a 8.8 fixed point of semitones
|
||||
TODO: detect "pitch bend range changes" & honor them!
|
||||
*/
|
||||
bend = (eventPos->data[0] & 0x7f) | ((eventPos->data[1] & 0x7f) << 7);
|
||||
|
||||
/* "Center" the bend */
|
||||
bend -= 0x2000;
|
||||
|
||||
/* Move it to our format: */
|
||||
bend <<= 4;
|
||||
|
||||
/* If it turns out the pitch bend didn't change, stop here */
|
||||
if(channel_pitch_bend[channel] == bend)
|
||||
break;
|
||||
|
||||
channel_pitch_bend[channel] = bend;
|
||||
if(part>=0 && part<=31)
|
||||
{
|
||||
/* Stuff a control event */
|
||||
REST_IF_NECESSARY();
|
||||
qtma_StuffControlEvent(*tunePos, part, kControllerPitchBend, bend);
|
||||
tunePos++;
|
||||
}
|
||||
break;
|
||||
case MIDI_STATUS_SYSEX:
|
||||
if (eventPos->status == 0xFF && eventPos->data[0] == 0x51) /* Tempo change */
|
||||
{
|
||||
tempo = (eventPos->extraData[0] << 16) +
|
||||
(eventPos->extraData[1] << 8) +
|
||||
eventPos->extraData[2];
|
||||
|
||||
tick = tempo * Ippqn;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* on to the next event */
|
||||
eventPos = eventPos->next;
|
||||
}
|
||||
|
||||
/* Finally, place an end marker */
|
||||
*tunePos = kEndMarkerValue;
|
||||
|
||||
return tuneSequence;
|
||||
}
|
||||
|
||||
Uint32 *BuildTuneHeader(int part_poly_max[32], int part_to_inst[32], int numParts)
|
||||
{
|
||||
Uint32 *myHeader;
|
||||
Uint32 *myPos1, *myPos2; /* pointers to the head and tail long words of a music event */
|
||||
NoteRequest *myNoteRequest;
|
||||
NoteAllocator myNoteAllocator; /* for the NAStuffToneDescription call */
|
||||
ComponentResult myErr = noErr;
|
||||
int part;
|
||||
|
||||
myHeader = NULL;
|
||||
myNoteAllocator = NULL;
|
||||
|
||||
/*
|
||||
* Open up the Note Allocator
|
||||
*/
|
||||
myNoteAllocator = OpenDefaultComponent(kNoteAllocatorComponentType,0);
|
||||
if (myNoteAllocator == NULL)
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* Allocate space for the tune header
|
||||
*/
|
||||
myHeader = (Uint32 *)
|
||||
NewPtrClear((numParts * kNoteRequestEventLength + kMarkerEventLength) * sizeof(Uint32));
|
||||
if (myHeader == NULL)
|
||||
goto bail;
|
||||
|
||||
myPos1 = myHeader;
|
||||
|
||||
/*
|
||||
* Loop over all parts
|
||||
*/
|
||||
for(part = 0; part < numParts; ++part)
|
||||
{
|
||||
/*
|
||||
* Stuff request for the instrument with the given polyphony
|
||||
*/
|
||||
myPos2 = myPos1 + (kNoteRequestEventLength - 1); /* last longword of general event */
|
||||
qtma_StuffGeneralEvent(*myPos1, *myPos2, part, kGeneralEventNoteRequest, kNoteRequestEventLength);
|
||||
myNoteRequest = (NoteRequest *)(myPos1 + 1);
|
||||
myNoteRequest->info.flags = 0;
|
||||
/* I'm told by the Apple people that the Quicktime types were poorly designed and it was
|
||||
* too late to change them. On little endian, the BigEndian(Short|Fixed) types are structs
|
||||
* while on big endian they are primitive types. Furthermore, Quicktime failed to
|
||||
* provide setter and getter functions. To get this to work, we need to case the
|
||||
* code for the two possible situations.
|
||||
* My assumption is that the right-side value was always expected to be BigEndian
|
||||
* as it was written way before the Universal Binary transition. So in the little endian
|
||||
* case, OSSwap is used.
|
||||
*/
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
myNoteRequest->info.polyphony.bigEndianValue = OSSwapHostToBigInt16(part_poly_max[part]);
|
||||
myNoteRequest->info.typicalPolyphony.bigEndianValue = OSSwapHostToBigInt32(0x00010000);
|
||||
#else
|
||||
myNoteRequest->info.polyphony = part_poly_max[part];
|
||||
myNoteRequest->info.typicalPolyphony = 0x00010000;
|
||||
#endif
|
||||
myErr = NAStuffToneDescription(myNoteAllocator,part_to_inst[part],&myNoteRequest->tone);
|
||||
if (myErr != noErr)
|
||||
goto bail;
|
||||
|
||||
/* move pointer to beginning of next event */
|
||||
myPos1 += kNoteRequestEventLength;
|
||||
}
|
||||
|
||||
*myPos1 = kEndMarkerValue; /* end of sequence marker */
|
||||
|
||||
|
||||
bail:
|
||||
if(myNoteAllocator)
|
||||
CloseComponent(myNoteAllocator);
|
||||
|
||||
/* if we encountered an error, dispose of the storage we allocated and return NULL */
|
||||
if (myErr != noErr) {
|
||||
DisposePtr((Ptr)myHeader);
|
||||
myHeader = NULL;
|
||||
}
|
||||
|
||||
return myHeader;
|
||||
}
|
||||
|
||||
#endif /* MacOS native MIDI support */
|
||||
322
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_macosx.c
Normal file
322
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_macosx.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
native_midi_macosx: Native Midi support on Mac OS X for the SDL_mixer library
|
||||
Copyright (C) 2009 Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is Mac OS X only, using Core MIDI.
|
||||
Mac OS 9 support via QuickTime is in native_midi_mac.c */
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if __MACOSX__
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#include "../SDL_mixer.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "native_midi.h"
|
||||
|
||||
/* Native Midi song */
|
||||
struct _NativeMidiSong
|
||||
{
|
||||
MusicPlayer player;
|
||||
MusicSequence sequence;
|
||||
MusicTimeStamp endTime;
|
||||
AudioUnit audiounit;
|
||||
int loops;
|
||||
};
|
||||
|
||||
static NativeMidiSong *currentsong = NULL;
|
||||
static int latched_volume = MIX_MAX_VOLUME;
|
||||
|
||||
static OSStatus
|
||||
GetSequenceLength(MusicSequence sequence, MusicTimeStamp *_sequenceLength)
|
||||
{
|
||||
// http://lists.apple.com/archives/Coreaudio-api/2003/Jul/msg00370.html
|
||||
// figure out sequence length
|
||||
UInt32 ntracks, i;
|
||||
MusicTimeStamp sequenceLength = 0;
|
||||
OSStatus err;
|
||||
|
||||
err = MusicSequenceGetTrackCount(sequence, &ntracks);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < ntracks; ++i)
|
||||
{
|
||||
MusicTrack track;
|
||||
MusicTimeStamp tracklen = 0;
|
||||
UInt32 tracklenlen = sizeof (tracklen);
|
||||
|
||||
err = MusicSequenceGetIndTrack(sequence, i, &track);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
err = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
|
||||
&tracklen, &tracklenlen);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
if (sequenceLength < tracklen)
|
||||
sequenceLength = tracklen;
|
||||
}
|
||||
|
||||
*_sequenceLength = sequenceLength;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/* we're looking for the sequence output audiounit. */
|
||||
static OSStatus
|
||||
GetSequenceAudioUnit(MusicSequence sequence, AudioUnit *aunit)
|
||||
{
|
||||
AUGraph graph;
|
||||
UInt32 nodecount, i;
|
||||
OSStatus err;
|
||||
|
||||
err = MusicSequenceGetAUGraph(sequence, &graph);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
err = AUGraphGetNodeCount(graph, &nodecount);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < nodecount; i++) {
|
||||
AUNode node;
|
||||
|
||||
if (AUGraphGetIndNode(graph, i, &node) != noErr)
|
||||
continue; /* better luck next time. */
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 /* this is deprecated, but works back to 10.0 */
|
||||
{
|
||||
struct ComponentDescription desc;
|
||||
UInt32 classdatasize = 0;
|
||||
void *classdata = NULL;
|
||||
err = AUGraphGetNodeInfo(graph, node, &desc, &classdatasize,
|
||||
&classdata, aunit);
|
||||
if (err != noErr)
|
||||
continue;
|
||||
else if (desc.componentType != kAudioUnitType_Output)
|
||||
continue;
|
||||
else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput)
|
||||
continue;
|
||||
}
|
||||
#else /* not deprecated, but requires 10.5 or later */
|
||||
{
|
||||
AudioComponentDescription desc;
|
||||
if (AUGraphNodeInfo(graph, node, &desc, aunit) != noErr)
|
||||
continue;
|
||||
else if (desc.componentType != kAudioUnitType_Output)
|
||||
continue;
|
||||
else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
return noErr; /* found it! */
|
||||
}
|
||||
|
||||
return kAUGraphErr_NodeNotFound;
|
||||
}
|
||||
|
||||
|
||||
int native_midi_detect()
|
||||
{
|
||||
return 1; /* always available. */
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
NativeMidiSong *retval = NULL;
|
||||
void *buf = NULL;
|
||||
int len = 0;
|
||||
CFDataRef data = NULL;
|
||||
|
||||
if (SDL_RWseek(rw, 0, RW_SEEK_END) < 0)
|
||||
goto fail;
|
||||
len = SDL_RWtell(rw);
|
||||
if (len < 0)
|
||||
goto fail;
|
||||
if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0)
|
||||
goto fail;
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL)
|
||||
goto fail;
|
||||
|
||||
if (SDL_RWread(rw, buf, len, 1) != 1)
|
||||
goto fail;
|
||||
|
||||
retval = malloc(sizeof(NativeMidiSong));
|
||||
if (retval == NULL)
|
||||
goto fail;
|
||||
|
||||
memset(retval, '\0', sizeof (*retval));
|
||||
|
||||
if (NewMusicPlayer(&retval->player) != noErr)
|
||||
goto fail;
|
||||
if (NewMusicSequence(&retval->sequence) != noErr)
|
||||
goto fail;
|
||||
|
||||
data = CFDataCreate(NULL, (const UInt8 *) buf, len);
|
||||
if (data == NULL)
|
||||
goto fail;
|
||||
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 /* this is deprecated, but works back to 10.3 */
|
||||
if (MusicSequenceLoadSMFDataWithFlags(retval->sequence, data, 0) != noErr)
|
||||
goto fail;
|
||||
#else /* not deprecated, but requires 10.5 or later */
|
||||
if (MusicSequenceFileLoadData(retval->sequence, data, 0, 0) != noErr)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
CFRelease(data);
|
||||
data = NULL;
|
||||
|
||||
if (GetSequenceLength(retval->sequence, &retval->endTime) != noErr)
|
||||
goto fail;
|
||||
|
||||
if (MusicPlayerSetSequence(retval->player, retval->sequence) != noErr)
|
||||
goto fail;
|
||||
|
||||
if (freerw)
|
||||
SDL_RWclose(rw);
|
||||
|
||||
return retval;
|
||||
|
||||
fail:
|
||||
if (retval) {
|
||||
if (retval->sequence)
|
||||
DisposeMusicSequence(retval->sequence);
|
||||
if (retval->player)
|
||||
DisposeMusicPlayer(retval->player);
|
||||
free(retval);
|
||||
}
|
||||
|
||||
if (data)
|
||||
CFRelease(data);
|
||||
|
||||
if (buf)
|
||||
free(buf);
|
||||
|
||||
if (freerw)
|
||||
SDL_RWclose(rw);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void native_midi_freesong(NativeMidiSong *song)
|
||||
{
|
||||
if (song != NULL) {
|
||||
if (currentsong == song)
|
||||
currentsong = NULL;
|
||||
MusicPlayerStop(song->player);
|
||||
DisposeMusicSequence(song->sequence);
|
||||
DisposeMusicPlayer(song->player);
|
||||
free(song);
|
||||
}
|
||||
}
|
||||
|
||||
void native_midi_start(NativeMidiSong *song, int loops)
|
||||
{
|
||||
int vol;
|
||||
|
||||
if (song == NULL)
|
||||
return;
|
||||
|
||||
SDL_PauseAudio(1);
|
||||
SDL_UnlockAudio();
|
||||
|
||||
if (currentsong)
|
||||
MusicPlayerStop(currentsong->player);
|
||||
|
||||
currentsong = song;
|
||||
currentsong->loops = loops;
|
||||
|
||||
MusicPlayerPreroll(song->player);
|
||||
MusicPlayerSetTime(song->player, 0);
|
||||
MusicPlayerStart(song->player);
|
||||
|
||||
GetSequenceAudioUnit(song->sequence, &song->audiounit);
|
||||
|
||||
vol = latched_volume;
|
||||
latched_volume++; /* just make this not match. */
|
||||
native_midi_setvolume(vol);
|
||||
|
||||
SDL_LockAudio();
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
void native_midi_stop()
|
||||
{
|
||||
if (currentsong) {
|
||||
SDL_PauseAudio(1);
|
||||
SDL_UnlockAudio();
|
||||
MusicPlayerStop(currentsong->player);
|
||||
currentsong = NULL;
|
||||
SDL_LockAudio();
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
}
|
||||
|
||||
int native_midi_active()
|
||||
{
|
||||
MusicTimeStamp currentTime = 0;
|
||||
if (currentsong == NULL)
|
||||
return 0;
|
||||
|
||||
MusicPlayerGetTime(currentsong->player, ¤tTime);
|
||||
if ((currentTime < currentsong->endTime) ||
|
||||
(currentTime >= kMusicTimeStamp_EndOfTrack)) {
|
||||
return 1;
|
||||
} else if (currentsong->loops) {
|
||||
--currentsong->loops;
|
||||
MusicPlayerSetTime(currentsong->player, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void native_midi_setvolume(int volume)
|
||||
{
|
||||
if (latched_volume == volume)
|
||||
return;
|
||||
|
||||
latched_volume = volume;
|
||||
if ((currentsong) && (currentsong->audiounit)) {
|
||||
const float floatvol = ((float) volume) / ((float) MIX_MAX_VOLUME);
|
||||
AudioUnitSetParameter(currentsong->audiounit, kHALOutputParam_Volume,
|
||||
kAudioUnitScope_Global, 0, floatvol, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const char *native_midi_error(void)
|
||||
{
|
||||
return ""; /* !!! FIXME */
|
||||
}
|
||||
|
||||
#endif /* Mac OS X native MIDI support */
|
||||
|
||||
312
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_win32.c
Normal file
312
apps/plugins/sdl/SDL_mixer/native_midi/native_midi_win32.c
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
native_midi: Hardware Midi support for the SDL_mixer library
|
||||
Copyright (C) 2000,2001 Florian 'Proff' Schulze <florian.proff.schulze@gmx.net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* everything below is currently one very big bad hack ;) Proff */
|
||||
|
||||
#if __WIN32__
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <mmsystem.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include "native_midi.h"
|
||||
#include "native_midi_common.h"
|
||||
|
||||
struct _NativeMidiSong {
|
||||
int MusicLoaded;
|
||||
int MusicPlaying;
|
||||
int Loops;
|
||||
int CurrentHdr;
|
||||
MIDIHDR MidiStreamHdr[2];
|
||||
MIDIEVENT *NewEvents;
|
||||
Uint16 ppqn;
|
||||
int Size;
|
||||
int NewPos;
|
||||
};
|
||||
|
||||
static UINT MidiDevice=MIDI_MAPPER;
|
||||
static HMIDISTRM hMidiStream;
|
||||
static NativeMidiSong *currentsong;
|
||||
|
||||
static int BlockOut(NativeMidiSong *song)
|
||||
{
|
||||
MMRESULT err;
|
||||
int BlockSize;
|
||||
MIDIHDR *hdr;
|
||||
|
||||
if ((song->MusicLoaded) && (song->NewEvents))
|
||||
{
|
||||
// proff 12/8/98: Added for safety
|
||||
song->CurrentHdr = !song->CurrentHdr;
|
||||
hdr = &song->MidiStreamHdr[song->CurrentHdr];
|
||||
midiOutUnprepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
|
||||
if (song->NewPos>=song->Size)
|
||||
return 0;
|
||||
BlockSize=(song->Size-song->NewPos);
|
||||
if (BlockSize<=0)
|
||||
return 0;
|
||||
if (BlockSize>36000)
|
||||
BlockSize=36000;
|
||||
hdr->lpData=(void *)((unsigned char *)song->NewEvents+song->NewPos);
|
||||
song->NewPos+=BlockSize;
|
||||
hdr->dwBufferLength=BlockSize;
|
||||
hdr->dwBytesRecorded=BlockSize;
|
||||
hdr->dwFlags=0;
|
||||
hdr->dwOffset=0;
|
||||
err=midiOutPrepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
|
||||
if (err!=MMSYSERR_NOERROR)
|
||||
return 0;
|
||||
err=midiStreamOut(hMidiStream,hdr,sizeof(MIDIHDR));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MIDItoStream(NativeMidiSong *song, MIDIEvent *evntlist)
|
||||
{
|
||||
int eventcount;
|
||||
MIDIEvent *event;
|
||||
MIDIEVENT *newevent;
|
||||
|
||||
eventcount=0;
|
||||
event=evntlist;
|
||||
while (event)
|
||||
{
|
||||
eventcount++;
|
||||
event=event->next;
|
||||
}
|
||||
song->NewEvents=malloc(eventcount*3*sizeof(DWORD));
|
||||
if (!song->NewEvents)
|
||||
return;
|
||||
memset(song->NewEvents,0,(eventcount*3*sizeof(DWORD)));
|
||||
|
||||
eventcount=0;
|
||||
event=evntlist;
|
||||
newevent=song->NewEvents;
|
||||
while (event)
|
||||
{
|
||||
int status = (event->status&0xF0)>>4;
|
||||
switch (status)
|
||||
{
|
||||
case MIDI_STATUS_NOTE_OFF:
|
||||
case MIDI_STATUS_NOTE_ON:
|
||||
case MIDI_STATUS_AFTERTOUCH:
|
||||
case MIDI_STATUS_CONTROLLER:
|
||||
case MIDI_STATUS_PROG_CHANGE:
|
||||
case MIDI_STATUS_PRESSURE:
|
||||
case MIDI_STATUS_PITCH_WHEEL:
|
||||
newevent->dwDeltaTime=event->time;
|
||||
newevent->dwEvent=(event->status|0x80)|(event->data[0]<<8)|(event->data[1]<<16)|(MEVT_SHORTMSG<<24);
|
||||
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
|
||||
eventcount++;
|
||||
break;
|
||||
|
||||
case MIDI_STATUS_SYSEX:
|
||||
if (event->status == 0xFF && event->data[0] == 0x51) /* Tempo change */
|
||||
{
|
||||
int tempo = (event->extraData[0] << 16) |
|
||||
(event->extraData[1] << 8) |
|
||||
event->extraData[2];
|
||||
newevent->dwDeltaTime=event->time;
|
||||
newevent->dwEvent=(MEVT_TEMPO<<24) | tempo;
|
||||
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
|
||||
eventcount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
event=event->next;
|
||||
}
|
||||
|
||||
song->Size=eventcount*3*sizeof(DWORD);
|
||||
|
||||
{
|
||||
int time;
|
||||
int temptime;
|
||||
|
||||
song->NewPos=0;
|
||||
time=0;
|
||||
newevent=song->NewEvents;
|
||||
while (song->NewPos<song->Size)
|
||||
{
|
||||
temptime=newevent->dwDeltaTime;
|
||||
newevent->dwDeltaTime-=time;
|
||||
time=temptime;
|
||||
if ((song->NewPos+12)>=song->Size)
|
||||
newevent->dwEvent |= MEVT_F_CALLBACK;
|
||||
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
|
||||
song->NewPos+=12;
|
||||
}
|
||||
}
|
||||
song->NewPos=0;
|
||||
song->MusicLoaded=1;
|
||||
}
|
||||
|
||||
void CALLBACK MidiProc( HMIDIIN hMidi, UINT uMsg, DWORD_PTR dwInstance,
|
||||
DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case MOM_DONE:
|
||||
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)¤tsong->MidiStreamHdr[currentsong->CurrentHdr]))
|
||||
BlockOut(currentsong);
|
||||
break;
|
||||
case MOM_POSITIONCB:
|
||||
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)¤tsong->MidiStreamHdr[currentsong->CurrentHdr])) {
|
||||
if (currentsong->Loops) {
|
||||
--currentsong->Loops;
|
||||
currentsong->NewPos=0;
|
||||
BlockOut(currentsong);
|
||||
} else {
|
||||
currentsong->MusicPlaying=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int native_midi_detect()
|
||||
{
|
||||
MMRESULT merr;
|
||||
HMIDISTRM MidiStream;
|
||||
|
||||
merr=midiStreamOpen(&MidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
|
||||
if (merr!=MMSYSERR_NOERROR)
|
||||
return 0;
|
||||
midiStreamClose(MidiStream);
|
||||
return 1;
|
||||
}
|
||||
|
||||
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
|
||||
{
|
||||
NativeMidiSong *newsong;
|
||||
MIDIEvent *evntlist = NULL;
|
||||
|
||||
newsong=malloc(sizeof(NativeMidiSong));
|
||||
if (!newsong) {
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
memset(newsong,0,sizeof(NativeMidiSong));
|
||||
|
||||
/* Attempt to load the midi file */
|
||||
evntlist = CreateMIDIEventList(rw, &newsong->ppqn);
|
||||
if (!evntlist)
|
||||
{
|
||||
free(newsong);
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MIDItoStream(newsong, evntlist);
|
||||
|
||||
FreeMIDIEventList(evntlist);
|
||||
|
||||
if (freerw) {
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
return newsong;
|
||||
}
|
||||
|
||||
void native_midi_freesong(NativeMidiSong *song)
|
||||
{
|
||||
if (hMidiStream)
|
||||
{
|
||||
midiStreamStop(hMidiStream);
|
||||
midiStreamClose(hMidiStream);
|
||||
}
|
||||
if (song)
|
||||
{
|
||||
if (song->NewEvents)
|
||||
free(song->NewEvents);
|
||||
free(song);
|
||||
}
|
||||
}
|
||||
|
||||
void native_midi_start(NativeMidiSong *song, int loops)
|
||||
{
|
||||
MMRESULT merr;
|
||||
MIDIPROPTIMEDIV mptd;
|
||||
|
||||
native_midi_stop();
|
||||
if (!hMidiStream)
|
||||
{
|
||||
merr=midiStreamOpen(&hMidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
|
||||
if (merr!=MMSYSERR_NOERROR)
|
||||
{
|
||||
hMidiStream = NULL; // should I do midiStreamClose(hMidiStream) before?
|
||||
return;
|
||||
}
|
||||
//midiStreamStop(hMidiStream);
|
||||
currentsong=song;
|
||||
currentsong->NewPos=0;
|
||||
currentsong->MusicPlaying=1;
|
||||
currentsong->Loops=loops;
|
||||
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
|
||||
mptd.dwTimeDiv=currentsong->ppqn;
|
||||
merr=midiStreamProperty(hMidiStream,(LPBYTE)&mptd,MIDIPROP_SET | MIDIPROP_TIMEDIV);
|
||||
BlockOut(song);
|
||||
merr=midiStreamRestart(hMidiStream);
|
||||
}
|
||||
}
|
||||
|
||||
void native_midi_stop()
|
||||
{
|
||||
if (!hMidiStream)
|
||||
return;
|
||||
midiStreamStop(hMidiStream);
|
||||
midiStreamClose(hMidiStream);
|
||||
currentsong=NULL;
|
||||
hMidiStream = NULL;
|
||||
}
|
||||
|
||||
int native_midi_active()
|
||||
{
|
||||
return currentsong->MusicPlaying;
|
||||
}
|
||||
|
||||
void native_midi_setvolume(int volume)
|
||||
{
|
||||
int calcVolume;
|
||||
if (volume > 128)
|
||||
volume = 128;
|
||||
if (volume < 0)
|
||||
volume = 0;
|
||||
calcVolume = (65535 * volume / 128);
|
||||
|
||||
midiOutSetVolume((HMIDIOUT)hMidiStream, MAKELONG(calcVolume , calcVolume));
|
||||
}
|
||||
|
||||
const char *native_midi_error(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif /* Windows native MIDI support */
|
||||
234
apps/plugins/sdl/SDL_mixer/playmus.c
Normal file
234
apps/plugins/sdl/SDL_mixer/playmus.c
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
PLAYMUS: A test application for the SDL mixer library.
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef unix
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
static int audio_open = 0;
|
||||
static Mix_Music *music = NULL;
|
||||
static int next_track = 0;
|
||||
|
||||
void CleanUp(int exitcode)
|
||||
{
|
||||
if( Mix_PlayingMusic() ) {
|
||||
Mix_FadeOutMusic(1500);
|
||||
SDL_Delay(1500);
|
||||
}
|
||||
if ( music ) {
|
||||
Mix_FreeMusic(music);
|
||||
music = NULL;
|
||||
}
|
||||
if ( audio_open ) {
|
||||
Mix_CloseAudio();
|
||||
audio_open = 0;
|
||||
}
|
||||
SDL_Quit();
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
void Usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-i] [-l] [-8] [-r rate] [-c channels] [-b buffers] [-v N] [-rwops] <musicfile>\n", argv0);
|
||||
}
|
||||
|
||||
void Menu(void)
|
||||
{
|
||||
char buf[10];
|
||||
|
||||
printf("Available commands: (p)ause (r)esume (h)alt volume(v#) > ");
|
||||
if (scanf("%s",buf) == 1) {
|
||||
switch(buf[0]){
|
||||
case 'p': case 'P':
|
||||
Mix_PauseMusic();
|
||||
break;
|
||||
case 'r': case 'R':
|
||||
Mix_ResumeMusic();
|
||||
break;
|
||||
case 'h': case 'H':
|
||||
Mix_HaltMusic();
|
||||
break;
|
||||
case 'v': case 'V':
|
||||
Mix_VolumeMusic(atoi(buf+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Music playing: %s Paused: %s\n", Mix_PlayingMusic() ? "yes" : "no",
|
||||
Mix_PausedMusic() ? "yes" : "no");
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
|
||||
void IntHandler(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
next_track++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_RWops *rwfp = NULL;
|
||||
int audio_rate;
|
||||
Uint16 audio_format;
|
||||
int audio_channels;
|
||||
int audio_buffers;
|
||||
int audio_volume = MIX_MAX_VOLUME;
|
||||
int looping = 0;
|
||||
int interactive = 0;
|
||||
int rwops = 0;
|
||||
int i;
|
||||
|
||||
/* Initialize variables */
|
||||
audio_rate = 22050;
|
||||
audio_format = AUDIO_S16;
|
||||
audio_channels = 2;
|
||||
audio_buffers = 4096;
|
||||
|
||||
/* Check command line usage */
|
||||
for ( i=1; argv[i] && (*argv[i] == '-'); ++i ) {
|
||||
if ( (strcmp(argv[i], "-r") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_rate = atoi(argv[i]);
|
||||
} else
|
||||
if ( strcmp(argv[i], "-m") == 0 ) {
|
||||
audio_channels = 1;
|
||||
} else
|
||||
if ( (strcmp(argv[i], "-c") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_channels = atoi(argv[i]);
|
||||
} else
|
||||
if ( (strcmp(argv[i], "-b") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_buffers = atoi(argv[i]);
|
||||
} else
|
||||
if ( (strcmp(argv[i], "-v") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_volume = atoi(argv[i]);
|
||||
} else
|
||||
if ( strcmp(argv[i], "-l") == 0 ) {
|
||||
looping = -1;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-i") == 0 ) {
|
||||
interactive = 1;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-8") == 0 ) {
|
||||
audio_format = AUDIO_U8;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-rwops") == 0 ) {
|
||||
rwops = 1;
|
||||
} else {
|
||||
Usage(argv[0]);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if ( ! argv[i] ) {
|
||||
Usage(argv[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Initialize the SDL library */
|
||||
if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
|
||||
return(255);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
signal(SIGINT, IntHandler);
|
||||
signal(SIGTERM, CleanUp);
|
||||
#endif
|
||||
|
||||
/* Open the audio device */
|
||||
if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
|
||||
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
|
||||
return(2);
|
||||
} else {
|
||||
Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
|
||||
printf("Opened audio at %d Hz %d bit %s (%s), %d bytes audio buffer\n", audio_rate,
|
||||
(audio_format&0xFF),
|
||||
(audio_channels > 2) ? "surround" : (audio_channels > 1) ? "stereo" : "mono",
|
||||
(audio_format&0x1000) ? "BE" : "LE",
|
||||
audio_buffers );
|
||||
}
|
||||
audio_open = 1;
|
||||
|
||||
/* Set the music volume */
|
||||
Mix_VolumeMusic(audio_volume);
|
||||
|
||||
/* Set the external music player, if any */
|
||||
Mix_SetMusicCMD(SDL_getenv("MUSIC_CMD"));
|
||||
|
||||
while (argv[i]) {
|
||||
next_track = 0;
|
||||
|
||||
/* Load the requested music file */
|
||||
if ( rwops ) {
|
||||
rwfp = SDL_RWFromFile(argv[i], "rb");
|
||||
music = Mix_LoadMUS_RW(rwfp);
|
||||
} else {
|
||||
music = Mix_LoadMUS(argv[i]);
|
||||
}
|
||||
if ( music == NULL ) {
|
||||
fprintf(stderr, "Couldn't load %s: %s\n",
|
||||
argv[i], SDL_GetError());
|
||||
CleanUp(2);
|
||||
}
|
||||
|
||||
/* Play and then exit */
|
||||
printf("Playing %s\n", argv[i]);
|
||||
Mix_FadeInMusic(music,looping,2000);
|
||||
while ( !next_track && (Mix_PlayingMusic() || Mix_PausedMusic()) ) {
|
||||
if(interactive)
|
||||
Menu();
|
||||
else
|
||||
SDL_Delay(100);
|
||||
}
|
||||
Mix_FreeMusic(music);
|
||||
if ( rwops ) {
|
||||
SDL_RWclose(rwfp);
|
||||
}
|
||||
music = NULL;
|
||||
|
||||
/* If the user presses Ctrl-C more than once, exit. */
|
||||
SDL_Delay(500);
|
||||
if ( next_track > 1 ) break;
|
||||
|
||||
i++;
|
||||
}
|
||||
CleanUp(0);
|
||||
|
||||
/* Not reached, but fixes compiler warnings */
|
||||
return 0;
|
||||
}
|
||||
497
apps/plugins/sdl/SDL_mixer/playwave.c
Normal file
497
apps/plugins/sdl/SDL_mixer/playwave.c
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
PLAYWAVE: A test application for the SDL mixer library.
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef unix
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* rcg06132001 various mixer tests. Define the ones you want.
|
||||
*/
|
||||
/*#define TEST_MIX_DECODERS*/
|
||||
/*#define TEST_MIX_VERSIONS*/
|
||||
/*#define TEST_MIX_CHANNELFINISHED*/
|
||||
/*#define TEST_MIX_PANNING*/
|
||||
/*#define TEST_MIX_DISTANCE*/
|
||||
/*#define TEST_MIX_POSITION*/
|
||||
|
||||
|
||||
#if (defined TEST_MIX_POSITION)
|
||||
|
||||
#if (defined TEST_MIX_PANNING)
|
||||
#error TEST_MIX_POSITION interferes with TEST_MIX_PANNING.
|
||||
#endif
|
||||
|
||||
#if (defined TEST_MIX_DISTANCE)
|
||||
#error TEST_MIX_POSITION interferes with TEST_MIX_DISTANCE.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* rcg06192001 for debugging purposes. */
|
||||
static void output_test_warnings(void)
|
||||
{
|
||||
#if (defined TEST_MIX_CHANNELFINISHED)
|
||||
fprintf(stderr, "Warning: TEST_MIX_CHANNELFINISHED is enabled in this binary...\n");
|
||||
#endif
|
||||
#if (defined TEST_MIX_PANNING)
|
||||
fprintf(stderr, "Warning: TEST_MIX_PANNING is enabled in this binary...\n");
|
||||
#endif
|
||||
#if (defined TEST_MIX_VERSIONS)
|
||||
fprintf(stderr, "Warning: TEST_MIX_VERSIONS is enabled in this binary...\n");
|
||||
#endif
|
||||
#if (defined TEST_MIX_DISTANCE)
|
||||
fprintf(stderr, "Warning: TEST_MIX_DISTANCE is enabled in this binary...\n");
|
||||
#endif
|
||||
#if (defined TEST_MIX_POSITION)
|
||||
fprintf(stderr, "Warning: TEST_MIX_POSITION is enabled in this binary...\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int audio_open = 0;
|
||||
static Mix_Chunk *wave = NULL;
|
||||
|
||||
/* rcg06042009 Report available decoders. */
|
||||
#if (defined TEST_MIX_DECODERS)
|
||||
static void report_decoders(void)
|
||||
{
|
||||
int i, total;
|
||||
|
||||
printf("Supported decoders...\n");
|
||||
total = Mix_GetNumChunkDecoders();
|
||||
for (i = 0; i < total; i++) {
|
||||
fprintf(stderr, " - chunk decoder: %s\n", Mix_GetChunkDecoder(i));
|
||||
}
|
||||
|
||||
total = Mix_GetNumMusicDecoders();
|
||||
for (i = 0; i < total; i++) {
|
||||
fprintf(stderr, " - music decoder: %s\n", Mix_GetMusicDecoder(i));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* rcg06192001 Check new Mixer version API. */
|
||||
#if (defined TEST_MIX_VERSIONS)
|
||||
static void output_versions(const char *libname, const SDL_version *compiled,
|
||||
const SDL_version *linked)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"This program was compiled against %s %d.%d.%d,\n"
|
||||
" and is dynamically linked to %d.%d.%d.\n", libname,
|
||||
compiled->major, compiled->minor, compiled->patch,
|
||||
linked->major, linked->minor, linked->patch);
|
||||
}
|
||||
|
||||
static void test_versions(void)
|
||||
{
|
||||
SDL_version compiled;
|
||||
const SDL_version *linked;
|
||||
|
||||
SDL_VERSION(&compiled);
|
||||
linked = SDL_Linked_Version();
|
||||
output_versions("SDL", &compiled, linked);
|
||||
|
||||
SDL_MIXER_VERSION(&compiled);
|
||||
linked = Mix_Linked_Version();
|
||||
output_versions("SDL_mixer", &compiled, linked);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TEST_MIX_CHANNELFINISHED /* rcg06072001 */
|
||||
static volatile int channel_is_done = 0;
|
||||
static void channel_complete_callback(int chan)
|
||||
{
|
||||
Mix_Chunk *done_chunk = Mix_GetChunk(chan);
|
||||
fprintf(stderr, "We were just alerted that Mixer channel #%d is done.\n", chan);
|
||||
fprintf(stderr, "Channel's chunk pointer is (%p).\n", done_chunk);
|
||||
fprintf(stderr, " Which %s correct.\n", (wave == done_chunk) ? "is" : "is NOT");
|
||||
channel_is_done = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* rcg06192001 abstract this out for testing purposes. */
|
||||
static int still_playing(void)
|
||||
{
|
||||
#ifdef TEST_MIX_CHANNELFINISHED
|
||||
return(!channel_is_done);
|
||||
#else
|
||||
return(Mix_Playing(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if (defined TEST_MIX_PANNING)
|
||||
static void do_panning_update(void)
|
||||
{
|
||||
static Uint8 leftvol = 128;
|
||||
static Uint8 rightvol = 128;
|
||||
static Uint8 leftincr = -1;
|
||||
static Uint8 rightincr = 1;
|
||||
static int panningok = 1;
|
||||
static Uint32 next_panning_update = 0;
|
||||
|
||||
if ((panningok) && (SDL_GetTicks() >= next_panning_update)) {
|
||||
panningok = Mix_SetPanning(0, leftvol, rightvol);
|
||||
if (!panningok) {
|
||||
fprintf(stderr, "Mix_SetPanning(0, %d, %d) failed!\n",
|
||||
(int) leftvol, (int) rightvol);
|
||||
fprintf(stderr, "Reason: [%s].\n", Mix_GetError());
|
||||
}
|
||||
|
||||
if ((leftvol == 255) || (leftvol == 0)) {
|
||||
if (leftvol == 255)
|
||||
printf("All the way in the left speaker.\n");
|
||||
leftincr *= -1;
|
||||
}
|
||||
|
||||
if ((rightvol == 255) || (rightvol == 0)) {
|
||||
if (rightvol == 255)
|
||||
printf("All the way in the right speaker.\n");
|
||||
rightincr *= -1;
|
||||
}
|
||||
|
||||
leftvol += leftincr;
|
||||
rightvol += rightincr;
|
||||
next_panning_update = SDL_GetTicks() + 10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined TEST_MIX_DISTANCE)
|
||||
static void do_distance_update(void)
|
||||
{
|
||||
static Uint8 distance = 1;
|
||||
static Uint8 distincr = 1;
|
||||
static int distanceok = 1;
|
||||
static Uint32 next_distance_update = 0;
|
||||
|
||||
if ((distanceok) && (SDL_GetTicks() >= next_distance_update)) {
|
||||
distanceok = Mix_SetDistance(0, distance);
|
||||
if (!distanceok) {
|
||||
fprintf(stderr, "Mix_SetDistance(0, %d) failed!\n", (int) distance);
|
||||
fprintf(stderr, "Reason: [%s].\n", Mix_GetError());
|
||||
}
|
||||
|
||||
if (distance == 0) {
|
||||
printf("Distance at nearest point.\n");
|
||||
distincr *= -1;
|
||||
}
|
||||
else if (distance == 255) {
|
||||
printf("Distance at furthest point.\n");
|
||||
distincr *= -1;
|
||||
}
|
||||
|
||||
distance += distincr;
|
||||
next_distance_update = SDL_GetTicks() + 15;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined TEST_MIX_POSITION)
|
||||
static void do_position_update(void)
|
||||
{
|
||||
static Sint16 distance = 1;
|
||||
static Sint8 distincr = 1;
|
||||
static Uint16 angle = 0;
|
||||
static Sint8 angleincr = 1;
|
||||
static int positionok = 1;
|
||||
static Uint32 next_position_update = 0;
|
||||
|
||||
if ((positionok) && (SDL_GetTicks() >= next_position_update)) {
|
||||
positionok = Mix_SetPosition(0, angle, distance);
|
||||
if (!positionok) {
|
||||
fprintf(stderr, "Mix_SetPosition(0, %d, %d) failed!\n",
|
||||
(int) angle, (int) distance);
|
||||
fprintf(stderr, "Reason: [%s].\n", Mix_GetError());
|
||||
}
|
||||
|
||||
if (angle == 0) {
|
||||
printf("Due north; now rotating clockwise...\n");
|
||||
angleincr = 1;
|
||||
}
|
||||
|
||||
else if (angle == 360) {
|
||||
printf("Due north; now rotating counter-clockwise...\n");
|
||||
angleincr = -1;
|
||||
}
|
||||
|
||||
distance += distincr;
|
||||
|
||||
if (distance < 0) {
|
||||
distance = 0;
|
||||
distincr = 3;
|
||||
printf("Distance is very, very near. Stepping away by threes...\n");
|
||||
} else if (distance > 255) {
|
||||
distance = 255;
|
||||
distincr = -3;
|
||||
printf("Distance is very, very far. Stepping towards by threes...\n");
|
||||
}
|
||||
|
||||
angle += angleincr;
|
||||
next_position_update = SDL_GetTicks() + 30;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void CleanUp(int exitcode)
|
||||
{
|
||||
if ( wave ) {
|
||||
Mix_FreeChunk(wave);
|
||||
wave = NULL;
|
||||
}
|
||||
if ( audio_open ) {
|
||||
Mix_CloseAudio();
|
||||
audio_open = 0;
|
||||
}
|
||||
SDL_Quit();
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
|
||||
static void Usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-8] [-r rate] [-c channels] [-f] [-F] [-l] [-m] <wavefile>\n", argv0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rcg06182001 This is sick, but cool.
|
||||
*
|
||||
* Actually, it's meant to be an example of how to manipulate a voice
|
||||
* without having to use the mixer effects API. This is more processing
|
||||
* up front, but no extra during the mixing process. Also, in a case like
|
||||
* this, when you need to touch the whole sample at once, it's the only
|
||||
* option you've got. And, with the effects API, you are altering a copy of
|
||||
* the original sample for each playback, and thus, your changes aren't
|
||||
* permanent; here, you've got a reversed sample, and that's that until
|
||||
* you either reverse it again, or reload it.
|
||||
*/
|
||||
static void flip_sample(Mix_Chunk *wave)
|
||||
{
|
||||
Uint16 format;
|
||||
int channels, i, incr;
|
||||
Uint8 *start = wave->abuf;
|
||||
Uint8 *end = wave->abuf + wave->alen;
|
||||
|
||||
Mix_QuerySpec(NULL, &format, &channels);
|
||||
incr = (format & 0xFF) * channels;
|
||||
|
||||
end -= incr;
|
||||
|
||||
switch (incr) {
|
||||
case 8:
|
||||
for (i = wave->alen / 2; i >= 0; i -= 1) {
|
||||
Uint8 tmp = *start;
|
||||
*start = *end;
|
||||
*end = tmp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
for (i = wave->alen / 2; i >= 0; i -= 2) {
|
||||
Uint16 tmp = *start;
|
||||
*((Uint16 *) start) = *((Uint16 *) end);
|
||||
*((Uint16 *) end) = tmp;
|
||||
start += 2;
|
||||
end -= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
for (i = wave->alen / 2; i >= 0; i -= 4) {
|
||||
Uint32 tmp = *start;
|
||||
*((Uint32 *) start) = *((Uint32 *) end);
|
||||
*((Uint32 *) end) = tmp;
|
||||
start += 4;
|
||||
end -= 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unhandled format in sample flipping.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int audio_rate;
|
||||
Uint16 audio_format;
|
||||
int audio_channels;
|
||||
int loops = 0;
|
||||
int i;
|
||||
int reverse_stereo = 0;
|
||||
int reverse_sample = 0;
|
||||
|
||||
#ifdef HAVE_SETBUF
|
||||
setbuf(stdout, NULL); /* rcg06132001 for debugging purposes. */
|
||||
setbuf(stderr, NULL); /* rcg06192001 for debugging purposes, too. */
|
||||
#endif
|
||||
output_test_warnings();
|
||||
|
||||
/* Initialize variables */
|
||||
audio_rate = MIX_DEFAULT_FREQUENCY;
|
||||
audio_format = MIX_DEFAULT_FORMAT;
|
||||
audio_channels = 2;
|
||||
|
||||
/* Check command line usage */
|
||||
for ( i=1; argv[i] && (*argv[i] == '-'); ++i ) {
|
||||
if ( (strcmp(argv[i], "-r") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_rate = atoi(argv[i]);
|
||||
} else
|
||||
if ( strcmp(argv[i], "-m") == 0 ) {
|
||||
audio_channels = 1;
|
||||
} else
|
||||
if ( (strcmp(argv[i], "-c") == 0) && argv[i+1] ) {
|
||||
++i;
|
||||
audio_channels = atoi(argv[i]);
|
||||
} else
|
||||
if ( strcmp(argv[i], "-l") == 0 ) {
|
||||
loops = -1;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-8") == 0 ) {
|
||||
audio_format = AUDIO_U8;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-f") == 0 ) { /* rcg06122001 flip stereo */
|
||||
reverse_stereo = 1;
|
||||
} else
|
||||
if ( strcmp(argv[i], "-F") == 0 ) { /* rcg06172001 flip sample */
|
||||
reverse_sample = 1;
|
||||
} else {
|
||||
Usage(argv[0]);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if ( ! argv[i] ) {
|
||||
Usage(argv[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Initialize the SDL library */
|
||||
if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
|
||||
return(255);
|
||||
}
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
signal(SIGINT, CleanUp);
|
||||
signal(SIGTERM, CleanUp);
|
||||
#endif
|
||||
|
||||
/* Open the audio device */
|
||||
if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, 4096) < 0) {
|
||||
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
|
||||
CleanUp(2);
|
||||
} else {
|
||||
Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
|
||||
printf("Opened audio at %d Hz %d bit %s", audio_rate,
|
||||
(audio_format&0xFF),
|
||||
(audio_channels > 2) ? "surround" :
|
||||
(audio_channels > 1) ? "stereo" : "mono");
|
||||
if ( loops ) {
|
||||
printf(" (looping)\n");
|
||||
} else {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
audio_open = 1;
|
||||
|
||||
#if (defined TEST_MIX_VERSIONS)
|
||||
test_versions();
|
||||
#endif
|
||||
|
||||
#if (defined TEST_MIX_DECODERS)
|
||||
report_decoders();
|
||||
#endif
|
||||
|
||||
/* Load the requested wave file */
|
||||
wave = Mix_LoadWAV(argv[i]);
|
||||
if ( wave == NULL ) {
|
||||
fprintf(stderr, "Couldn't load %s: %s\n",
|
||||
argv[i], SDL_GetError());
|
||||
CleanUp(2);
|
||||
}
|
||||
|
||||
if (reverse_sample) {
|
||||
flip_sample(wave);
|
||||
}
|
||||
|
||||
#ifdef TEST_MIX_CHANNELFINISHED /* rcg06072001 */
|
||||
Mix_ChannelFinished(channel_complete_callback);
|
||||
#endif
|
||||
|
||||
if ( (!Mix_SetReverseStereo(MIX_CHANNEL_POST, reverse_stereo)) &&
|
||||
(reverse_stereo) )
|
||||
{
|
||||
printf("Failed to set up reverse stereo effect!\n");
|
||||
printf("Reason: [%s].\n", Mix_GetError());
|
||||
}
|
||||
|
||||
/* Play and then exit */
|
||||
Mix_PlayChannel(0, wave, loops);
|
||||
|
||||
while (still_playing()) {
|
||||
|
||||
#if (defined TEST_MIX_PANNING) /* rcg06132001 */
|
||||
do_panning_update();
|
||||
#endif
|
||||
|
||||
#if (defined TEST_MIX_DISTANCE) /* rcg06192001 */
|
||||
do_distance_update();
|
||||
#endif
|
||||
|
||||
#if (defined TEST_MIX_POSITION) /* rcg06202001 */
|
||||
do_position_update();
|
||||
#endif
|
||||
|
||||
SDL_Delay(1);
|
||||
|
||||
} /* while still_playing() loop... */
|
||||
|
||||
CleanUp(0);
|
||||
|
||||
/* Not reached, but fixes compiler warnings */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* end of playwave.c ... */
|
||||
|
||||
127
apps/plugins/sdl/SDL_mixer/timidity/COPYING
Normal file
127
apps/plugins/sdl/SDL_mixer/timidity/COPYING
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
The "Artistic License"
|
||||
|
||||
Preamble
|
||||
|
||||
The intent of this document is to state the conditions under which a
|
||||
Package may be copied, such that the Copyright Holder maintains some
|
||||
semblance of artistic control over the development of the package,
|
||||
while giving the users of the package the right to use and distribute
|
||||
the Package in a more-or-less customary fashion, plus the right to make
|
||||
reasonable modifications.
|
||||
|
||||
Definitions:
|
||||
|
||||
"Package" refers to the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection of files
|
||||
created through textual modification.
|
||||
|
||||
"Standard Version" refers to such a Package if it has not been
|
||||
modified, or has been modified in accordance with the wishes
|
||||
of the Copyright Holder as specified below.
|
||||
|
||||
"Copyright Holder" is whoever is named in the copyright or
|
||||
copyrights for the package.
|
||||
|
||||
"You" is you, if you're thinking about copying or distributing
|
||||
this Package.
|
||||
|
||||
"Reasonable copying fee" is whatever you can justify on the
|
||||
basis of media cost, duplication charges, time of people involved,
|
||||
and so on. (You will not be required to justify it to the
|
||||
Copyright Holder, but only to the computing community at large
|
||||
as a market that must bear the fee.)
|
||||
|
||||
"Freely Available" means that no fee is charged for the item
|
||||
itself, though there may be fees involved in handling the item.
|
||||
It also means that recipients of the item may redistribute it
|
||||
under the same conditions they received it.
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of the
|
||||
Standard Version of this Package without restriction, provided that you
|
||||
duplicate all of the original copyright notices and associated disclaimers.
|
||||
|
||||
2. You may apply bug fixes, portability fixes and other modifications
|
||||
derived from the Public Domain or from the Copyright Holder. A Package
|
||||
modified in such a way shall still be considered the Standard Version.
|
||||
|
||||
3. You may otherwise modify your copy of this Package in any way, provided
|
||||
that you insert a prominent notice in each changed file stating how and
|
||||
when you changed that file, and provided that you do at least ONE of the
|
||||
following:
|
||||
|
||||
a) place your modifications in the Public Domain or otherwise make them
|
||||
Freely Available, such as by posting said modifications to Usenet or
|
||||
an equivalent medium, or placing the modifications on a major archive
|
||||
site such as uunet.uu.net, or by allowing the Copyright Holder to include
|
||||
your modifications in the Standard Version of the Package.
|
||||
|
||||
b) use the modified Package only within your corporation or organization.
|
||||
|
||||
c) rename any non-standard executables so the names do not conflict
|
||||
with standard executables, which must also be provided, and provide
|
||||
a separate manual page for each non-standard executable that clearly
|
||||
documents how it differs from the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
4. You may distribute the programs of this Package in object code or
|
||||
executable form, provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute a Standard Version of the executables and library files,
|
||||
together with instructions (in the manual page or equivalent) on where
|
||||
to get the Standard Version.
|
||||
|
||||
b) accompany the distribution with the machine-readable source of
|
||||
the Package with your modifications.
|
||||
|
||||
c) give non-standard executables non-standard names, and clearly
|
||||
document the differences in manual pages (or equivalent), together
|
||||
with instructions on where to get the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
5. You may charge a reasonable copying fee for any distribution of this
|
||||
Package. You may charge any fee you choose for support of this
|
||||
Package. You may not charge a fee for this Package itself. However,
|
||||
you may distribute this Package in aggregate with other (possibly
|
||||
commercial) programs as part of a larger (possibly commercial) software
|
||||
distribution provided that you do not advertise this Package as a
|
||||
product of your own. You may embed this Package's interpreter within
|
||||
an executable of yours (by linking); this shall be construed as a mere
|
||||
form of aggregation, provided that the complete Standard Version of the
|
||||
interpreter is so embedded.
|
||||
|
||||
6. The scripts and library files supplied as input to or produced as
|
||||
output from the programs of this Package do not automatically fall
|
||||
under the copyright of this Package, but belong to whoever generated
|
||||
them, and may be sold commercially, and may be aggregated with this
|
||||
Package. If such scripts or library files are aggregated with this
|
||||
Package via the so-called "undump" or "unexec" methods of producing a
|
||||
binary executable image, then distribution of such an image shall
|
||||
neither be construed as a distribution of this Package nor shall it
|
||||
fall under the restrictions of Paragraphs 3 and 4, provided that you do
|
||||
not represent such an executable image as a Standard Version of this
|
||||
Package.
|
||||
|
||||
7. C subroutines (or comparably compiled subroutines in other
|
||||
languages) supplied by you and linked into this Package in order to
|
||||
emulate subroutines and variables of the language defined by this
|
||||
Package shall not be considered part of this Package, but are the
|
||||
equivalent of input as in Paragraph 6, provided these subroutines do
|
||||
not change the language in any way that would cause it to fail the
|
||||
regression tests for the language.
|
||||
|
||||
8. Aggregation of this Package with a commercial distribution is always
|
||||
permitted provided that the use of this Package is embedded; that is,
|
||||
when no overt attempt is made to make this Package's interfaces visible
|
||||
to the end user of the commercial distribution. Such use shall not be
|
||||
construed as a distribution of this Package.
|
||||
|
||||
9. The name of the Copyright Holder may not be used to endorse or promote
|
||||
products derived from this software without specific prior written permission.
|
||||
|
||||
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
The End
|
||||
112
apps/plugins/sdl/SDL_mixer/timidity/FAQ
Normal file
112
apps/plugins/sdl/SDL_mixer/timidity/FAQ
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
---------------------------*-indented-text-*------------------------------
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Frequently Asked Questions with answers:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: What is it?
|
||||
|
||||
A: Where? Well Chris, TiMidity is a software-only synthesizer, MIDI
|
||||
renderer, MIDI to WAVE converter, realtime MIDI player for UNIX machines,
|
||||
even (I've heard) a Netscape helper application. It takes a MIDI file
|
||||
and writes a WAVE or raw PCM data or plays it on your digital audio
|
||||
device. It sounds much more realistic than FM synthesis, but you need a
|
||||
~100Mhz processor to listen to 32kHz stereo music in the background while
|
||||
you work. 11kHz mono can be played on a low-end 486, and, to some, it
|
||||
still sounds better than FM.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: I don't have a GUS, can I use TiMidity?
|
||||
|
||||
A: Yes. That's the point. You don't need a Gravis Ultrasound to use
|
||||
TiMidity, you just need GUS-compatible patches, which are freely
|
||||
available on the Internet. See below for pointers.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: I have a GUS, can I use TiMidity?
|
||||
|
||||
A: The DOS port doesn't have GUS support, and TiMidity won't be taking
|
||||
advantage of the board's internal synthesizer under other operating
|
||||
systems either. So it kind of defeats the purpose. But you can use it.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: I tried playing a MIDI file I got off the Net but all I got was a
|
||||
dozen warnings saying "No instrument mapped to tone bank 0, program
|
||||
xx - this instrument will not be heard". What's wrong?
|
||||
|
||||
A: The General MIDI standard specifies 128 melodic instruments and
|
||||
some sixty percussion sounds. If you wish to play arbitrary General
|
||||
MIDI files, you'll need to get more patch files.
|
||||
|
||||
There's a program called Midia for SGI's, which also plays MIDI
|
||||
files and has a lot more bells and whistles than TiMidity. It uses
|
||||
GUS-compatible patches, too -- so you can get the 8 MB set at
|
||||
ftp://archive.cs.umbc.edu/pub/midia for pretty good GM compatibility.
|
||||
|
||||
There are also many excellent patches on the Ultrasound FTP sites.
|
||||
I can recommend Dustin McCartney's collections gsdrum*.zip and
|
||||
wow*.zip in the "[.../]sound/patches/files" directory. The huge
|
||||
ProPats series (pp3-*.zip) contains good patches as well. General
|
||||
MIDI files can also be found on these sites.
|
||||
|
||||
This site list is from the GUS FAQ:
|
||||
|
||||
> FTP Sites Archive Directories
|
||||
> --------- -------------------
|
||||
> Main N.American Site: archive.orst.edu pub/packages/gravis
|
||||
> wuarchive.wustl.edu systems/ibmpc/ultrasound
|
||||
> Main Asian Site: nctuccca.edu.tw PC/ultrasound
|
||||
> Main European Site: src.doc.ic.ac.uk packages/ultrasound
|
||||
> Main Australian Site: ftp.mpx.com.au /ultrasound/general
|
||||
> /ultrasound/submit
|
||||
> South African Site: ftp.sun.ac.za /pub/packages/ultrasound
|
||||
> Submissions: archive.epas.utoronto.ca pub/pc/ultrasound/submit
|
||||
> Newly Validated Files: archive.epas.utoronto.ca pub/pc/ultrasound
|
||||
>
|
||||
> Mirrors: garbo.uwasa.fi mirror/ultrasound
|
||||
> ftp.st.nepean.uws.edu.au pc/ultrasound
|
||||
> ftp.luth.se pub/msdos/ultrasound
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: Some files have awful clicks and pops.
|
||||
|
||||
A: Find out which patch is responsible for the clicking (try "timidity
|
||||
-P<patch> <midi/test-decay|midi/test-panning>". Add "strip=tail" in
|
||||
the config file after its name. If this doesn't fix it, mail me the
|
||||
patch.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Q: I'm playing Fantasie Impromptu in the background. When I run Netscape,
|
||||
the sound gets choppy and it takes ten minutes to load. What can I do?
|
||||
|
||||
A: Here are some things to try:
|
||||
|
||||
- Use a lower sampling rate.
|
||||
|
||||
- Use mono output. This can improve performance by 10-30%.
|
||||
(Using 8-bit instead of 16-bit output makes no difference.)
|
||||
|
||||
- Use a smaller number of simultaneous voices.
|
||||
|
||||
- Make sure you compiled with FAST_DECAY and PRECALC_LOOPS enabled
|
||||
in config.h
|
||||
|
||||
- If you don't have hardware to compute sines, recompile with
|
||||
LOOKUP_SINE enabled in config.h
|
||||
|
||||
- Recompile with LOOKUP_HACK enabled in config.h.
|
||||
|
||||
- Recompile with LINEAR_INTERPOLATION disabled in config.h.
|
||||
|
||||
- Recompile with DANGEROUS_RENICE enabled in config.h, and make
|
||||
TiMidity setuid root. This will help only if you frequently play
|
||||
music while other processes are running.
|
||||
|
||||
- Recompile with an Intel-optimized gcc for a 5-15%
|
||||
performance increase.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
57
apps/plugins/sdl/SDL_mixer/timidity/README
Normal file
57
apps/plugins/sdl/SDL_mixer/timidity/README
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
[This version of timidity has been stripped for simplicity in porting to SDL]
|
||||
---------------------------------*-text-*---------------------------------
|
||||
|
||||
From http://www.cgs.fi/~tt/discontinued.html :
|
||||
|
||||
If you'd like to continue hacking on TiMidity, feel free. I'm
|
||||
hereby extending the TiMidity license agreement: you can now
|
||||
select the most convenient license for your needs from (1) the
|
||||
GNU GPL, (2) the GNU LGPL, or (3) the Perl Artistic License.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
* 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.
|
||||
|
||||
* Timidity is no longer supported, but can be found by searching the web.
|
||||
|
||||
|
||||
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.]
|
||||
238
apps/plugins/sdl/SDL_mixer/timidity/common.c
Normal file
238
apps/plugins/sdl/SDL_mixer/timidity/common.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "ctrlmode.h"
|
||||
|
||||
/* I guess "rb" should be right for any libc */
|
||||
#define OPEN_MODE "rb"
|
||||
|
||||
char current_filename[PATH_MAX];
|
||||
|
||||
static PathList *pathlist=NULL;
|
||||
|
||||
/* Try to open a file for reading. If the filename ends in one of the
|
||||
defined compressor extensions, pipe the file through the decompressor */
|
||||
static FILE *try_to_open(const char *name, int decompress, int noise_mode)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(name, OPEN_MODE); /* First just check that the file exists */
|
||||
|
||||
if (!fp)
|
||||
return 0;
|
||||
|
||||
#ifdef DECOMPRESSOR_LIST
|
||||
if (decompress)
|
||||
{
|
||||
int l,el;
|
||||
static char *decompressor_list[] = DECOMPRESSOR_LIST, **dec;
|
||||
const char *cp;
|
||||
char tmp[PATH_MAX], tmp2[PATH_MAX], *cp2;
|
||||
/* Check if it's a compressed file */
|
||||
l=strlen(name);
|
||||
for (dec=decompressor_list; *dec; dec+=2)
|
||||
{
|
||||
el=strlen(*dec);
|
||||
if ((el>=l) || (strcmp(name+l-el, *dec)))
|
||||
continue;
|
||||
|
||||
/* Yes. Close the file, open a pipe instead. */
|
||||
fclose(fp);
|
||||
|
||||
/* Quote some special characters in the file name */
|
||||
cp=name;
|
||||
cp2=tmp2;
|
||||
while (*cp)
|
||||
{
|
||||
switch(*cp)
|
||||
{
|
||||
case '\'':
|
||||
case '\\':
|
||||
case ' ':
|
||||
case '`':
|
||||
case '!':
|
||||
case '"':
|
||||
case '&':
|
||||
case ';':
|
||||
*cp2++='\\';
|
||||
}
|
||||
*cp2++=*cp++;
|
||||
}
|
||||
*cp2=0;
|
||||
|
||||
sprintf(tmp, *(dec+1), tmp2);
|
||||
fp=popen(tmp, "r");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
/* This is meant to find and open files for reading, possibly piping
|
||||
them through a decompressor. */
|
||||
FILE *open_file(const char *name, int decompress, int noise_mode)
|
||||
{
|
||||
FILE *fp;
|
||||
PathList *plp;
|
||||
int l;
|
||||
|
||||
if (!name || !(*name))
|
||||
{
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Attempted to open nameless file.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pathlist==NULL) {
|
||||
/* Generate path list */
|
||||
#ifdef DEFAULT_PATH
|
||||
add_to_pathlist(DEFAULT_PATH);
|
||||
#endif
|
||||
#ifdef DEFAULT_PATH1
|
||||
add_to_pathlist(DEFAULT_PATH1);
|
||||
#endif
|
||||
#ifdef DEFAULT_PATH2
|
||||
add_to_pathlist(DEFAULT_PATH2);
|
||||
#endif
|
||||
#ifdef DEFAULT_PATH3
|
||||
add_to_pathlist(DEFAULT_PATH3);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* First try the given name */
|
||||
|
||||
strncpy(current_filename, name, PATH_MAX - 1);
|
||||
current_filename[PATH_MAX - 1]='\0';
|
||||
|
||||
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
|
||||
if ((fp=try_to_open(current_filename, decompress, noise_mode)))
|
||||
return fp;
|
||||
|
||||
#ifdef ENOENT
|
||||
if (noise_mode && (errno != ENOENT))
|
||||
{
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
|
||||
current_filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
plp=pathlist;
|
||||
if (name[0] != PATH_SEP)
|
||||
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)
|
||||
strcat(current_filename, PATH_STRING);
|
||||
}
|
||||
strcat(current_filename, name);
|
||||
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
|
||||
if ((fp=try_to_open(current_filename, decompress, noise_mode)))
|
||||
return fp;
|
||||
#ifdef ENOENT
|
||||
if (noise_mode && (errno != ENOENT))
|
||||
{
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
|
||||
current_filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
plp=plp->next;
|
||||
}
|
||||
|
||||
/* Nothing could be opened. */
|
||||
|
||||
*current_filename=0;
|
||||
|
||||
if (noise_mode>=2)
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name, strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This closes files opened with open_file */
|
||||
void close_file(FILE *fp)
|
||||
{
|
||||
#ifdef DECOMPRESSOR_LIST
|
||||
if (pclose(fp)) /* Any better ideas? */
|
||||
#endif
|
||||
fclose(fp);
|
||||
|
||||
strncpy(current_filename, "MIDI file", PATH_MAX - 1);
|
||||
}
|
||||
|
||||
/* This is meant for skipping a few bytes in a file or fifo. */
|
||||
void skip(FILE *fp, size_t len)
|
||||
{
|
||||
size_t c;
|
||||
char tmp[PATH_MAX];
|
||||
while (len>0)
|
||||
{
|
||||
c=len;
|
||||
if (c>PATH_MAX) c=PATH_MAX;
|
||||
len-=c;
|
||||
if (c!=fread(tmp, 1, c, fp))
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: skip: %s",
|
||||
current_filename, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* This'll allocate memory or die. */
|
||||
void *safe_malloc(size_t count)
|
||||
{
|
||||
void *p;
|
||||
if (count > (1<<21))
|
||||
{
|
||||
ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
|
||||
"Strange, I feel like allocating %d bytes. This must be a bug.",
|
||||
count);
|
||||
}
|
||||
else if ((p=malloc(count)))
|
||||
return p;
|
||||
else
|
||||
ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count);
|
||||
|
||||
ctl->close();
|
||||
exit(10);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* This adds a directory to the path list */
|
||||
void add_to_pathlist(const char *s)
|
||||
{
|
||||
PathList *plp=safe_malloc(sizeof(PathList));
|
||||
strcpy((plp->path=safe_malloc(strlen(s)+1)),s);
|
||||
plp->next=pathlist;
|
||||
pathlist=plp;
|
||||
}
|
||||
|
||||
/* Free memory associated to path list */
|
||||
void free_pathlist(void)
|
||||
{
|
||||
PathList *plp, *next_plp;
|
||||
|
||||
plp = pathlist;
|
||||
while (plp) {
|
||||
if (plp->path) {
|
||||
free(plp->path);
|
||||
plp->path=NULL;
|
||||
}
|
||||
next_plp = plp->next;
|
||||
free(plp);
|
||||
plp = next_plp;
|
||||
}
|
||||
pathlist = NULL;
|
||||
}
|
||||
39
apps/plugins/sdl/SDL_mixer/timidity/common.h
Normal file
39
apps/plugins/sdl/SDL_mixer/timidity/common.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef PATH_MAX /* GNU Hurd doesn't limit path size, thus no PATH_MAX... */
|
||||
#define PATH_MAX 1024 /* ...so we'll just impose an arbitrary limit. */
|
||||
#endif
|
||||
|
||||
extern char *program_name, current_filename[];
|
||||
|
||||
extern FILE *msgfp;
|
||||
|
||||
extern int num_ochannels;
|
||||
|
||||
#define MULTICHANNEL_OUT
|
||||
#define MAX_OUT_CHANNELS 6
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
void *next;
|
||||
} PathList;
|
||||
|
||||
/* Noise modes for open_file */
|
||||
#define OF_SILENT 0
|
||||
#define OF_NORMAL 1
|
||||
#define OF_VERBOSE 2
|
||||
|
||||
extern FILE *open_file(const char *name, int decompress, int noise_mode);
|
||||
extern void add_to_pathlist(const char *s);
|
||||
extern void free_pathlist(void);
|
||||
extern void close_file(FILE *fp);
|
||||
extern void skip(FILE *fp, size_t len);
|
||||
extern void *safe_malloc(size_t count);
|
||||
229
apps/plugins/sdl/SDL_mixer/timidity/config.h
Normal file
229
apps/plugins/sdl/SDL_mixer/timidity/config.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
/* This is for use with the SDL library */
|
||||
#ifndef __TIMIDITY_CONFIG_H__
|
||||
#define __TIMIDITY_CONFIG_H__
|
||||
#define SDL
|
||||
#include "SDL_config.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#define TIMIDITY_ERROR_SIZE 1024
|
||||
|
||||
/* 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)
|
||||
|
||||
/* A somewhat arbitrary frequency range. The low end of this will
|
||||
sound terrible as no lowpass filtering is performed on most
|
||||
instruments before resampling. */
|
||||
#define MIN_OUTPUT_RATE 4000
|
||||
#define MAX_OUTPUT_RATE 65000
|
||||
|
||||
/* In percent. */
|
||||
/* #define DEFAULT_AMPLIFICATION 70 */
|
||||
/* #define DEFAULT_AMPLIFICATION 50 */
|
||||
#define DEFAULT_AMPLIFICATION 30
|
||||
|
||||
/* Default sampling rate, default polyphony, and maximum polyphony.
|
||||
All but the last can be overridden from the command line. */
|
||||
#define DEFAULT_RATE 32000
|
||||
/* #define DEFAULT_VOICES 32 */
|
||||
/* #define MAX_VOICES 48 */
|
||||
#define DEFAULT_VOICES 256
|
||||
#define MAX_VOICES 256
|
||||
#define MAXCHAN 16
|
||||
/* #define MAXCHAN 64 */
|
||||
#define MAXNOTE 128
|
||||
|
||||
/* 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
|
||||
|
||||
/* Strongly recommended. This option increases CPU usage by half, but
|
||||
without it sound quality is very poor. */
|
||||
#define LINEAR_INTERPOLATION
|
||||
|
||||
/* This is an experimental kludge that needs to be done right, but if
|
||||
you've got an 8-bit sound card, or cheap multimedia speakers hooked
|
||||
to your 16-bit output device, you should definitely give it a try.
|
||||
|
||||
Defining LOOKUP_HACK causes table lookups to be used in mixing
|
||||
instead of multiplication. We convert the sample data to 8 bits at
|
||||
load time and volumes to logarithmic 7-bit values before looking up
|
||||
the product, which degrades sound quality noticeably.
|
||||
|
||||
Defining LOOKUP_HACK should save ~20% of CPU on an Intel machine.
|
||||
LOOKUP_INTERPOLATION might give another ~5% */
|
||||
/* #define LOOKUP_HACK
|
||||
#define LOOKUP_INTERPOLATION */
|
||||
|
||||
/* 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
|
||||
|
||||
#define MAX_SAMPLE_SIZE (1 << (32-FRACTION_BITS))
|
||||
|
||||
typedef double FLOAT_T;
|
||||
|
||||
/* 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
|
||||
|
||||
/* On some machines (especially PCs without math coprocessors),
|
||||
looking up sine values in a table will be significantly faster than
|
||||
computing them on the fly. Uncomment this to use lookups. */
|
||||
/* #define LOOKUP_SINE */
|
||||
|
||||
/* Shawn McHorse's resampling optimizations. These may not in fact be
|
||||
faster on your particular machine and compiler. You'll have to run
|
||||
a benchmark to find out. */
|
||||
#define PRECALC_LOOPS
|
||||
|
||||
/* If calling ldexp() is faster than a floating point multiplication
|
||||
on your machine/compiler/libm, uncomment this. It doesn't make much
|
||||
difference either way, but hey -- it was on the TODO list, so it
|
||||
got done. */
|
||||
/* #define USE_LDEXP */
|
||||
|
||||
/**************************************************************************/
|
||||
/* 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_BITS (32 - FRACTION_BITS)
|
||||
#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
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
|
||||
/* 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))
|
||||
# define XCHG_LONG(x) ((((x)&0xFF)<<24) | \
|
||||
(((x)&0xFF00)<<8) | \
|
||||
(((x)&0xFF0000)>>8) | \
|
||||
(((x)>>24)&0xFF))
|
||||
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
#define LE_SHORT(x) x
|
||||
#define LE_LONG(x) x
|
||||
#define BE_SHORT(x) XCHG_SHORT(x)
|
||||
#define BE_LONG(x) XCHG_LONG(x)
|
||||
#else
|
||||
#define BE_SHORT(x) x
|
||||
#define BE_LONG(x) x
|
||||
#define LE_SHORT(x) XCHG_SHORT(x)
|
||||
#define LE_LONG(x) XCHG_LONG(x)
|
||||
#endif
|
||||
|
||||
#define MAX_AMPLIFICATION 800
|
||||
|
||||
/* You could specify a complete path, e.g. "/etc/timidity.cfg", and
|
||||
then specify the library directory in the configuration file. */
|
||||
#define CONFIG_FILE "/.rockbox/timidity/timidity.cfg"
|
||||
#define CONFIG_FILE_ETC "/.rockbox/timidity/timidity.cfg"
|
||||
|
||||
#if defined(__WIN32__) || defined(__OS2__)
|
||||
#define DEFAULT_PATH "C:\\TIMIDITY"
|
||||
#else
|
||||
#define DEFAULT_PATH "/.rockbox/patchset"
|
||||
#define DEFAULT_PATH1 "/.rockbox/duke3d"
|
||||
#define DEFAULT_PATH2 "/.rockbox/timidity"
|
||||
#define DEFAULT_PATH3 "/.rockbox/midi"
|
||||
#endif
|
||||
|
||||
/* These affect general volume */
|
||||
#define GUARD_BITS 3
|
||||
#define AMP_BITS (15-GUARD_BITS)
|
||||
|
||||
#ifdef LOOKUP_HACK
|
||||
typedef int8 sample_t;
|
||||
typedef uint8 final_volume_t;
|
||||
# define FINAL_VOLUME(v) (~_l2u[v])
|
||||
# define MIXUP_SHIFT 5
|
||||
# define MAX_AMP_VALUE 4095
|
||||
#else
|
||||
typedef int16 sample_t;
|
||||
typedef int32 final_volume_t;
|
||||
# define FINAL_VOLUME(v) (v)
|
||||
# define MAX_AMP_VALUE ((1<<(AMP_BITS+1))-1)
|
||||
#endif
|
||||
|
||||
typedef int16 resample_t;
|
||||
|
||||
#ifdef USE_LDEXP
|
||||
# define FSCALE(a,b) ldexp((a),(b))
|
||||
# define FSCALENEG(a,b) ldexp((a),-(b))
|
||||
#else
|
||||
# define FSCALE(a,b) (float)((a) * (double)(1<<(b)))
|
||||
# define FSCALENEG(a,b) (float)((a) * (1.0L / (double)(1<<(b))))
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
#define VIBRATO_SAMPLE_INCREMENTS 32
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* The path separator (D.M.) */
|
||||
#if defined(__WIN32__) || defined(__OS2__)
|
||||
# define PATH_SEP '\\'
|
||||
# define PATH_STRING "\\"
|
||||
#else
|
||||
# define PATH_SEP '/'
|
||||
# define PATH_STRING "/"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
26
apps/plugins/sdl/SDL_mixer/timidity/ctrlmode.c
Normal file
26
apps/plugins/sdl/SDL_mixer/timidity/ctrlmode.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ctrlmode.h"
|
||||
|
||||
#ifdef SDL
|
||||
extern ControlMode sdl_control_mode;
|
||||
# ifndef DEFAULT_CONTROL_MODE
|
||||
# define DEFAULT_CONTROL_MODE &sdl_control_mode
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ControlMode *ctl_list[]={
|
||||
#ifdef SDL
|
||||
&sdl_control_mode,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
ControlMode *ctl=DEFAULT_CONTROL_MODE;
|
||||
74
apps/plugins/sdl/SDL_mixer/timidity/ctrlmode.h
Normal file
74
apps/plugins/sdl/SDL_mixer/timidity/ctrlmode.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
/* Return values for ControlMode.read */
|
||||
|
||||
#define RC_ERROR -1
|
||||
#define RC_NONE 0
|
||||
#define RC_QUIT 1
|
||||
#define RC_NEXT 2
|
||||
#define RC_PREVIOUS 3 /* Restart this song at beginning, or the previous
|
||||
song if we're less than a second into this one. */
|
||||
#define RC_FORWARD 4
|
||||
#define RC_BACK 5
|
||||
#define RC_JUMP 6
|
||||
#define RC_TOGGLE_PAUSE 7 /* Pause/continue */
|
||||
#define RC_RESTART 8 /* Restart song at beginning */
|
||||
|
||||
#define RC_PAUSE 9 /* Really pause playing */
|
||||
#define RC_CONTINUE 10 /* Continue if paused */
|
||||
#define RC_REALLY_PREVIOUS 11 /* Really go to the previous song */
|
||||
#define RC_CHANGE_VOLUME 12
|
||||
#define RC_LOAD_FILE 13 /* Load a new midifile */
|
||||
#define RC_TUNE_END 14 /* The tune is over, play it again sam? */
|
||||
|
||||
#define CMSG_INFO 0
|
||||
#define CMSG_WARNING 1
|
||||
#define CMSG_ERROR 2
|
||||
#define CMSG_FATAL 3
|
||||
#define CMSG_TRACE 4
|
||||
#define CMSG_TIME 5
|
||||
#define CMSG_TOTAL 6
|
||||
#define CMSG_FILE 7
|
||||
#define CMSG_TEXT 8
|
||||
|
||||
#define VERB_NORMAL 0
|
||||
#define VERB_VERBOSE 1
|
||||
#define VERB_NOISY 2
|
||||
#define VERB_DEBUG 3
|
||||
#define VERB_DEBUG_SILLY 4
|
||||
|
||||
typedef struct {
|
||||
char *id_name, id_character;
|
||||
int verbosity, trace_playing, opened;
|
||||
|
||||
int (*open)(int using_stdin, int using_stdout);
|
||||
void (*pass_playing_list)(int number_of_files, char *list_of_files[]);
|
||||
void (*close)(void);
|
||||
int (*read)(int32 *valp);
|
||||
int (*cmsg)(int type, int verbosity_level, char *fmt, ...);
|
||||
|
||||
void (*refresh)(void);
|
||||
void (*reset)(void);
|
||||
void (*file_name)(char *name);
|
||||
void (*total_time)(int tt);
|
||||
void (*current_time)(int ct);
|
||||
|
||||
void (*note)(int v);
|
||||
void (*master_volume)(int mv);
|
||||
void (*program)(int channel, int val); /* val<0 means drum set -val */
|
||||
void (*volume)(int channel, int val);
|
||||
void (*expression)(int channel, int val);
|
||||
void (*panning)(int channel, int val);
|
||||
void (*sustain)(int channel, int val);
|
||||
void (*pitch_bend)(int channel, int val);
|
||||
|
||||
} ControlMode;
|
||||
|
||||
extern ControlMode *ctl_list[], *ctl;
|
||||
extern char timidity_error[];
|
||||
187
apps/plugins/sdl/SDL_mixer/timidity/filter.c
Normal file
187
apps/plugins/sdl/SDL_mixer/timidity/filter.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
|
||||
filter.c: written by Vincent Pagel ( pagel@loria.fr )
|
||||
|
||||
implements fir antialiasing filter : should help when setting sample
|
||||
rates as low as 8Khz.
|
||||
|
||||
April 95
|
||||
- first draft
|
||||
|
||||
22/5/95
|
||||
- modify "filter" so that it simulate leading and trailing 0 in the buffer
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "ctrlmode.h"
|
||||
#include "instrum.h"
|
||||
#include "filter.h"
|
||||
|
||||
/* bessel function */
|
||||
static float ino(float x)
|
||||
{
|
||||
float y, de, e, sde;
|
||||
int i;
|
||||
|
||||
y = x / 2;
|
||||
e = 1.0;
|
||||
de = 1.0;
|
||||
i = 1;
|
||||
do {
|
||||
de = de * y / (float) i;
|
||||
sde = de * de;
|
||||
e += sde;
|
||||
} while (!( (e * 1.0e-08 - sde > 0) || (i++ > 25) ));
|
||||
return(e);
|
||||
}
|
||||
|
||||
/* Kaiser Window (symetric) */
|
||||
static void kaiser(float *w,int n,float beta)
|
||||
{
|
||||
float xind, xi;
|
||||
int i;
|
||||
|
||||
xind = (float)((2*n - 1) * (2*n - 1));
|
||||
for (i =0; i<n ; i++)
|
||||
{
|
||||
xi = (float)(i + 0.5);
|
||||
w[i] = ino((float)(beta * sqrt((double)(1. - 4 * xi * xi / xind))))
|
||||
/ ino((float)beta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fir coef in g, cuttoff frequency in fc
|
||||
*/
|
||||
static void designfir(float *g , float fc)
|
||||
{
|
||||
int i;
|
||||
float xi, omega, att, beta ;
|
||||
float w[ORDER2];
|
||||
|
||||
for (i =0; i < ORDER2 ;i++)
|
||||
{
|
||||
xi = (float) (i + 0.5);
|
||||
omega = (float)(PI * xi);
|
||||
g[i] = (float)(sin( (double) omega * fc) / omega);
|
||||
}
|
||||
|
||||
att = 40.; /* attenuation in db */
|
||||
beta = (float) (exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886
|
||||
* (att - 20.96));
|
||||
kaiser( w, ORDER2, beta);
|
||||
|
||||
/* Matrix product */
|
||||
for (i =0; i < ORDER2 ; i++)
|
||||
g[i] = g[i] * w[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* FIR filtering -> apply the filter given by coef[] to the data buffer
|
||||
* Note that we simulate leading and trailing 0 at the border of the
|
||||
* data buffer
|
||||
*/
|
||||
static void filter(sample_t *result,sample_t *data, int32 length,float coef[])
|
||||
{
|
||||
int32 sample,i,sample_window;
|
||||
int16 peak = 0;
|
||||
float sum;
|
||||
|
||||
/* Simulate leading 0 at the begining of the buffer */
|
||||
for (sample = 0; sample < ORDER2 ; sample++ )
|
||||
{
|
||||
sum = 0.0;
|
||||
sample_window= sample - ORDER2;
|
||||
|
||||
for (i = 0; i < ORDER ;i++)
|
||||
sum += (float)(coef[i] *
|
||||
((sample_window<0)? 0.0 : data[sample_window++])) ;
|
||||
|
||||
/* Saturation ??? */
|
||||
if (sum> 32767.) { sum=32767.; peak++; }
|
||||
if (sum< -32768.) { sum=-32768; peak++; }
|
||||
result[sample] = (sample_t) sum;
|
||||
}
|
||||
|
||||
/* The core of the buffer */
|
||||
for (sample = ORDER2; sample < length - ORDER + ORDER2 ; sample++ )
|
||||
{
|
||||
sum = 0.0;
|
||||
sample_window= sample - ORDER2;
|
||||
|
||||
for (i = 0; i < ORDER ;i++)
|
||||
sum += data[sample_window++] * coef[i];
|
||||
|
||||
/* Saturation ??? */
|
||||
if (sum> 32767.) { sum=32767.; peak++; }
|
||||
if (sum< -32768.) { sum=-32768; peak++; }
|
||||
result[sample] = (sample_t) sum;
|
||||
}
|
||||
|
||||
/* Simulate 0 at the end of the buffer */
|
||||
for (sample = length - ORDER + ORDER2; sample < length ; sample++ )
|
||||
{
|
||||
sum = 0.0;
|
||||
sample_window= sample - ORDER2;
|
||||
|
||||
for (i = 0; i < ORDER ;i++)
|
||||
sum += (float)(coef[i] *
|
||||
((sample_window>=length)? 0.0 : data[sample_window++])) ;
|
||||
|
||||
/* Saturation ??? */
|
||||
if (sum> 32767.) { sum=32767.; peak++; }
|
||||
if (sum< -32768.) { sum=-32768; peak++; }
|
||||
result[sample] = (sample_t) sum;
|
||||
}
|
||||
|
||||
if (peak)
|
||||
ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||
"Saturation %2.3f %%.", 100.0*peak/ (float) length);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Prevent aliasing by filtering any freq above the output_rate */
|
||||
/* */
|
||||
/* I don't worry about looping point -> they will remain soft if they */
|
||||
/* were already */
|
||||
/***********************************************************************/
|
||||
void antialiasing(Sample *sp, int32 output_rate )
|
||||
{
|
||||
sample_t *temp;
|
||||
int i;
|
||||
float fir_symetric[ORDER];
|
||||
float fir_coef[ORDER2];
|
||||
float freq_cut; /* cutoff frequency [0..1.0] FREQ_CUT/SAMP_FREQ*/
|
||||
|
||||
|
||||
ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: Fsample=%iKHz",
|
||||
sp->sample_rate);
|
||||
|
||||
/* No oversampling */
|
||||
if (output_rate>=sp->sample_rate)
|
||||
return;
|
||||
|
||||
freq_cut= (float) output_rate / (float) sp->sample_rate;
|
||||
ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: cutoff=%f%%",
|
||||
freq_cut*100.);
|
||||
|
||||
designfir(fir_coef,freq_cut);
|
||||
|
||||
/* Make the filter symetric */
|
||||
for (i = 0 ; i<ORDER2 ;i++)
|
||||
fir_symetric[ORDER-1 - i] = fir_symetric[i] = fir_coef[ORDER2-1 - i];
|
||||
|
||||
/* We apply the filter we have designed on a copy of the patch */
|
||||
temp = safe_malloc(sp->data_length);
|
||||
memcpy(temp,sp->data,sp->data_length);
|
||||
|
||||
filter(sp->data,temp,sp->data_length/sizeof(sample_t),fir_symetric);
|
||||
|
||||
free(temp);
|
||||
}
|
||||
23
apps/plugins/sdl/SDL_mixer/timidity/filter.h
Normal file
23
apps/plugins/sdl/SDL_mixer/timidity/filter.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
|
||||
filter.h : written by Vincent Pagel ( pagel@loria.fr )
|
||||
|
||||
implements fir antialiasing filter : should help when setting sample
|
||||
rates as low as 8Khz.
|
||||
|
||||
*/
|
||||
|
||||
/* Order of the FIR filter = 20 should be enough ! */
|
||||
#define ORDER 20
|
||||
#define ORDER2 ORDER/2
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265
|
||||
#endif
|
||||
|
||||
extern void antialiasing(Sample *sp, int32 output_rate);
|
||||
1018
apps/plugins/sdl/SDL_mixer/timidity/instrum.c
Normal file
1018
apps/plugins/sdl/SDL_mixer/timidity/instrum.c
Normal file
File diff suppressed because it is too large
Load diff
168
apps/plugins/sdl/SDL_mixer/timidity/instrum.h
Normal file
168
apps/plugins/sdl/SDL_mixer/timidity/instrum.h
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
int32
|
||||
loop_start, loop_end, data_length,
|
||||
sample_rate, low_freq, high_freq, root_freq;
|
||||
uint8
|
||||
root_tune, fine_tune;
|
||||
int32
|
||||
envelope_rate[7], envelope_offset[7],
|
||||
modulation_rate[7], modulation_offset[7];
|
||||
FLOAT_T
|
||||
volume, resonance,
|
||||
modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc;
|
||||
sample_t *data;
|
||||
int32
|
||||
tremolo_sweep_increment, tremolo_phase_increment,
|
||||
lfo_sweep_increment, lfo_phase_increment,
|
||||
vibrato_sweep_increment, vibrato_control_ratio,
|
||||
cutoff_freq;
|
||||
uint8
|
||||
reverberation, chorusdepth,
|
||||
tremolo_depth, vibrato_depth,
|
||||
modes;
|
||||
uint8
|
||||
attenuation, freq_center;
|
||||
int8
|
||||
panning, note_to_use, exclusiveClass;
|
||||
int16
|
||||
scale_tuning, keyToModEnvHold, keyToModEnvDecay,
|
||||
keyToVolEnvHold, keyToVolEnvDecay;
|
||||
int32
|
||||
freq_scale, vibrato_delay;
|
||||
} Sample;
|
||||
|
||||
/* 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)
|
||||
#define MODES_FAST_RELEASE (1<<7)
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
int samples;
|
||||
Sample *sample;
|
||||
} Instrument;
|
||||
#endif
|
||||
|
||||
#define INST_GUS 0
|
||||
#define INST_SF2 1
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
int samples;
|
||||
Sample *sample;
|
||||
int left_samples;
|
||||
Sample *left_sample;
|
||||
int right_samples;
|
||||
Sample *right_sample;
|
||||
unsigned char *contents;
|
||||
} Instrument;
|
||||
|
||||
|
||||
typedef struct _InstrumentLayer {
|
||||
uint8 lo, hi;
|
||||
int size;
|
||||
Instrument *instrument;
|
||||
struct _InstrumentLayer *next;
|
||||
} InstrumentLayer;
|
||||
|
||||
struct cfg_type {
|
||||
int font_code;
|
||||
int num;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#define FONT_NORMAL 0
|
||||
#define FONT_FFF 1
|
||||
#define FONT_SBK 2
|
||||
#define FONT_TONESET 3
|
||||
#define FONT_DRUMSET 4
|
||||
#define FONT_PRESET 5
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
InstrumentLayer *layer;
|
||||
int font_type, sf_ix, last_used, tuning;
|
||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
||||
} ToneBankElement;
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
char *name;
|
||||
Instrument *instrument;
|
||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
||||
} ToneBankElement;
|
||||
#endif
|
||||
/* A hack to delay instrument loading until after reading the
|
||||
entire MIDI file. */
|
||||
#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1))
|
||||
|
||||
#define MAXPROG 128
|
||||
#define MAXBANK 130
|
||||
#define SFXBANK (MAXBANK-1)
|
||||
#define SFXDRUM1 (MAXBANK-2)
|
||||
#define SFXDRUM2 (MAXBANK-1)
|
||||
#define XGDRUM 1
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
ToneBankElement tone[128];
|
||||
} ToneBank;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ToneBankElement tone[MAXPROG];
|
||||
} ToneBank;
|
||||
|
||||
|
||||
extern char *sf_file;
|
||||
|
||||
extern ToneBank *tonebank[], *drumset[];
|
||||
|
||||
#if 0
|
||||
extern Instrument *default_instrument;
|
||||
#endif
|
||||
extern InstrumentLayer *default_instrument;
|
||||
extern int default_program;
|
||||
extern int antialiasing_allowed;
|
||||
extern int fast_decay;
|
||||
extern int free_instruments_afterwards;
|
||||
|
||||
#define SPECIAL_PROGRAM -1
|
||||
|
||||
extern int load_missing_instruments(void);
|
||||
extern void free_instruments(void);
|
||||
extern void end_soundfont(void);
|
||||
extern int set_default_instrument(const char *name);
|
||||
|
||||
|
||||
extern int32 convert_tremolo_sweep(uint8 sweep);
|
||||
extern int32 convert_vibrato_sweep(uint8 sweep, int32 vib_control_ratio);
|
||||
extern int32 convert_tremolo_rate(uint8 rate);
|
||||
extern int32 convert_vibrato_rate(uint8 rate);
|
||||
|
||||
extern int init_soundfont(char *fname, int oldbank, int newbank, int level);
|
||||
extern InstrumentLayer *load_sbk_patch(const char *name, int gm_num, int bank, int percussion,
|
||||
int panning, int amp, int note_to_use, int sf_ix);
|
||||
extern int current_tune_number;
|
||||
extern int max_patch_memory;
|
||||
extern int current_patch_memory;
|
||||
#define XMAPMAX 800
|
||||
extern int xmap[XMAPMAX][5];
|
||||
extern void pcmap(int *b, int *v, int *p, int *drums);
|
||||
|
||||
847
apps/plugins/sdl/SDL_mixer/timidity/mix.c
Normal file
847
apps/plugins/sdl/SDL_mixer/timidity/mix.c
Normal file
|
|
@ -0,0 +1,847 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "ctrlmode.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
#include "mix.h"
|
||||
|
||||
/* Returns 1 if envelope runs out */
|
||||
int recompute_envelope(int v)
|
||||
{
|
||||
int stage;
|
||||
|
||||
stage = voice[v].envelope_stage;
|
||||
|
||||
if (stage>5)
|
||||
{
|
||||
/* Envelope ran out. */
|
||||
int tmp=(voice[v].status == VOICE_DIE); /* Already displayed as dead */
|
||||
voice[v].status = VOICE_FREE;
|
||||
if(!tmp)
|
||||
ctl->note(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
if (voice[v].status==VOICE_ON || voice[v].status==VOICE_SUSTAINED)
|
||||
{
|
||||
if (stage>2)
|
||||
{
|
||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||
voice[v].envelope_increment=0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
voice[v].envelope_stage=stage+1;
|
||||
|
||||
if (voice[v].envelope_volume==voice[v].sample->envelope_offset[stage])
|
||||
return recompute_envelope(v);
|
||||
voice[v].envelope_target=voice[v].sample->envelope_offset[stage];
|
||||
voice[v].envelope_increment = voice[v].sample->envelope_rate[stage];
|
||||
if (voice[v].envelope_target<voice[v].envelope_volume)
|
||||
voice[v].envelope_increment = -voice[v].envelope_increment;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apply_envelope_to_amp(int v)
|
||||
{
|
||||
FLOAT_T lamp=voice[v].left_amp, ramp, lramp, rramp, ceamp, lfeamp;
|
||||
int32 la,ra, lra, rra, cea, lfea;
|
||||
if (voice[v].panned == PANNED_MYSTERY)
|
||||
{
|
||||
lramp=voice[v].lr_amp;
|
||||
ramp=voice[v].right_amp;
|
||||
ceamp=voice[v].ce_amp;
|
||||
rramp=voice[v].rr_amp;
|
||||
lfeamp=voice[v].lfe_amp;
|
||||
|
||||
if (voice[v].tremolo_phase_increment)
|
||||
{
|
||||
FLOAT_T tv = voice[v].tremolo_volume;
|
||||
lramp *= tv;
|
||||
lamp *= tv;
|
||||
ceamp *= tv;
|
||||
ramp *= tv;
|
||||
rramp *= tv;
|
||||
lfeamp *= tv;
|
||||
}
|
||||
if (voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
FLOAT_T ev = (FLOAT_T)vol_table[voice[v].envelope_volume>>23];
|
||||
lramp *= ev;
|
||||
lamp *= ev;
|
||||
ceamp *= ev;
|
||||
ramp *= ev;
|
||||
rramp *= ev;
|
||||
lfeamp *= ev;
|
||||
}
|
||||
|
||||
la = (int32)FSCALE(lamp,AMP_BITS);
|
||||
ra = (int32)FSCALE(ramp,AMP_BITS);
|
||||
lra = (int32)FSCALE(lramp,AMP_BITS);
|
||||
rra = (int32)FSCALE(rramp,AMP_BITS);
|
||||
cea = (int32)FSCALE(ceamp,AMP_BITS);
|
||||
lfea = (int32)FSCALE(lfeamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE) la=MAX_AMP_VALUE;
|
||||
if (ra>MAX_AMP_VALUE) ra=MAX_AMP_VALUE;
|
||||
if (lra>MAX_AMP_VALUE) lra=MAX_AMP_VALUE;
|
||||
if (rra>MAX_AMP_VALUE) rra=MAX_AMP_VALUE;
|
||||
if (cea>MAX_AMP_VALUE) cea=MAX_AMP_VALUE;
|
||||
if (lfea>MAX_AMP_VALUE) lfea=MAX_AMP_VALUE;
|
||||
|
||||
voice[v].lr_mix=FINAL_VOLUME(lra);
|
||||
voice[v].left_mix=FINAL_VOLUME(la);
|
||||
voice[v].ce_mix=FINAL_VOLUME(cea);
|
||||
voice[v].right_mix=FINAL_VOLUME(ra);
|
||||
voice[v].rr_mix=FINAL_VOLUME(rra);
|
||||
voice[v].lfe_mix=FINAL_VOLUME(lfea);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (voice[v].tremolo_phase_increment)
|
||||
lamp *= voice[v].tremolo_volume;
|
||||
if (voice[v].sample->modes & MODES_ENVELOPE)
|
||||
lamp *= (FLOAT_T)vol_table[voice[v].envelope_volume>>23];
|
||||
|
||||
la = (int32)FSCALE(lamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE)
|
||||
la=MAX_AMP_VALUE;
|
||||
|
||||
voice[v].left_mix=FINAL_VOLUME(la);
|
||||
}
|
||||
}
|
||||
|
||||
static int update_envelope(int v)
|
||||
{
|
||||
voice[v].envelope_volume += voice[v].envelope_increment;
|
||||
/* Why is there no ^^ operator?? */
|
||||
if (((voice[v].envelope_increment < 0) &&
|
||||
(voice[v].envelope_volume <= voice[v].envelope_target)) ||
|
||||
((voice[v].envelope_increment > 0) &&
|
||||
(voice[v].envelope_volume >= voice[v].envelope_target)))
|
||||
{
|
||||
voice[v].envelope_volume = voice[v].envelope_target;
|
||||
if (recompute_envelope(v))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_tremolo(int v)
|
||||
{
|
||||
int32 depth=voice[v].sample->tremolo_depth<<7;
|
||||
|
||||
if (voice[v].tremolo_sweep)
|
||||
{
|
||||
/* Update sweep position */
|
||||
|
||||
voice[v].tremolo_sweep_position += voice[v].tremolo_sweep;
|
||||
if (voice[v].tremolo_sweep_position>=(1<<SWEEP_SHIFT))
|
||||
voice[v].tremolo_sweep=0; /* Swept to max amplitude */
|
||||
else
|
||||
{
|
||||
/* Need to adjust depth */
|
||||
depth *= voice[v].tremolo_sweep_position;
|
||||
depth >>= SWEEP_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
voice[v].tremolo_phase += voice[v].tremolo_phase_increment;
|
||||
|
||||
/* if (voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
|
||||
voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT; */
|
||||
|
||||
voice[v].tremolo_volume = (FLOAT_T)
|
||||
(1.0 - FSCALENEG((sine(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(int v)
|
||||
{
|
||||
if (voice[v].envelope_increment && update_envelope(v))
|
||||
return 1;
|
||||
|
||||
if (voice[v].tremolo_phase_increment)
|
||||
update_tremolo(v);
|
||||
|
||||
apply_envelope_to_amp(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LOOKUP_HACK
|
||||
# define MIXATION(a) *lp++ += mixup[(a<<8) | (uint8)s];
|
||||
#else
|
||||
# define MIXATION(a) *lp++ += (a)*s;
|
||||
#endif
|
||||
|
||||
#define MIXSKIP lp++
|
||||
#define MIXMAX(a,b) *lp++ += ((a>b)?a:b) * s
|
||||
#define MIXCENT(a,b) *lp++ += (a/2+b/2) * s
|
||||
#define MIXHALF(a) *lp++ += (a>>1)*s;
|
||||
|
||||
static void mix_mystery_signal(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
Voice *vp = voice + v;
|
||||
final_volume_t
|
||||
left_rear=vp->lr_mix,
|
||||
left=vp->left_mix,
|
||||
center=vp->ce_mix,
|
||||
right=vp->right_mix,
|
||||
right_rear=vp->rr_mix,
|
||||
lfe=vp->lfe_mix;
|
||||
int cc;
|
||||
resample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
|
||||
left_rear = vp->lr_mix;
|
||||
left = vp->left_mix;
|
||||
center = vp->ce_mix;
|
||||
right = vp->right_mix;
|
||||
right_rear = vp->rr_mix;
|
||||
lfe = vp->lfe_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
if (num_ochannels >= 4) {
|
||||
MIXATION(left_rear);
|
||||
MIXATION(right_rear);
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXATION(center);
|
||||
MIXATION(lfe);
|
||||
}
|
||||
}
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left_rear = vp->lr_mix;
|
||||
left = vp->left_mix;
|
||||
center = vp->ce_mix;
|
||||
right = vp->right_mix;
|
||||
right_rear = vp->rr_mix;
|
||||
lfe = vp->lfe_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
if (num_ochannels >= 4) {
|
||||
MIXATION(left_rear);
|
||||
MIXATION(right_rear);
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXATION(center);
|
||||
MIXATION(lfe);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center_signal(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
Voice *vp = voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
resample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
else if (num_ochannels == 4) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
else if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
else if (num_ochannels == 4) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
else if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single_left_signal(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
Voice *vp = voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
resample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single_right_signal(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
Voice *vp = voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
resample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXSKIP;
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
} if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXSKIP;
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
} if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono_signal(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
Voice *vp = voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
resample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = control_ratio;
|
||||
if (update_signal(v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
cc = control_ratio;
|
||||
if (update_signal(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(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left_rear=voice[v].lr_mix,
|
||||
left=voice[v].left_mix,
|
||||
center=voice[v].ce_mix,
|
||||
right=voice[v].right_mix,
|
||||
right_rear=voice[v].rr_mix,
|
||||
lfe=voice[v].lfe_mix;
|
||||
resample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
if (num_ochannels >= 4) {
|
||||
MIXATION(left_rear);
|
||||
MIXATION(right_rear);
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXATION(center);
|
||||
MIXATION(lfe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left=voice[v].left_mix;
|
||||
resample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
else if (num_ochannels == 4) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
}
|
||||
else if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single_left(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left=voice[v].left_mix;
|
||||
resample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void mix_single_right(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left=voice[v].left_mix;
|
||||
resample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
if (num_ochannels >= 4) {
|
||||
MIXSKIP;
|
||||
MIXHALF(left);
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono(resample_t *sp, int32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left=voice[v].left_mix;
|
||||
resample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ramp a note out in c samples */
|
||||
static void ramp_out(resample_t *sp, int32 *lp, int v, int32 c)
|
||||
{
|
||||
|
||||
/* should be final_volume_t, but uint8 gives trouble. */
|
||||
int32 left_rear, left, center, right, right_rear, lfe, li, ri;
|
||||
|
||||
resample_t s = 0; /* silly warning about uninitialized s */
|
||||
|
||||
/* Fix by James Caldwell */
|
||||
if ( c == 0 ) c = 1;
|
||||
|
||||
left = 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 (!(play_mode->encoding & PE_MONO))
|
||||
{
|
||||
if (voice[v].panned==PANNED_MYSTERY)
|
||||
{
|
||||
left_rear = voice[v].lr_mix;
|
||||
center=voice[v].ce_mix;
|
||||
right=voice[v].right_mix;
|
||||
right_rear = voice[v].rr_mix;
|
||||
lfe = voice[v].lfe_mix;
|
||||
|
||||
ri=-(right/c);
|
||||
while (c--)
|
||||
{
|
||||
left_rear += li; if (left_rear<0) left_rear=0;
|
||||
left += li; if (left<0) left=0;
|
||||
center += li; if (center<0) center=0;
|
||||
right += ri; if (right<0) right=0;
|
||||
right_rear += ri; if (right_rear<0) right_rear=0;
|
||||
lfe += li; if (lfe<0) lfe=0;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
if (num_ochannels >= 4) {
|
||||
MIXATION(left_rear);
|
||||
MIXATION(right_rear);
|
||||
}
|
||||
if (num_ochannels == 6) {
|
||||
MIXATION(center);
|
||||
MIXATION(lfe);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (voice[v].panned==PANNED_CENTER)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
if (num_ochannels == 2) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
else if (num_ochannels == 4) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
}
|
||||
else if (num_ochannels == 6) {
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (voice[v].panned==PANNED_LEFT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
if (num_ochannels >= 4) {
|
||||
MIXATION(left);
|
||||
MIXSKIP;
|
||||
} if (num_ochannels == 6) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (voice[v].panned==PANNED_RIGHT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
if (num_ochannels >= 4) {
|
||||
MIXSKIP;
|
||||
MIXATION(left);
|
||||
} if (num_ochannels == 6) {
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mono output. */
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************** interface function ******************/
|
||||
|
||||
void mix_voice(int32 *buf, int v, int32 c)
|
||||
{
|
||||
Voice *vp=voice+v;
|
||||
int32 count=c;
|
||||
resample_t *sp;
|
||||
if (c<0) return;
|
||||
if (vp->status==VOICE_DIE)
|
||||
{
|
||||
if (count>=MAX_DIE_TIME)
|
||||
count=MAX_DIE_TIME;
|
||||
sp=resample_voice(v, &count);
|
||||
ramp_out(sp, buf, v, count);
|
||||
vp->status=VOICE_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp=resample_voice(v, &count);
|
||||
if (count<0) return;
|
||||
if (play_mode->encoding & PE_MONO)
|
||||
{
|
||||
/* Mono output. */
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mono_signal(sp, buf, v, count);
|
||||
else
|
||||
mix_mono(sp, buf, v, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vp->panned == PANNED_MYSTERY)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mystery_signal(sp, buf, v, count);
|
||||
else
|
||||
mix_mystery(sp, buf, v, count);
|
||||
}
|
||||
else if (vp->panned == PANNED_CENTER)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_center_signal(sp, buf, v, count);
|
||||
else
|
||||
mix_center(sp, buf, v, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's either full left or full right. In either case,
|
||||
every other sample is 0. Just get the offset right: */
|
||||
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
{
|
||||
if (vp->panned == PANNED_RIGHT)
|
||||
mix_single_right_signal(sp, buf, v, count);
|
||||
else mix_single_left_signal(sp, buf, v, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vp->panned == PANNED_RIGHT)
|
||||
mix_single_right(sp, buf, v, count);
|
||||
else mix_single_left(sp, buf, v, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
apps/plugins/sdl/SDL_mixer/timidity/mix.h
Normal file
11
apps/plugins/sdl/SDL_mixer/timidity/mix.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
extern void mix_voice(int32 *buf, int v, int32 c);
|
||||
extern int recompute_envelope(int v);
|
||||
extern void apply_envelope_to_amp(int v);
|
||||
122
apps/plugins/sdl/SDL_mixer/timidity/output.c
Normal file
122
apps/plugins/sdl/SDL_mixer/timidity/output.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "output.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
#ifdef SDL
|
||||
extern PlayMode sdl_play_mode;
|
||||
#define DEFAULT_PLAY_MODE &sdl_play_mode
|
||||
#endif
|
||||
|
||||
PlayMode *play_mode_list[] = {
|
||||
#ifdef DEFAULT_PLAY_MODE
|
||||
DEFAULT_PLAY_MODE,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
#ifdef DEFAULT_PLAY_MODE
|
||||
PlayMode *play_mode=DEFAULT_PLAY_MODE;
|
||||
#endif
|
||||
|
||||
/*****************************************************************/
|
||||
/* Some functions to convert signed 32-bit data to other formats */
|
||||
|
||||
void s32tos8(void *dp, int32 *lp, int32 c)
|
||||
{
|
||||
int8 *cp=(int8 *)(dp);
|
||||
int32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-8-GUARD_BITS);
|
||||
if (l>127) l=127;
|
||||
else if (l<-128) l=-128;
|
||||
*cp++ = (int8) (l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou8(void *dp, int32 *lp, int32 c)
|
||||
{
|
||||
uint8 *cp=(uint8 *)(dp);
|
||||
int32 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, int32 *lp, int32 c)
|
||||
{
|
||||
int16 *sp=(int16 *)(dp);
|
||||
int32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = (int16)(l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16(void *dp, int32 *lp, int32 c)
|
||||
{
|
||||
uint16 *sp=(uint16 *)(dp);
|
||||
int32 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, int32 *lp, int32 c)
|
||||
{
|
||||
int16 *sp=(int16 *)(dp);
|
||||
int32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = XCHG_SHORT((int16)(l));
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16x(void *dp, int32 *lp, int32 c)
|
||||
{
|
||||
uint16 *sp=(uint16 *)(dp);
|
||||
int32 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));
|
||||
}
|
||||
}
|
||||
|
||||
void s32toulaw(void *dp, int32 *lp, int32 c)
|
||||
{
|
||||
uint8 *up=(uint8 *)(dp);
|
||||
int32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-13-GUARD_BITS);
|
||||
if (l > 4095) l=4095;
|
||||
else if (l<-4096) l=-4096;
|
||||
*up++ = _l2u[l];
|
||||
}
|
||||
}
|
||||
60
apps/plugins/sdl/SDL_mixer/timidity/output.h
Normal file
60
apps/plugins/sdl/SDL_mixer/timidity/output.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
/* Data format encoding bits */
|
||||
|
||||
#define PE_MONO 0x01 /* versus stereo */
|
||||
#define PE_SIGNED 0x02 /* versus unsigned */
|
||||
#define PE_16BIT 0x04 /* versus 8-bit */
|
||||
#define PE_ULAW 0x08 /* versus linear */
|
||||
#define PE_BYTESWAP 0x10 /* versus the other way */
|
||||
|
||||
typedef struct {
|
||||
int32 rate, encoding;
|
||||
char *id_name;
|
||||
} PlayMode;
|
||||
|
||||
extern PlayMode *play_mode_list[], *play_mode;
|
||||
extern int init_buffers(int kbytes);
|
||||
|
||||
/* Conversion functions -- These overwrite the int32 data in *lp with
|
||||
data in another format */
|
||||
|
||||
/* The size of the output buffers */
|
||||
extern int AUDIO_BUFFER_SIZE;
|
||||
|
||||
/* Actual copy function */
|
||||
extern void (*s32tobuf)(void *dp, int32 *lp, int32 c);
|
||||
|
||||
/* 8-bit signed and unsigned*/
|
||||
extern void s32tos8(void *dp, int32 *lp, int32 c);
|
||||
extern void s32tou8(void *dp, int32 *lp, int32 c);
|
||||
|
||||
/* 16-bit */
|
||||
extern void s32tos16(void *dp, int32 *lp, int32 c);
|
||||
extern void s32tou16(void *dp, int32 *lp, int32 c);
|
||||
|
||||
/* byte-exchanged 16-bit */
|
||||
extern void s32tos16x(void *dp, int32 *lp, int32 c);
|
||||
extern void s32tou16x(void *dp, int32 *lp, int32 c);
|
||||
|
||||
/* uLaw (8 bits) */
|
||||
extern void s32toulaw(void *dp, int32 *lp, int32 c);
|
||||
|
||||
/* little-endian and big-endian specific */
|
||||
#if SDL_BYTEORDER == SDL_LIL_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
|
||||
1746
apps/plugins/sdl/SDL_mixer/timidity/playmidi.c
Normal file
1746
apps/plugins/sdl/SDL_mixer/timidity/playmidi.c
Normal file
File diff suppressed because it is too large
Load diff
160
apps/plugins/sdl/SDL_mixer/timidity/playmidi.h
Normal file
160
apps/plugins/sdl/SDL_mixer/timidity/playmidi.h
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int32 time;
|
||||
uint8 channel, type, a, b;
|
||||
} MidiEvent;
|
||||
|
||||
/* 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_TONE_KIT 17
|
||||
#define ME_MASTERVOLUME 18
|
||||
#define ME_CHANNEL_PRESSURE 19
|
||||
|
||||
#define ME_HARMONICCONTENT 71
|
||||
#define ME_RELEASETIME 72
|
||||
#define ME_ATTACKTIME 73
|
||||
#define ME_BRIGHTNESS 74
|
||||
|
||||
#define ME_REVERBERATION 91
|
||||
#define ME_CHORUSDEPTH 93
|
||||
|
||||
#define ME_EOT 99
|
||||
|
||||
|
||||
#define SFX_BANKTYPE 64
|
||||
|
||||
typedef struct {
|
||||
int
|
||||
bank, program, volume, sustain, panning, pitchbend, expression,
|
||||
mono, /* one note only on this channel -- not implemented yet */
|
||||
/* new stuff */
|
||||
variationbank, reverberation, chorusdepth, harmoniccontent,
|
||||
releasetime, attacktime, brightness, kit, sfx,
|
||||
/* end new */
|
||||
pitchsens;
|
||||
FLOAT_T
|
||||
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||
char transpose;
|
||||
char *name;
|
||||
} Channel;
|
||||
|
||||
/* Causes the instrument's default panning to be used. */
|
||||
#define NO_PANNING -1
|
||||
/* envelope points */
|
||||
#define MAXPOINT 7
|
||||
|
||||
typedef struct {
|
||||
uint8
|
||||
status, channel, note, velocity, clone_type;
|
||||
Sample *sample;
|
||||
Sample *left_sample;
|
||||
Sample *right_sample;
|
||||
int32 clone_voice;
|
||||
int32
|
||||
orig_frequency, frequency,
|
||||
sample_offset, loop_start, loop_end;
|
||||
int32
|
||||
envelope_volume, modulation_volume;
|
||||
int32
|
||||
envelope_target, modulation_target;
|
||||
int32
|
||||
tremolo_sweep, tremolo_sweep_position, tremolo_phase,
|
||||
lfo_sweep, lfo_sweep_position, lfo_phase,
|
||||
vibrato_sweep, vibrato_sweep_position, vibrato_depth, vibrato_delay,
|
||||
starttime, echo_delay_count;
|
||||
int32
|
||||
echo_delay,
|
||||
sample_increment,
|
||||
envelope_increment,
|
||||
modulation_increment,
|
||||
tremolo_phase_increment,
|
||||
lfo_phase_increment;
|
||||
|
||||
final_volume_t left_mix, right_mix, lr_mix, rr_mix, ce_mix, lfe_mix;
|
||||
|
||||
FLOAT_T
|
||||
left_amp, right_amp, lr_amp, rr_amp, ce_amp, lfe_amp,
|
||||
volume, tremolo_volume, lfo_volume;
|
||||
int32
|
||||
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
||||
int32
|
||||
envelope_rate[MAXPOINT], envelope_offset[MAXPOINT];
|
||||
int32
|
||||
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
||||
envelope_stage, modulation_stage, control_counter,
|
||||
modulation_delay, modulation_counter, panning, panned;
|
||||
} Voice;
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Envelope stages: */
|
||||
#define ATTACK 0
|
||||
#define HOLD 1
|
||||
#define DECAY 2
|
||||
#define RELEASE 3
|
||||
#define RELEASEB 4
|
||||
#define RELEASEC 5
|
||||
#define DELAY 6
|
||||
|
||||
extern Channel channel[16];
|
||||
extern Voice voice[MAX_VOICES];
|
||||
extern signed char drumvolume[MAXCHAN][MAXNOTE];
|
||||
extern signed char drumpanpot[MAXCHAN][MAXNOTE];
|
||||
extern signed char drumreverberation[MAXCHAN][MAXNOTE];
|
||||
extern signed char drumchorusdepth[MAXCHAN][MAXNOTE];
|
||||
|
||||
extern int32 control_ratio, amp_with_poly, amplification;
|
||||
extern int32 drumchannels;
|
||||
extern int adjust_panning_immediately;
|
||||
extern int voices;
|
||||
|
||||
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
|
||||
|
||||
extern int GM_System_On;
|
||||
extern int XG_System_On;
|
||||
extern int GS_System_On;
|
||||
|
||||
extern int XG_System_reverb_type;
|
||||
extern int XG_System_chorus_type;
|
||||
extern int XG_System_variation_type;
|
||||
|
||||
extern int play_midi(MidiEvent *el, int32 events, int32 samples);
|
||||
extern int play_midi_file(const char *fn);
|
||||
extern void dumb_pass_playing_list(int number_of_files, char *list_of_files[]);
|
||||
1065
apps/plugins/sdl/SDL_mixer/timidity/readmidi.c
Normal file
1065
apps/plugins/sdl/SDL_mixer/timidity/readmidi.c
Normal file
File diff suppressed because it is too large
Load diff
18
apps/plugins/sdl/SDL_mixer/timidity/readmidi.h
Normal file
18
apps/plugins/sdl/SDL_mixer/timidity/readmidi.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
MidiEvent event;
|
||||
void *next;
|
||||
} MidiEventList;
|
||||
|
||||
extern int32 quietchannels;
|
||||
|
||||
extern MidiEvent *read_midi_file(SDL_RWops *mrw, int32 *count, int32 *sp);
|
||||
|
||||
extern char midi_name[FILENAME_MAX+1];
|
||||
730
apps/plugins/sdl/SDL_mixer/timidity/resample.c
Normal file
730
apps/plugins/sdl/SDL_mixer/timidity/resample.c
Normal file
|
|
@ -0,0 +1,730 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "ctrlmode.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
|
||||
#ifdef LINEAR_INTERPOLATION
|
||||
# if defined(LOOKUP_HACK) && defined(LOOKUP_INTERPOLATION)
|
||||
# define RESAMPLATION \
|
||||
v1=src[ofs>>FRACTION_BITS];\
|
||||
v2=src[(ofs>>FRACTION_BITS)+1];\
|
||||
*dest++ = (resample_t)(v1 + (iplookup[(((v2-v1)<<5) & 0x03FE0) | \
|
||||
((ofs & FRACTION_MASK) >> (FRACTION_BITS-5))]));
|
||||
# else
|
||||
# define RESAMPLATION \
|
||||
v1=src[ofs>>FRACTION_BITS];\
|
||||
v2=src[(ofs>>FRACTION_BITS)+1];\
|
||||
*dest++ = (resample_t)(v1 + (((v2-v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));
|
||||
# endif
|
||||
# define INTERPVARS sample_t v1, v2
|
||||
#else
|
||||
/* Earplugs recommended for maximum listening enjoyment */
|
||||
# define RESAMPLATION *dest++ = src[ofs>>FRACTION_BITS];
|
||||
# define INTERPVARS
|
||||
#endif
|
||||
|
||||
#define FINALINTERP if (ofs == le) *dest++=src[ofs>>FRACTION_BITS];
|
||||
/* So it isn't interpolation. At least it's final. */
|
||||
|
||||
extern resample_t *resample_buffer;
|
||||
|
||||
/*************** resampling with fixed increment *****************/
|
||||
|
||||
static resample_t *rs_plain(int v, int32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
INTERPVARS;
|
||||
Voice
|
||||
*vp=&voice[v];
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
int32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->data_length,
|
||||
count=*countptr;
|
||||
|
||||
#ifdef PRECALC_LOOPS
|
||||
int32 i, j;
|
||||
|
||||
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;
|
||||
|
||||
for(j = 0; j < i; j++)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
|
||||
if (ofs >= le)
|
||||
{
|
||||
FINALINTERP;
|
||||
vp->status=VOICE_FREE;
|
||||
ctl->note(v);
|
||||
*countptr-=count+1;
|
||||
}
|
||||
|
||||
#else /* PRECALC_LOOPS */
|
||||
while (count--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs >= le)
|
||||
{
|
||||
FINALINTERP;
|
||||
vp->status=VOICE_FREE;
|
||||
ctl->note(v);
|
||||
*countptr-=count+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* PRECALC_LOOPS */
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return resample_buffer;
|
||||
}
|
||||
|
||||
static resample_t *rs_loop(Voice *vp, int32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
INTERPVARS;
|
||||
int32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
|
||||
#ifdef PRECALC_LOOPS
|
||||
int32 i;
|
||||
|
||||
if (ofs < 0 || le < 0) return resample_buffer;
|
||||
|
||||
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;
|
||||
if (i > 0)
|
||||
while (i--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
}
|
||||
#else
|
||||
while (count--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=le)
|
||||
ofs -= ll; /* Hopefully the loop is longer than an increment. */
|
||||
}
|
||||
#endif
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return resample_buffer;
|
||||
}
|
||||
|
||||
static resample_t *rs_bidir(Voice *vp, int32 count)
|
||||
{
|
||||
INTERPVARS;
|
||||
int32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
|
||||
#ifdef PRECALC_LOOPS
|
||||
int32
|
||||
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--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
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--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
if (ofs>=le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* PRECALC_LOOPS */
|
||||
/* Play normally until inside the loop region */
|
||||
|
||||
if (ofs < ls)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=ls)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
if (count>0)
|
||||
while (count--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le - (ofs - le);
|
||||
incr = -incr;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls + (ls - ofs);
|
||||
incr = -incr;
|
||||
}
|
||||
}
|
||||
#endif /* PRECALC_LOOPS */
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return 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 < VIBRATO_SAMPLE_INCREMENTS/2)
|
||||
return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
|
||||
else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
|
||||
return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
|
||||
else
|
||||
return phase-VIBRATO_SAMPLE_INCREMENTS/2;
|
||||
}
|
||||
|
||||
static int32 update_vibrato(Voice *vp, int sign)
|
||||
{
|
||||
int32 depth;
|
||||
int phase, pb;
|
||||
double a;
|
||||
|
||||
if (vp->vibrato_phase++ >= 2*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)(play_mode->rate)),
|
||||
FRACTION_BITS);
|
||||
|
||||
pb=(int)((sine(vp->vibrato_phase *
|
||||
(SINE_CYCLE_LENGTH/(2*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]=(int32) a;
|
||||
|
||||
if (sign)
|
||||
a = -a; /* need to preserve the loop direction */
|
||||
|
||||
return (int32) a;
|
||||
}
|
||||
|
||||
static resample_t *rs_vib_plain(int v, int32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
INTERPVARS;
|
||||
Voice *vp=&voice[v];
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
int32
|
||||
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(vp, 0);
|
||||
}
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs >= le)
|
||||
{
|
||||
FINALINTERP;
|
||||
vp->status=VOICE_FREE;
|
||||
ctl->note(v);
|
||||
*countptr-=count+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return resample_buffer;
|
||||
}
|
||||
|
||||
static resample_t *rs_vib_loop(Voice *vp, int32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
INTERPVARS;
|
||||
int32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
|
||||
#ifdef PRECALC_LOOPS
|
||||
int32 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--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
if(vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(vp, 0);
|
||||
vibflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* PRECALC_LOOPS */
|
||||
while (count--)
|
||||
{
|
||||
if (!cc--)
|
||||
{
|
||||
cc=vp->vibrato_control_ratio;
|
||||
incr=update_vibrato(vp, 0);
|
||||
}
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=le)
|
||||
ofs -= ll; /* Hopefully the loop is longer than an increment. */
|
||||
}
|
||||
#endif /* PRECALC_LOOPS */
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return resample_buffer;
|
||||
}
|
||||
|
||||
static resample_t *rs_vib_bidir(Voice *vp, int32 count)
|
||||
{
|
||||
INTERPVARS;
|
||||
int32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
resample_t
|
||||
*dest=resample_buffer;
|
||||
sample_t
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
|
||||
#ifdef PRECALC_LOOPS
|
||||
int32
|
||||
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--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(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--)
|
||||
{
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(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;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* PRECALC_LOOPS */
|
||||
/* Play normally until inside the loop region */
|
||||
|
||||
if (ofs < ls)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
if (!cc--)
|
||||
{
|
||||
cc=vp->vibrato_control_ratio;
|
||||
incr=update_vibrato(vp, 0);
|
||||
}
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=ls)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
if (count>0)
|
||||
while (count--)
|
||||
{
|
||||
if (!cc--)
|
||||
{
|
||||
cc=vp->vibrato_control_ratio;
|
||||
incr=update_vibrato(vp, (incr < 0));
|
||||
}
|
||||
RESAMPLATION;
|
||||
ofs += incr;
|
||||
if (ofs>=le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le - (ofs - le);
|
||||
incr = -incr;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls + (ls - ofs);
|
||||
incr = -incr;
|
||||
}
|
||||
}
|
||||
#endif /* PRECALC_LOOPS */
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return resample_buffer;
|
||||
}
|
||||
|
||||
resample_t *resample_voice(int v, int32 *countptr)
|
||||
{
|
||||
int32 ofs;
|
||||
uint8 modes;
|
||||
Voice *vp=&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;
|
||||
ctl->note(v);
|
||||
|
||||
/* 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 (resample_t *)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(vp, *countptr);
|
||||
else
|
||||
return rs_vib_loop(vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_vib_plain(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(vp, *countptr);
|
||||
else
|
||||
return rs_loop(vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_plain(v, countptr);
|
||||
}
|
||||
}
|
||||
|
||||
void pre_resample(Sample * sp)
|
||||
{
|
||||
double a, xdiff;
|
||||
int32 incr, ofs, newlen, count;
|
||||
int16 *src = (int16 *) sp->data;
|
||||
resample_t *newdata, *dest;
|
||||
int16 v1, v2, v3, v4, *vptr;
|
||||
static const char note_name[12][3] =
|
||||
{
|
||||
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
||||
};
|
||||
|
||||
ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
|
||||
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) * play_mode->rate);
|
||||
if (a <= 0) return;
|
||||
newlen = (int32)(sp->data_length / a);
|
||||
if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE) return;
|
||||
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);
|
||||
v1 = (vptr == src) ? *vptr : *(vptr - 1);
|
||||
v2 = *vptr;
|
||||
v3 = *(vptr + 1);
|
||||
v4 = *(vptr + 2);
|
||||
xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);
|
||||
*dest++ = (int16)(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++ = (resample_t)(v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));
|
||||
}
|
||||
else
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
|
||||
sp->data_length = newlen;
|
||||
sp->loop_start = (int32)(sp->loop_start / a);
|
||||
sp->loop_end = (int32)(sp->loop_end / a);
|
||||
free(sp->data);
|
||||
sp->data = (sample_t *) newdata;
|
||||
sp->sample_rate = 0;
|
||||
}
|
||||
10
apps/plugins/sdl/SDL_mixer/timidity/resample.h
Normal file
10
apps/plugins/sdl/SDL_mixer/timidity/resample.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
extern resample_t *resample_voice(int v, int32 *countptr);
|
||||
extern void pre_resample(Sample *sp);
|
||||
19
apps/plugins/sdl/SDL_mixer/timidity/sdl_a.c
Normal file
19
apps/plugins/sdl/SDL_mixer/timidity/sdl_a.c
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "output.h"
|
||||
|
||||
/* export the playback mode */
|
||||
|
||||
#define dpm sdl_play_mode
|
||||
|
||||
PlayMode dpm = {
|
||||
DEFAULT_RATE, PE_16BIT|PE_SIGNED,
|
||||
"SDL audio"
|
||||
};
|
||||
136
apps/plugins/sdl/SDL_mixer/timidity/sdl_c.c
Normal file
136
apps/plugins/sdl/SDL_mixer/timidity/sdl_c.c
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
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 Perl Artistic License, available in COPYING.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "ctrlmode.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
|
||||
static void ctl_refresh(void);
|
||||
static void ctl_total_time(int tt);
|
||||
static void ctl_master_volume(int mv);
|
||||
static void ctl_file_name(char *name);
|
||||
static void ctl_current_time(int ct);
|
||||
static void ctl_note(int v);
|
||||
static void ctl_program(int ch, int val);
|
||||
static void ctl_volume(int channel, int val);
|
||||
static void ctl_expression(int channel, int val);
|
||||
static void ctl_panning(int channel, int val);
|
||||
static void ctl_sustain(int channel, int val);
|
||||
static void ctl_pitch_bend(int channel, int val);
|
||||
static void ctl_reset(void);
|
||||
static int ctl_open(int using_stdin, int using_stdout);
|
||||
static void ctl_close(void);
|
||||
static int ctl_read(int32 *valp);
|
||||
static int cmsg(int type, int verbosity_level, char *fmt, ...);
|
||||
|
||||
/**********************************/
|
||||
/* export the interface functions */
|
||||
|
||||
#define ctl sdl_control_mode
|
||||
|
||||
ControlMode ctl=
|
||||
{
|
||||
"SDL interface", 's',
|
||||
1,0,0,
|
||||
ctl_open,NULL, ctl_close, ctl_read, cmsg,
|
||||
ctl_refresh, ctl_reset, ctl_file_name, ctl_total_time, ctl_current_time,
|
||||
ctl_note,
|
||||
ctl_master_volume, ctl_program, ctl_volume,
|
||||
ctl_expression, ctl_panning, ctl_sustain, ctl_pitch_bend
|
||||
};
|
||||
|
||||
static int ctl_open(int using_stdin, int using_stdout)
|
||||
{
|
||||
ctl.opened=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ctl_close(void)
|
||||
{
|
||||
ctl.opened=0;
|
||||
}
|
||||
|
||||
static int ctl_read(int32 *valp)
|
||||
{
|
||||
return RC_NONE;
|
||||
}
|
||||
|
||||
static int cmsg(int type, int verbosity_level, char *fmt, ...)
|
||||
{
|
||||
#ifdef GREGS_DEBUG
|
||||
va_list ap;
|
||||
int flag_newline = 1;
|
||||
if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
|
||||
ctl.verbosity<verbosity_level-1)
|
||||
return 0;
|
||||
if (*fmt == '~')
|
||||
{
|
||||
flag_newline = 0;
|
||||
fmt++;
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
if (!ctl.opened)
|
||||
{
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (flag_newline) fprintf(stderr, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (flag_newline) fprintf(stderr, "\n");
|
||||
}
|
||||
va_end(ap);
|
||||
if (!flag_newline) fflush(stderr);
|
||||
return 0;
|
||||
#else
|
||||
va_list ap;
|
||||
if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
|
||||
ctl.verbosity<verbosity_level)
|
||||
return 0;
|
||||
va_start(ap, fmt);
|
||||
char buf[128];
|
||||
vsnprintf(buf, 128, fmt, ap);
|
||||
puts(buf);
|
||||
SDL_vsnprintf(timidity_error, TIMIDITY_ERROR_SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ctl_refresh(void) { }
|
||||
|
||||
static void ctl_total_time(int tt) {}
|
||||
|
||||
static void ctl_master_volume(int mv) {}
|
||||
|
||||
static void ctl_file_name(char *name) {}
|
||||
|
||||
static void ctl_current_time(int ct) {}
|
||||
|
||||
static void ctl_note(int v) {}
|
||||
|
||||
static void ctl_program(int ch, int val) {}
|
||||
|
||||
static void ctl_volume(int channel, int val) {}
|
||||
|
||||
static void ctl_expression(int channel, int val) {}
|
||||
|
||||
static void ctl_panning(int channel, int val) {}
|
||||
|
||||
static void ctl_sustain(int channel, int val) {}
|
||||
|
||||
static void ctl_pitch_bend(int channel, int val) {}
|
||||
|
||||
static void ctl_reset(void) {}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue