Added SDL_sound lib
This commit is contained in:
25
project/jni/sdl_sound/Android.mk
Normal file
25
project/jni/sdl_sound/Android.mk
Normal file
@@ -0,0 +1,25 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := sdl_sound
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/../sdl-$(SDL_VERSION)/include $(LOCAL_PATH)/include $(LOCAL_PATH)/decoders $(LOCAL_PATH)/decoders/mpglib \
|
||||
$(LOCAL_PATH)/../flac/include $(LOCAL_PATH)/../ogg/include \
|
||||
$(LOCAL_PATH)/../vorbis/include $(LOCAL_PATH)/../tremor/include $(LOCAL_PATH)/../mikmod/include \
|
||||
$(LOCAL_PATH)/timidity
|
||||
LOCAL_CFLAGS := -O3 -DHAVE_CONFIG_H -DLAYER1 -DLAYER2 -DLAYER3
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c)) \
|
||||
$(addprefix decoders/, $(notdir $(wildcard $(LOCAL_PATH)/decoders/*.c))) \
|
||||
$(addprefix decoders/mpglib/, $(notdir $(wildcard $(LOCAL_PATH)/decoders/mpglib/*.c)))
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := sdl-$(SDL_VERSION)
|
||||
LOCAL_STATIC_LIBRARIES := flac mikmod vorbis ogg
|
||||
|
||||
LOCAL_LDLIBS :=
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
376
project/jni/sdl_sound/CHANGELOG
Normal file
376
project/jni/sdl_sound/CHANGELOG
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* CHANGELOG.
|
||||
*/
|
||||
|
||||
04202008 - Upped version to 1.0.3 (brown paper bag release for soname bug).
|
||||
04192008 - Apparently MICRO_VERSION in configure.in doesn't do what I think;
|
||||
reset for binary compatibility (thanks, Hans!).
|
||||
04182008 - Include <math.h> in shn.c.
|
||||
04172008 - Look for Speex includes in new directory. Converted all text
|
||||
encoding from ISO-8859-1 to UTF-8. Fixed "make dist" script for
|
||||
dealing with Subversion instead of CVS. Added Speex to the README.
|
||||
Upped version to 1.0.2.
|
||||
04112008 - Check if Speex header has bogus data (CVE-2008-1686).
|
||||
08062007 - Updated my email address.
|
||||
07152007 - Minor correction in Timidity resampling code (Thanks, Sam!).
|
||||
07062007 - Fixed uninitialized buffer in mpglib. (Thanks, Phil!).
|
||||
10292006 - Fixed bogus memory dereference when SMPEG fails init (thanks, Chris!)
|
||||
10272006 - FLAC 1.1.3 breaks their API _again_, so we try to do the right
|
||||
thing at build time. (Thanks, Josh!).
|
||||
05122006 - Patched to get mpglib compiling again (thanks, Sam!).
|
||||
12172005 - Fixed gcc4 whining in playsound_simple.c.
|
||||
12062005 - Trimmed a bunch of junk out of the build system, and now it works
|
||||
on Mac OS X again.
|
||||
10122005 - Check for libmodplug headers in two possible places (thanks, Tyler!)
|
||||
10012005 - Added playsound_simple.c.
|
||||
05302005 - Backport from devtree: Fixed automake nonsense.
|
||||
11122004 - Backport from devtree: fix .voc decoder crash on file open.
|
||||
05082004 - Fixed "bootstrap" to work with MacOSX.
|
||||
05072004 - Backed out some commits, converted repository to Subversion, and
|
||||
branched off to a 1.1.0 development tree. Changed MikMod URL...old
|
||||
one is now a porn site. :(
|
||||
10252003 - VOC decoder was broken. Now it isn't.
|
||||
10142003 - Build system fix: acinclude.m4 had some word wrapping badness.
|
||||
10122003 - Fixed "make dist" behaviour to not packaged generated docs, and
|
||||
made sure other files are always packaged, regardless of config.
|
||||
Upped version to 1.0.1.
|
||||
10102003 - Changed some SDL_Error()s to __Sound_SetError() in new DLS code
|
||||
to fix linking issues.
|
||||
10052003 - Fixed memory corruption when freeing DLS instruments,
|
||||
and bug when timidity is initialized multiple times (Thanks, Sam!).
|
||||
09252003 - Sam Lantinga added support for DLS instruments to the MIDI decoder.
|
||||
09132003 - Happy September. Added Speex (.spx) decoder.
|
||||
08052003 - Fixed MIDI decoder on bigendian systems.
|
||||
03102003 - Never actually created samplelist_mutex (Thanks, Glenn Maynard!).
|
||||
01302003 - Patches to make SDL_sound more Visual C happy (Thanks, Eric!).
|
||||
01122003 - Fix to smpeg.c's rewinding code (Thanks, Eric). Put Visual C 6
|
||||
project files in CVS, without external binaries (Thanks, Eric).
|
||||
12212002 - Fixed ogg.c to decode a full buffer at a time instead of one ogg
|
||||
packet per call, and mikmod has a check during initialization to
|
||||
prevent a clash with SDL_mixer (Thanks, Eric).
|
||||
12092002 - Changed Sound_Init()'s call to SDL_Init() to SDL_InitSubSystem(),
|
||||
to prevent unwanted use of the SDL parachute (thanks, Glenn).
|
||||
10092002 - Fixed a "make dist" issue and upped version to 1.0.0! Woohoo!
|
||||
09302002 - libFLAC broke their API (again!) for version 1.0.4. That was the
|
||||
last straw. I ripped the version detection and obsolete FLAC
|
||||
support out, so you need libFLAC 1.0.4 for that decoder now (and
|
||||
they'll probably break the API again for 1.0.5. Argh).
|
||||
09262002 - Happy September. Fixed SDLCALL issues in SDL_sound.h, so it should
|
||||
work with Win32/WinCE builds again. I hope. Merged latest altcvt
|
||||
from Frank into CVS.
|
||||
08222002 - Borland project files in CVS, thanks to Dominique Louis. There are
|
||||
project files for C++ Builder 6 (Windows), C++ Builder for Linux
|
||||
(aka Kylix 3) and Borland's C++ Command line compiler.
|
||||
08172002 - Timidity memory leak cleanup by Torbjörn.
|
||||
07292002 - Valgrind cleanups; memory leak patches, etc.
|
||||
07212002 - done_flag was not being reset between files in playsound, so the
|
||||
first file would playback, and then any following tracks in a given
|
||||
run would "finish" immediately. Fixed.
|
||||
07132002 - More altcvt fixes from Frank Ranostaj.
|
||||
07122002 - Changed inline keyword to compile universally.
|
||||
07102002 - Fixed a bug in command line handling in playsound.c. Fixes from
|
||||
Torbjörn and myself to get flac.c friendly between versions of
|
||||
libFLAC. Mutex'd a potential race condition in decoders/modplug.c.
|
||||
FIXME cleanups here and there.
|
||||
07092002 - Fixed typo in documentation (SDL_sound.h).
|
||||
07052002 - Cleaned up some stuff in playsound.c, removing some FIXMEs.
|
||||
Commandline validation is improved, too. FIXME removal in
|
||||
voc.c; should report i/o errors correctly now. Changed DECLSPEC
|
||||
to SNDDECLSPEC to prevent SDL conflict, and added SDLCALL support.
|
||||
Removed all instances of Sound_SetError()...now they are either
|
||||
__Sound_SetError or BAIL*_MACRO.
|
||||
07022002 - Added WinCE support pack to website, updated INSTALL with CE info.
|
||||
More altcvt fixes from Frank Ranostaj.
|
||||
07012002 - Fixed configure.in to work around bug in older autoconfs. Started
|
||||
merging Tyler's WinCE (PocketPC) port. Added checks for assert.h
|
||||
and signal.h to configure.in/config.h.in, and #if HAVE_*_H checks
|
||||
where appropriate in the code. Moved #include <assert.h> (along
|
||||
with the HAVE_ASSERT_H check) to SDL_sound_internal.h, and removed
|
||||
unnecessary #includes from the individual source files. Added
|
||||
"md_reverb = 1;" to MIKMOD_init(). Modplug got some WinCE-specific
|
||||
setting tweaks, and some settings maintanance code. configure.in
|
||||
checks if setbuf() is available.
|
||||
06292002 - More altcvt fixes from Frank Ranostaj...mostly working now?
|
||||
06252002 - More altcvt fixes from Frank Ranostaj.
|
||||
06132002 - Patch from Torbjörn to fix stereo AIFF files.
|
||||
06212002 - More altcvt fixes from Frank Ranostaj.
|
||||
06132002 - Patch from Torbjörn to make the WAV decoder more tolerant.
|
||||
06122002 - Committed some altcvt enhancements from Frank Ranostaj.
|
||||
06112002 - Fixed some debug messages in smpeg.c and mpglib.c.
|
||||
06072002 - Manpages! Finally installed Doxygen and scratched together a
|
||||
Doxyfile. After some revision to physfs.h, we've got a rather
|
||||
nice API reference.
|
||||
06062002 - Added URLs for official and unofficial versions of ModPlug in
|
||||
decoders/modplug.c. Cleaned up some FIXMEs.
|
||||
05222002 - Torbjörn sent in some more fixes for altcvt: mono to stereo
|
||||
conversion works, now.
|
||||
05222002 - Torbjörn sent in some initial cleanups and fixes for altcvt, and
|
||||
fixed a bug in playsound when not all three of --rate, --channels
|
||||
and --format are specified.
|
||||
05202002 - Some .cvsignores from Max and me. Added a seek implementations for
|
||||
the SMPEG, ogg, aiff, wav-adpcm, voc, and au decoders. Added a seek
|
||||
stub to quicktime.c. playsound now takes milliseconds in the seek
|
||||
lists: --seek "00:00:400" or whatnot. Corrected playsound's usage
|
||||
text. Other au.c cleanups for extra robustness. Added an
|
||||
experimental audio converter that Frank Ranostaj sent to the SDL
|
||||
mailing list about a month ago: enable it with --enable-altcvt at
|
||||
configure time, but be warned that it doesn't work very well right
|
||||
now.
|
||||
04292002 - Darrell Walisser updated the Mac Classic and OS X project
|
||||
files, fixed some portability issues, and added an
|
||||
experimental decoder that uses Apple's QuickTime libraries
|
||||
(see decoders/quicktime.c). I've included the Mac project files
|
||||
in CVS, now. Removed all use of alloca() from playsound.
|
||||
04242002 - Added --seek option and bugfixes to playsound.c. Torbjörn comes
|
||||
through with seek support for the FLAC, MIDI, and ModPlug
|
||||
decoders (and some stub code for MikMod), and a bugfix for sample
|
||||
flag manipulation in the base library (and his own --seek code for
|
||||
playsound, which unfortunately we're not using).
|
||||
04232002 - Cleaned up the playsound command line handling. Most command line
|
||||
options (--rate, --format, --predecode, etc) are specified per-file
|
||||
and reset to their defaults after each sample is played back.
|
||||
--loop now takes a numeric argument: --loop 2 will playback the
|
||||
sample three times (one playback and two loops). Added Darrell
|
||||
to the playsound credits.
|
||||
04212002 - Initial work to add a Sound_Seek() API. Removed the NEEDSEEK
|
||||
sample flag (replaced it with CANSEEK). Hack to change the internal
|
||||
Sound_SetError() function to __Sound_SetError(). Added internal
|
||||
function __Sound_convertMsToBytePos().
|
||||
04082002 - Cleaned up the archive support in playsound a little bit, and
|
||||
fixed a PhysicsFS bug in the process.
|
||||
03252002 - Win32 patches and fixes from Tyler Montbriand: handled "inline"
|
||||
keyword, fixed SNDDBG macros in mpglib, and renamed a conflicting
|
||||
file (decoders/mpglib/common.c to decoders/mpglib/mpglib_common.c).
|
||||
03172002 - Removed an unneeded #include in mpglib that broke build on BeOS.
|
||||
mpglib seems to work find on BeOS. Reworked some of mpglib.c so we
|
||||
can determine the audio format when accepting the data stream. Some
|
||||
other minor cleanups here and there.
|
||||
03162002 - Tied the PhysicsFS code into the build system (code disabled if
|
||||
physfs not found or --disable-physfs passed to ./configure.)
|
||||
03152002 - Added PhysicsFS support to playsound, so you can play sound files
|
||||
that are in ZIP files without unzipping them. Needs to be merged
|
||||
into build system (I was just testing my PhysFS->RWops glue code).
|
||||
03142002 - Changed configure script's --enable-vorbis to --enable-ogg. Removed
|
||||
global state variable from mpglib, so it should be reentrant now
|
||||
(patches sent to mpglib's actual maintainer). playsound can now
|
||||
read from stdin.
|
||||
03102002 - Added a FIXME note to decoders/mpglib.c. playsound now reports
|
||||
errors in the thread where they occured, which also fixes a double
|
||||
report of errors during predecoding. Removed all calls to exit() in
|
||||
mpglib. These calls now report errors correctly to SDL_sound, which
|
||||
passes them on to the application (patch also sent to mpglib's
|
||||
actual maintainer). Replaced all stderr chatter in mpglib with
|
||||
Sound_SetError() calls.
|
||||
03072002 - decoders/mpglib.c now disregards ID3 tags instead of passing them
|
||||
on as valid MP3 data to mpglib. Added some (buggy) example code for
|
||||
adjusting an audio stream's volume (via the new --volume command
|
||||
line in playsound).
|
||||
03032002 - Fixed mpglib's build configuration to include general build flags
|
||||
so that things like --enable-debug work as expected.
|
||||
02212002 - Changed SMPEG's URL to point to the icculus.org site. Added an
|
||||
mpglib decoder (internal to SDL_sound; relies on no external libs)
|
||||
and changes mp3.c to smpeg.c (and other associated things).
|
||||
02112002 - Committed a patch from Torbjörn to fix incorrect memory accesses
|
||||
in the Timidity code. Changed the magic number in the AU decoder
|
||||
to be bigendian (seems appropriate). Updated README for
|
||||
completeness, and TODO for accuracy. Darrell sent in updated
|
||||
MacOS X Project Builder files (on the website).
|
||||
02072002 - Committed a patch Torbjörn sent in awhile ago for preventing
|
||||
confusion with Timidity++-specific stuff in the timidity.cfg file.
|
||||
Tyler Montbriand sent in an updated Visual C package.
|
||||
Updated SDL_sound.h's comments a little. Upped version to 0.1.5.
|
||||
02052002 - Fixed a cleanup I broke last night. Added CWProject.sit to the
|
||||
EXTRA_DIST section of Makefile.am, and updated the README with
|
||||
MacOS (9/X) install instructions.
|
||||
02042002 - Darrell Walisser submitted some cleanups and CodeWarrior project
|
||||
files for MacOS 9. Sweet!
|
||||
01232002 - Max fixed decoders/Makefile.am to work with seperate build
|
||||
directories, and corrected some dates in this file.
|
||||
01192002 - Torbjörn sent in patches implementing the rewind method for the
|
||||
rest of the decoders except shn.c, for which I added a kludged
|
||||
implementation. Added more info to the README. Hunted down the
|
||||
reason why SMPEG can't decode before calling SDL_OpenAudio(), and
|
||||
it can't be fixed without a change to SMPEG (not MY fault! :) ).
|
||||
Made ModPlug take priority over MikMod when selecting a decoder.
|
||||
Mutex-protected the internal samples list, and fixed some bugs in
|
||||
the management of that list. Changed some stuff to use uniform
|
||||
coding conventions.
|
||||
01182002 - SDL_sound/playsound builds and runs on BeOS now. Fixed an assertion
|
||||
bug I introduced yesterday.
|
||||
01172002 - Implemented Sound_Rewind(), and added a --loop command line to
|
||||
playsound for testing. Rewrote the audio callback to handle looping
|
||||
with both predecoded and streamed samples. Most of the decoders
|
||||
just have an assert(0) in their internal rewinding method at this
|
||||
point. I implemented the WAV, VOC, AU, AIFF, and RAW ones, for now.
|
||||
(...and skeleton.c, for what that's worth.) A few tweaks in the
|
||||
core API implementation to fix unlikely but possible leaks.
|
||||
01112002 - Mattias Engdegård sent in an .AU decoder. Nice! He also tweaked
|
||||
playsound to try and wait until SDL has completed playing a given
|
||||
sound before closing the audio device. Changed a macro in
|
||||
decoders/shn.c to be more uniform with the other decoders.
|
||||
SDL_sound error messages are now maintained on a per-thread basis,
|
||||
and do not interfere with SDL_[GS]etError() anymore.
|
||||
01112002 - Committed the rest of Torbjörn's MOD patches, to clean up file
|
||||
extension handling.
|
||||
01092002 - Torbjörn comes through with a ModPlug-based decoder, which should
|
||||
work nicely for decoding multiple .MODs at once. Now we need to
|
||||
figure out what to do with two decoders that can decode the same
|
||||
file. For now, if you explicitly want either MikMod or ModPlug, you
|
||||
should explicitly enable one decoder and disable the other on the
|
||||
configure command line ("--enable-modplug --disable-mikmod", for
|
||||
example), otherwise configure will try to sort out the best one for
|
||||
your system. Choice is a wonderful thing. :)
|
||||
01042002 - Forgot to bump playsound's version to match SDL_sound's. Fixed.
|
||||
Added some notes to the top of COPYING about other libraries, etc.
|
||||
A real MIDI decoder (using a hacked version of the hacked version
|
||||
of Timidity from SDL_mixer) is now in place and working well,
|
||||
thanks to Torbjörn.
|
||||
01012002 - Happy New Year. Added some debug output to wav.c for future
|
||||
codecs (GSM comes to mind). Fixed the SMPEG decoder's URL to point
|
||||
to Loki's webpage.
|
||||
12302001 - Upped version to 0.1.4.
|
||||
12272001 - Added --audiobuf and --decodebuf options to playsound to make
|
||||
tracking down a bug in the ADPCM decoder easier (plus, it could
|
||||
help for benchmarking, etc later on...). Found a printf() bug in
|
||||
playsound (extra comma in there...). ADPCM decoder appears to be
|
||||
functional now. Tried to add ElectricFence support to
|
||||
configure.in, and failed. All this libtool/autoconf stuff makes my
|
||||
head hurt.
|
||||
12262001 - Changed remaining references to the "LICENSE" file into "COPYING".
|
||||
Work progresses on the ADPCM-compressed .wav decoder. Updates to
|
||||
the documentation in SDL_sound.h. Hhmm...find_chunk() in wav.c was
|
||||
badly broken. Fixed.
|
||||
12162001 - FLAC decoder now checks for the magic number unless the file
|
||||
extension is recognized. This was changed back because searching
|
||||
for metadata, while probably more effective, is VERY expensive (and
|
||||
useless) on non-FLAC streams.
|
||||
12052001 - Put our names in a "--credits" option in playsound, and put the
|
||||
standard GNU disclaimers in there too, for good measure. Renamed
|
||||
LICENSE to COPYING to match GNU standards more closely (and to
|
||||
end Max's torment. :) ) Tweaks to wav.c, and work on aiff.c to
|
||||
make it easier to support multiple audio formats (for compression
|
||||
handling later down the road).
|
||||
11302001 - Torbjörn and I make Sound_DecodeAll() more robust: checks for
|
||||
previous decoding failures and sets an appropriate error, handles
|
||||
decoders that change their buffers on the fly (such as the FLAC
|
||||
decoder), and deals with out-of-memory conditions more gracefully.
|
||||
11252001 - (With thanks to Andreas Umbach for pointing it out) Fixed some
|
||||
problems with Sound_DecodeAll(). For local testing of this bug,
|
||||
added a --predecode command line to playsound. Minor fixes to
|
||||
theoretical bugs in Sound_FreeSample(). playsound no longer
|
||||
buffers stdout and stderr. Updated Sound_DecodeAll()'s comments in
|
||||
SDL_sound.h ...
|
||||
11192001 - FLAC decoder cleanups from Torbjörn.
|
||||
11092001 - Torbjörn fixes playsound's audio callback after I broke it, again.
|
||||
A bug in configure.in was preventing SMPEG from being used unless
|
||||
--enable-debug was set; fixed. Changed this file to list latest
|
||||
changes first. Torbjörn submitted a FLAC decoder that utilizes
|
||||
libFLAC (http://flac.sf.net/). Cool.
|
||||
11012001 - API COMPATIBILITY BREAKAGE: Decoders can now list multiple file
|
||||
extensions each. Playsound has been updated to handle this.
|
||||
Playsound now registers a SIGINT handler, so you can skip tracks
|
||||
and/or abort the way that mpg123 does.
|
||||
10232001 - Rewrote playsound.c's audio_callback() to no longer need the
|
||||
overflow buffer hack, which streamlines it a little and trims the
|
||||
memory requirements for playsound by about 16 kilobytes.
|
||||
10172001 - Torbjörn catches a problem with the overflow buffer in playsound's
|
||||
audio callback.
|
||||
10152001 - Torbjörn sends in a default sample format for the MIDI decoder,
|
||||
and the starts of the audio conversion funcitonality (ripped
|
||||
from SDL). Officially released 0.1.3. Added LICENSE and
|
||||
CHANGELOG to the distribution. (Again, from Torbjörn) added in
|
||||
the start of a tweaked audio converter.
|
||||
10122001 - Torbjörn Andersson submitted command line enhancements to
|
||||
playsound, and I cleaned up the --help output.
|
||||
10092001 - Patches to shn.c for Visual C compatibility. Visual C project files
|
||||
available from the website. Changed Corona688 to Tyler Montbriand
|
||||
in CREDITS. Upped version to 0.1.3.
|
||||
10082001 - Restructured decoders/wav.c to allow for multiple formats, and
|
||||
put the start of a handler for the ADPCM format in place.
|
||||
10072001 - Changed the way decoders/mod.c handles samplerate so that it should
|
||||
work universally. This isn't an ideal solution, but it's probably
|
||||
the best we can do without rewriting mikmod. Made a change to ogg.c
|
||||
for portability: changed an int64_t to ogg_int64_t.
|
||||
10062001 - Made a change to SDL_sound.c for compiling on non-GNU toolchains.
|
||||
10052001 - Removed #include "SDL_endian" from aiff.c.
|
||||
10042001 - Changed some #if (defined SOUND_SUPPORTS_*) lines to
|
||||
#ifdef SOUND_SUPPORTS_* in voc.c and shn.c, for consistency with
|
||||
the other decoders.
|
||||
10032001 - After hours of tracking down a bogus pointer, the SHN decoder works!
|
||||
I can die happy. :) Max placated me with an --enable-debug option
|
||||
so I could stop my whining. Other autoconf goodies (such as
|
||||
reenabling -Werror for debug builds, etc). Torbjörn brings in a
|
||||
MIDI decoder, which reads from a Timidity process through a pipe.
|
||||
Changed playsound to open the audio device to match the properties
|
||||
of each sound file, which results in less conversion (and therefore,
|
||||
more chance of correct playback).
|
||||
10022001 - Changed a comment in mod.c to not refer to "the mikmod
|
||||
directory" anymore. Committed Torbjörn's patch for MP3 detection.
|
||||
(better late than never). __Sound_strcasecmp() now handles NULL
|
||||
strings gracefully, fixing the crash with "playsound bootstrap".
|
||||
More work on the SHN decoder.
|
||||
10012001 - Fixed a memory leak that Torbjörn found in the MOD decoder.
|
||||
09252001 - More autoconf work. Gave Max Horn write access to the CVS
|
||||
repository, so I don't drive him nuts tweaking this thing. :)
|
||||
Fixed a const complaint and some other stuff needed for compilation
|
||||
under Visual C++ 6.0 (no, it isn't ported yet). Put the SHN source
|
||||
in CVS, even though it isn't ready (and doesn't even compile). Do
|
||||
NOT enable it in your build!
|
||||
09242001 - Thank goodness, Torbjörn came through with the MP3 fix. Apparently
|
||||
SMPEG mixes each chunk of decoded data with whatever is already
|
||||
in the buffer you give it. I hate that. I'm going to patch SMPEG
|
||||
to let the programmer enable and disable that behaviour in a given
|
||||
(SMPEG *), since it's just a CPU eater in this case. The _D(())
|
||||
macro is now SNDDBG(()), since _D is taken on MacOS X's version of
|
||||
gcc (which was bound to happen on some platform sooner than later
|
||||
anyhow). Renamed test_sdlsound to playsound, and made it more
|
||||
robust in general: fixed potential overflow in audio_callback,
|
||||
made it chatter less, made it take multiple files and some other
|
||||
command lines. Initial autoconf support, thanks to Max Horn.
|
||||
09222001 - Torbjörn Andersson strikes again, with a collection of patches.
|
||||
First, some cosmetic tweaks for decoders/aiff.c. Next, a MOD player
|
||||
based on MikMod. This inspired me to add two more methods to
|
||||
Sound_DecoderFunctions: init() and quit(). Third, a fix to
|
||||
decoders/mp3.c so that SMPEG won't claim every stream it sees, MP3
|
||||
or not. I removed the multiple-streams-per-rwops code, after
|
||||
discussion on the mailing list. The init() and quit() methods
|
||||
led to the possibility that certain decoders will flag themselves
|
||||
as unavailable at runtime, and SDL_sound now handles this.
|
||||
Added [LIB|INC]PATH_[OGG|MOD]. Bigendian fixes; now works on
|
||||
PowerPC Linux. MikMod tweaks. Changed version to 0.1.2.
|
||||
09202001 - Torbjörn Andersson submitted several patches: fixed a comment in
|
||||
the .WAV decoder (whoops...screwed up my own search-and-replace.
|
||||
Hah.), made an attempt at putting multiple sound streams behind
|
||||
one RWops (gotta think on that one first), and, most importantly,
|
||||
added an AIFF decoder, which is very cool.
|
||||
09192001 - Added a skeleton decoder source file. Changed voc_read() to
|
||||
voc_read_waveform(), so it wouldn't be confused with VOC_read().
|
||||
Fixed a byte ordering bug in voc.c (reported as AUDIO_S16LSB, but
|
||||
we were swapping byte order of data ourselves. Fixed). Added basic
|
||||
.WAV support. Fixed Makefile so that -I. is always first;
|
||||
otherwise, a previously installed header might get used for the
|
||||
compiles, which is not good. SDL_sound.h now includes SDL_endian.h,
|
||||
since SDL.h doesn't, for some reason. Moved version defines in
|
||||
SDL_sound.h to top of file so I can find them. :)
|
||||
Changed version to 0.1.1. Committed patch from Tsuyoshi Iguchi to
|
||||
fix a segfault (I forgot to put a NULL terminator at the end of
|
||||
the available_decoders array), fixing the only bug preventing the
|
||||
test program from running on FreeBSD 4.3. Sweet. Added Ogg Vorbis
|
||||
decoder. Rewrote the test program's SDL audio callback to be more
|
||||
robust (Ogg exposed a nasty bug in it). Fixed a byte-ordering issue
|
||||
in the VOC decoder.
|
||||
09182001 - Implemented MP3 support through SMPEG (not working yet, though) and
|
||||
wrote the Reference Counting RWops wrapper. Added other little
|
||||
things like the _D(()) macro. Added VOC support, which went up with
|
||||
surprisingly little struggle, which means it MUST be leaking
|
||||
memory. :)
|
||||
09172001 - Changed some overlooked "voice" to "sound". Implemented base API.
|
||||
So...tired. Everything's different. :)
|
||||
Also put in a RAW decoder and a simple test program.
|
||||
09142001 - Changed name to SDL_sound, added Sound_DecodeAll() to spec.
|
||||
09132001 - Initial spec proposed on SDL mailing list, under name "SDL_voice".
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
||||
/* end of CHANGELOG ... */
|
||||
|
||||
524
project/jni/sdl_sound/COPYING
Normal file
524
project/jni/sdl_sound/COPYING
Normal file
@@ -0,0 +1,524 @@
|
||||
Please note that the included source from Timidity, the MIDI decoder, is also
|
||||
licensed under the following terms (GNU LGPL), but can also be used
|
||||
separately under the GNU GPL, or the Perl Artistic License. Those licensing
|
||||
terms are not reprinted here, but can be found on the web easily.
|
||||
|
||||
Other external libraries (such as Ogg Vorbis, SMPEG, etc) have their own
|
||||
licenses which you should be aware of before including the related code
|
||||
in your configuration. Most (if not all) are also under the LGPL, but are
|
||||
external projects and we've got no control over them.
|
||||
|
||||
If you want to use SDL_sound under a closed-source license, please contact
|
||||
Ryan (icculus@icculus.org), and we can discuss an alternate license for
|
||||
money to be distributed between the contributors to this work, but I'd
|
||||
encourage you to abide by the LGPL, since the usual concern is whether you
|
||||
can use this library without releasing your own source code (you can).
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
66
project/jni/sdl_sound/CREDITS
Normal file
66
project/jni/sdl_sound/CREDITS
Normal file
@@ -0,0 +1,66 @@
|
||||
----------------------
|
||||
| SDL_sound credits. |
|
||||
----------------------
|
||||
|
||||
Initial API interface and implementation,
|
||||
RAW driver,
|
||||
VOC driver,
|
||||
SMPEG driver,
|
||||
MPGLIB driver,
|
||||
WAV driver,
|
||||
OGG driver,
|
||||
SHN driver,
|
||||
Unix support,
|
||||
BeOS support:
|
||||
Ryan C. Gordon
|
||||
|
||||
Bug fixes,
|
||||
FreeBSD testing:
|
||||
Tsuyoshi Iguchi
|
||||
|
||||
Code cleanups,
|
||||
SMPEG fixes,
|
||||
AIFF driver,
|
||||
MikMod driver,
|
||||
MIDI driver,
|
||||
ModPlug driver,
|
||||
FLAC driver:
|
||||
Torbjörn Andersson
|
||||
|
||||
autoconf,
|
||||
MacOS X support:
|
||||
Max Horn
|
||||
|
||||
win32 support,
|
||||
PocketPC support,
|
||||
other fixes:
|
||||
Tyler Montbriand
|
||||
|
||||
AU driver,
|
||||
Mattias Engdegård
|
||||
|
||||
MacOS Classic support,
|
||||
quicktime decoder,
|
||||
OS X fixes:
|
||||
Darrell Walisser
|
||||
|
||||
Alternate audio conversion code:
|
||||
Frank Ranostaj
|
||||
|
||||
Initial Borland C++ project files:
|
||||
Dominique Louis
|
||||
|
||||
Bugfixes and stuff:
|
||||
Eric Wing
|
||||
|
||||
FLAC 1.1.3 updates:
|
||||
Josh Coalson
|
||||
|
||||
SMPEG fixes:
|
||||
Chris Nelson
|
||||
|
||||
Other stuff:
|
||||
Your name here! Patches go to icculus@icculus.org ...
|
||||
|
||||
/* end of CREDITS ... */
|
||||
|
||||
105
project/jni/sdl_sound/INSTALL
Normal file
105
project/jni/sdl_sound/INSTALL
Normal file
@@ -0,0 +1,105 @@
|
||||
Building is pretty easy. Please read README, too, as it duplicates and
|
||||
expands upon much of this information.
|
||||
|
||||
|
||||
ALL PLATFORMS:
|
||||
|
||||
Please understand your rights and mine: read the text file COPYING in the root
|
||||
of the source tree. If you can't abide by it, delete this source tree now.
|
||||
|
||||
The best documentation for the SDL_sound API is SDL_sound.h. It is VERY
|
||||
heavily commented, and makes an excellent, in-depth reference to all the
|
||||
functions. The official API reference is generated from this file with
|
||||
a program called "Doxygen" (http://www.doxygen.org/)
|
||||
|
||||
|
||||
Borland C++ Builder for Linux (Kylix 3):
|
||||
Unzip the "borland.zip" file in the root of the source tree and use the
|
||||
project files in the newly-created Borland/k3 directory. Makefiles for the
|
||||
command line compiler are in Borland/freebcc ...
|
||||
|
||||
|
||||
Unix:
|
||||
(If you pulled the source from CVS), run ./bootstrap
|
||||
|
||||
run ./configure --help, and see if there's any options you need. Rerun
|
||||
configure with those options. If this is confusing to you, just run
|
||||
./configure with no options: the defaults are generally decent, and
|
||||
configure is usually smart enough to figure out what's best..
|
||||
|
||||
If configuration succeeded, run "make".
|
||||
|
||||
Run "make install" as root to install the library for use on your system.
|
||||
|
||||
This should work for most Unix-style systems, including Linux, *BSD, BeOS, and
|
||||
MacOS X. Reports of success and failure are welcome.
|
||||
|
||||
|
||||
MacOS 9 users:
|
||||
Included with the source is CWProject.sit, which contains project files for
|
||||
CodeWarrior 5.0 and later.
|
||||
|
||||
|
||||
MacOS X command line tools:
|
||||
You can use the "UNIX" instructions above if you like the command line tools.
|
||||
|
||||
|
||||
MacOS X Project Builder:
|
||||
If you prefer to use Project Builder, use the project files included with
|
||||
this source: PBProjects.tar.gz...unpack it in the root of the SDL_sound
|
||||
folder. This archive contains several external libraries you would have
|
||||
to download/install manually if you used the command line tools (these
|
||||
libraries are for extra decoders, and are NOT required for SDL_sound to
|
||||
function...however, without them, the number of sound formats you can
|
||||
decode is reduced.)
|
||||
|
||||
|
||||
BeOS:
|
||||
You can use the "UNIX" instructions above, too.
|
||||
|
||||
|
||||
Win32 Visual C:
|
||||
For Visual C, use:
|
||||
http://icculus.org/SDL_sound/downloads/sdl_sound_visualc_srcs.zip
|
||||
...and unzip it somewhere. This zipfile has a complete copy of the
|
||||
SDL_sound sources, Visual C project files, and several external libraries,
|
||||
too. This zip is everything you should need, and you can scrap this copy of
|
||||
the source.
|
||||
|
||||
|
||||
Win32 Cygwin:
|
||||
Cygwin users can try their luck with the Unix build instructions in this
|
||||
tarball instead.
|
||||
|
||||
|
||||
Win32 Borland C++ Builder 6:
|
||||
Unzip the "borland.zip" file in the root of the source tree and use the
|
||||
project files in the newly-created Borland/bcb6 directory. Makefiles for the
|
||||
command line compiler are in Borland/freebcc ... these are unmaintained, and
|
||||
you will need to go find the external libraries you want to use (those that
|
||||
wish to maintain these project files should contact me).
|
||||
|
||||
|
||||
If building is successful, there will be a shared library and a binary
|
||||
called "playsound".
|
||||
|
||||
|
||||
Windows CE (Microsoft PocketPC):
|
||||
You'll need Microsoft's PocketPC development environment, and this zipfile:
|
||||
http://icculus.org/SDL_sound/downloads/SDL_soundCE.zip
|
||||
|
||||
Unzip that into the root of this source tree. The new "wce" directory has
|
||||
project files, and the source to some of the external decoders is included.
|
||||
Note that not all of the decoders are supported on PocketPC (but please, do
|
||||
send us patches if you get them working!)
|
||||
|
||||
|
||||
OTHER PLATFORMS:
|
||||
|
||||
Send me patches, and instructions, and I'll list them here. Consider
|
||||
joining the SDL_sound mailing list. Details are at:
|
||||
http://icculus.org/SDL_sound/
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
||||
|
||||
58
project/jni/sdl_sound/README
Normal file
58
project/jni/sdl_sound/README
Normal file
@@ -0,0 +1,58 @@
|
||||
SDL_sound. An abstract soundfile decoder.
|
||||
|
||||
SDL_sound is a library that handles the decoding of several popular sound file
|
||||
formats, such as .WAV and .MP3. It is meant to make the programmer's sound
|
||||
playback tasks simpler. The programmer gives SDL_sound a filename, or feeds
|
||||
it data directly from one of many sources, and then reads the decoded
|
||||
waveform data back at her leisure. If resource constraints are a concern,
|
||||
SDL_sound can process sound data in programmer-specified blocks. Alternately,
|
||||
SDL_sound can decode a whole sound file and hand back a single pointer to the
|
||||
whole waveform. SDL_sound can also handle sample rate, audio format, and
|
||||
channel conversion on-the-fly and behind-the-scenes, if the programmer
|
||||
desires.
|
||||
|
||||
Please check the website for the most up-to-date information about SDL_sound:
|
||||
http://icculus.org/SDL_sound/
|
||||
|
||||
SDL_sound _REQUIRES_ Simple Directmedia Layer (SDL) to function, and cannot
|
||||
be built without it. You can get SDL from http://www.libsdl.org/. SDL_sound
|
||||
has only been tried with the SDL 1.2 series, but may work on older versions.
|
||||
Reports of success or failure are welcome.
|
||||
|
||||
Some optional external libraries that SDL_sound can use and where to find them:
|
||||
SMPEG (used to decode MP3s): http://icculus.org/smpeg/
|
||||
libvorbisfile (used to decode OGGs): http://www.xiph.org/ogg/vorbis/
|
||||
libSpeex (used to decode SPXs): http://speex.org/
|
||||
libFLAC (used to decode FLACs): http://flac.sourceforge.net/
|
||||
libModPlug (used to decode MODs, etc): http://modplug-xmms.sourceforge.net/
|
||||
libMikMod (used to decode MODs, etc, too): http://www.mikmod.org/
|
||||
|
||||
Experimental QuickTime support for the Mac is included, but has not been
|
||||
integrated with the build system, and probably doesn't work with
|
||||
QuickTime for Windows.
|
||||
|
||||
These external libraries are OPTIONAL. SDL_sound will build and function
|
||||
without them, but various sound file formats are not supported unless these
|
||||
libraries are available. Unless explicitly disabled during initial build
|
||||
configuration, SDL_sound always supports these file formats internally:
|
||||
|
||||
- Microsoft .WAV files (uncompressed and MS-ADPCM encoded).
|
||||
- Creative Labs .VOC files
|
||||
- Shorten (.SHN) files
|
||||
- Audio Interchange format (AIFF) files
|
||||
- Sun Audio (.AU) files
|
||||
- MIDI files
|
||||
- MP3 files (internal decoder, different than the one SMPEG uses)
|
||||
- Raw waveform data
|
||||
|
||||
Building/Installing:
|
||||
Please read the INSTALL document.
|
||||
|
||||
Reporting bugs/commenting:
|
||||
There is a mailing list available. To subscribe, send a blank email to
|
||||
sdlsound-subscribe@icculus.org. This is the best way to get in touch with
|
||||
SDL_sound developers.
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
||||
|
||||
905
project/jni/sdl_sound/SDL_sound.c
Normal file
905
project/jni/sdl_sound/SDL_sound.c
Normal file
@@ -0,0 +1,905 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file implements the core API, which is relatively simple.
|
||||
* The real meat of SDL_sound is in the decoders directory.
|
||||
*
|
||||
* Documentation is in SDL_sound.h ... It's verbose, honest. :)
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
|
||||
/* The various decoder drivers... */
|
||||
|
||||
#if (defined SOUND_SUPPORTS_SMPEG)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_SMPEG;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MPGLIB)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_MPGLIB;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MIKMOD)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_MIKMOD;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MODPLUG)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_MODPLUG;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_WAV)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_WAV;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_AIFF)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_AIFF;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_AU)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_AU;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_OGG)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_OGG;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_VOC)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_RAW)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_RAW;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_SHN)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_SHN;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MIDI)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_MIDI;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_FLAC)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_FLAC;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_QUICKTIME)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_QuickTime;
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_SPEEX)
|
||||
extern const Sound_DecoderFunctions __Sound_DecoderFunctions_SPEEX;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int available;
|
||||
const Sound_DecoderFunctions *funcs;
|
||||
} decoder_element;
|
||||
|
||||
static decoder_element decoders[] =
|
||||
{
|
||||
#if (defined SOUND_SUPPORTS_SMPEG)
|
||||
{ 0, &__Sound_DecoderFunctions_SMPEG },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MPGLIB)
|
||||
{ 0, &__Sound_DecoderFunctions_MPGLIB },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MODPLUG)
|
||||
{ 0, &__Sound_DecoderFunctions_MODPLUG },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MIKMOD)
|
||||
{ 0, &__Sound_DecoderFunctions_MIKMOD },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_WAV)
|
||||
{ 0, &__Sound_DecoderFunctions_WAV },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_AIFF)
|
||||
{ 0, &__Sound_DecoderFunctions_AIFF },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_AU)
|
||||
{ 0, &__Sound_DecoderFunctions_AU },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_OGG)
|
||||
{ 0, &__Sound_DecoderFunctions_OGG },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_VOC)
|
||||
{ 0, &__Sound_DecoderFunctions_VOC },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_RAW)
|
||||
{ 0, &__Sound_DecoderFunctions_RAW },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_SHN)
|
||||
{ 0, &__Sound_DecoderFunctions_SHN },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_FLAC)
|
||||
{ 0, &__Sound_DecoderFunctions_FLAC },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_MIDI)
|
||||
{ 0, &__Sound_DecoderFunctions_MIDI },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_QUICKTIME)
|
||||
{ 0, &__Sound_DecoderFunctions_QuickTime },
|
||||
#endif
|
||||
|
||||
#if (defined SOUND_SUPPORTS_SPEEX)
|
||||
{ 0, &__Sound_DecoderFunctions_SPEEX },
|
||||
#endif
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* General SDL_sound state ... */
|
||||
|
||||
typedef struct __SOUND_ERRMSGTYPE__
|
||||
{
|
||||
Uint32 tid;
|
||||
int error_available;
|
||||
char error_string[128];
|
||||
struct __SOUND_ERRMSGTYPE__ *next;
|
||||
} ErrMsg;
|
||||
|
||||
static ErrMsg *error_msgs = NULL;
|
||||
static SDL_mutex *errorlist_mutex = NULL;
|
||||
|
||||
static Sound_Sample *sample_list = NULL; /* this is a linked list. */
|
||||
static SDL_mutex *samplelist_mutex = NULL;
|
||||
|
||||
static const Sound_DecoderInfo **available_decoders = NULL;
|
||||
static int initialized = 0;
|
||||
|
||||
|
||||
/* functions ... */
|
||||
|
||||
void Sound_GetLinkedVersion(Sound_Version *ver)
|
||||
{
|
||||
if (ver != NULL)
|
||||
{
|
||||
ver->major = SOUND_VER_MAJOR;
|
||||
ver->minor = SOUND_VER_MINOR;
|
||||
ver->patch = SOUND_VER_PATCH;
|
||||
} /* if */
|
||||
} /* Sound_GetLinkedVersion */
|
||||
|
||||
|
||||
int Sound_Init(void)
|
||||
{
|
||||
size_t i;
|
||||
size_t pos = 0;
|
||||
size_t total = sizeof (decoders) / sizeof (decoders[0]);
|
||||
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
||||
|
||||
sample_list = NULL;
|
||||
error_msgs = NULL;
|
||||
|
||||
available_decoders = (const Sound_DecoderInfo **)
|
||||
malloc((total) * sizeof (Sound_DecoderInfo *));
|
||||
BAIL_IF_MACRO(available_decoders == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
errorlist_mutex = SDL_CreateMutex();
|
||||
samplelist_mutex = SDL_CreateMutex();
|
||||
|
||||
for (i = 0; decoders[i].funcs != NULL; i++)
|
||||
{
|
||||
decoders[i].available = decoders[i].funcs->init();
|
||||
if (decoders[i].available)
|
||||
{
|
||||
available_decoders[pos] = &(decoders[i].funcs->info);
|
||||
pos++;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
available_decoders[pos] = NULL;
|
||||
|
||||
initialized = 1;
|
||||
return(1);
|
||||
} /* Sound_Init */
|
||||
|
||||
|
||||
int Sound_Quit(void)
|
||||
{
|
||||
ErrMsg *err;
|
||||
ErrMsg *nexterr = NULL;
|
||||
size_t i;
|
||||
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
|
||||
while (((volatile Sound_Sample *) sample_list) != NULL)
|
||||
Sound_FreeSample(sample_list);
|
||||
|
||||
initialized = 0;
|
||||
|
||||
SDL_DestroyMutex(samplelist_mutex);
|
||||
samplelist_mutex = NULL;
|
||||
sample_list = NULL;
|
||||
|
||||
for (i = 0; decoders[i].funcs != NULL; i++)
|
||||
{
|
||||
if (decoders[i].available)
|
||||
{
|
||||
decoders[i].funcs->quit();
|
||||
decoders[i].available = 0;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (available_decoders != NULL)
|
||||
free((void *) available_decoders);
|
||||
available_decoders = NULL;
|
||||
|
||||
/* clean up error state for each thread... */
|
||||
SDL_LockMutex(errorlist_mutex);
|
||||
for (err = error_msgs; err != NULL; err = nexterr)
|
||||
{
|
||||
nexterr = err->next;
|
||||
free(err);
|
||||
} /* for */
|
||||
error_msgs = NULL;
|
||||
SDL_UnlockMutex(errorlist_mutex);
|
||||
SDL_DestroyMutex(errorlist_mutex);
|
||||
errorlist_mutex = NULL;
|
||||
|
||||
return(1);
|
||||
} /* Sound_Quit */
|
||||
|
||||
|
||||
const Sound_DecoderInfo **Sound_AvailableDecoders(void)
|
||||
{
|
||||
return(available_decoders); /* READ. ONLY. */
|
||||
} /* Sound_AvailableDecoders */
|
||||
|
||||
|
||||
static ErrMsg *findErrorForCurrentThread(void)
|
||||
{
|
||||
ErrMsg *i;
|
||||
Uint32 tid;
|
||||
|
||||
if (error_msgs != NULL)
|
||||
{
|
||||
tid = SDL_ThreadID();
|
||||
|
||||
SDL_LockMutex(errorlist_mutex);
|
||||
for (i = error_msgs; i != NULL; i = i->next)
|
||||
{
|
||||
if (i->tid == tid)
|
||||
{
|
||||
SDL_UnlockMutex(errorlist_mutex);
|
||||
return(i);
|
||||
} /* if */
|
||||
} /* for */
|
||||
SDL_UnlockMutex(errorlist_mutex);
|
||||
} /* if */
|
||||
|
||||
return(NULL); /* no error available. */
|
||||
} /* findErrorForCurrentThread */
|
||||
|
||||
|
||||
const char *Sound_GetError(void)
|
||||
{
|
||||
const char *retval = NULL;
|
||||
ErrMsg *err;
|
||||
|
||||
if (!initialized)
|
||||
return(ERR_NOT_INITIALIZED);
|
||||
|
||||
err = findErrorForCurrentThread();
|
||||
if ((err != NULL) && (err->error_available))
|
||||
{
|
||||
retval = err->error_string;
|
||||
err->error_available = 0;
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* Sound_GetError */
|
||||
|
||||
|
||||
void Sound_ClearError(void)
|
||||
{
|
||||
ErrMsg *err;
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
err = findErrorForCurrentThread();
|
||||
if (err != NULL)
|
||||
err->error_available = 0;
|
||||
} /* Sound_ClearError */
|
||||
|
||||
|
||||
/*
|
||||
* This is declared in the internal header.
|
||||
*/
|
||||
void __Sound_SetError(const char *str)
|
||||
{
|
||||
ErrMsg *err;
|
||||
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
SNDDBG(("__Sound_SetError(\"%s\");%s\n", str,
|
||||
(initialized) ? "" : " [NOT INITIALIZED!]"));
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
err = findErrorForCurrentThread();
|
||||
if (err == NULL)
|
||||
{
|
||||
err = (ErrMsg *) malloc(sizeof (ErrMsg));
|
||||
if (err == NULL)
|
||||
return; /* uhh...? */
|
||||
|
||||
memset((void *) err, '\0', sizeof (ErrMsg));
|
||||
err->tid = SDL_ThreadID();
|
||||
|
||||
SDL_LockMutex(errorlist_mutex);
|
||||
err->next = error_msgs;
|
||||
error_msgs = err;
|
||||
SDL_UnlockMutex(errorlist_mutex);
|
||||
} /* if */
|
||||
|
||||
err->error_available = 1;
|
||||
strncpy(err->error_string, str, sizeof (err->error_string));
|
||||
err->error_string[sizeof (err->error_string) - 1] = '\0';
|
||||
} /* __Sound_SetError */
|
||||
|
||||
|
||||
Uint32 __Sound_convertMsToBytePos(Sound_AudioInfo *info, Uint32 ms)
|
||||
{
|
||||
/* "frames" == "sample frames" */
|
||||
float frames_per_ms = ((float) info->rate) / 1000.0f;
|
||||
Uint32 frame_offset = (Uint32) (frames_per_ms * ((float) ms));
|
||||
Uint32 frame_size = (Uint32) ((info->format & 0xFF) / 8) * info->channels;
|
||||
return(frame_offset * frame_size);
|
||||
} /* __Sound_convertMsToBytePos */
|
||||
|
||||
|
||||
/*
|
||||
* -ansi and -pedantic flags prevent use of strcasecmp() on Linux, and
|
||||
* I honestly don't want to mess around with figuring out if a given
|
||||
* platform has "strcasecmp", "stricmp", or
|
||||
* "compare_two_damned_strings_case_insensitive", which I hear is in the
|
||||
* next release of Carbon. :) This is exported so decoders may use it if
|
||||
* they like.
|
||||
*/
|
||||
int __Sound_strcasecmp(const char *x, const char *y)
|
||||
{
|
||||
int ux, uy;
|
||||
|
||||
if (x == y) /* same pointer? Both NULL? */
|
||||
return(0);
|
||||
|
||||
if (x == NULL)
|
||||
return(-1);
|
||||
|
||||
if (y == NULL)
|
||||
return(1);
|
||||
|
||||
do
|
||||
{
|
||||
ux = toupper((int) *x);
|
||||
uy = toupper((int) *y);
|
||||
if (ux > uy)
|
||||
return(1);
|
||||
else if (ux < uy)
|
||||
return(-1);
|
||||
x++;
|
||||
y++;
|
||||
} while ((ux) && (uy));
|
||||
|
||||
return(0);
|
||||
} /* __Sound_strcasecmp */
|
||||
|
||||
|
||||
/*
|
||||
* Allocate a Sound_Sample, and fill in most of its fields. Those that need
|
||||
* to be filled in later, by a decoder, will be initialized to zero.
|
||||
*/
|
||||
static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired,
|
||||
Uint32 bufferSize)
|
||||
{
|
||||
Sound_Sample *retval = malloc(sizeof (Sound_Sample));
|
||||
Sound_SampleInternal *internal = malloc(sizeof (Sound_SampleInternal));
|
||||
if ((retval == NULL) || (internal == NULL))
|
||||
{
|
||||
__Sound_SetError(ERR_OUT_OF_MEMORY);
|
||||
if (retval)
|
||||
free(retval);
|
||||
if (internal)
|
||||
free(internal);
|
||||
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
memset(retval, '\0', sizeof (Sound_Sample));
|
||||
memset(internal, '\0', sizeof (Sound_SampleInternal));
|
||||
|
||||
assert(bufferSize > 0);
|
||||
retval->buffer = malloc(bufferSize); /* pure ugly. */
|
||||
if (!retval->buffer)
|
||||
{
|
||||
__Sound_SetError(ERR_OUT_OF_MEMORY);
|
||||
free(internal);
|
||||
free(retval);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
memset(retval->buffer, '\0', bufferSize);
|
||||
retval->buffer_size = bufferSize;
|
||||
|
||||
if (desired != NULL)
|
||||
memcpy(&retval->desired, desired, sizeof (Sound_AudioInfo));
|
||||
|
||||
internal->rw = rw;
|
||||
retval->opaque = internal;
|
||||
return(retval);
|
||||
} /* alloc_sample */
|
||||
|
||||
|
||||
#if (defined DEBUG_CHATTER)
|
||||
static __inline__ const char *fmt_to_str(Uint16 fmt)
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
case AUDIO_U8:
|
||||
return("U8");
|
||||
case AUDIO_S8:
|
||||
return("S8");
|
||||
case AUDIO_U16LSB:
|
||||
return("U16LSB");
|
||||
case AUDIO_S16LSB:
|
||||
return("S16LSB");
|
||||
case AUDIO_U16MSB:
|
||||
return("U16MSB");
|
||||
case AUDIO_S16MSB:
|
||||
return("S16MSB");
|
||||
} /* switch */
|
||||
|
||||
return("Unknown");
|
||||
} /* fmt_to_str */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The bulk of the Sound_NewSample() work is done here...
|
||||
* Ask the specified decoder to handle the data in (rw), and if
|
||||
* so, construct the Sound_Sample. Otherwise, try to wind (rw)'s stream
|
||||
* back to where it was, and return false.
|
||||
*/
|
||||
static int init_sample(const Sound_DecoderFunctions *funcs,
|
||||
Sound_Sample *sample, const char *ext,
|
||||
Sound_AudioInfo *_desired)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
Sound_AudioInfo desired;
|
||||
int pos = SDL_RWtell(internal->rw);
|
||||
|
||||
/* fill in the funcs for this decoder... */
|
||||
sample->decoder = &funcs->info;
|
||||
internal->funcs = funcs;
|
||||
if (!funcs->open(sample, ext))
|
||||
{
|
||||
SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
/* success; we've got a decoder! */
|
||||
|
||||
/* Now we need to set up the conversion buffer... */
|
||||
|
||||
memcpy(&desired, (_desired != NULL) ? _desired : &sample->actual,
|
||||
sizeof (Sound_AudioInfo));
|
||||
|
||||
if (desired.format == 0)
|
||||
desired.format = sample->actual.format;
|
||||
if (desired.channels == 0)
|
||||
desired.channels = sample->actual.channels;
|
||||
if (desired.rate == 0)
|
||||
desired.rate = sample->actual.rate;
|
||||
|
||||
if (Sound_BuildAudioCVT(&internal->sdlcvt,
|
||||
sample->actual.format,
|
||||
sample->actual.channels,
|
||||
sample->actual.rate,
|
||||
desired.format,
|
||||
desired.channels,
|
||||
desired.rate,
|
||||
sample->buffer_size) == -1)
|
||||
{
|
||||
__Sound_SetError(SDL_GetError());
|
||||
funcs->close(sample);
|
||||
SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (internal->sdlcvt.len_mult > 1)
|
||||
{
|
||||
void *rc = realloc(sample->buffer,
|
||||
sample->buffer_size * internal->sdlcvt.len_mult);
|
||||
if (rc == NULL)
|
||||
{
|
||||
funcs->close(sample);
|
||||
SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
sample->buffer = rc;
|
||||
} /* if */
|
||||
|
||||
/* these pointers are all one and the same. */
|
||||
memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo));
|
||||
internal->sdlcvt.buf = internal->buffer = sample->buffer;
|
||||
internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult;
|
||||
internal->sdlcvt.len = internal->buffer_size;
|
||||
|
||||
/* Prepend our new Sound_Sample to the sample_list... */
|
||||
SDL_LockMutex(samplelist_mutex);
|
||||
internal->next = sample_list;
|
||||
if (sample_list != NULL)
|
||||
((Sound_SampleInternal *) sample_list->opaque)->prev = sample;
|
||||
sample_list = sample;
|
||||
SDL_UnlockMutex(samplelist_mutex);
|
||||
|
||||
SNDDBG(("New sample DESIRED format: %s format, %d rate, %d channels.\n",
|
||||
fmt_to_str(sample->desired.format),
|
||||
sample->desired.rate,
|
||||
sample->desired.channels));
|
||||
|
||||
SNDDBG(("New sample ACTUAL format: %s format, %d rate, %d channels.\n",
|
||||
fmt_to_str(sample->actual.format),
|
||||
sample->actual.rate,
|
||||
sample->actual.channels));
|
||||
|
||||
SNDDBG(("On-the-fly conversion: %s.\n",
|
||||
internal->sdlcvt.needed ? "ENABLED" : "DISABLED"));
|
||||
|
||||
return(1);
|
||||
} /* init_sample */
|
||||
|
||||
|
||||
Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext,
|
||||
Sound_AudioInfo *desired, Uint32 bSize)
|
||||
{
|
||||
Sound_Sample *retval;
|
||||
decoder_element *decoder;
|
||||
|
||||
/* sanity checks. */
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL);
|
||||
BAIL_IF_MACRO(rw == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
|
||||
retval = alloc_sample(rw, desired, bSize);
|
||||
if (!retval)
|
||||
return(NULL); /* alloc_sample() sets error message... */
|
||||
|
||||
if (ext != NULL)
|
||||
{
|
||||
for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++)
|
||||
{
|
||||
if (decoder->available)
|
||||
{
|
||||
const char **decoderExt = decoder->funcs->info.extensions;
|
||||
while (*decoderExt)
|
||||
{
|
||||
if (__Sound_strcasecmp(*decoderExt, ext) == 0)
|
||||
{
|
||||
if (init_sample(decoder->funcs, retval, ext, desired))
|
||||
return(retval);
|
||||
break; /* done with this decoder either way. */
|
||||
} /* if */
|
||||
decoderExt++;
|
||||
} /* while */
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* if */
|
||||
|
||||
/* no direct extension match? Try everything we've got... */
|
||||
for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++)
|
||||
{
|
||||
if (decoder->available)
|
||||
{
|
||||
int should_try = 1;
|
||||
const char **decoderExt = decoder->funcs->info.extensions;
|
||||
|
||||
/* skip if we would have tried decoder above... */
|
||||
while (*decoderExt)
|
||||
{
|
||||
if (__Sound_strcasecmp(*decoderExt, ext) == 0)
|
||||
{
|
||||
should_try = 0;
|
||||
break;
|
||||
} /* if */
|
||||
decoderExt++;
|
||||
} /* while */
|
||||
|
||||
if (should_try)
|
||||
{
|
||||
if (init_sample(decoder->funcs, retval, ext, desired))
|
||||
return(retval);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* nothing could handle the sound data... */
|
||||
free(retval->opaque);
|
||||
if (retval->buffer != NULL)
|
||||
free(retval->buffer);
|
||||
free(retval);
|
||||
SDL_RWclose(rw);
|
||||
__Sound_SetError(ERR_UNSUPPORTED_FORMAT);
|
||||
return(NULL);
|
||||
} /* Sound_NewSample */
|
||||
|
||||
|
||||
Sound_Sample *Sound_NewSampleFromFile(const char *filename,
|
||||
Sound_AudioInfo *desired,
|
||||
Uint32 bufferSize)
|
||||
{
|
||||
const char *ext;
|
||||
SDL_RWops *rw;
|
||||
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL);
|
||||
BAIL_IF_MACRO(filename == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
|
||||
ext = strrchr(filename, '.');
|
||||
rw = SDL_RWFromFile(filename, "rb");
|
||||
BAIL_IF_MACRO(rw == NULL, SDL_GetError(), NULL);
|
||||
|
||||
if (ext != NULL)
|
||||
ext++;
|
||||
|
||||
return(Sound_NewSample(rw, ext, desired, bufferSize));
|
||||
} /* Sound_NewSampleFromFile */
|
||||
|
||||
|
||||
void Sound_FreeSample(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
__Sound_SetError(ERR_NOT_INITIALIZED);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
if (sample == NULL)
|
||||
{
|
||||
__Sound_SetError(ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
SDL_LockMutex(samplelist_mutex);
|
||||
|
||||
/* update the sample_list... */
|
||||
if (internal->prev != NULL)
|
||||
{
|
||||
Sound_SampleInternal *prevInternal;
|
||||
prevInternal = (Sound_SampleInternal *) internal->prev->opaque;
|
||||
prevInternal->next = internal->next;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
assert(sample_list == sample);
|
||||
sample_list = internal->next;
|
||||
} /* else */
|
||||
|
||||
if (internal->next != NULL)
|
||||
{
|
||||
Sound_SampleInternal *nextInternal;
|
||||
nextInternal = (Sound_SampleInternal *) internal->next->opaque;
|
||||
nextInternal->prev = internal->prev;
|
||||
} /* if */
|
||||
|
||||
SDL_UnlockMutex(samplelist_mutex);
|
||||
|
||||
/* nuke it... */
|
||||
internal->funcs->close(sample);
|
||||
|
||||
if (internal->rw != NULL) /* this condition is a "just in case" thing. */
|
||||
SDL_RWclose(internal->rw);
|
||||
|
||||
if ((internal->buffer != NULL) && (internal->buffer != sample->buffer))
|
||||
free(internal->buffer);
|
||||
|
||||
free(internal);
|
||||
|
||||
if (sample->buffer != NULL)
|
||||
free(sample->buffer);
|
||||
|
||||
free(sample);
|
||||
} /* Sound_FreeSample */
|
||||
|
||||
|
||||
int Sound_SetBufferSize(Sound_Sample *sample, Uint32 newSize)
|
||||
{
|
||||
void *newBuf = NULL;
|
||||
Sound_SampleInternal *internal = NULL;
|
||||
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
internal = ((Sound_SampleInternal *) sample->opaque);
|
||||
newBuf = realloc(sample->buffer, newSize * internal->sdlcvt.len_mult);
|
||||
BAIL_IF_MACRO(newBuf == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
internal->sdlcvt.buf = internal->buffer = sample->buffer = newBuf;
|
||||
sample->buffer_size = newSize;
|
||||
internal->buffer_size = newSize / internal->sdlcvt.len_mult;
|
||||
internal->sdlcvt.len = internal->buffer_size;
|
||||
|
||||
return(1);
|
||||
} /* Sound_SetBufferSize */
|
||||
|
||||
|
||||
Uint32 Sound_Decode(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = NULL;
|
||||
Uint32 retval = 0;
|
||||
|
||||
/* a boatload of sanity checks... */
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0);
|
||||
BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0);
|
||||
|
||||
internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
assert(sample->buffer != NULL);
|
||||
assert(sample->buffer_size > 0);
|
||||
assert(internal->buffer != NULL);
|
||||
assert(internal->buffer_size > 0);
|
||||
|
||||
/* reset EAGAIN. Decoder can flip it back on if it needs to. */
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_EAGAIN;
|
||||
retval = internal->funcs->read(sample);
|
||||
|
||||
if (retval > 0 && internal->sdlcvt.needed)
|
||||
{
|
||||
internal->sdlcvt.len = retval;
|
||||
Sound_ConvertAudio(&internal->sdlcvt);
|
||||
retval = internal->sdlcvt.len_cvt;
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* Sound_Decode */
|
||||
|
||||
|
||||
Uint32 Sound_DecodeAll(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = NULL;
|
||||
void *buf = NULL;
|
||||
Uint32 newBufSize = 0;
|
||||
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0);
|
||||
BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0);
|
||||
|
||||
internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
while ( ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) &&
|
||||
((sample->flags & SOUND_SAMPLEFLAG_ERROR) == 0) )
|
||||
{
|
||||
Uint32 br = Sound_Decode(sample);
|
||||
void *ptr = realloc(buf, newBufSize + br);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
__Sound_SetError(ERR_OUT_OF_MEMORY);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
buf = ptr;
|
||||
memcpy( ((char *) buf) + newBufSize, sample->buffer, br );
|
||||
newBufSize += br;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
if (buf == NULL) /* ...in case first call to realloc() fails... */
|
||||
return(sample->buffer_size);
|
||||
|
||||
if (internal->buffer != sample->buffer)
|
||||
free(internal->buffer);
|
||||
|
||||
free(sample->buffer);
|
||||
|
||||
internal->sdlcvt.buf = internal->buffer = sample->buffer = buf;
|
||||
sample->buffer_size = newBufSize;
|
||||
internal->buffer_size = newBufSize / internal->sdlcvt.len_mult;
|
||||
internal->sdlcvt.len = internal->buffer_size;
|
||||
|
||||
return(newBufSize);
|
||||
} /* Sound_DecodeAll */
|
||||
|
||||
|
||||
int Sound_Rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal;
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
|
||||
internal = (Sound_SampleInternal *) sample->opaque;
|
||||
if (!internal->funcs->rewind(sample))
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_EAGAIN;
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_ERROR;
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
return(1);
|
||||
} /* Sound_Rewind */
|
||||
|
||||
|
||||
int Sound_Seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal;
|
||||
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
if (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK))
|
||||
BAIL_MACRO(ERR_CANNOT_SEEK, 0);
|
||||
|
||||
internal = (Sound_SampleInternal *) sample->opaque;
|
||||
BAIL_IF_MACRO(!internal->funcs->seek(sample, ms), NULL, 0);
|
||||
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_EAGAIN;
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_ERROR;
|
||||
sample->flags &= ~SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
return(1);
|
||||
} /* Sound_Rewind */
|
||||
|
||||
|
||||
/* end of SDL_sound.c ... */
|
||||
|
||||
326
project/jni/sdl_sound/SDL_sound_internal.h
Normal file
326
project/jni/sdl_sound/SDL_sound_internal.h
Normal file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Internal function/structure declaration. Do NOT include in your
|
||||
* application.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDL_SOUND_INTERNAL_H_
|
||||
#define _INCLUDE_SDL_SOUND_INTERNAL_H_
|
||||
|
||||
#ifndef __SDL_SOUND_INTERNAL__
|
||||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
/* SDL 1.2.4 defines this, but better safe than sorry. */
|
||||
#if (!defined(__inline__))
|
||||
# define __inline__
|
||||
#endif
|
||||
|
||||
#if (defined DEBUG_CHATTER)
|
||||
#define SNDDBG(x) printf x
|
||||
#else
|
||||
#define SNDDBG(x)
|
||||
#endif
|
||||
|
||||
#if HAVE_ASSERT_H
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
extern char *strrchr(const char *s, int c);
|
||||
# ifdef NDEBUG
|
||||
# define assert(x)
|
||||
# else
|
||||
# define assert(x) if(!x) { fprintf(stderr,"Assertion failed in %s, line %s.\n",__FILE__,__LINE__); fclose(stderr); fclose(stdout); exit(1); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if (!defined assert) /* if all else fails. */
|
||||
# define assert(x)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct __SOUND_DECODERFUNCTIONS__
|
||||
{
|
||||
/* This is a block of info about your decoder. See SDL_sound.h. */
|
||||
const Sound_DecoderInfo info;
|
||||
|
||||
/*
|
||||
* This is called during the Sound_Init() function. Use this to
|
||||
* set up any global state that your decoder needs, such as
|
||||
* initializing an external library, etc.
|
||||
*
|
||||
* Return non-zero if initialization is successful, zero if there's
|
||||
* a fatal error. If this method fails, then this decoder is
|
||||
* flagged as unavailable until SDL_sound() is shut down and
|
||||
* reinitialized, in which case this method will be tried again.
|
||||
*
|
||||
* Note that the decoders quit() method won't be called if this
|
||||
* method fails, so if you can't intialize, you'll have to clean
|
||||
* up the half-initialized state in this method.
|
||||
*/
|
||||
int (*init)(void);
|
||||
|
||||
/*
|
||||
* This is called during the Sound_Quit() function. Use this to
|
||||
* clean up any global state that your decoder has used during its
|
||||
* lifespan.
|
||||
*/
|
||||
void (*quit)(void);
|
||||
|
||||
/*
|
||||
* Returns non-zero if (sample) has a valid fileformat that this
|
||||
* driver can handle. Zero if this driver can NOT handle the data.
|
||||
*
|
||||
* Extension, which may be NULL, is just a hint as to the form of
|
||||
* data that is being passed in. Most decoders should determine if
|
||||
* they can handle the data by the data itself, but others, like
|
||||
* the raw data handler, need this hint to know if they should
|
||||
* accept the data in the first place.
|
||||
*
|
||||
* (sample)'s (opaque) field should be cast to a Sound_SampleInternal
|
||||
* pointer:
|
||||
*
|
||||
* Sound_SampleInternal *internal;
|
||||
* internal = (Sound_SampleInternal *) sample->opaque;
|
||||
*
|
||||
* Certain fields of sample will be filled in for the decoder before
|
||||
* this call, and others should be filled in by the decoder. Some
|
||||
* fields are offlimits, and should NOT be modified. The list:
|
||||
*
|
||||
* in Sound_SampleInternal section:
|
||||
* Sound_Sample *next; (offlimits)
|
||||
* Sound_Sample *prev; (offlimits)
|
||||
* SDL_RWops *rw; (can use, but do NOT close it)
|
||||
* const Sound_DecoderFunctions *funcs; (that's this structure)
|
||||
* Sound_AudioCVT sdlcvt; (offlimits)
|
||||
* void *buffer; (offlimits until read() method)
|
||||
* Uint32 buffer_size; (offlimits until read() method)
|
||||
* void *decoder_private; (read and write access)
|
||||
*
|
||||
* in rest of Sound_Sample:
|
||||
* void *opaque; (this was internal section, above)
|
||||
* const Sound_DecoderInfo *decoder; (read only)
|
||||
* Sound_AudioInfo desired; (read only, usually not needed here)
|
||||
* Sound_AudioInfo actual; (please fill this in)
|
||||
* void *buffer; (offlimits)
|
||||
* Uint32 buffer_size; (offlimits)
|
||||
* Sound_SampleFlags flags; (set appropriately)
|
||||
*/
|
||||
int (*open)(Sound_Sample *sample, const char *ext);
|
||||
|
||||
/*
|
||||
* Clean up. SDL_sound is done with this sample, so the decoder should
|
||||
* clean up any resources it allocated. Anything that wasn't
|
||||
* explicitly allocated by the decoder should be LEFT ALONE, since
|
||||
* the higher-level SDL_sound layer will clean up its own mess.
|
||||
*/
|
||||
void (*close)(Sound_Sample *sample);
|
||||
|
||||
/*
|
||||
* Get more data from (sample). The decoder should get a pointer to
|
||||
* the internal structure...
|
||||
*
|
||||
* Sound_SampleInternal *internal;
|
||||
* internal = (Sound_SampleInternal *) sample->opaque;
|
||||
*
|
||||
* ...and then start decoding. Fill in up to internal->buffer_size
|
||||
* bytes of decoded sound in the space pointed to by
|
||||
* internal->buffer. The encoded data is read in from internal->rw.
|
||||
* Data should be decoded in the format specified during the
|
||||
* decoder's open() method in the sample->actual field. The
|
||||
* conversion to the desired format is done at a higher level.
|
||||
*
|
||||
* The return value is the number of bytes decoded into
|
||||
* internal->buffer, which can be no more than internal->buffer_size,
|
||||
* but can be less. If it is less, you should set a state flag:
|
||||
*
|
||||
* If there's just no more data (end of file, etc), then do:
|
||||
* sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
*
|
||||
* If there's an unrecoverable error, then do:
|
||||
* __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
|
||||
* sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
*
|
||||
* If there's more data, but you'd have to block for considerable
|
||||
* amounts of time to get at it, or there's a recoverable error,
|
||||
* then do:
|
||||
* __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
|
||||
* sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
*
|
||||
* SDL_sound will not call your read() method for any samples with
|
||||
* SOUND_SAMPLEFLAG_EOF or SOUND_SAMPLEFLAG_ERROR set. The
|
||||
* SOUND_SAMPLEFLAG_EAGAIN flag is reset before each call to this
|
||||
* method.
|
||||
*/
|
||||
Uint32 (*read)(Sound_Sample *sample);
|
||||
|
||||
/*
|
||||
* Reset the decoding to the beginning of the stream. Nonzero on
|
||||
* success, zero on failure.
|
||||
*
|
||||
* The purpose of this method is to allow for higher efficiency than
|
||||
* an application could get by just recreating the sample externally;
|
||||
* not only do they not have to reopen the RWops, reallocate buffers,
|
||||
* and potentially pass the data through several rejecting decoders,
|
||||
* but certain decoders will not have to recreate their existing
|
||||
* state (search for metadata, etc) since they already know they
|
||||
* have a valid audio stream with a given set of characteristics.
|
||||
*
|
||||
* The decoder is responsible for calling seek() on the associated
|
||||
* SDL_RWops. A failing call to seek() should be the ONLY reason that
|
||||
* this method should ever fail!
|
||||
*/
|
||||
int (*rewind)(Sound_Sample *sample);
|
||||
|
||||
/*
|
||||
* Reposition the decoding to an arbitrary point. Nonzero on
|
||||
* success, zero on failure.
|
||||
*
|
||||
* The purpose of this method is to allow for higher efficiency than
|
||||
* an application could get by just rewinding the sample and
|
||||
* decoding to a given point.
|
||||
*
|
||||
* The decoder is responsible for calling seek() on the associated
|
||||
* SDL_RWops.
|
||||
*
|
||||
* If there is an error, try to recover so that the next read will
|
||||
* continue as if nothing happened.
|
||||
*/
|
||||
int (*seek)(Sound_Sample *sample, Uint32 ms);
|
||||
} Sound_DecoderFunctions;
|
||||
|
||||
|
||||
/* A structure to hold a set of audio conversion filters and buffers */
|
||||
#if (defined SOUND_USE_ALTCVT)
|
||||
#include "alt_audio_convert.h"
|
||||
#else
|
||||
typedef struct Sound_AudioCVT
|
||||
{
|
||||
int needed; /* Set to 1 if conversion possible */
|
||||
Uint16 src_format; /* Source audio format */
|
||||
Uint16 dst_format; /* Target audio format */
|
||||
double rate_incr; /* Rate conversion increment */
|
||||
Uint8 *buf; /* Buffer to hold entire audio data */
|
||||
int len; /* Length of original audio buffer */
|
||||
int len_cvt; /* Length of converted audio buffer */
|
||||
int len_mult; /* buffer must be len*len_mult big */
|
||||
double len_ratio; /* Given len, final size is len*len_ratio */
|
||||
void (*filters[20])(struct Sound_AudioCVT *cvt, Uint16 *format);
|
||||
int filter_index; /* Current audio conversion function */
|
||||
} Sound_AudioCVT;
|
||||
#endif
|
||||
|
||||
extern SNDDECLSPEC int Sound_BuildAudioCVT(Sound_AudioCVT *cvt,
|
||||
Uint16 src_format, Uint8 src_channels, Uint32 src_rate,
|
||||
Uint16 dst_format, Uint8 dst_channels, Uint32 dst_rate,
|
||||
Uint32 dst_size);
|
||||
|
||||
extern SNDDECLSPEC int Sound_ConvertAudio(Sound_AudioCVT *cvt);
|
||||
|
||||
|
||||
|
||||
typedef struct __SOUND_SAMPLEINTERNAL__
|
||||
{
|
||||
Sound_Sample *next;
|
||||
Sound_Sample *prev;
|
||||
SDL_RWops *rw;
|
||||
const Sound_DecoderFunctions *funcs;
|
||||
Sound_AudioCVT sdlcvt;
|
||||
void *buffer;
|
||||
Uint32 buffer_size;
|
||||
void *decoder_private;
|
||||
} Sound_SampleInternal;
|
||||
|
||||
|
||||
/* error messages... */
|
||||
#define ERR_IS_INITIALIZED "Already initialized"
|
||||
#define ERR_NOT_INITIALIZED "Not initialized"
|
||||
#define ERR_INVALID_ARGUMENT "Invalid argument"
|
||||
#define ERR_OUT_OF_MEMORY "Out of memory"
|
||||
#define ERR_NOT_SUPPORTED "Operation not supported"
|
||||
#define ERR_UNSUPPORTED_FORMAT "Sound format unsupported"
|
||||
#define ERR_NOT_A_HANDLE "Not a file handle"
|
||||
#define ERR_NO_SUCH_FILE "No such file"
|
||||
#define ERR_PAST_EOF "Past end of file"
|
||||
#define ERR_IO_ERROR "I/O error"
|
||||
#define ERR_COMPRESSION "(De)compression error"
|
||||
#define ERR_PREV_ERROR "Previous decoding already caused an error"
|
||||
#define ERR_PREV_EOF "Previous decoding already triggered EOF"
|
||||
#define ERR_CANNOT_SEEK "Sample is not seekable"
|
||||
|
||||
/*
|
||||
* Call this to set the message returned by Sound_GetError().
|
||||
* Please only use the ERR_* constants above, or add new constants to the
|
||||
* above group, but I want these all in one place.
|
||||
*
|
||||
* Calling this with a NULL argument is a safe no-op.
|
||||
*/
|
||||
void __Sound_SetError(const char *err);
|
||||
|
||||
/*
|
||||
* Call this to convert milliseconds to an actual byte position, based on
|
||||
* audio data characteristics.
|
||||
*/
|
||||
Uint32 __Sound_convertMsToBytePos(Sound_AudioInfo *info, Uint32 ms);
|
||||
|
||||
/*
|
||||
* Use this if you need a cross-platform stricmp().
|
||||
*/
|
||||
int __Sound_strcasecmp(const char *x, const char *y);
|
||||
|
||||
|
||||
/* These get used all over for lessening code clutter. */
|
||||
#define BAIL_MACRO(e, r) { __Sound_SetError(e); return r; }
|
||||
#define BAIL_IF_MACRO(c, e, r) if (c) { __Sound_SetError(e); return r; }
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*------------ ----------------*/
|
||||
/*------------ You MUST implement the following functions ----------------*/
|
||||
/*------------ if porting to a new platform. ----------------*/
|
||||
/*------------ (see platform/unix.c for an example) ----------------*/
|
||||
/*------------ ----------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* (None, right now.) */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#endif /* defined _INCLUDE_SDL_SOUND_INTERNAL_H_ */
|
||||
|
||||
/* end of SDL_sound_internal.h ... */
|
||||
|
||||
29
project/jni/sdl_sound/TODO
Normal file
29
project/jni/sdl_sound/TODO
Normal file
@@ -0,0 +1,29 @@
|
||||
More immediate:
|
||||
- Fix the crappy rewind implementation in shn.c's SHN_rewind().
|
||||
- Finish implementing seek() method in decoders, see below.
|
||||
- Add a sdlsound-config script?
|
||||
- Make sure we can build shared libs on Cygwin, BeOS, Mac OS X...
|
||||
|
||||
Decoders still needing seek() method:
|
||||
(If decoder can't seek, clean up the stub and report an error.)
|
||||
- mikmod.c
|
||||
- shn.c
|
||||
- mpglib.c
|
||||
- quicktime.c
|
||||
|
||||
General stuff TODO:
|
||||
- Hack on the experimental audio conversion routines.
|
||||
- Handle compression and other chunks in WAV files.
|
||||
- Handle compression and other chunks in AIFF-C files.
|
||||
|
||||
Quicktime stuff that'd be cool, but isn't crucial:
|
||||
- Integrate decoders/quicktime.c with build system (for OS X)?
|
||||
- Make decoders/quicktime.c more robust.
|
||||
- Make decoders/quicktime.c work on win32?
|
||||
- There's no seek() method.
|
||||
|
||||
Ongoing:
|
||||
- look for "FIXME"s in the code.
|
||||
|
||||
/* end of TODO ... */
|
||||
|
||||
1057
project/jni/sdl_sound/alt_audio_convert.c
Normal file
1057
project/jni/sdl_sound/alt_audio_convert.c
Normal file
File diff suppressed because it is too large
Load Diff
89
project/jni/sdl_sound/alt_audio_convert.h
Normal file
89
project/jni/sdl_sound/alt_audio_convert.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Extended Audio Converter for SDL (Simple DirectMedia Layer)
|
||||
* Copyright (C) 2002 Frank Ranostaj
|
||||
* Institute of Applied Physik
|
||||
* Johann Wolfgang Goethe-Universität
|
||||
* Frankfurt am Main, Germany
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Frank Ranostaj
|
||||
* ranostaj@stud.uni-frankfurt.de
|
||||
*
|
||||
* (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.)
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_AUDIO_CONVERT_H_
|
||||
#define _INCLUDE_AUDIO_CONVERT_H_
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#define Sound_AI_Loop 0x2
|
||||
#define _fsize 32
|
||||
|
||||
typedef struct{
|
||||
Sint16 numerator;
|
||||
Sint16 denominator;
|
||||
} Fraction;
|
||||
|
||||
typedef struct{
|
||||
Sint16 c[16][4*_fsize];
|
||||
Uint8 incr[16];
|
||||
Fraction ratio;
|
||||
int mask;
|
||||
} VarFilter;
|
||||
|
||||
typedef struct{
|
||||
Uint8* buffer;
|
||||
int mode;
|
||||
VarFilter *filter;
|
||||
} AdapterC;
|
||||
|
||||
typedef int (*Adapter) ( AdapterC Data, int length );
|
||||
|
||||
typedef struct{
|
||||
VarFilter filter;
|
||||
int filter_index;
|
||||
Adapter adapter[32];
|
||||
/* buffer must be len*len_mult(+len_add) big */
|
||||
int len_mult;
|
||||
int len_add;
|
||||
double add;
|
||||
|
||||
/* the following elements are provided for compatibility: */
|
||||
/* the size of the output is approx len*len_ratio */
|
||||
double len_ratio;
|
||||
Uint8* buf; /* input/output buffer */
|
||||
int needed; /* 0 if nothing to be done, 1 otherwise */
|
||||
int len; /* Length of the input */
|
||||
int len_cvt; /* Length of converted audio buffer */
|
||||
} Sound_AudioCVT;
|
||||
|
||||
#define SDL_SOUND_Loop 0x10
|
||||
|
||||
#ifndef SNDDECLSPEC
|
||||
#define SNDDECLSPEC DECLSPEC
|
||||
#endif
|
||||
|
||||
extern SNDDECLSPEC int Sound_AltConvertAudio( Sound_AudioCVT *Data,
|
||||
Uint8* buffer, int length, int mode );
|
||||
|
||||
extern SNDDECLSPEC int Sound_AltBuildAudioCVT( Sound_AudioCVT *Data,
|
||||
SDL_AudioSpec src, SDL_AudioSpec dst );
|
||||
|
||||
extern SNDDECLSPEC int Sound_estimateBufferSize( Sound_AudioCVT *Data,
|
||||
int length );
|
||||
|
||||
#endif /* _INCLUDE_AUDIO_CONVERT_H_ */
|
||||
|
||||
739
project/jni/sdl_sound/audio_convert.c
Normal file
739
project/jni/sdl_sound/audio_convert.c
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 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
|
||||
|
||||
Sam Lantinga
|
||||
slouken@devolution.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was derived from SDL's SDL_audiocvt.c and is an attempt to
|
||||
* address the shortcomings of it.
|
||||
*
|
||||
* Perhaps we can adapt some good filters from SoX?
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if !SOUND_USE_ALTCVT
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
/* Functions for audio drivers to perform runtime conversion of audio format */
|
||||
|
||||
|
||||
/*
|
||||
* Toggle endianness. This filter is, of course, only applied to 16-bit
|
||||
* audio data.
|
||||
*/
|
||||
|
||||
static void Sound_ConvertEndian(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *data, tmp;
|
||||
|
||||
/* SNDDBG(("Converting audio endianness\n")); */
|
||||
|
||||
data = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
tmp = data[0];
|
||||
data[0] = data[1];
|
||||
data[1] = tmp;
|
||||
data += 2;
|
||||
} /* for */
|
||||
|
||||
*format = (*format ^ 0x1000);
|
||||
} /* Sound_ConvertEndian */
|
||||
|
||||
|
||||
/*
|
||||
* Toggle signed/unsigned. Apparently this is done by toggling the most
|
||||
* significant bit of each sample.
|
||||
*/
|
||||
|
||||
static void Sound_ConvertSign(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *data;
|
||||
|
||||
/* SNDDBG(("Converting audio signedness\n")); */
|
||||
|
||||
data = cvt->buf;
|
||||
|
||||
/* 16-bit sound? */
|
||||
if ((*format & 0xFF) == 16)
|
||||
{
|
||||
/* Little-endian? */
|
||||
if ((*format & 0x1000) != 0x1000)
|
||||
++data;
|
||||
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
*data ^= 0x80;
|
||||
data += 2;
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
for (i = cvt->len_cvt; i; --i)
|
||||
*data++ ^= 0x80;
|
||||
} /* else */
|
||||
|
||||
*format = (*format ^ 0x8000);
|
||||
} /* Sound_ConvertSign */
|
||||
|
||||
|
||||
/*
|
||||
* Convert 16-bit to 8-bit. This is done by taking the most significant byte
|
||||
* of each 16-bit sample.
|
||||
*/
|
||||
|
||||
static void Sound_Convert8(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
/* SNDDBG(("Converting to 8-bit\n")); */
|
||||
|
||||
src = cvt->buf;
|
||||
dst = cvt->buf;
|
||||
|
||||
/* Little-endian? */
|
||||
if ((*format & 0x1000) != 0x1000)
|
||||
++src;
|
||||
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
*dst = *src;
|
||||
src += 2;
|
||||
dst += 1;
|
||||
} /* for */
|
||||
|
||||
*format = ((*format & ~0x9010) | AUDIO_U8);
|
||||
cvt->len_cvt /= 2;
|
||||
} /* Sound_Convert8 */
|
||||
|
||||
|
||||
/* Convert 8-bit to 16-bit - LSB */
|
||||
|
||||
static void Sound_Convert16LSB(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
/* SNDDBG(("Converting to 16-bit LSB\n")); */
|
||||
|
||||
src = cvt->buf + cvt->len_cvt;
|
||||
dst = cvt->buf + cvt->len_cvt * 2;
|
||||
|
||||
for (i = cvt->len_cvt; i; --i)
|
||||
{
|
||||
src -= 1;
|
||||
dst -= 2;
|
||||
dst[1] = *src;
|
||||
dst[0] = 0;
|
||||
} /* for */
|
||||
|
||||
*format = ((*format & ~0x0008) | AUDIO_U16LSB);
|
||||
cvt->len_cvt *= 2;
|
||||
} /* Sound_Convert16LSB */
|
||||
|
||||
|
||||
/* Convert 8-bit to 16-bit - MSB */
|
||||
|
||||
static void Sound_Convert16MSB(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
/* SNDDBG(("Converting to 16-bit MSB\n")); */
|
||||
|
||||
src = cvt->buf + cvt->len_cvt;
|
||||
dst = cvt->buf + cvt->len_cvt * 2;
|
||||
|
||||
for (i = cvt->len_cvt; i; --i)
|
||||
{
|
||||
src -= 1;
|
||||
dst -= 2;
|
||||
dst[0] = *src;
|
||||
dst[1] = 0;
|
||||
} /* for */
|
||||
|
||||
*format = ((*format & ~0x0008) | AUDIO_U16MSB);
|
||||
cvt->len_cvt *= 2;
|
||||
} /* Sound_Convert16MSB */
|
||||
|
||||
|
||||
/* Duplicate a mono channel to both stereo channels */
|
||||
|
||||
static void Sound_ConvertStereo(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* SNDDBG(("Converting to stereo\n")); */
|
||||
|
||||
/* 16-bit sound? */
|
||||
if ((*format & 0xFF) == 16)
|
||||
{
|
||||
Uint16 *src, *dst;
|
||||
|
||||
src = (Uint16 *) (cvt->buf + cvt->len_cvt);
|
||||
dst = (Uint16 *) (cvt->buf + cvt->len_cvt * 2);
|
||||
|
||||
for (i = cvt->len_cvt/2; i; --i)
|
||||
{
|
||||
dst -= 2;
|
||||
src -= 1;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
Uint8 *src, *dst;
|
||||
|
||||
src = cvt->buf + cvt->len_cvt;
|
||||
dst = cvt->buf + cvt->len_cvt * 2;
|
||||
|
||||
for (i = cvt->len_cvt; i; --i)
|
||||
{
|
||||
dst -= 2;
|
||||
src -= 1;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
} /* for */
|
||||
} /* else */
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
} /* Sound_ConvertStereo */
|
||||
|
||||
|
||||
/* Effectively mix right and left channels into a single channel */
|
||||
|
||||
static void Sound_ConvertMono(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Sint32 sample;
|
||||
Uint8 *u_src, *u_dst;
|
||||
Sint8 *s_src, *s_dst;
|
||||
|
||||
/* SNDDBG(("Converting to mono\n")); */
|
||||
|
||||
switch (*format)
|
||||
{
|
||||
case AUDIO_U8:
|
||||
u_src = cvt->buf;
|
||||
u_dst = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
sample = u_src[0] + u_src[1];
|
||||
*u_dst = (sample > 255) ? 255 : sample;
|
||||
u_src += 2;
|
||||
u_dst += 1;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case AUDIO_S8:
|
||||
s_src = (Sint8 *) cvt->buf;
|
||||
s_dst = (Sint8 *) cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
sample = s_src[0] + s_src[1];
|
||||
if (sample > 127)
|
||||
*s_dst = 127;
|
||||
else if (sample < -128)
|
||||
*s_dst = -128;
|
||||
else
|
||||
*s_dst = sample;
|
||||
|
||||
s_src += 2;
|
||||
s_dst += 1;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case AUDIO_U16MSB:
|
||||
u_src = cvt->buf;
|
||||
u_dst = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 4; i; --i)
|
||||
{
|
||||
sample = (Uint16) ((u_src[0] << 8) | u_src[1])
|
||||
+ (Uint16) ((u_src[2] << 8) | u_src[3]);
|
||||
if (sample > 65535)
|
||||
{
|
||||
u_dst[0] = 0xFF;
|
||||
u_dst[1] = 0xFF;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
u_dst[1] = (sample & 0xFF);
|
||||
sample >>= 8;
|
||||
u_dst[0] = (sample & 0xFF);
|
||||
} /* else */
|
||||
u_src += 4;
|
||||
u_dst += 2;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case AUDIO_U16LSB:
|
||||
u_src = cvt->buf;
|
||||
u_dst = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 4; i; --i)
|
||||
{
|
||||
sample = (Uint16) ((u_src[1] << 8) | u_src[0])
|
||||
+ (Uint16) ((u_src[3] << 8) | u_src[2]);
|
||||
if (sample > 65535)
|
||||
{
|
||||
u_dst[0] = 0xFF;
|
||||
u_dst[1] = 0xFF;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
u_dst[0] = (sample & 0xFF);
|
||||
sample >>= 8;
|
||||
u_dst[1] = (sample & 0xFF);
|
||||
} /* else */
|
||||
u_src += 4;
|
||||
u_dst += 2;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case AUDIO_S16MSB:
|
||||
u_src = cvt->buf;
|
||||
u_dst = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 4; i; --i)
|
||||
{
|
||||
sample = (Sint16) ((u_src[0] << 8) | u_src[1])
|
||||
+ (Sint16) ((u_src[2] << 8) | u_src[3]);
|
||||
if (sample > 32767)
|
||||
{
|
||||
u_dst[0] = 0x7F;
|
||||
u_dst[1] = 0xFF;
|
||||
} /* if */
|
||||
else if (sample < -32768)
|
||||
{
|
||||
u_dst[0] = 0x80;
|
||||
u_dst[1] = 0x00;
|
||||
} /* else if */
|
||||
else
|
||||
{
|
||||
u_dst[1] = (sample & 0xFF);
|
||||
sample >>= 8;
|
||||
u_dst[0] = (sample & 0xFF);
|
||||
} /* else */
|
||||
u_src += 4;
|
||||
u_dst += 2;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
u_src = cvt->buf;
|
||||
u_dst = cvt->buf;
|
||||
|
||||
for (i = cvt->len_cvt / 4; i; --i)
|
||||
{
|
||||
sample = (Sint16) ((u_src[1] << 8) | u_src[0])
|
||||
+ (Sint16) ((u_src[3] << 8) | u_src[2]);
|
||||
if (sample > 32767)
|
||||
{
|
||||
u_dst[1] = 0x7F;
|
||||
u_dst[0] = 0xFF;
|
||||
} /* if */
|
||||
else if (sample < -32768)
|
||||
{
|
||||
u_dst[1] = 0x80;
|
||||
u_dst[0] = 0x00;
|
||||
} /* else if */
|
||||
else
|
||||
{
|
||||
u_dst[0] = (sample & 0xFF);
|
||||
sample >>= 8;
|
||||
u_dst[1] = (sample & 0xFF);
|
||||
} /* else */
|
||||
u_src += 4;
|
||||
u_dst += 2;
|
||||
} /* for */
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
} /* Sound_ConvertMono */
|
||||
|
||||
|
||||
/* Convert rate up by multiple of 2 */
|
||||
|
||||
static void Sound_RateMUL2(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
/* SNDDBG(("Converting audio rate * 2\n")); */
|
||||
|
||||
src = cvt->buf + cvt->len_cvt;
|
||||
dst = cvt->buf + cvt->len_cvt*2;
|
||||
|
||||
/* 8- or 16-bit sound? */
|
||||
switch (*format & 0xFF)
|
||||
{
|
||||
case 8:
|
||||
for (i = cvt->len_cvt; i; --i)
|
||||
{
|
||||
src -= 1;
|
||||
dst -= 2;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case 16:
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
src -= 2;
|
||||
dst -= 4;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
dst[3] = src[1];
|
||||
} /* for */
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
} /* Sound_RateMUL2 */
|
||||
|
||||
|
||||
/* Convert rate down by multiple of 2 */
|
||||
|
||||
static void Sound_RateDIV2(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
int i;
|
||||
Uint8 *src, *dst;
|
||||
|
||||
/* SNDDBG(("Converting audio rate / 2\n")); */
|
||||
|
||||
src = cvt->buf;
|
||||
dst = cvt->buf;
|
||||
|
||||
/* 8- or 16-bit sound? */
|
||||
switch (*format & 0xFF)
|
||||
{
|
||||
case 8:
|
||||
for (i = cvt->len_cvt / 2; i; --i)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
src += 2;
|
||||
dst += 1;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case 16:
|
||||
for (i = cvt->len_cvt / 4; i; --i)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
src += 4;
|
||||
dst += 2;
|
||||
}
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
} /* Sound_RateDIV2 */
|
||||
|
||||
|
||||
/* Very slow rate conversion routine */
|
||||
|
||||
static void Sound_RateSLOW(Sound_AudioCVT *cvt, Uint16 *format)
|
||||
{
|
||||
double ipos;
|
||||
int i, clen;
|
||||
Uint8 *output8;
|
||||
Uint16 *output16;
|
||||
|
||||
/* SNDDBG(("Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr)); */
|
||||
|
||||
clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
|
||||
|
||||
if (cvt->rate_incr > 1.0)
|
||||
{
|
||||
/* 8- or 16-bit sound? */
|
||||
switch (*format & 0xFF)
|
||||
{
|
||||
case 8:
|
||||
output8 = cvt->buf;
|
||||
|
||||
ipos = 0.0;
|
||||
for (i = clen; i; --i)
|
||||
{
|
||||
*output8 = cvt->buf[(int) ipos];
|
||||
ipos += cvt->rate_incr;
|
||||
output8 += 1;
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case 16:
|
||||
output16 = (Uint16 *) cvt->buf;
|
||||
|
||||
clen &= ~1;
|
||||
ipos = 0.0;
|
||||
for (i = clen / 2; i; --i)
|
||||
{
|
||||
*output16 = ((Uint16 *) cvt->buf)[(int) ipos];
|
||||
ipos += cvt->rate_incr;
|
||||
output16 += 1;
|
||||
} /* for */
|
||||
break;
|
||||
} /* switch */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* 8- or 16-bit sound */
|
||||
switch (*format & 0xFF)
|
||||
{
|
||||
case 8:
|
||||
output8 = cvt->buf + clen;
|
||||
|
||||
ipos = (double) cvt->len_cvt;
|
||||
for (i = clen; i; --i)
|
||||
{
|
||||
ipos -= cvt->rate_incr;
|
||||
output8 -= 1;
|
||||
*output8 = cvt->buf[(int) ipos];
|
||||
} /* for */
|
||||
break;
|
||||
|
||||
case 16:
|
||||
clen &= ~1;
|
||||
output16 = (Uint16 *) (cvt->buf + clen);
|
||||
ipos = (double) cvt->len_cvt / 2;
|
||||
for (i = clen / 2; i; --i)
|
||||
{
|
||||
ipos -= cvt->rate_incr;
|
||||
output16 -= 1;
|
||||
*output16 = ((Uint16 *) cvt->buf)[(int) ipos];
|
||||
} /* for */
|
||||
break;
|
||||
} /* switch */
|
||||
} /* else */
|
||||
|
||||
cvt->len_cvt = clen;
|
||||
} /* Sound_RateSLOW */
|
||||
|
||||
|
||||
int Sound_ConvertAudio(Sound_AudioCVT *cvt)
|
||||
{
|
||||
Uint16 format;
|
||||
|
||||
/* Make sure there's data to convert */
|
||||
if (cvt->buf == NULL)
|
||||
{
|
||||
__Sound_SetError("No buffer allocated for conversion");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
/* Return okay if no conversion is necessary */
|
||||
cvt->len_cvt = cvt->len;
|
||||
if (cvt->filters[0] == NULL)
|
||||
return(0);
|
||||
|
||||
/* Set up the conversion and go! */
|
||||
format = cvt->src_format;
|
||||
for (cvt->filter_index = 0; cvt->filters[cvt->filter_index];
|
||||
cvt->filter_index++)
|
||||
{
|
||||
cvt->filters[cvt->filter_index](cvt, &format);
|
||||
}
|
||||
return(0);
|
||||
} /* Sound_ConvertAudio */
|
||||
|
||||
|
||||
/*
|
||||
* Creates a set of audio filters to convert from one format to another.
|
||||
* Returns -1 if the format conversion is not supported, or 1 if the
|
||||
* audio filter is set up.
|
||||
*/
|
||||
|
||||
int Sound_BuildAudioCVT(Sound_AudioCVT *cvt,
|
||||
Uint16 src_format, Uint8 src_channels, Uint32 src_rate,
|
||||
Uint16 dst_format, Uint8 dst_channels, Uint32 dst_rate,
|
||||
Uint32 dst_size)
|
||||
{
|
||||
/* Start off with no conversion necessary */
|
||||
cvt->needed = 0;
|
||||
cvt->filter_index = 0;
|
||||
cvt->filters[0] = NULL;
|
||||
cvt->len_mult = 1;
|
||||
cvt->len_ratio = 1.0;
|
||||
|
||||
/* First filter: Endian conversion from src to dst */
|
||||
if ((src_format & 0x1000) != (dst_format & 0x1000) &&
|
||||
((src_format & 0xff) != 8))
|
||||
{
|
||||
SNDDBG(("Adding filter: Sound_ConvertEndian\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_ConvertEndian;
|
||||
} /* if */
|
||||
|
||||
/* Second filter: Sign conversion -- signed/unsigned */
|
||||
if ((src_format & 0x8000) != (dst_format & 0x8000))
|
||||
{
|
||||
SNDDBG(("Adding filter: Sound_ConvertSign\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_ConvertSign;
|
||||
} /* if */
|
||||
|
||||
/* Next filter: Convert 16 bit <--> 8 bit PCM. */
|
||||
if ((src_format & 0xFF) != (dst_format & 0xFF))
|
||||
{
|
||||
switch (dst_format & 0x10FF)
|
||||
{
|
||||
case AUDIO_U8:
|
||||
SNDDBG(("Adding filter: Sound_Convert8\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_Convert8;
|
||||
cvt->len_ratio /= 2;
|
||||
break;
|
||||
|
||||
case AUDIO_U16LSB:
|
||||
SNDDBG(("Adding filter: Sound_Convert16LSB\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_Convert16LSB;
|
||||
cvt->len_mult *= 2;
|
||||
cvt->len_ratio *= 2;
|
||||
break;
|
||||
|
||||
case AUDIO_U16MSB:
|
||||
SNDDBG(("Adding filter: Sound_Convert16MSB\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_Convert16MSB;
|
||||
cvt->len_mult *= 2;
|
||||
cvt->len_ratio *= 2;
|
||||
break;
|
||||
} /* switch */
|
||||
} /* if */
|
||||
|
||||
/* Next filter: Mono/Stereo conversion */
|
||||
if (src_channels != dst_channels)
|
||||
{
|
||||
while ((src_channels * 2) <= dst_channels)
|
||||
{
|
||||
SNDDBG(("Adding filter: Sound_ConvertStereo\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_ConvertStereo;
|
||||
cvt->len_mult *= 2;
|
||||
src_channels *= 2;
|
||||
cvt->len_ratio *= 2;
|
||||
} /* while */
|
||||
|
||||
/* This assumes that 4 channel audio is in the format:
|
||||
* Left {front/back} + Right {front/back}
|
||||
* so converting to L/R stereo works properly.
|
||||
*/
|
||||
while (((src_channels % 2) == 0) &&
|
||||
((src_channels / 2) >= dst_channels))
|
||||
{
|
||||
SNDDBG(("Adding filter: Sound_ConvertMono\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_ConvertMono;
|
||||
src_channels /= 2;
|
||||
cvt->len_ratio /= 2;
|
||||
} /* while */
|
||||
|
||||
if ( src_channels != dst_channels ) {
|
||||
/* Uh oh.. */;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
/* Do rate conversion */
|
||||
cvt->rate_incr = 0.0;
|
||||
if ((src_rate / 100) != (dst_rate / 100))
|
||||
{
|
||||
Uint32 hi_rate, lo_rate;
|
||||
int len_mult;
|
||||
double len_ratio;
|
||||
void (*rate_cvt)(Sound_AudioCVT *cvt, Uint16 *format);
|
||||
|
||||
if (src_rate > dst_rate)
|
||||
{
|
||||
hi_rate = src_rate;
|
||||
lo_rate = dst_rate;
|
||||
SNDDBG(("Adding filter: Sound_RateDIV2\n"));
|
||||
rate_cvt = Sound_RateDIV2;
|
||||
len_mult = 1;
|
||||
len_ratio = 0.5;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
hi_rate = dst_rate;
|
||||
lo_rate = src_rate;
|
||||
SNDDBG(("Adding filter: Sound_RateMUL2\n"));
|
||||
rate_cvt = Sound_RateMUL2;
|
||||
len_mult = 2;
|
||||
len_ratio = 2.0;
|
||||
} /* else */
|
||||
|
||||
/* If hi_rate = lo_rate*2^x then conversion is easy */
|
||||
while (((lo_rate * 2) / 100) <= (hi_rate / 100))
|
||||
{
|
||||
cvt->filters[cvt->filter_index++] = rate_cvt;
|
||||
cvt->len_mult *= len_mult;
|
||||
lo_rate *= 2;
|
||||
cvt->len_ratio *= len_ratio;
|
||||
} /* while */
|
||||
|
||||
/* We may need a slow conversion here to finish up */
|
||||
if ((lo_rate / 100) != (hi_rate / 100))
|
||||
{
|
||||
if (src_rate < dst_rate)
|
||||
{
|
||||
cvt->rate_incr = (double) lo_rate / hi_rate;
|
||||
cvt->len_mult *= 2;
|
||||
cvt->len_ratio /= cvt->rate_incr;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
cvt->rate_incr = (double) hi_rate / lo_rate;
|
||||
cvt->len_ratio *= cvt->rate_incr;
|
||||
} /* else */
|
||||
SNDDBG(("Adding filter: Sound_RateSLOW\n"));
|
||||
cvt->filters[cvt->filter_index++] = Sound_RateSLOW;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
/* Set up the filter information */
|
||||
if (cvt->filter_index != 0)
|
||||
{
|
||||
cvt->needed = 1;
|
||||
cvt->src_format = src_format;
|
||||
cvt->dst_format = dst_format;
|
||||
cvt->len = 0;
|
||||
cvt->buf = NULL;
|
||||
cvt->filters[cvt->filter_index] = NULL;
|
||||
} /* if */
|
||||
|
||||
return(cvt->needed);
|
||||
} /* Sound_BuildAudioCVT */
|
||||
|
||||
#endif /* !SOUND_USE_ALTCVT */
|
||||
|
||||
/* end of audio_convert.c ... */
|
||||
|
||||
133
project/jni/sdl_sound/config.h
Normal file
133
project/jni/sdl_sound/config.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define for debug builds. */
|
||||
/* #undef DEBUG */
|
||||
|
||||
/* Define for debug build chattering. */
|
||||
#undef DEBUG_CHATTER
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `setbuf' function. */
|
||||
#define HAVE_SETBUF 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#define HAVE_STRRCHR 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to disable debugging. */
|
||||
/* #define NDEBUG */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "SDL_sound"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "SDL_sound"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "SDL_sound"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "SDL_sound 1.0.3"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "SDL_sound"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.0.3"
|
||||
|
||||
/* Define if modplug header is in own directory. */
|
||||
#undef SOUND_MODPLUG_IN_OWN_PATH
|
||||
|
||||
/* Define if AIFF support is desired. */
|
||||
#define SOUND_SUPPORTS_AIFF 1
|
||||
|
||||
/* Define if AU support is desired. */
|
||||
#define SOUND_SUPPORTS_AU 1
|
||||
|
||||
/* Define if FLAC support is desired. */
|
||||
#define SOUND_SUPPORTS_FLAC 1
|
||||
|
||||
/* Define if MIDI support is desired. */
|
||||
#undef SOUND_SUPPORTS_MIDI
|
||||
|
||||
/* Define if MIKMOD support is desired. */
|
||||
#define SOUND_SUPPORTS_MIKMOD 1
|
||||
|
||||
/* Define if MODPLUG support is desired. */
|
||||
#undef SOUND_SUPPORTS_MODPLUG
|
||||
|
||||
/* Define if MPGLIB support is desired. */
|
||||
#define SOUND_SUPPORTS_MPGLIB 1
|
||||
|
||||
/* Define if OGG support is desired. */
|
||||
#define SOUND_SUPPORTS_OGG 1
|
||||
|
||||
/* Define if RAW support is desired. */
|
||||
#undef SOUND_SUPPORTS_RAW
|
||||
|
||||
/* Define if SHN support is desired. */
|
||||
#define SOUND_SUPPORTS_SHN 1
|
||||
|
||||
/* Define if SMPEG support is desired. */
|
||||
#undef SOUND_SUPPORTS_SMPEG
|
||||
|
||||
/* Define if SPEEX support is desired. */
|
||||
#undef SOUND_SUPPORTS_SPEEX
|
||||
|
||||
/* Define if VOC support is desired. */
|
||||
#define SOUND_SUPPORTS_VOC 1
|
||||
|
||||
/* Define if WAV support is desired. */
|
||||
#define SOUND_SUPPORTS_WAV 1
|
||||
|
||||
/* Define to use alternate audio converter. */
|
||||
#undef SOUND_USE_ALTCVT
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0.3"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/*#undef const*/
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/*#undef size_t*/
|
||||
22
project/jni/sdl_sound/decoders/Makefile.am
Normal file
22
project/jni/sdl_sound/decoders/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
noinst_LTLIBRARIES = libdecoders.la
|
||||
|
||||
SUBDIRS = timidity mpglib
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/decoders/timidity
|
||||
|
||||
libdecoders_la_SOURCES = \
|
||||
aiff.c \
|
||||
au.c \
|
||||
mikmod.c \
|
||||
modplug.c \
|
||||
mpglib.c \
|
||||
smpeg.c \
|
||||
ogg.c \
|
||||
raw.c \
|
||||
shn.c \
|
||||
voc.c \
|
||||
midi.c \
|
||||
flac.c \
|
||||
speex.c \
|
||||
quicktime.c \
|
||||
wav.c
|
||||
593
project/jni/sdl_sound/decoders/Makefile.in
Normal file
593
project/jni/sdl_sound/decoders/Makefile.in
Normal file
@@ -0,0 +1,593 @@
|
||||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = decoders
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libdecoders_la_LIBADD =
|
||||
am_libdecoders_la_OBJECTS = aiff.lo au.lo mikmod.lo modplug.lo \
|
||||
mpglib.lo smpeg.lo ogg.lo raw.lo shn.lo voc.lo midi.lo flac.lo \
|
||||
speex.lo quicktime.lo wav.lo
|
||||
libdecoders_la_OBJECTS = $(am_libdecoders_la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(libdecoders_la_SOURCES)
|
||||
DIST_SOURCES = $(libdecoders_la_SOURCES)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-exec-recursive install-info-recursive \
|
||||
install-recursive installcheck-recursive installdirs-recursive \
|
||||
pdf-recursive ps-recursive uninstall-info-recursive \
|
||||
uninstall-recursive
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BINARY_AGE = @BINARY_AGE@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INTERFACE_AGE = @INTERFACE_AGE@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_AGE = @LT_AGE@
|
||||
LT_CURRENT = @LT_CURRENT@
|
||||
LT_RELEASE = @LT_RELEASE@
|
||||
LT_REVISION = @LT_REVISION@
|
||||
MAJOR_VERSION = @MAJOR_VERSION@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MICRO_VERSION = @MICRO_VERSION@
|
||||
MINOR_VERSION = @MINOR_VERSION@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
USE_MPGLIB_FALSE = @USE_MPGLIB_FALSE@
|
||||
USE_MPGLIB_TRUE = @USE_MPGLIB_TRUE@
|
||||
USE_PHYSICSFS_FALSE = @USE_PHYSICSFS_FALSE@
|
||||
USE_PHYSICSFS_TRUE = @USE_PHYSICSFS_TRUE@
|
||||
USE_TIMIDITY_FALSE = @USE_TIMIDITY_FALSE@
|
||||
USE_TIMIDITY_TRUE = @USE_TIMIDITY_TRUE@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
noinst_LTLIBRARIES = libdecoders.la
|
||||
SUBDIRS = timidity mpglib
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/decoders/timidity
|
||||
libdecoders_la_SOURCES = \
|
||||
aiff.c \
|
||||
au.c \
|
||||
mikmod.c \
|
||||
modplug.c \
|
||||
mpglib.c \
|
||||
smpeg.c \
|
||||
ogg.c \
|
||||
raw.c \
|
||||
shn.c \
|
||||
voc.c \
|
||||
midi.c \
|
||||
flac.c \
|
||||
speex.c \
|
||||
quicktime.c \
|
||||
wav.c
|
||||
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign decoders/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign decoders/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libdecoders.la: $(libdecoders_la_OBJECTS) $(libdecoders_la_DEPENDENCIES)
|
||||
$(LINK) $(libdecoders_la_LDFLAGS) $(libdecoders_la_OBJECTS) $(libdecoders_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aiff.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/au.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flac.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mikmod.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modplug.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpglib.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ogg.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quicktime.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shn.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smpeg.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speex.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/voc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wav.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(mkdir_p) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||
(cd $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$top_distdir" \
|
||||
distdir="$$distdir/$$subdir" \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile $(LTLIBRARIES)
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
uninstall-info: uninstall-info-recursive
|
||||
|
||||
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
|
||||
clean clean-generic clean-libtool clean-noinstLTLIBRARIES \
|
||||
clean-recursive ctags ctags-recursive distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-recursive distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-exec install-exec-am install-info \
|
||||
install-info-am install-man install-strip installcheck \
|
||||
installcheck-am installdirs installdirs-am maintainer-clean \
|
||||
maintainer-clean-generic maintainer-clean-recursive \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
|
||||
tags tags-recursive uninstall uninstall-am uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
569
project/jni/sdl_sound/decoders/aiff.c
Normal file
569
project/jni/sdl_sound/decoders/aiff.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* AIFF decoder for SDL_sound
|
||||
*
|
||||
* [Insert something profound about the AIFF file format here.]
|
||||
*
|
||||
* This code was ripped from a decoder I had written for SDL_mixer, which was
|
||||
* based on SDL_mixer's old AIFF music loader. (This loader was unfortunately
|
||||
* completely broken, but it was still useful because all the pieces were
|
||||
* still there, so to speak.)
|
||||
*
|
||||
* When rewriting it for SDL_sound, I changed its structure to be more like
|
||||
* the WAV loader Ryan wrote. Had they not both been part of the same project
|
||||
* it would have been embarrassing how similar they are.
|
||||
*
|
||||
* It is not the most feature-complete AIFF loader the world has ever seen.
|
||||
* For instance, it only makes a token attempt at implementing the AIFF-C
|
||||
* standard; basically the parts of it that I can easily understand and test.
|
||||
* It's a start, though.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file was written by Torbjörn Andersson. (d91tan@Update.UU.SE)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_AIFF
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static Uint32 SANE_to_Uint32 (Uint8 *sanebuf);
|
||||
|
||||
|
||||
static int AIFF_init(void);
|
||||
static void AIFF_quit(void);
|
||||
static int AIFF_open(Sound_Sample *sample, const char *ext);
|
||||
static void AIFF_close(Sound_Sample *sample);
|
||||
static Uint32 AIFF_read(Sound_Sample *sample);
|
||||
static int AIFF_rewind(Sound_Sample *sample);
|
||||
static int AIFF_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_aiff[] = { "AIFF", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_AIFF =
|
||||
{
|
||||
{
|
||||
extensions_aiff,
|
||||
"Audio Interchange File Format",
|
||||
"Torbjörn Andersson <d91tan@Update.UU.SE>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
AIFF_init, /* init() method */
|
||||
AIFF_quit, /* quit() method */
|
||||
AIFF_open, /* open() method */
|
||||
AIFF_close, /* close() method */
|
||||
AIFF_read, /* read() method */
|
||||
AIFF_rewind, /* rewind() method */
|
||||
AIFF_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* aiff_t is what we store in our internal->decoder_private field... *
|
||||
*****************************************************************************/
|
||||
typedef struct S_AIFF_FMT_T
|
||||
{
|
||||
Uint32 type;
|
||||
|
||||
Uint32 total_bytes;
|
||||
Uint32 data_starting_offset;
|
||||
|
||||
void (*free)(struct S_AIFF_FMT_T *fmt);
|
||||
Uint32 (*read_sample)(Sound_Sample *sample);
|
||||
int (*rewind_sample)(Sound_Sample *sample);
|
||||
int (*seek_sample)(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
this is ripped from wav.c as ann example of format-specific data.
|
||||
please replace with something more appropriate when the need arises.
|
||||
*/
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
Uint16 cbSize;
|
||||
Uint16 wSamplesPerBlock;
|
||||
Uint16 wNumCoef;
|
||||
ADPCMCOEFSET *aCoeff;
|
||||
} adpcm;
|
||||
|
||||
/* put other format-specific data here... */
|
||||
} fmt;
|
||||
#endif
|
||||
} fmt_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fmt_t fmt;
|
||||
Sint32 bytesLeft;
|
||||
} aiff_t;
|
||||
|
||||
|
||||
|
||||
/* Chunk management code... */
|
||||
|
||||
#define formID 0x4D524F46 /* "FORM", in ascii. */
|
||||
#define aiffID 0x46464941 /* "AIFF", in ascii. */
|
||||
#define aifcID 0x43464941 /* "AIFC", in ascii. */
|
||||
#define ssndID 0x444E5353 /* "SSND", in ascii. */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The COMM chunk... *
|
||||
*****************************************************************************/
|
||||
|
||||
#define commID 0x4D4D4F43 /* "COMM", in ascii. */
|
||||
|
||||
/* format/compression types... */
|
||||
#define noneID 0x454E4F4E /* "NONE", in ascii. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint32 ckID;
|
||||
Uint32 ckDataSize;
|
||||
Uint16 numChannels;
|
||||
Uint32 numSampleFrames;
|
||||
Uint16 sampleSize;
|
||||
Uint32 sampleRate;
|
||||
/*
|
||||
* We don't handle AIFF-C compressed audio yet, but for those
|
||||
* interested the allowed compression types are supposed to be
|
||||
*
|
||||
* compressionType compressionName meaning
|
||||
* ---------------------------------------------------------------
|
||||
* 'NONE' "not compressed" uncompressed, that is,
|
||||
* straight digitized samples
|
||||
* 'ACE2' "ACE 2-to-1" 2-to-1 IIGS ACE (Audio
|
||||
* Compression / Expansion)
|
||||
* 'ACE8' "ACE 8-to-3" 8-to-3 IIGS ACE (Audio
|
||||
* Compression / Expansion)
|
||||
* 'MAC3' "MACE 3-to-1" 3-to-1 Macintosh Audio
|
||||
* Compression / Expansion
|
||||
* 'MAC6' "MACE 6-to-1" 6-to-1 Macintosh Audio
|
||||
* Compression / Expansion
|
||||
*
|
||||
* A pstring is a "Pascal-style string", that is, "one byte followed
|
||||
* by test bytes followed when needed by one pad byte. The total
|
||||
* number of bytes in a pstring must be even. The pad byte is
|
||||
* included when the number of text bytes is even, so the total of
|
||||
* text bytes + one count byte + one pad byte will be even. This pad
|
||||
* byte is not reflected in the count."
|
||||
*
|
||||
* As for how these compression algorithms work, your guess is as
|
||||
* good as mine.
|
||||
*/
|
||||
Uint32 compressionType;
|
||||
#if 0
|
||||
pstring compressionName;
|
||||
#endif
|
||||
} comm_t;
|
||||
|
||||
|
||||
/*
|
||||
* Read in a comm_t from disk. This makes this process safe regardless of
|
||||
* the processor's byte order or how the comm_t structure is packed.
|
||||
*/
|
||||
|
||||
static int read_comm_chunk(SDL_RWops *rw, comm_t *comm)
|
||||
{
|
||||
Uint8 sampleRate[10];
|
||||
|
||||
/* skip reading the chunk ID, since it was already read at this point... */
|
||||
comm->ckID = commID;
|
||||
|
||||
if (SDL_RWread(rw, &comm->ckDataSize, sizeof (comm->ckDataSize), 1) != 1)
|
||||
return(0);
|
||||
comm->ckDataSize = SDL_SwapBE32(comm->ckDataSize);
|
||||
|
||||
if (SDL_RWread(rw, &comm->numChannels, sizeof (comm->numChannels), 1) != 1)
|
||||
return(0);
|
||||
comm->numChannels = SDL_SwapBE16(comm->numChannels);
|
||||
|
||||
if (SDL_RWread(rw, &comm->numSampleFrames,
|
||||
sizeof (comm->numSampleFrames), 1) != 1)
|
||||
return(0);
|
||||
comm->numSampleFrames = SDL_SwapBE32(comm->numSampleFrames);
|
||||
|
||||
if (SDL_RWread(rw, &comm->sampleSize, sizeof (comm->sampleSize), 1) != 1)
|
||||
return(0);
|
||||
comm->sampleSize = SDL_SwapBE16(comm->sampleSize);
|
||||
|
||||
if (SDL_RWread(rw, sampleRate, sizeof (sampleRate), 1) != 1)
|
||||
return(0);
|
||||
comm->sampleRate = SANE_to_Uint32(sampleRate);
|
||||
|
||||
if (comm->ckDataSize > sizeof(comm->numChannels)
|
||||
+ sizeof(comm->numSampleFrames)
|
||||
+ sizeof(comm->sampleSize)
|
||||
+ sizeof(sampleRate))
|
||||
{
|
||||
if (SDL_RWread(rw, &comm->compressionType,
|
||||
sizeof (comm->compressionType), 1) != 1)
|
||||
return(0);
|
||||
comm->compressionType = SDL_SwapBE32(comm->compressionType);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
comm->compressionType = noneID;
|
||||
} /* else */
|
||||
|
||||
return(1);
|
||||
} /* read_comm_chunk */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The SSND chunk... *
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint32 ckID;
|
||||
Uint32 ckDataSize;
|
||||
Uint32 offset;
|
||||
Uint32 blockSize;
|
||||
/*
|
||||
* Then, comm->numSampleFrames sample frames. (It's better to get the
|
||||
* length from numSampleFrames than from ckDataSize.)
|
||||
*/
|
||||
} ssnd_t;
|
||||
|
||||
|
||||
static int read_ssnd_chunk(SDL_RWops *rw, ssnd_t *ssnd)
|
||||
{
|
||||
/* skip reading the chunk ID, since it was already read at this point... */
|
||||
ssnd->ckID = ssndID;
|
||||
|
||||
if (SDL_RWread(rw, &ssnd->ckDataSize, sizeof (ssnd->ckDataSize), 1) != 1)
|
||||
return(0);
|
||||
ssnd->ckDataSize = SDL_SwapBE32(ssnd->ckDataSize);
|
||||
|
||||
if (SDL_RWread(rw, &ssnd->offset, sizeof (ssnd->offset), 1) != 1)
|
||||
return(0);
|
||||
ssnd->offset = SDL_SwapBE32(ssnd->offset);
|
||||
|
||||
if (SDL_RWread(rw, &ssnd->blockSize, sizeof (ssnd->blockSize), 1) != 1)
|
||||
return(0);
|
||||
ssnd->blockSize = SDL_SwapBE32(ssnd->blockSize);
|
||||
|
||||
/* Leave the SDL_RWops position indicator at the start of the samples */
|
||||
if (SDL_RWseek(rw, (int) ssnd->offset, SEEK_CUR) == -1)
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
} /* read_ssnd_chunk */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Normal, uncompressed aiff handler... *
|
||||
*****************************************************************************/
|
||||
|
||||
static Uint32 read_sample_fmt_normal(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
Uint32 max = (internal->buffer_size < (Uint32) a->bytesLeft) ?
|
||||
internal->buffer_size : (Uint32) a->bytesLeft;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/*
|
||||
* We don't actually do any decoding, so we read the AIFF data
|
||||
* directly into the internal buffer...
|
||||
*/
|
||||
retval = SDL_RWread(internal->rw, internal->buffer, 1, max);
|
||||
|
||||
a->bytesLeft -= retval;
|
||||
|
||||
/* Make sure the read went smoothly... */
|
||||
if ((retval == 0) || (a->bytesLeft == 0))
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
else if (retval == -1)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
|
||||
/* (next call this EAGAIN may turn into an EOF or error.) */
|
||||
else if (retval < internal->buffer_size)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
|
||||
return(retval);
|
||||
} /* read_sample_fmt_normal */
|
||||
|
||||
|
||||
static int rewind_sample_fmt_normal(Sound_Sample *sample)
|
||||
{
|
||||
/* no-op. */
|
||||
return(1);
|
||||
} /* rewind_sample_fmt_normal */
|
||||
|
||||
|
||||
static int seek_sample_fmt_normal(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
fmt_t *fmt = &a->fmt;
|
||||
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int pos = (int) (fmt->data_starting_offset + offset);
|
||||
int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
|
||||
a->bytesLeft = fmt->total_bytes - offset;
|
||||
return(1); /* success. */
|
||||
} /* seek_sample_fmt_normal */
|
||||
|
||||
|
||||
static void free_fmt_normal(fmt_t *fmt)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* free_fmt_normal */
|
||||
|
||||
|
||||
static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
|
||||
{
|
||||
/* (don't need to read more from the RWops...) */
|
||||
fmt->free = free_fmt_normal;
|
||||
fmt->read_sample = read_sample_fmt_normal;
|
||||
fmt->rewind_sample = rewind_sample_fmt_normal;
|
||||
fmt->seek_sample = seek_sample_fmt_normal;
|
||||
return(1);
|
||||
} /* read_fmt_normal */
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Everything else... *
|
||||
*****************************************************************************/
|
||||
|
||||
static int AIFF_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* AIFF_init */
|
||||
|
||||
|
||||
static void AIFF_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* AIFF_quit */
|
||||
|
||||
|
||||
/*
|
||||
* Sample rate is encoded as an "80 bit IEEE Standard 754 floating point
|
||||
* number (Standard Apple Numeric Environment [SANE] data type Extended)".
|
||||
* Whose bright idea was that?
|
||||
*
|
||||
* This function was adapted from libsndfile, and while I do know a little
|
||||
* bit about the IEEE floating point standard I don't pretend to fully
|
||||
* understand this.
|
||||
*/
|
||||
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]);
|
||||
} /* SANE_to_Uint32 */
|
||||
|
||||
|
||||
static int find_chunk(SDL_RWops *rw, Uint32 id)
|
||||
{
|
||||
Sint32 siz = 0;
|
||||
Uint32 _id = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
BAIL_IF_MACRO(SDL_RWread(rw, &_id, sizeof (_id), 1) != 1, NULL, 0);
|
||||
if (SDL_SwapLE32(_id) == id)
|
||||
return(1);
|
||||
|
||||
BAIL_IF_MACRO(SDL_RWread(rw, &siz, sizeof (siz), 1) != 1, NULL, 0);
|
||||
siz = SDL_SwapBE32(siz);
|
||||
assert(siz > 0);
|
||||
BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_CUR) == -1, NULL, 0);
|
||||
} /* while */
|
||||
|
||||
return(0); /* shouldn't hit this, but just in case... */
|
||||
} /* find_chunk */
|
||||
|
||||
|
||||
static int read_fmt(SDL_RWops *rw, comm_t *c, fmt_t *fmt)
|
||||
{
|
||||
fmt->type = c->compressionType;
|
||||
|
||||
/* if it's in this switch statement, we support the format. */
|
||||
switch (fmt->type)
|
||||
{
|
||||
case noneID:
|
||||
SNDDBG(("AIFF: Appears to be uncompressed audio.\n"));
|
||||
return(read_fmt_normal(rw, fmt));
|
||||
|
||||
/* add other types here. */
|
||||
|
||||
default:
|
||||
SNDDBG(("AIFF: Format %lu is unknown.\n",
|
||||
(unsigned int) fmt->type));
|
||||
BAIL_MACRO("AIFF: Unsupported format", 0);
|
||||
} /* switch */
|
||||
|
||||
assert(0); /* shouldn't hit this point. */
|
||||
return(0);
|
||||
} /* read_fmt */
|
||||
|
||||
|
||||
static int AIFF_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
Uint32 chunk_id;
|
||||
int bytes_per_sample;
|
||||
long pos;
|
||||
comm_t c;
|
||||
ssnd_t s;
|
||||
aiff_t *a;
|
||||
|
||||
BAIL_IF_MACRO(SDL_ReadLE32(rw) != formID, "AIFF: Not a FORM file.", 0);
|
||||
SDL_ReadBE32(rw); /* throw the length away; we don't need it. */
|
||||
|
||||
chunk_id = SDL_ReadLE32(rw);
|
||||
BAIL_IF_MACRO(chunk_id != aiffID && chunk_id != aifcID,
|
||||
"AIFF: Not an AIFF or AIFC file.", 0);
|
||||
|
||||
/* Chunks may appear in any order, so we establish base camp here. */
|
||||
pos = SDL_RWtell(rw);
|
||||
|
||||
BAIL_IF_MACRO(!find_chunk(rw, commID), "AIFF: No common chunk.", 0);
|
||||
BAIL_IF_MACRO(!read_comm_chunk(rw, &c),
|
||||
"AIFF: Can't read common chunk.", 0);
|
||||
|
||||
sample->actual.channels = (Uint8) c.numChannels;
|
||||
sample->actual.rate = c.sampleRate;
|
||||
|
||||
if (c.sampleSize <= 8)
|
||||
{
|
||||
sample->actual.format = AUDIO_S8;
|
||||
bytes_per_sample = c.numChannels;
|
||||
} /* if */
|
||||
else if (c.sampleSize <= 16)
|
||||
{
|
||||
sample->actual.format = AUDIO_S16MSB;
|
||||
bytes_per_sample = 2 * c.numChannels;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
BAIL_MACRO("AIFF: Unsupported sample size.", 0);
|
||||
} /* else */
|
||||
|
||||
BAIL_IF_MACRO(c.sampleRate == 0, "AIFF: Unsupported sample rate.", 0);
|
||||
|
||||
a = (aiff_t *) malloc(sizeof(aiff_t));
|
||||
BAIL_IF_MACRO(a == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
if (!read_fmt(rw, &c, &(a->fmt)))
|
||||
{
|
||||
free(a);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
SDL_RWseek(rw, pos, SEEK_SET); /* if the seek fails, let it go... */
|
||||
|
||||
if (!find_chunk(rw, ssndID))
|
||||
{
|
||||
free(a);
|
||||
BAIL_MACRO("AIFF: No sound data chunk.", 0);
|
||||
} /* if */
|
||||
|
||||
if (!read_ssnd_chunk(rw, &s))
|
||||
{
|
||||
free(a);
|
||||
BAIL_MACRO("AIFF: Can't read sound data chunk.", 0);
|
||||
} /* if */
|
||||
|
||||
a->fmt.total_bytes = a->bytesLeft = bytes_per_sample * c.numSampleFrames;
|
||||
a->fmt.data_starting_offset = SDL_RWtell(rw);
|
||||
internal->decoder_private = (void *) a;
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
|
||||
SNDDBG(("AIFF: Accepting data stream.\n"));
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* AIFF_open */
|
||||
|
||||
|
||||
static void AIFF_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
a->fmt.free(&(a->fmt));
|
||||
free(a);
|
||||
} /* AIFF_close */
|
||||
|
||||
|
||||
static Uint32 AIFF_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
return(a->fmt.read_sample(sample));
|
||||
} /* AIFF_read */
|
||||
|
||||
|
||||
static int AIFF_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
fmt_t *fmt = &a->fmt;
|
||||
int rc = SDL_RWseek(internal->rw, fmt->data_starting_offset, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != fmt->data_starting_offset, ERR_IO_ERROR, 0);
|
||||
a->bytesLeft = fmt->total_bytes;
|
||||
return(fmt->rewind_sample(sample));
|
||||
} /* AIFF_rewind */
|
||||
|
||||
|
||||
static int AIFF_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
aiff_t *a = (aiff_t *) internal->decoder_private;
|
||||
return(a->fmt.seek_sample(sample, ms));
|
||||
} /* AIFF_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_AIFF */
|
||||
|
||||
/* end of aiff.c ... */
|
||||
|
||||
376
project/jni/sdl_sound/decoders/au.c
Normal file
376
project/jni/sdl_sound/decoders/au.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sun/NeXT .au decoder for SDL_sound.
|
||||
* Formats supported: 8 and 16 bit linear PCM, 8 bit µ-law.
|
||||
* Files without valid header are assumed to be 8 bit µ-law, 8kHz, mono.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Mattias Engdegård. (f91-men@nada.kth.se)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_AU
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int AU_init(void);
|
||||
static void AU_quit(void);
|
||||
static int AU_open(Sound_Sample *sample, const char *ext);
|
||||
static void AU_close(Sound_Sample *sample);
|
||||
static Uint32 AU_read(Sound_Sample *sample);
|
||||
static int AU_rewind(Sound_Sample *sample);
|
||||
static int AU_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
/*
|
||||
* Sometimes the extension ".snd" is used for these files (mostly on the NeXT),
|
||||
* and the magic number comes from this. However it may clash with other
|
||||
* formats and is somewhat of an anachronism, so only .au is used here.
|
||||
*/
|
||||
static const char *extensions_au[] = { "AU", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_AU =
|
||||
{
|
||||
{
|
||||
extensions_au,
|
||||
"Sun/NeXT audio file format",
|
||||
"Mattias Engdegård <f91-men@nada.kth.se>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
AU_init, /* init() method */
|
||||
AU_quit, /* quit() method */
|
||||
AU_open, /* open() method */
|
||||
AU_close, /* close() method */
|
||||
AU_read, /* read() method */
|
||||
AU_rewind, /* rewind() method */
|
||||
AU_seek /* seek() method */
|
||||
};
|
||||
|
||||
/* no init/deinit needed */
|
||||
static int AU_init(void)
|
||||
{
|
||||
return(1);
|
||||
} /* AU_init */
|
||||
|
||||
static void AU_quit(void)
|
||||
{
|
||||
/* no-op. */
|
||||
} /* AU_quit */
|
||||
|
||||
struct au_file_hdr
|
||||
{
|
||||
Uint32 magic;
|
||||
Uint32 hdr_size;
|
||||
Uint32 data_size;
|
||||
Uint32 encoding;
|
||||
Uint32 sample_rate;
|
||||
Uint32 channels;
|
||||
};
|
||||
|
||||
#define HDR_SIZE 24
|
||||
|
||||
enum
|
||||
{
|
||||
AU_ENC_ULAW_8 = 1, /* 8-bit ISDN µ-law */
|
||||
AU_ENC_LINEAR_8 = 2, /* 8-bit linear PCM */
|
||||
AU_ENC_LINEAR_16 = 3, /* 16-bit linear PCM */
|
||||
|
||||
/* the rest are unsupported (I have never seen them in the wild) */
|
||||
AU_ENC_LINEAR_24 = 4, /* 24-bit linear PCM */
|
||||
AU_ENC_LINEAR_32 = 5, /* 32-bit linear PCM */
|
||||
AU_ENC_FLOAT = 6, /* 32-bit IEEE floating point */
|
||||
AU_ENC_DOUBLE = 7, /* 64-bit IEEE floating point */
|
||||
/* more Sun formats, not supported either */
|
||||
AU_ENC_ADPCM_G721 = 23,
|
||||
AU_ENC_ADPCM_G722 = 24,
|
||||
AU_ENC_ADPCM_G723_3 = 25,
|
||||
AU_ENC_ADPCM_G723_5 = 26,
|
||||
AU_ENC_ALAW_8 = 27
|
||||
};
|
||||
|
||||
struct audec
|
||||
{
|
||||
Uint32 total;
|
||||
Uint32 remaining;
|
||||
Uint32 start_offset;
|
||||
int encoding;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Read in the AU header from disk. This makes this process safe
|
||||
* regardless of the processor's byte order or how the au_file_hdr
|
||||
* structure is packed.
|
||||
*/
|
||||
static int read_au_header(SDL_RWops *rw, struct au_file_hdr *hdr)
|
||||
{
|
||||
if (SDL_RWread(rw, &hdr->magic, sizeof (hdr->magic), 1) != 1)
|
||||
return(0);
|
||||
hdr->magic = SDL_SwapBE32(hdr->magic);
|
||||
|
||||
if (SDL_RWread(rw, &hdr->hdr_size, sizeof (hdr->hdr_size), 1) != 1)
|
||||
return(0);
|
||||
hdr->hdr_size = SDL_SwapBE32(hdr->hdr_size);
|
||||
|
||||
if (SDL_RWread(rw, &hdr->data_size, sizeof (hdr->data_size), 1) != 1)
|
||||
return(0);
|
||||
hdr->data_size = SDL_SwapBE32(hdr->data_size);
|
||||
|
||||
if (SDL_RWread(rw, &hdr->encoding, sizeof (hdr->encoding), 1) != 1)
|
||||
return(0);
|
||||
hdr->encoding = SDL_SwapBE32(hdr->encoding);
|
||||
|
||||
if (SDL_RWread(rw, &hdr->sample_rate, sizeof (hdr->sample_rate), 1) != 1)
|
||||
return(0);
|
||||
hdr->sample_rate = SDL_SwapBE32(hdr->sample_rate);
|
||||
|
||||
if (SDL_RWread(rw, &hdr->channels, sizeof (hdr->channels), 1) != 1)
|
||||
return(0);
|
||||
hdr->channels = SDL_SwapBE32(hdr->channels);
|
||||
|
||||
return(1);
|
||||
} /* read_au_header */
|
||||
|
||||
|
||||
#define AU_MAGIC 0x2E736E64 /* ".snd", in ASCII (bigendian number) */
|
||||
|
||||
static int AU_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
int skip, hsize, i;
|
||||
struct au_file_hdr hdr;
|
||||
struct audec *dec;
|
||||
char c;
|
||||
|
||||
/* read_au_header() will do byte order swapping. */
|
||||
BAIL_IF_MACRO(!read_au_header(rw, &hdr), "AU: bad header", 0);
|
||||
|
||||
dec = malloc(sizeof *dec);
|
||||
BAIL_IF_MACRO(dec == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
internal->decoder_private = dec;
|
||||
|
||||
if (hdr.magic == AU_MAGIC)
|
||||
{
|
||||
/* valid magic */
|
||||
dec->encoding = hdr.encoding;
|
||||
switch(dec->encoding)
|
||||
{
|
||||
case AU_ENC_ULAW_8:
|
||||
/* Convert 8-bit µ-law to 16-bit linear on the fly. This is
|
||||
slightly wasteful if the audio driver must convert them
|
||||
back, but µ-law only devices are rare (mostly _old_ Suns) */
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
break;
|
||||
|
||||
case AU_ENC_LINEAR_8:
|
||||
sample->actual.format = AUDIO_S8;
|
||||
break;
|
||||
|
||||
case AU_ENC_LINEAR_16:
|
||||
sample->actual.format = AUDIO_S16MSB;
|
||||
break;
|
||||
|
||||
default:
|
||||
free(dec);
|
||||
BAIL_MACRO("AU: Unsupported .au encoding", 0);
|
||||
} /* switch */
|
||||
|
||||
sample->actual.rate = hdr.sample_rate;
|
||||
sample->actual.channels = hdr.channels;
|
||||
dec->remaining = hdr.data_size;
|
||||
hsize = hdr.hdr_size;
|
||||
|
||||
/* skip remaining part of header (input may be unseekable) */
|
||||
for (i = HDR_SIZE; i < hsize; i++)
|
||||
{
|
||||
if (SDL_RWread(rw, &c, 1, 1) != 1)
|
||||
{
|
||||
free(dec);
|
||||
BAIL_MACRO(ERR_IO_ERROR, 0);
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* if */
|
||||
|
||||
else if (__Sound_strcasecmp(ext, "au") == 0)
|
||||
{
|
||||
/*
|
||||
* A number of files in the wild have the .au extension but no valid
|
||||
* header; these are traditionally assumed to be 8kHz µ-law. Handle
|
||||
* them here only if the extension is recognized.
|
||||
*/
|
||||
|
||||
SNDDBG(("AU: Invalid header, assuming raw 8kHz µ-law.\n"));
|
||||
/* if seeking fails, we lose 24 samples. big deal */
|
||||
SDL_RWseek(rw, -HDR_SIZE, SEEK_CUR);
|
||||
dec->encoding = AU_ENC_ULAW_8;
|
||||
dec->remaining = (Uint32)-1; /* no limit */
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
sample->actual.rate = 8000;
|
||||
sample->actual.channels = 1;
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
free(dec);
|
||||
BAIL_MACRO("AU: Not an .AU stream.", 0);
|
||||
} /* else */
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
dec->total = dec->remaining;
|
||||
dec->start_offset = SDL_RWtell(rw);
|
||||
|
||||
SNDDBG(("AU: Accepting data stream.\n"));
|
||||
return(1);
|
||||
} /* AU_open */
|
||||
|
||||
|
||||
static void AU_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = sample->opaque;
|
||||
free(internal->decoder_private);
|
||||
} /* AU_close */
|
||||
|
||||
|
||||
/* table to convert from µ-law encoding to signed 16-bit samples,
|
||||
generated by a throwaway perl script */
|
||||
static Sint16 ulaw_to_linear[256] = {
|
||||
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
|
||||
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
|
||||
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
|
||||
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
|
||||
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
|
||||
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
|
||||
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
|
||||
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
|
||||
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
|
||||
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
|
||||
-876, -844, -812, -780, -748, -716, -684, -652,
|
||||
-620, -588, -556, -524, -492, -460, -428, -396,
|
||||
-372, -356, -340, -324, -308, -292, -276, -260,
|
||||
-244, -228, -212, -196, -180, -164, -148, -132,
|
||||
-120, -112, -104, -96, -88, -80, -72, -64,
|
||||
-56, -48, -40, -32, -24, -16, -8, 0,
|
||||
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
|
||||
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
|
||||
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
|
||||
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
|
||||
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
|
||||
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
|
||||
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
|
||||
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
|
||||
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
|
||||
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
|
||||
876, 844, 812, 780, 748, 716, 684, 652,
|
||||
620, 588, 556, 524, 492, 460, 428, 396,
|
||||
372, 356, 340, 324, 308, 292, 276, 260,
|
||||
244, 228, 212, 196, 180, 164, 148, 132,
|
||||
120, 112, 104, 96, 88, 80, 72, 64,
|
||||
56, 48, 40, 32, 24, 16, 8, 0
|
||||
};
|
||||
|
||||
|
||||
static Uint32 AU_read(Sound_Sample *sample)
|
||||
{
|
||||
int ret;
|
||||
Sound_SampleInternal *internal = sample->opaque;
|
||||
struct audec *dec = internal->decoder_private;
|
||||
int maxlen;
|
||||
Uint8 *buf;
|
||||
|
||||
maxlen = internal->buffer_size;
|
||||
buf = internal->buffer;
|
||||
if (dec->encoding == AU_ENC_ULAW_8)
|
||||
{
|
||||
/* We read µ-law samples into the second half of the buffer, so
|
||||
we can expand them to 16-bit samples afterwards */
|
||||
maxlen >>= 1;
|
||||
buf += maxlen;
|
||||
} /* if */
|
||||
|
||||
if (maxlen > dec->remaining)
|
||||
maxlen = dec->remaining;
|
||||
ret = SDL_RWread(internal->rw, buf, 1, maxlen);
|
||||
if (ret == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
else if (ret == -1)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
else
|
||||
{
|
||||
dec->remaining -= ret;
|
||||
if (ret < maxlen)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
|
||||
if (dec->encoding == AU_ENC_ULAW_8)
|
||||
{
|
||||
int i;
|
||||
Sint16 *dst = internal->buffer;
|
||||
for (i = 0; i < ret; i++)
|
||||
dst[i] = ulaw_to_linear[buf[i]];
|
||||
ret <<= 1; /* return twice as much as read */
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
return(ret);
|
||||
} /* AU_read */
|
||||
|
||||
|
||||
static int AU_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
struct audec *dec = (struct audec *) internal->decoder_private;
|
||||
int rc = SDL_RWseek(internal->rw, dec->start_offset, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != dec->start_offset, ERR_IO_ERROR, 0);
|
||||
dec->remaining = dec->total;
|
||||
return(1);
|
||||
} /* AU_rewind */
|
||||
|
||||
|
||||
static int AU_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
struct audec *dec = (struct audec *) internal->decoder_private;
|
||||
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int rc;
|
||||
int pos;
|
||||
|
||||
if (dec->encoding == AU_ENC_ULAW_8)
|
||||
offset >>= 1; /* halve the byte offset for compression. */
|
||||
|
||||
pos = (int) (dec->start_offset + offset);
|
||||
rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
|
||||
dec->remaining = dec->total - offset;
|
||||
return(1);
|
||||
} /* AU_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_AU */
|
||||
|
||||
566
project/jni/sdl_sound/decoders/flac.c
Normal file
566
project/jni/sdl_sound/decoders/flac.c
Normal file
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* FLAC decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles FLAC audio, that is to say the Free Lossless Audio
|
||||
* Codec. It depends on libFLAC for decoding, which can be grabbed from:
|
||||
* http://flac.sourceforge.net
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Torbjörn Andersson. (d91tan@Update.UU.SE)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_FLAC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include <FLAC/export.h>
|
||||
|
||||
/* FLAC 1.1.3 has FLAC_API_VERSION_CURRENT == 8 */
|
||||
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8
|
||||
#define LEGACY_FLAC
|
||||
#else
|
||||
#undef LEGACY_FLAC
|
||||
#endif
|
||||
|
||||
#ifdef LEGACY_FLAC
|
||||
#include <FLAC/seekable_stream_decoder.h>
|
||||
|
||||
#define D_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
|
||||
|
||||
#define d_new() FLAC__seekable_stream_decoder_new()
|
||||
#define d_init(x) FLAC__seekable_stream_decoder_init(x)
|
||||
#define d_process_metadata(x) FLAC__seekable_stream_decoder_process_until_end_of_metadata(x)
|
||||
#define d_process_one_frame(x) FLAC__seekable_stream_decoder_process_single(x)
|
||||
#define d_get_state(x) FLAC__seekable_stream_decoder_get_state(x)
|
||||
#define d_finish(x) FLAC__seekable_stream_decoder_finish(x)
|
||||
#define d_delete(x) FLAC__seekable_stream_decoder_delete(x)
|
||||
#define d_set_read_callback(x, y) FLAC__seekable_stream_decoder_set_read_callback(x, y)
|
||||
#define d_set_write_callback(x, y) FLAC__seekable_stream_decoder_set_write_callback(x, y)
|
||||
#define d_set_metadata_callback(x, y) FLAC__seekable_stream_decoder_set_metadata_callback(x, y)
|
||||
#define d_set_error_callback(x, y) FLAC__seekable_stream_decoder_set_error_callback(x, y)
|
||||
#define d_set_client_data(x, y) FLAC__seekable_stream_decoder_set_client_data(x, y)
|
||||
|
||||
typedef FLAC__SeekableStreamDecoder decoder_t;
|
||||
typedef FLAC__SeekableStreamDecoderReadStatus d_read_status_t;
|
||||
|
||||
#define D_SEEK_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
|
||||
#define D_SEEK_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
|
||||
#define D_TELL_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
|
||||
#define D_TELL_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
|
||||
#define D_LENGTH_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
|
||||
#define D_LENGTH_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
|
||||
|
||||
#define d_set_seek_callback(x, y) FLAC__seekable_stream_decoder_set_seek_callback(x, y)
|
||||
#define d_set_tell_callback(x, y) FLAC__seekable_stream_decoder_set_tell_callback(x, y)
|
||||
#define d_set_length_callback(x, y) FLAC__seekable_stream_decoder_set_length_callback(x, y)
|
||||
#define d_set_eof_callback(x, y) FLAC__seekable_stream_decoder_set_eof_callback(x, y)
|
||||
#define d_seek_absolute(x, y) FLAC__seekable_stream_decoder_seek_absolute(x, y)
|
||||
|
||||
typedef FLAC__SeekableStreamDecoderSeekStatus d_seek_status_t;
|
||||
typedef FLAC__SeekableStreamDecoderTellStatus d_tell_status_t;
|
||||
typedef FLAC__SeekableStreamDecoderLengthStatus d_length_status_t;
|
||||
#else
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
||||
#define D_END_OF_STREAM FLAC__STREAM_DECODER_END_OF_STREAM
|
||||
|
||||
#define d_new() FLAC__stream_decoder_new()
|
||||
#define d_process_metadata(x) FLAC__stream_decoder_process_until_end_of_metadata(x)
|
||||
#define d_process_one_frame(x) FLAC__stream_decoder_process_single(x)
|
||||
#define d_get_state(x) FLAC__stream_decoder_get_state(x)
|
||||
#define d_finish(x) FLAC__stream_decoder_finish(x)
|
||||
#define d_delete(x) FLAC__stream_decoder_delete(x)
|
||||
|
||||
typedef FLAC__StreamDecoder decoder_t;
|
||||
typedef FLAC__StreamDecoderReadStatus d_read_status_t;
|
||||
|
||||
#define D_SEEK_STATUS_OK FLAC__STREAM_DECODER_SEEK_STATUS_OK
|
||||
#define D_SEEK_STATUS_ERROR FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
|
||||
#define D_TELL_STATUS_OK FLAC__STREAM_DECODER_TELL_STATUS_OK
|
||||
#define D_TELL_STATUS_ERROR FLAC__STREAM_DECODER_TELL_STATUS_ERROR
|
||||
#define D_LENGTH_STATUS_OK FLAC__STREAM_DECODER_LENGTH_STATUS_OK
|
||||
#define D_LENGTH_STATUS_ERROR FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
|
||||
|
||||
#define d_seek_absolute(x, y) FLAC__stream_decoder_seek_absolute(x, y)
|
||||
|
||||
typedef FLAC__StreamDecoderSeekStatus d_seek_status_t;
|
||||
typedef FLAC__StreamDecoderTellStatus d_tell_status_t;
|
||||
typedef FLAC__StreamDecoderLengthStatus d_length_status_t;
|
||||
#endif
|
||||
|
||||
#define D_WRITE_CONTINUE FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
|
||||
#define D_READ_END_OF_STREAM FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
|
||||
#define D_READ_ABORT FLAC__STREAM_DECODER_READ_STATUS_ABORT
|
||||
#define D_READ_CONTINUE FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
|
||||
|
||||
#define d_error_status_string FLAC__StreamDecoderErrorStatusString
|
||||
|
||||
typedef FLAC__StreamDecoderErrorStatus d_error_status_t;
|
||||
typedef FLAC__StreamMetadata d_metadata_t;
|
||||
typedef FLAC__StreamDecoderWriteStatus d_write_status_t;
|
||||
|
||||
|
||||
static int FLAC_init(void);
|
||||
static void FLAC_quit(void);
|
||||
static int FLAC_open(Sound_Sample *sample, const char *ext);
|
||||
static void FLAC_close(Sound_Sample *sample);
|
||||
static Uint32 FLAC_read(Sound_Sample *sample);
|
||||
static int FLAC_rewind(Sound_Sample *sample);
|
||||
static int FLAC_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_flac[] = { "FLAC", "FLA", NULL };
|
||||
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_FLAC =
|
||||
{
|
||||
{
|
||||
extensions_flac,
|
||||
"Free Lossless Audio Codec",
|
||||
"Torbjörn Andersson <d91tan@Update.UU.SE>",
|
||||
"http://flac.sourceforge.net/"
|
||||
},
|
||||
|
||||
FLAC_init, /* init() method */
|
||||
FLAC_quit, /* quit() method */
|
||||
FLAC_open, /* open() method */
|
||||
FLAC_close, /* close() method */
|
||||
FLAC_read, /* read() method */
|
||||
FLAC_rewind, /* rewind() method */
|
||||
FLAC_seek /* seek() method */
|
||||
};
|
||||
|
||||
/* This is what we store in our internal->decoder_private field. */
|
||||
typedef struct
|
||||
{
|
||||
decoder_t *decoder;
|
||||
SDL_RWops *rw;
|
||||
Sound_Sample *sample;
|
||||
Uint32 frame_size;
|
||||
Uint8 is_flac;
|
||||
Uint32 stream_length;
|
||||
} flac_t;
|
||||
|
||||
|
||||
static void free_flac(flac_t *f)
|
||||
{
|
||||
d_finish(f->decoder);
|
||||
d_delete(f->decoder);
|
||||
free(f);
|
||||
} /* free_flac */
|
||||
|
||||
|
||||
#ifdef LEGACY_FLAC
|
||||
static d_read_status_t read_callback(
|
||||
const decoder_t *decoder, FLAC__byte buffer[],
|
||||
unsigned int *bytes, void *client_data)
|
||||
#else
|
||||
static d_read_status_t read_callback(
|
||||
const decoder_t *decoder, FLAC__byte buffer[],
|
||||
size_t *bytes, void *client_data)
|
||||
#endif
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
Uint32 retval;
|
||||
|
||||
retval = SDL_RWread(f->rw, (Uint8 *) buffer, 1, *bytes);
|
||||
|
||||
if (retval == 0)
|
||||
{
|
||||
*bytes = 0;
|
||||
f->sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(D_READ_END_OF_STREAM);
|
||||
} /* if */
|
||||
|
||||
if (retval == -1)
|
||||
{
|
||||
*bytes = 0;
|
||||
f->sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(D_READ_ABORT);
|
||||
} /* if */
|
||||
|
||||
if (retval < *bytes)
|
||||
{
|
||||
*bytes = retval;
|
||||
f->sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
} /* if */
|
||||
|
||||
return(D_READ_CONTINUE);
|
||||
} /* read_callback */
|
||||
|
||||
|
||||
static d_write_status_t write_callback(
|
||||
const decoder_t *decoder, const FLAC__Frame *frame,
|
||||
const FLAC__int32 * const buffer[],
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
Uint32 i, j;
|
||||
Uint32 sample;
|
||||
Uint8 *dst;
|
||||
|
||||
f->frame_size = frame->header.channels * frame->header.blocksize
|
||||
* frame->header.bits_per_sample / 8;
|
||||
|
||||
if (f->frame_size > f->sample->buffer_size)
|
||||
Sound_SetBufferSize(f->sample, f->frame_size);
|
||||
|
||||
dst = f->sample->buffer;
|
||||
|
||||
/* If the sample is neither exactly 8-bit nor 16-bit, it will have to
|
||||
* be converted. Unfortunately the buffer is read-only, so we either
|
||||
* have to check for each sample, or make a copy of the buffer. I'm
|
||||
* not sure which way is best, so I've arbitrarily picked the former.
|
||||
*/
|
||||
if (f->sample->actual.format == AUDIO_S8)
|
||||
{
|
||||
for (i = 0; i < frame->header.blocksize; i++)
|
||||
for (j = 0; j < frame->header.channels; j++)
|
||||
{
|
||||
sample = buffer[j][i];
|
||||
if (frame->header.bits_per_sample < 8)
|
||||
sample <<= (8 - frame->header.bits_per_sample);
|
||||
*dst++ = sample & 0x00ff;
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < frame->header.blocksize; i++)
|
||||
for (j = 0; j < frame->header.channels; j++)
|
||||
{
|
||||
sample = buffer[j][i];
|
||||
if (frame->header.bits_per_sample < 16)
|
||||
sample <<= (16 - frame->header.bits_per_sample);
|
||||
else if (frame->header.bits_per_sample > 16)
|
||||
sample >>= (frame->header.bits_per_sample - 16);
|
||||
*dst++ = (sample & 0xff00) >> 8;
|
||||
*dst++ = sample & 0x00ff;
|
||||
} /* for */
|
||||
} /* else */
|
||||
|
||||
return(D_WRITE_CONTINUE);
|
||||
} /* write_callback */
|
||||
|
||||
|
||||
static void metadata_callback(
|
||||
const decoder_t *decoder,
|
||||
const d_metadata_t *metadata,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
|
||||
SNDDBG(("FLAC: Metadata callback.\n"));
|
||||
|
||||
/* There are several kinds of metadata, but STREAMINFO is the only
|
||||
* one that always has to be there.
|
||||
*/
|
||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
||||
{
|
||||
SNDDBG(("FLAC: Metadata is streaminfo.\n"));
|
||||
|
||||
f->is_flac = 1;
|
||||
f->sample->actual.channels = metadata->data.stream_info.channels;
|
||||
f->sample->actual.rate = metadata->data.stream_info.sample_rate;
|
||||
|
||||
if (metadata->data.stream_info.bits_per_sample > 8)
|
||||
f->sample->actual.format = AUDIO_S16MSB;
|
||||
else
|
||||
f->sample->actual.format = AUDIO_S8;
|
||||
} /* if */
|
||||
} /* metadata_callback */
|
||||
|
||||
|
||||
static void error_callback(
|
||||
const decoder_t *decoder,
|
||||
d_error_status_t status,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
|
||||
__Sound_SetError(d_error_status_string[status]);
|
||||
f->sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
} /* error_callback */
|
||||
|
||||
|
||||
static d_seek_status_t seek_callback(
|
||||
const decoder_t *decoder,
|
||||
FLAC__uint64 absolute_byte_offset,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
|
||||
if (SDL_RWseek(f->rw, absolute_byte_offset, SEEK_SET) >= 0)
|
||||
{
|
||||
return(D_SEEK_STATUS_OK);
|
||||
} /* if */
|
||||
|
||||
return(D_SEEK_STATUS_ERROR);
|
||||
} /* seek_callback*/
|
||||
|
||||
|
||||
static d_tell_status_t tell_callback(
|
||||
const decoder_t *decoder,
|
||||
FLAC__uint64 *absolute_byte_offset,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
int pos;
|
||||
|
||||
pos = SDL_RWtell(f->rw);
|
||||
|
||||
if (pos < 0)
|
||||
{
|
||||
return(D_TELL_STATUS_ERROR);
|
||||
} /* if */
|
||||
|
||||
*absolute_byte_offset = pos;
|
||||
return(D_TELL_STATUS_OK);
|
||||
} /* tell_callback */
|
||||
|
||||
|
||||
static d_length_status_t length_callback(
|
||||
const decoder_t *decoder,
|
||||
FLAC__uint64 *stream_length,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
|
||||
if (f->sample->flags & SOUND_SAMPLEFLAG_CANSEEK)
|
||||
{
|
||||
*stream_length = f->stream_length;
|
||||
return(D_LENGTH_STATUS_OK);
|
||||
} /* if */
|
||||
|
||||
return(D_LENGTH_STATUS_ERROR);
|
||||
} /* length_callback */
|
||||
|
||||
|
||||
static FLAC__bool eof_callback(
|
||||
const decoder_t *decoder,
|
||||
void *client_data)
|
||||
{
|
||||
flac_t *f = (flac_t *) client_data;
|
||||
int pos;
|
||||
|
||||
/* Maybe we could check for SOUND_SAMPLEFLAG_EOF here instead? */
|
||||
pos = SDL_RWtell(f->rw);
|
||||
|
||||
if (pos >= 0 && pos >= f->stream_length)
|
||||
{
|
||||
return(true);
|
||||
} /* if */
|
||||
|
||||
return(false);
|
||||
} /* eof_callback */
|
||||
|
||||
|
||||
static int FLAC_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* FLAC_init */
|
||||
|
||||
|
||||
static void FLAC_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* FLAC_quit */
|
||||
|
||||
|
||||
#define FLAC_MAGIC 0x43614C66 /* "fLaC" in ASCII. */
|
||||
|
||||
static int FLAC_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
decoder_t *decoder;
|
||||
flac_t *f;
|
||||
int i;
|
||||
int has_extension = 0;
|
||||
Uint32 pos;
|
||||
|
||||
/*
|
||||
* If the extension is "flac", we'll believe that this is really meant
|
||||
* to be a FLAC stream, and will try to grok it from existing metadata.
|
||||
* metadata searching can be a very expensive operation, however, so
|
||||
* unless the user swears that it is a FLAC stream through the extension,
|
||||
* we decide what to do based on the existance of a 32-bit magic number.
|
||||
*/
|
||||
for (i = 0; extensions_flac[i] != NULL; i++)
|
||||
{
|
||||
if (__Sound_strcasecmp(ext, extensions_flac[i]) == 0)
|
||||
{
|
||||
has_extension = 1;
|
||||
break;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (!has_extension)
|
||||
{
|
||||
int rc;
|
||||
Uint32 flac_magic = SDL_ReadLE32(rw);
|
||||
BAIL_IF_MACRO(flac_magic != FLAC_MAGIC, "FLAC: Not a FLAC stream.", 0);
|
||||
|
||||
/* move back over magic number for metadata scan... */
|
||||
rc = SDL_RWseek(internal->rw, -sizeof (flac_magic), SEEK_CUR);
|
||||
BAIL_IF_MACRO(rc < 0, ERR_IO_ERROR, 0);
|
||||
} /* if */
|
||||
|
||||
f = (flac_t *) malloc(sizeof (flac_t));
|
||||
BAIL_IF_MACRO(f == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
decoder = d_new();
|
||||
if (decoder == NULL)
|
||||
{
|
||||
free(f);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
#ifdef LEGACY_FLAC
|
||||
d_set_read_callback(decoder, read_callback);
|
||||
d_set_write_callback(decoder, write_callback);
|
||||
d_set_metadata_callback(decoder, metadata_callback);
|
||||
d_set_error_callback(decoder, error_callback);
|
||||
d_set_seek_callback(decoder, seek_callback);
|
||||
d_set_tell_callback(decoder, tell_callback);
|
||||
d_set_length_callback(decoder, length_callback);
|
||||
d_set_eof_callback(decoder, eof_callback);
|
||||
|
||||
d_set_client_data(decoder, f);
|
||||
#endif
|
||||
|
||||
f->rw = internal->rw;
|
||||
f->sample = sample;
|
||||
f->decoder = decoder;
|
||||
f->sample->actual.format = 0;
|
||||
f->is_flac = 0 /* !!! FIXME: should be "has_extension", not "0". */;
|
||||
|
||||
internal->decoder_private = f;
|
||||
/* really should check the init return value here: */
|
||||
#ifdef LEGACY_FLAC
|
||||
d_init(decoder);
|
||||
#else
|
||||
FLAC__stream_decoder_init_stream(decoder, read_callback, seek_callback,
|
||||
tell_callback, length_callback,
|
||||
eof_callback, write_callback,
|
||||
metadata_callback, error_callback, f);
|
||||
#endif
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_NONE;
|
||||
|
||||
pos = SDL_RWtell(f->rw);
|
||||
if (SDL_RWseek(f->rw, 0, SEEK_END) > 0)
|
||||
{
|
||||
f->stream_length = SDL_RWtell(f->rw);
|
||||
if (SDL_RWseek(f->rw, pos, SEEK_SET) == -1)
|
||||
{
|
||||
free_flac(f);
|
||||
BAIL_MACRO(ERR_IO_ERROR, 0);
|
||||
} /* if */
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
} /* if */
|
||||
|
||||
/*
|
||||
* If we are not sure this is a FLAC stream, check for the STREAMINFO
|
||||
* metadata block. If not, we'd have to peek at the first audio frame
|
||||
* and get the sound format from there, but that is not yet
|
||||
* implemented.
|
||||
*/
|
||||
if (!f->is_flac)
|
||||
{
|
||||
d_process_metadata(decoder);
|
||||
|
||||
/* Still not FLAC? Give up. */
|
||||
if (!f->is_flac)
|
||||
{
|
||||
free_flac(f);
|
||||
BAIL_MACRO("FLAC: No metadata found. Not a FLAC stream?", 0);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("FLAC: Accepting data stream.\n"));
|
||||
return(1);
|
||||
} /* FLAC_open */
|
||||
|
||||
|
||||
static void FLAC_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
flac_t *f = (flac_t *) internal->decoder_private;
|
||||
|
||||
free_flac(f);
|
||||
} /* FLAC_close */
|
||||
|
||||
|
||||
static Uint32 FLAC_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
flac_t *f = (flac_t *) internal->decoder_private;
|
||||
Uint32 len;
|
||||
|
||||
if (!d_process_one_frame(f->decoder))
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
BAIL_MACRO("FLAC: Couldn't decode frame.", 0);
|
||||
} /* if */
|
||||
|
||||
if (d_get_state(f->decoder) == D_END_OF_STREAM)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
/* An error may have been signalled through the error callback. */
|
||||
if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
|
||||
return(0);
|
||||
|
||||
return(f->frame_size);
|
||||
} /* FLAC_read */
|
||||
|
||||
|
||||
static int FLAC_rewind(Sound_Sample *sample)
|
||||
{
|
||||
return FLAC_seek(sample, 0);
|
||||
} /* FLAC_rewind */
|
||||
|
||||
|
||||
static int FLAC_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
flac_t *f = (flac_t *) internal->decoder_private;
|
||||
|
||||
d_seek_absolute(f->decoder, (ms * sample->actual.rate) / 1000);
|
||||
return(1);
|
||||
} /* FLAC_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_FLAC */
|
||||
|
||||
/* end of flac.c ... */
|
||||
175
project/jni/sdl_sound/decoders/midi.c
Normal file
175
project/jni/sdl_sound/decoders/midi.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* MIDI decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles MIDI data through a stripped-down version of TiMidity.
|
||||
* See the documentation in the timidity subdirectory.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Torbjörn Andersson. (d91tan@Update.UU.SE)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_MIDI
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
|
||||
|
||||
static int MIDI_init(void);
|
||||
static void MIDI_quit(void);
|
||||
static int MIDI_open(Sound_Sample *sample, const char *ext);
|
||||
static void MIDI_close(Sound_Sample *sample);
|
||||
static Uint32 MIDI_read(Sound_Sample *sample);
|
||||
static int MIDI_rewind(Sound_Sample *sample);
|
||||
static int MIDI_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_midi[] = { "MIDI", "MID", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_MIDI =
|
||||
{
|
||||
{
|
||||
extensions_midi,
|
||||
"MIDI decoder, using a subset of TiMidity",
|
||||
"Torbjörn Andersson <d91tan@Update.UU.SE>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
MIDI_init, /* init() method */
|
||||
MIDI_quit, /* quit() method */
|
||||
MIDI_open, /* open() method */
|
||||
MIDI_close, /* close() method */
|
||||
MIDI_read, /* read() method */
|
||||
MIDI_rewind, /* rewind() method */
|
||||
MIDI_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
static int MIDI_init(void)
|
||||
{
|
||||
BAIL_IF_MACRO(Timidity_Init() < 0, "MIDI: Could not initialise", 0);
|
||||
return(1);
|
||||
} /* MIDI_init */
|
||||
|
||||
|
||||
static void MIDI_quit(void)
|
||||
{
|
||||
Timidity_Exit();
|
||||
} /* MIDI_quit */
|
||||
|
||||
|
||||
static int MIDI_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
SDL_AudioSpec spec;
|
||||
MidiSong *song;
|
||||
|
||||
spec.channels = 2;
|
||||
spec.format = AUDIO_S16SYS;
|
||||
spec.freq = 44100;
|
||||
spec.samples = 4096;
|
||||
|
||||
song = Timidity_LoadSong(rw, &spec);
|
||||
BAIL_IF_MACRO(song == NULL, "MIDI: Not a MIDI file.", 0);
|
||||
Timidity_SetVolume(song, 100);
|
||||
Timidity_Start(song);
|
||||
|
||||
SNDDBG(("MIDI: Accepting data stream.\n"));
|
||||
|
||||
internal->decoder_private = (void *) song;
|
||||
|
||||
sample->actual.channels = 2;
|
||||
sample->actual.rate = 44100;
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* MIDI_open */
|
||||
|
||||
|
||||
static void MIDI_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MidiSong *song = (MidiSong *) internal->decoder_private;
|
||||
|
||||
Timidity_FreeSong(song);
|
||||
} /* MIDI_close */
|
||||
|
||||
|
||||
static Uint32 MIDI_read(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MidiSong *song = (MidiSong *) internal->decoder_private;
|
||||
|
||||
retval = Timidity_PlaySome(song, internal->buffer, internal->buffer_size);
|
||||
|
||||
/* Make sure the read went smoothly... */
|
||||
if (retval == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
else if (retval == -1)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
|
||||
/* (next call this EAGAIN may turn into an EOF or error.) */
|
||||
else if (retval < internal->buffer_size)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
|
||||
return(retval);
|
||||
} /* MIDI_read */
|
||||
|
||||
|
||||
static int MIDI_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MidiSong *song = (MidiSong *) internal->decoder_private;
|
||||
|
||||
Timidity_Start(song);
|
||||
return(1);
|
||||
} /* MIDI_rewind */
|
||||
|
||||
|
||||
static int MIDI_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MidiSong *song = (MidiSong *) internal->decoder_private;
|
||||
|
||||
Timidity_Seek(song, ms);
|
||||
return(1);
|
||||
} /* MIDI_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_MIDI */
|
||||
|
||||
|
||||
/* end of midi.c ... */
|
||||
|
||||
344
project/jni/sdl_sound/decoders/mikmod.c
Normal file
344
project/jni/sdl_sound/decoders/mikmod.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module player for SDL_sound. This driver handles anything MikMod does, and
|
||||
* is based on SDL_mixer.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Torbjörn Andersson (d91tan@Update.UU.SE)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_MIKMOD
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "mikmod.h"
|
||||
|
||||
|
||||
static int MIKMOD_init(void);
|
||||
static void MIKMOD_quit(void);
|
||||
static int MIKMOD_open(Sound_Sample *sample, const char *ext);
|
||||
static void MIKMOD_close(Sound_Sample *sample);
|
||||
static Uint32 MIKMOD_read(Sound_Sample *sample);
|
||||
static int MIKMOD_rewind(Sound_Sample *sample);
|
||||
static int MIKMOD_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_mikmod[] =
|
||||
{
|
||||
"669", /* Composer 669 */
|
||||
"AMF", /* DMP Advanced Module Format */
|
||||
"DSM", /* DSIK internal format */
|
||||
"FAR", /* Farandole module */
|
||||
"GDM", /* General DigiMusic module */
|
||||
"IMF", /* Imago Orpheus module */
|
||||
"IT", /* Impulse tracker */
|
||||
"M15", /* 15 instrument MOD / Ultimate Sound Tracker (old M15 format) */
|
||||
"MED", /* Amiga MED module */
|
||||
"MOD", /* Generic MOD (Protracker, StarTracker, FastTracker, etc) */
|
||||
"MTM", /* MTM module */
|
||||
"OKT", /* Oktalyzer module */
|
||||
"S3M", /* Screamtracker module */
|
||||
"STM", /* Screamtracker 2 module */
|
||||
"STX", /* STMIK 0.2 module */
|
||||
"ULT", /* Ultratracker module */
|
||||
"UNI", /* UNIMOD - libmikmod's and APlayer's internal module format */
|
||||
"XM", /* Fasttracker module */
|
||||
NULL
|
||||
};
|
||||
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_MIKMOD =
|
||||
{
|
||||
{
|
||||
extensions_mikmod,
|
||||
"Play modules through MikMod",
|
||||
"Torbjörn Andersson <d91tan@Update.UU.SE>",
|
||||
"http://mikmod.raphnet.net/"
|
||||
},
|
||||
|
||||
MIKMOD_init, /* init() method */
|
||||
MIKMOD_quit, /* quit() method */
|
||||
MIKMOD_open, /* open() method */
|
||||
MIKMOD_close, /* close() method */
|
||||
MIKMOD_read, /* read() method */
|
||||
MIKMOD_rewind, /* rewind() method */
|
||||
MIKMOD_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
/* Make MikMod read from a RWops... */
|
||||
|
||||
typedef struct MRWOPSREADER {
|
||||
MREADER core;
|
||||
Sound_Sample *sample;
|
||||
int end;
|
||||
} MRWOPSREADER;
|
||||
|
||||
static BOOL _mm_RWopsReader_eof(MREADER *reader)
|
||||
{
|
||||
MRWOPSREADER *rwops_reader = (MRWOPSREADER *) reader;
|
||||
Sound_Sample *sample = rwops_reader->sample;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
int pos = SDL_RWtell(internal->rw);
|
||||
|
||||
if (rwops_reader->end == pos)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
} /* _mm_RWopsReader_eof */
|
||||
|
||||
|
||||
static BOOL _mm_RWopsReader_read(MREADER *reader, void *ptr, size_t size)
|
||||
{
|
||||
MRWOPSREADER *rwops_reader = (MRWOPSREADER *) reader;
|
||||
Sound_Sample *sample = rwops_reader->sample;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
return(SDL_RWread(internal->rw, ptr, size, 1));
|
||||
} /* _mm_RWopsReader_Read */
|
||||
|
||||
|
||||
static int _mm_RWopsReader_get(MREADER *reader)
|
||||
{
|
||||
char buf;
|
||||
MRWOPSREADER *rwops_reader = (MRWOPSREADER *) reader;
|
||||
Sound_Sample *sample = rwops_reader->sample;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
if (SDL_RWread(internal->rw, &buf, 1, 1) != 1)
|
||||
return(EOF);
|
||||
|
||||
return((int) buf);
|
||||
} /* _mm_RWopsReader_get */
|
||||
|
||||
|
||||
static BOOL _mm_RWopsReader_seek(MREADER *reader, long offset, int whence)
|
||||
{
|
||||
MRWOPSREADER *rwops_reader = (MRWOPSREADER *) reader;
|
||||
Sound_Sample *sample = rwops_reader->sample;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
return(SDL_RWseek(internal->rw, offset, whence));
|
||||
} /* _mm_RWopsReader_seek */
|
||||
|
||||
|
||||
static long _mm_RWopsReader_tell(MREADER *reader)
|
||||
{
|
||||
MRWOPSREADER *rwops_reader = (MRWOPSREADER *) reader;
|
||||
Sound_Sample *sample = rwops_reader->sample;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
return(SDL_RWtell(internal->rw));
|
||||
} /* _mm_RWopsReader_tell */
|
||||
|
||||
|
||||
static MREADER *_mm_new_rwops_reader(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
MRWOPSREADER *reader = (MRWOPSREADER *) malloc(sizeof (MRWOPSREADER));
|
||||
if (reader != NULL)
|
||||
{
|
||||
int failed_seek = 1;
|
||||
int here;
|
||||
reader->core.Eof = _mm_RWopsReader_eof;
|
||||
reader->core.Read = _mm_RWopsReader_read;
|
||||
reader->core.Get = _mm_RWopsReader_get;
|
||||
reader->core.Seek = _mm_RWopsReader_seek;
|
||||
reader->core.Tell = _mm_RWopsReader_tell;
|
||||
reader->sample = sample;
|
||||
|
||||
/* RWops does not explicitly support an eof check, so we shall find
|
||||
the end manually - this requires seek support for the RWop */
|
||||
here = SDL_RWtell(internal->rw);
|
||||
if (here != -1)
|
||||
{
|
||||
reader->end = SDL_RWseek(internal->rw, 0, SEEK_END);
|
||||
if (reader->end != -1)
|
||||
{
|
||||
/* Move back */
|
||||
if (SDL_RWseek(internal->rw, here, SEEK_SET) != -1)
|
||||
failed_seek = 0;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (failed_seek)
|
||||
{
|
||||
free(reader);
|
||||
reader = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return((MREADER *) reader);
|
||||
} /* _mm_new_rwops_reader */
|
||||
|
||||
|
||||
static void _mm_delete_rwops_reader(MREADER *reader)
|
||||
{
|
||||
/* SDL_sound will delete the RWops and sample at a higher level... */
|
||||
if (reader != NULL)
|
||||
free(reader);
|
||||
} /* _mm_delete_rwops_reader */
|
||||
|
||||
|
||||
|
||||
static int MIKMOD_init(void)
|
||||
{
|
||||
MikMod_RegisterDriver(&drv_nos);
|
||||
|
||||
/* Quick and dirty hack to prevent an infinite loop problem
|
||||
* found when using SDL_mixer and SDL_sound together and
|
||||
* both have MikMod compiled in. So, check to see if
|
||||
* MikMod has already been registered first before calling
|
||||
* RegisterAllLoaders()
|
||||
*/
|
||||
if(MikMod_InfoLoader() == NULL)
|
||||
{
|
||||
MikMod_RegisterAllLoaders();
|
||||
}
|
||||
/*
|
||||
* Both DMODE_SOFT_MUSIC and DMODE_16BITS should be set by default,
|
||||
* so this is just for clarity. I haven't experimented with any of
|
||||
* the other flags. There are a few which are said to give better
|
||||
* sound quality.
|
||||
*/
|
||||
md_mode |= (DMODE_SOFT_MUSIC | DMODE_16BITS);
|
||||
md_mixfreq = 0;
|
||||
md_reverb = 1;
|
||||
|
||||
BAIL_IF_MACRO(MikMod_Init(""), MikMod_strerror(MikMod_errno), 0);
|
||||
|
||||
return(1); /* success. */
|
||||
} /* MIKMOD_init */
|
||||
|
||||
|
||||
static void MIKMOD_quit(void)
|
||||
{
|
||||
MikMod_Exit();
|
||||
md_mixfreq = 0;
|
||||
} /* MIKMOD_quit */
|
||||
|
||||
|
||||
static int MIKMOD_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MREADER *reader;
|
||||
MODULE *module;
|
||||
|
||||
reader = _mm_new_rwops_reader(sample);
|
||||
BAIL_IF_MACRO(reader == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
module = Player_LoadGeneric(reader, 64, 0);
|
||||
_mm_delete_rwops_reader(reader);
|
||||
BAIL_IF_MACRO(module == NULL, "MIKMOD: Not a module file.", 0);
|
||||
|
||||
module->extspd = 1;
|
||||
module->panflag = 1;
|
||||
module->wrap = 0;
|
||||
module->loop = 0;
|
||||
|
||||
if (md_mixfreq == 0)
|
||||
md_mixfreq = (!sample->desired.rate) ? 44100 : sample->desired.rate;
|
||||
|
||||
sample->actual.channels = 2;
|
||||
sample->actual.rate = md_mixfreq;
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
internal->decoder_private = (void *) module;
|
||||
|
||||
Player_Start(module);
|
||||
Player_SetPosition(0);
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_NONE;
|
||||
|
||||
SNDDBG(("MIKMOD: Name: %s\n", module->songname));
|
||||
SNDDBG(("MIKMOD: Type: %s\n", module->modtype));
|
||||
SNDDBG(("MIKMOD: Accepting data stream\n"));
|
||||
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* MIKMOD_open */
|
||||
|
||||
|
||||
static void MIKMOD_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MODULE *module = (MODULE *) internal->decoder_private;
|
||||
|
||||
Player_Free(module);
|
||||
} /* MIKMOD_close */
|
||||
|
||||
|
||||
static Uint32 MIKMOD_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MODULE *module = (MODULE *) internal->decoder_private;
|
||||
|
||||
/* Switch to the current module, stopping any previous one. */
|
||||
Player_Start(module);
|
||||
if (!Player_Active())
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(0);
|
||||
} /* if */
|
||||
return((Uint32) VC_WriteBytes(internal->buffer, internal->buffer_size));
|
||||
} /* MIKMOD_read */
|
||||
|
||||
|
||||
static int MIKMOD_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MODULE *module = (MODULE *) internal->decoder_private;
|
||||
|
||||
Player_Start(module);
|
||||
Player_SetPosition(0);
|
||||
return(1);
|
||||
} /* MIKMOD_rewind */
|
||||
|
||||
|
||||
static int MIKMOD_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
#if 0
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
MODULE *module = (MODULE *) internal->decoder_private;
|
||||
|
||||
/*
|
||||
* Heaven may know what the argument to Player_SetPosition() is.
|
||||
* I, however, haven't the faintest idea.
|
||||
*/
|
||||
Player_Start(module);
|
||||
Player_SetPosition(ms);
|
||||
return(1);
|
||||
#else
|
||||
BAIL_MACRO("MIKMOD: Seeking not implemented", 0);
|
||||
#endif
|
||||
} /* MIKMOD_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_MIKMOD */
|
||||
|
||||
|
||||
/* end of mikmod.c ... */
|
||||
340
project/jni/sdl_sound/decoders/modplug.c
Normal file
340
project/jni/sdl_sound/decoders/modplug.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module player for SDL_sound. This driver handles anything that ModPlug does.
|
||||
*
|
||||
* ModPlug can be found at http://sourceforge.net/projects/modplug-xmms
|
||||
*
|
||||
* An unofficial version of modplug with all C++ dependencies removed is also
|
||||
* available: http://freecraft.net/snapshots/
|
||||
* (Look for something like "libmodplug-johns-*.tar.gz")
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Torbjörn Andersson (d91tan@Update.UU.SE)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_MODPLUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#if SOUND_MODPLUG_IN_OWN_PATH
|
||||
#include "libmodplug/modplug.h"
|
||||
#else
|
||||
#include "modplug.h"
|
||||
#endif
|
||||
|
||||
static int MODPLUG_init(void);
|
||||
static void MODPLUG_quit(void);
|
||||
static int MODPLUG_open(Sound_Sample *sample, const char *ext);
|
||||
static void MODPLUG_close(Sound_Sample *sample);
|
||||
static Uint32 MODPLUG_read(Sound_Sample *sample);
|
||||
static int MODPLUG_rewind(Sound_Sample *sample);
|
||||
static int MODPLUG_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_modplug[] =
|
||||
{
|
||||
/* The XMMS plugin is apparently able to load compressed modules as
|
||||
* well, but libmodplug does not handle this.
|
||||
*/
|
||||
"669", /* Composer 669 / UNIS 669 module */
|
||||
"AMF", /* ASYLUM Music Format / Advanced Music Format(DSM) */
|
||||
"AMS", /* AMS module */
|
||||
"DBM", /* DigiBooster Pro Module */
|
||||
"DMF", /* DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) */
|
||||
"DSM", /* DSIK Internal Format module */
|
||||
"FAR", /* Farandole module */
|
||||
"IT", /* Impulse Tracker IT file */
|
||||
"MDL", /* DigiTracker module */
|
||||
#if 0
|
||||
"J2B", /* Not implemented? What is it anyway? */
|
||||
#endif
|
||||
"MED", /* OctaMed MED file */
|
||||
"MOD", /* ProTracker / NoiseTracker MOD/NST file */
|
||||
"MT2", /* MadTracker 2.0 */
|
||||
"MTM", /* MTM file */
|
||||
"OKT", /* Oktalyzer module */
|
||||
"PTM", /* PTM PolyTracker module */
|
||||
"PSM", /* PSM module */
|
||||
"S3M", /* ScreamTracker file */
|
||||
"STM", /* ST 2.xx */
|
||||
"ULT",
|
||||
"UMX",
|
||||
"XM", /* FastTracker II */
|
||||
NULL
|
||||
};
|
||||
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_MODPLUG =
|
||||
{
|
||||
{
|
||||
extensions_modplug,
|
||||
"Play modules through ModPlug",
|
||||
"Torbjörn Andersson <d91tan@Update.UU.SE>",
|
||||
"http://modplug-xmms.sourceforge.net/"
|
||||
},
|
||||
|
||||
MODPLUG_init, /* init() method */
|
||||
MODPLUG_quit, /* quit() method */
|
||||
MODPLUG_open, /* open() method */
|
||||
MODPLUG_close, /* close() method */
|
||||
MODPLUG_read, /* read() method */
|
||||
MODPLUG_rewind, /* rewind() method */
|
||||
MODPLUG_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
static ModPlug_Settings settings;
|
||||
static Sound_AudioInfo current_audioinfo;
|
||||
static unsigned int total_mods_decoding = 0;
|
||||
static SDL_mutex *modplug_mutex = NULL;
|
||||
|
||||
static int MODPLUG_init(void)
|
||||
{
|
||||
assert(modplug_mutex == NULL);
|
||||
|
||||
/*
|
||||
* The settings will require some experimenting. I've borrowed some
|
||||
* of them from the XMMS ModPlug plugin.
|
||||
*/
|
||||
settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION |
|
||||
MODPLUG_ENABLE_REVERB |
|
||||
MODPLUG_ENABLE_MEGABASS |
|
||||
MODPLUG_ENABLE_SURROUND;
|
||||
|
||||
settings.mReverbDepth = 30;
|
||||
settings.mReverbDelay = 100;
|
||||
settings.mBassAmount = 40;
|
||||
settings.mBassRange = 30;
|
||||
settings.mSurroundDepth = 20;
|
||||
settings.mSurroundDelay = 20;
|
||||
#endif
|
||||
|
||||
settings.mChannels = 2;
|
||||
settings.mBits = 16;
|
||||
settings.mFrequency = 44100;
|
||||
settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
||||
settings.mLoopCount = 0;
|
||||
|
||||
current_audioinfo.channels = 2;
|
||||
current_audioinfo.rate = 44100;
|
||||
current_audioinfo.format = AUDIO_S16SYS;
|
||||
total_mods_decoding = 0;
|
||||
|
||||
modplug_mutex = SDL_CreateMutex();
|
||||
|
||||
ModPlug_SetSettings(&settings);
|
||||
return(1); /* success. */
|
||||
} /* MODPLUG_init */
|
||||
|
||||
|
||||
static void MODPLUG_quit(void)
|
||||
{
|
||||
assert(total_mods_decoding == 0);
|
||||
|
||||
if (modplug_mutex != NULL)
|
||||
{
|
||||
SDL_DestroyMutex(modplug_mutex);
|
||||
modplug_mutex = NULL;
|
||||
} /* if */
|
||||
} /* MODPLUG_quit */
|
||||
|
||||
|
||||
/*
|
||||
* Most MOD files I've seen have tended to be a few hundred KB, even if some
|
||||
* of them were much smaller than that.
|
||||
*/
|
||||
#define CHUNK_SIZE 65536
|
||||
|
||||
static int MODPLUG_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
ModPlugFile *module;
|
||||
Uint8 *data;
|
||||
size_t size;
|
||||
Uint32 retval;
|
||||
int has_extension = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Apparently ModPlug's loaders are too forgiving. They gladly accept
|
||||
* streams that they shouldn't. For now, rely on file extension instead.
|
||||
*/
|
||||
for (i = 0; extensions_modplug[i] != NULL; i++)
|
||||
{
|
||||
if (__Sound_strcasecmp(ext, extensions_modplug[i]) == 0)
|
||||
{
|
||||
has_extension = 1;
|
||||
break;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (!has_extension)
|
||||
{
|
||||
SNDDBG(("MODPLUG: Unrecognized file type: %s\n", ext));
|
||||
BAIL_MACRO("MODPLUG: Not a module file.", 0);
|
||||
} /* if */
|
||||
|
||||
/*
|
||||
* ModPlug needs the entire stream in one big chunk. I don't like it,
|
||||
* but I don't think there's any way around it.
|
||||
*/
|
||||
data = (Uint8 *) malloc(CHUNK_SIZE);
|
||||
BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
size = 0;
|
||||
|
||||
do
|
||||
{
|
||||
retval = SDL_RWread(internal->rw, &data[size], 1, CHUNK_SIZE);
|
||||
size += retval;
|
||||
if (retval == CHUNK_SIZE)
|
||||
{
|
||||
data = (Uint8 *) realloc(data, size + CHUNK_SIZE);
|
||||
BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
} while (retval > 0);
|
||||
|
||||
/*
|
||||
* It's only safe to change these settings when there're
|
||||
* no other mods being decoded...
|
||||
*/
|
||||
if (modplug_mutex != NULL)
|
||||
SDL_LockMutex(modplug_mutex);
|
||||
|
||||
if (total_mods_decoding > 0)
|
||||
{
|
||||
/* other mods decoding: use the same settings they are. */
|
||||
memcpy(&sample->actual, ¤t_audioinfo, sizeof (Sound_AudioInfo));
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* no other mods decoding: define the new ModPlug output settings. */
|
||||
memcpy(&sample->actual, &sample->desired, sizeof (Sound_AudioInfo));
|
||||
if (sample->actual.rate == 0)
|
||||
sample->actual.rate = 44100;
|
||||
if (sample->actual.channels == 0)
|
||||
sample->actual.channels = 2;
|
||||
if (sample->actual.format == 0)
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
|
||||
memcpy(¤t_audioinfo, &sample->actual, sizeof (Sound_AudioInfo));
|
||||
settings.mChannels=sample->actual.channels;
|
||||
settings.mFrequency=sample->actual.rate;
|
||||
settings.mBits = sample->actual.format & 0xFF;
|
||||
ModPlug_SetSettings(&settings);
|
||||
} /* else */
|
||||
|
||||
/*
|
||||
* The buffer may be a bit too large, but that doesn't matter. I think
|
||||
* it's safe to free it as soon as ModPlug_Load() is finished anyway.
|
||||
*/
|
||||
module = ModPlug_Load((void *) data, size);
|
||||
free(data);
|
||||
if (module == NULL)
|
||||
{
|
||||
if (modplug_mutex != NULL)
|
||||
SDL_UnlockMutex(modplug_mutex);
|
||||
|
||||
BAIL_MACRO("MODPLUG: Not a module file.", 0);
|
||||
} /* if */
|
||||
|
||||
total_mods_decoding++;
|
||||
|
||||
if (modplug_mutex != NULL)
|
||||
SDL_UnlockMutex(modplug_mutex);
|
||||
|
||||
SNDDBG(("MODPLUG: [%d ms] %s\n",
|
||||
ModPlug_GetLength(module), ModPlug_GetName(module)));
|
||||
|
||||
internal->decoder_private = (void *) module;
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
|
||||
SNDDBG(("MODPLUG: Accepting data stream\n"));
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* MODPLUG_open */
|
||||
|
||||
|
||||
static void MODPLUG_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
||||
|
||||
if (modplug_mutex != NULL)
|
||||
SDL_LockMutex(modplug_mutex);
|
||||
|
||||
total_mods_decoding--;
|
||||
|
||||
if (modplug_mutex != NULL)
|
||||
SDL_UnlockMutex(modplug_mutex);
|
||||
|
||||
ModPlug_Unload(module);
|
||||
} /* MODPLUG_close */
|
||||
|
||||
|
||||
static Uint32 MODPLUG_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
||||
int retval;
|
||||
|
||||
retval = ModPlug_Read(module, internal->buffer, internal->buffer_size);
|
||||
if (retval == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(retval);
|
||||
} /* MODPLUG_read */
|
||||
|
||||
|
||||
static int MODPLUG_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
||||
|
||||
ModPlug_Seek(module, 0);
|
||||
return(1);
|
||||
} /* MODPLUG_rewind */
|
||||
|
||||
|
||||
static int MODPLUG_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
||||
|
||||
/* Assume that this will work. */
|
||||
ModPlug_Seek(module, ms);
|
||||
return(1);
|
||||
} /* MODPLUG_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_MODPLUG */
|
||||
|
||||
|
||||
/* end of modplug.c ... */
|
||||
298
project/jni/sdl_sound/decoders/mpglib.c
Normal file
298
project/jni/sdl_sound/decoders/mpglib.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* MPGLIB decoder for SDL_sound. This is a very lightweight MP3 decoder,
|
||||
* which is included with the SDL_sound source, so that it doesn't rely on
|
||||
* unnecessary external libraries.
|
||||
*
|
||||
* The SMPEG decoder plays back more forms of MPEGs, and may behave better or
|
||||
* worse under various conditions. mpglib is (apparently) more efficient than
|
||||
* SMPEG, and, again, doesn't need an external library. You should test both
|
||||
* decoders and use what you find works best for you.
|
||||
*
|
||||
* mpglib is an LGPL'd portion of mpg123, which can be found in its original
|
||||
* form at: http://www.mpg123.de/
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory. The included
|
||||
* source code for mpglib falls under the LGPL, which is the same license as
|
||||
* SDL_sound (so you can consider it a single work).
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_MPGLIB
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mpglib/mpg123_sdlsound.h"
|
||||
#include "mpglib/mpglib_sdlsound.h"
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int MPGLIB_init(void);
|
||||
static void MPGLIB_quit(void);
|
||||
static int MPGLIB_open(Sound_Sample *sample, const char *ext);
|
||||
static void MPGLIB_close(Sound_Sample *sample);
|
||||
static Uint32 MPGLIB_read(Sound_Sample *sample);
|
||||
static int MPGLIB_rewind(Sound_Sample *sample);
|
||||
static int MPGLIB_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_mpglib[] = { "MP3", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_MPGLIB =
|
||||
{
|
||||
{
|
||||
extensions_mpglib,
|
||||
"MP3 decoding via internal mpglib",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
MPGLIB_init, /* init() method */
|
||||
MPGLIB_quit, /* quit() method */
|
||||
MPGLIB_open, /* open() method */
|
||||
MPGLIB_close, /* close() method */
|
||||
MPGLIB_read, /* read() method */
|
||||
MPGLIB_rewind, /* rewind() method */
|
||||
MPGLIB_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
/* this is what we store in our internal->decoder_private field... */
|
||||
typedef struct
|
||||
{
|
||||
struct mpstr mp;
|
||||
Uint8 inbuf[16384];
|
||||
Uint8 outbuf[8192];
|
||||
int outleft;
|
||||
int outpos;
|
||||
} mpglib_t;
|
||||
|
||||
|
||||
|
||||
static int MPGLIB_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* MPGLIB_init */
|
||||
|
||||
|
||||
static void MPGLIB_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* MPGLIB_quit */
|
||||
|
||||
|
||||
static int MPGLIB_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
mpglib_t *mpg = NULL;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* If I understand things correctly, MP3 files don't really have any
|
||||
* magic header we can check for. The MP3 player is expected to just
|
||||
* pick the first thing that looks like a valid frame and start
|
||||
* playing from there.
|
||||
*
|
||||
* So here's what we do: If the caller insists that this is really
|
||||
* MP3 we'll take his word for it. Otherwise, use the same test as
|
||||
* SDL_mixer does and check if the stream starts with something that
|
||||
* looks like a frame.
|
||||
*
|
||||
* A frame begins with 11 bits of frame sync (all bits must be set),
|
||||
* followed by a two-bit MPEG Audio version ID:
|
||||
*
|
||||
* 00 - MPEG Version 2.5 (later extension of MPEG 2)
|
||||
* 01 - reserved
|
||||
* 10 - MPEG Version 2 (ISO/IEC 13818-3)
|
||||
* 11 - MPEG Version 1 (ISO/IEC 11172-3)
|
||||
*
|
||||
* Apparently we don't handle MPEG Version 2.5.
|
||||
*/
|
||||
if (__Sound_strcasecmp(ext, "MP3") != 0)
|
||||
{
|
||||
Uint8 mp3_magic[2];
|
||||
|
||||
if (SDL_RWread(internal->rw, mp3_magic, sizeof (mp3_magic), 1) != 1)
|
||||
BAIL_MACRO("MPGLIB: Could not read MP3 magic.", 0);
|
||||
|
||||
if (mp3_magic[0] != 0xFF || (mp3_magic[1] & 0xF0) != 0xF0)
|
||||
BAIL_MACRO("MPGLIB: Not an MP3 stream.", 0);
|
||||
|
||||
/* If the seek fails, we'll probably miss a frame, but oh well. */
|
||||
SDL_RWseek(internal->rw, -sizeof (mp3_magic), SEEK_CUR);
|
||||
} /* if */
|
||||
|
||||
mpg = (mpglib_t *) malloc(sizeof (mpglib_t));
|
||||
BAIL_IF_MACRO(mpg == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(mpg, '\0', sizeof (mpglib_t));
|
||||
InitMP3(&mpg->mp);
|
||||
|
||||
rc = SDL_RWread(internal->rw, mpg->inbuf, 1, sizeof (mpg->inbuf));
|
||||
if (rc <= 0)
|
||||
{
|
||||
free(mpg);
|
||||
BAIL_MACRO("MPGLIB: Failed to read any data at all", 0);
|
||||
} /* if */
|
||||
|
||||
if (decodeMP3(&mpg->mp, mpg->inbuf, rc,
|
||||
mpg->outbuf, sizeof (mpg->outbuf),
|
||||
&mpg->outleft) == MP3_ERR)
|
||||
{
|
||||
free(mpg);
|
||||
BAIL_MACRO("MPGLIB: Not an MP3 stream?", 0);
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("MPGLIB: Accepting data stream.\n"));
|
||||
|
||||
internal->decoder_private = mpg;
|
||||
sample->actual.rate = mpglib_freqs[mpg->mp.fr.sampling_frequency];
|
||||
sample->actual.channels = mpg->mp.fr.stereo;
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
sample->flags = SOUND_SAMPLEFLAG_NONE;
|
||||
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* MPGLIB_open */
|
||||
|
||||
|
||||
static void MPGLIB_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
|
||||
ExitMP3(&mpg->mp);
|
||||
free(mpg);
|
||||
} /* MPGLIB_close */
|
||||
|
||||
|
||||
static Uint32 MPGLIB_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
|
||||
Uint32 bw = 0;
|
||||
int rc;
|
||||
|
||||
while (bw < internal->buffer_size)
|
||||
{
|
||||
if (mpg->outleft > 0)
|
||||
{
|
||||
size_t cpysize = internal->buffer_size - bw;
|
||||
if (cpysize > mpg->outleft)
|
||||
cpysize = mpg->outleft;
|
||||
memcpy(((Uint8 *) internal->buffer) + bw,
|
||||
mpg->outbuf + mpg->outpos, cpysize);
|
||||
bw += cpysize;
|
||||
mpg->outpos += cpysize;
|
||||
mpg->outleft -= cpysize;
|
||||
continue;
|
||||
} /* if */
|
||||
|
||||
/* need to decode more from the MP3 stream... */
|
||||
mpg->outpos = 0;
|
||||
rc = decodeMP3(&mpg->mp, NULL, 0, mpg->outbuf,
|
||||
sizeof (mpg->outbuf), &mpg->outleft);
|
||||
if (rc == MP3_ERR)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(bw);
|
||||
} /* if */
|
||||
|
||||
else if (rc == MP3_NEED_MORE)
|
||||
{
|
||||
rc = SDL_RWread(internal->rw, mpg->inbuf, 1, sizeof (mpg->inbuf));
|
||||
if (rc == -1)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(bw);
|
||||
} /* if */
|
||||
|
||||
else if (rc == 0)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(bw);
|
||||
} /* else if */
|
||||
|
||||
/* make sure there isn't an ID3 tag. */
|
||||
/*
|
||||
* !!! FIXME: This can fail under the following circumstances:
|
||||
* First, if there's the sequence "TAG" 128 bytes from the end
|
||||
* of a read that isn't the EOF. This is unlikely.
|
||||
* Second, if the TAG sequence is split between two reads (ie,
|
||||
* the last byte of a read is 'T', and the next read is the
|
||||
* final 127 bytes of the stream, being the rest of the ID3 tag).
|
||||
* While this is more likely, it's still not very likely at all.
|
||||
* Still, something SHOULD be done about this.
|
||||
* ID3v2 tags are more complex, too, not to mention LYRICS tags,
|
||||
* etc, which aren't handled, either. Hey, this IS meant to be
|
||||
* a lightweight decoder. Use SMPEG if you need an all-purpose
|
||||
* decoder. mpglib really assumes you control all your assets.
|
||||
*/
|
||||
if (rc >= 128)
|
||||
{
|
||||
Uint8 *ptr = &mpg->inbuf[rc - 128];
|
||||
if ((ptr[0] == 'T') && (ptr[1] == 'A') && (ptr[2] == 'G'))
|
||||
rc -= 128; /* disregard it. */
|
||||
} /* if */
|
||||
|
||||
rc = decodeMP3(&mpg->mp, mpg->inbuf, rc,
|
||||
mpg->outbuf, sizeof (mpg->outbuf),
|
||||
&mpg->outleft);
|
||||
if (rc == MP3_ERR)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(bw);
|
||||
} /* if */
|
||||
} /* else if */
|
||||
} /* while */
|
||||
|
||||
return(bw);
|
||||
} /* MPGLIB_read */
|
||||
|
||||
|
||||
static int MPGLIB_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
mpglib_t *mpg = ((mpglib_t *) internal->decoder_private);
|
||||
BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
|
||||
|
||||
/* this is just resetting some fields in a structure; it's very fast. */
|
||||
ExitMP3(&mpg->mp);
|
||||
InitMP3(&mpg->mp);
|
||||
mpg->outpos = mpg->outleft = 0;
|
||||
return(1);
|
||||
} /* MPGLIB_rewind */
|
||||
|
||||
|
||||
static int MPGLIB_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
BAIL_MACRO("MPGLIB: Seeking not implemented", 0);
|
||||
} /* MPGLIB_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_MPGLIB */
|
||||
|
||||
|
||||
/* end of mpglib.c ... */
|
||||
|
||||
4
project/jni/sdl_sound/decoders/mpglib/CHANGES
Normal file
4
project/jni/sdl_sound/decoders/mpglib/CHANGES
Normal file
@@ -0,0 +1,4 @@
|
||||
14/Oct/1999:
|
||||
- VBR fix
|
||||
- Layer2 and Layer1 added
|
||||
|
||||
39
project/jni/sdl_sound/decoders/mpglib/README
Normal file
39
project/jni/sdl_sound/decoders/mpglib/README
Normal file
@@ -0,0 +1,39 @@
|
||||
MP3 library
|
||||
-----------
|
||||
Version 0.2a
|
||||
|
||||
This decoder is a 'light' version (thrown out all unnecessay parts)
|
||||
from the mpg123 package. I made this for a company.
|
||||
|
||||
Currently only Layer3 is enabled to save some space. Layer1,2 isn't
|
||||
tested at all. The interface will not change significantly.
|
||||
A backport to the mpg123 package is planed.
|
||||
|
||||
compiled and tested only on Solaris 2.6
|
||||
main.c contains a simple demo application for library.
|
||||
|
||||
COPYING: you may use this source under LGPL terms!
|
||||
(Yes, I switched to LGPL for the _mpglib_ part!)
|
||||
|
||||
PLEASE NOTE: This software may contain patented algorithms (at least
|
||||
patented in some countries). It may be not allowed to sell/use products
|
||||
based on this source code in these countries. Check this out first!
|
||||
|
||||
COPYRIGHT of MP3 music:
|
||||
Please note, that the duplicating of copyrighted music without explicit
|
||||
permission violates the rights of the owner.
|
||||
|
||||
SENDING PATCHES:
|
||||
The current version is under LGPL. Please consider this when sending patches or
|
||||
changes. I also want to have the freedom to sell the code to companies that
|
||||
cannot or do not want to use the code under LGPL. So, if you send me
|
||||
significant patches, I need your explicit permission to do this. Of course,
|
||||
there will always be the LGPLed open source version of the 100% same code.
|
||||
In the case you cannot accept this: the code is free, it's your freedom
|
||||
to distribute your changes again under LGPL.
|
||||
|
||||
FEEDBACK:
|
||||
I'm interessted to here from you, when you use this package as part
|
||||
of another project.
|
||||
|
||||
|
||||
7
project/jni/sdl_sound/decoders/mpglib/README-sdlsound
Normal file
7
project/jni/sdl_sound/decoders/mpglib/README-sdlsound
Normal file
@@ -0,0 +1,7 @@
|
||||
This package, according to the README, is under the LGPL, which means it uses
|
||||
the same license as SDL_sound.
|
||||
|
||||
mpglib is part of mpg123, which can be found at http://www.mpg123.de/ ...
|
||||
|
||||
--ryan.
|
||||
|
||||
0
project/jni/sdl_sound/decoders/mpglib/TODO
Normal file
0
project/jni/sdl_sound/decoders/mpglib/TODO
Normal file
315
project/jni/sdl_sound/decoders/mpglib/dct64_i386.c
Normal file
315
project/jni/sdl_sound/decoders/mpglib/dct64_i386.c
Normal file
@@ -0,0 +1,315 @@
|
||||
|
||||
/*
|
||||
* Discrete Cosine Tansform (DCT) for subband synthesis
|
||||
* optimized for machines with no auto-increment.
|
||||
* The performance is highly compiler dependend. Maybe
|
||||
* the dct64.c version for 'normal' processor may be faster
|
||||
* even for Intel processors.
|
||||
*/
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
|
||||
static void dct64_1(real *out0,real *out1,real *b1,real *b2,real *samples)
|
||||
{
|
||||
|
||||
{
|
||||
register real *costab = pnts[0];
|
||||
|
||||
b1[0x00] = samples[0x00] + samples[0x1F];
|
||||
b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0];
|
||||
|
||||
b1[0x01] = samples[0x01] + samples[0x1E];
|
||||
b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1];
|
||||
|
||||
b1[0x02] = samples[0x02] + samples[0x1D];
|
||||
b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2];
|
||||
|
||||
b1[0x03] = samples[0x03] + samples[0x1C];
|
||||
b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3];
|
||||
|
||||
b1[0x04] = samples[0x04] + samples[0x1B];
|
||||
b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4];
|
||||
|
||||
b1[0x05] = samples[0x05] + samples[0x1A];
|
||||
b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5];
|
||||
|
||||
b1[0x06] = samples[0x06] + samples[0x19];
|
||||
b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6];
|
||||
|
||||
b1[0x07] = samples[0x07] + samples[0x18];
|
||||
b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7];
|
||||
|
||||
b1[0x08] = samples[0x08] + samples[0x17];
|
||||
b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8];
|
||||
|
||||
b1[0x09] = samples[0x09] + samples[0x16];
|
||||
b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9];
|
||||
|
||||
b1[0x0A] = samples[0x0A] + samples[0x15];
|
||||
b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA];
|
||||
|
||||
b1[0x0B] = samples[0x0B] + samples[0x14];
|
||||
b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB];
|
||||
|
||||
b1[0x0C] = samples[0x0C] + samples[0x13];
|
||||
b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC];
|
||||
|
||||
b1[0x0D] = samples[0x0D] + samples[0x12];
|
||||
b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD];
|
||||
|
||||
b1[0x0E] = samples[0x0E] + samples[0x11];
|
||||
b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE];
|
||||
|
||||
b1[0x0F] = samples[0x0F] + samples[0x10];
|
||||
b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF];
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
register real *costab = pnts[1];
|
||||
|
||||
b2[0x00] = b1[0x00] + b1[0x0F];
|
||||
b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0];
|
||||
b2[0x01] = b1[0x01] + b1[0x0E];
|
||||
b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1];
|
||||
b2[0x02] = b1[0x02] + b1[0x0D];
|
||||
b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2];
|
||||
b2[0x03] = b1[0x03] + b1[0x0C];
|
||||
b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3];
|
||||
b2[0x04] = b1[0x04] + b1[0x0B];
|
||||
b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4];
|
||||
b2[0x05] = b1[0x05] + b1[0x0A];
|
||||
b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5];
|
||||
b2[0x06] = b1[0x06] + b1[0x09];
|
||||
b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6];
|
||||
b2[0x07] = b1[0x07] + b1[0x08];
|
||||
b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7];
|
||||
|
||||
b2[0x10] = b1[0x10] + b1[0x1F];
|
||||
b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0];
|
||||
b2[0x11] = b1[0x11] + b1[0x1E];
|
||||
b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1];
|
||||
b2[0x12] = b1[0x12] + b1[0x1D];
|
||||
b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2];
|
||||
b2[0x13] = b1[0x13] + b1[0x1C];
|
||||
b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3];
|
||||
b2[0x14] = b1[0x14] + b1[0x1B];
|
||||
b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4];
|
||||
b2[0x15] = b1[0x15] + b1[0x1A];
|
||||
b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5];
|
||||
b2[0x16] = b1[0x16] + b1[0x19];
|
||||
b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6];
|
||||
b2[0x17] = b1[0x17] + b1[0x18];
|
||||
b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7];
|
||||
}
|
||||
|
||||
{
|
||||
register real *costab = pnts[2];
|
||||
|
||||
b1[0x00] = b2[0x00] + b2[0x07];
|
||||
b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0];
|
||||
b1[0x01] = b2[0x01] + b2[0x06];
|
||||
b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1];
|
||||
b1[0x02] = b2[0x02] + b2[0x05];
|
||||
b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2];
|
||||
b1[0x03] = b2[0x03] + b2[0x04];
|
||||
b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3];
|
||||
|
||||
b1[0x08] = b2[0x08] + b2[0x0F];
|
||||
b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0];
|
||||
b1[0x09] = b2[0x09] + b2[0x0E];
|
||||
b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1];
|
||||
b1[0x0A] = b2[0x0A] + b2[0x0D];
|
||||
b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2];
|
||||
b1[0x0B] = b2[0x0B] + b2[0x0C];
|
||||
b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3];
|
||||
|
||||
b1[0x10] = b2[0x10] + b2[0x17];
|
||||
b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0];
|
||||
b1[0x11] = b2[0x11] + b2[0x16];
|
||||
b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1];
|
||||
b1[0x12] = b2[0x12] + b2[0x15];
|
||||
b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2];
|
||||
b1[0x13] = b2[0x13] + b2[0x14];
|
||||
b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3];
|
||||
|
||||
b1[0x18] = b2[0x18] + b2[0x1F];
|
||||
b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0];
|
||||
b1[0x19] = b2[0x19] + b2[0x1E];
|
||||
b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1];
|
||||
b1[0x1A] = b2[0x1A] + b2[0x1D];
|
||||
b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2];
|
||||
b1[0x1B] = b2[0x1B] + b2[0x1C];
|
||||
b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3];
|
||||
}
|
||||
|
||||
{
|
||||
register real const cos0 = pnts[3][0];
|
||||
register real const cos1 = pnts[3][1];
|
||||
|
||||
b2[0x00] = b1[0x00] + b1[0x03];
|
||||
b2[0x03] = (b1[0x00] - b1[0x03]) * cos0;
|
||||
b2[0x01] = b1[0x01] + b1[0x02];
|
||||
b2[0x02] = (b1[0x01] - b1[0x02]) * cos1;
|
||||
|
||||
b2[0x04] = b1[0x04] + b1[0x07];
|
||||
b2[0x07] = (b1[0x07] - b1[0x04]) * cos0;
|
||||
b2[0x05] = b1[0x05] + b1[0x06];
|
||||
b2[0x06] = (b1[0x06] - b1[0x05]) * cos1;
|
||||
|
||||
b2[0x08] = b1[0x08] + b1[0x0B];
|
||||
b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0;
|
||||
b2[0x09] = b1[0x09] + b1[0x0A];
|
||||
b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1;
|
||||
|
||||
b2[0x0C] = b1[0x0C] + b1[0x0F];
|
||||
b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0;
|
||||
b2[0x0D] = b1[0x0D] + b1[0x0E];
|
||||
b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1;
|
||||
|
||||
b2[0x10] = b1[0x10] + b1[0x13];
|
||||
b2[0x13] = (b1[0x10] - b1[0x13]) * cos0;
|
||||
b2[0x11] = b1[0x11] + b1[0x12];
|
||||
b2[0x12] = (b1[0x11] - b1[0x12]) * cos1;
|
||||
|
||||
b2[0x14] = b1[0x14] + b1[0x17];
|
||||
b2[0x17] = (b1[0x17] - b1[0x14]) * cos0;
|
||||
b2[0x15] = b1[0x15] + b1[0x16];
|
||||
b2[0x16] = (b1[0x16] - b1[0x15]) * cos1;
|
||||
|
||||
b2[0x18] = b1[0x18] + b1[0x1B];
|
||||
b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0;
|
||||
b2[0x19] = b1[0x19] + b1[0x1A];
|
||||
b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1;
|
||||
|
||||
b2[0x1C] = b1[0x1C] + b1[0x1F];
|
||||
b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0;
|
||||
b2[0x1D] = b1[0x1D] + b1[0x1E];
|
||||
b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1;
|
||||
}
|
||||
|
||||
{
|
||||
register real const cos0 = pnts[4][0];
|
||||
|
||||
b1[0x00] = b2[0x00] + b2[0x01];
|
||||
b1[0x01] = (b2[0x00] - b2[0x01]) * cos0;
|
||||
b1[0x02] = b2[0x02] + b2[0x03];
|
||||
b1[0x03] = (b2[0x03] - b2[0x02]) * cos0;
|
||||
b1[0x02] += b1[0x03];
|
||||
|
||||
b1[0x04] = b2[0x04] + b2[0x05];
|
||||
b1[0x05] = (b2[0x04] - b2[0x05]) * cos0;
|
||||
b1[0x06] = b2[0x06] + b2[0x07];
|
||||
b1[0x07] = (b2[0x07] - b2[0x06]) * cos0;
|
||||
b1[0x06] += b1[0x07];
|
||||
b1[0x04] += b1[0x06];
|
||||
b1[0x06] += b1[0x05];
|
||||
b1[0x05] += b1[0x07];
|
||||
|
||||
b1[0x08] = b2[0x08] + b2[0x09];
|
||||
b1[0x09] = (b2[0x08] - b2[0x09]) * cos0;
|
||||
b1[0x0A] = b2[0x0A] + b2[0x0B];
|
||||
b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0;
|
||||
b1[0x0A] += b1[0x0B];
|
||||
|
||||
b1[0x0C] = b2[0x0C] + b2[0x0D];
|
||||
b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0;
|
||||
b1[0x0E] = b2[0x0E] + b2[0x0F];
|
||||
b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0;
|
||||
b1[0x0E] += b1[0x0F];
|
||||
b1[0x0C] += b1[0x0E];
|
||||
b1[0x0E] += b1[0x0D];
|
||||
b1[0x0D] += b1[0x0F];
|
||||
|
||||
b1[0x10] = b2[0x10] + b2[0x11];
|
||||
b1[0x11] = (b2[0x10] - b2[0x11]) * cos0;
|
||||
b1[0x12] = b2[0x12] + b2[0x13];
|
||||
b1[0x13] = (b2[0x13] - b2[0x12]) * cos0;
|
||||
b1[0x12] += b1[0x13];
|
||||
|
||||
b1[0x14] = b2[0x14] + b2[0x15];
|
||||
b1[0x15] = (b2[0x14] - b2[0x15]) * cos0;
|
||||
b1[0x16] = b2[0x16] + b2[0x17];
|
||||
b1[0x17] = (b2[0x17] - b2[0x16]) * cos0;
|
||||
b1[0x16] += b1[0x17];
|
||||
b1[0x14] += b1[0x16];
|
||||
b1[0x16] += b1[0x15];
|
||||
b1[0x15] += b1[0x17];
|
||||
|
||||
b1[0x18] = b2[0x18] + b2[0x19];
|
||||
b1[0x19] = (b2[0x18] - b2[0x19]) * cos0;
|
||||
b1[0x1A] = b2[0x1A] + b2[0x1B];
|
||||
b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0;
|
||||
b1[0x1A] += b1[0x1B];
|
||||
|
||||
b1[0x1C] = b2[0x1C] + b2[0x1D];
|
||||
b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0;
|
||||
b1[0x1E] = b2[0x1E] + b2[0x1F];
|
||||
b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0;
|
||||
b1[0x1E] += b1[0x1F];
|
||||
b1[0x1C] += b1[0x1E];
|
||||
b1[0x1E] += b1[0x1D];
|
||||
b1[0x1D] += b1[0x1F];
|
||||
}
|
||||
|
||||
out0[0x10*16] = b1[0x00];
|
||||
out0[0x10*12] = b1[0x04];
|
||||
out0[0x10* 8] = b1[0x02];
|
||||
out0[0x10* 4] = b1[0x06];
|
||||
out0[0x10* 0] = b1[0x01];
|
||||
out1[0x10* 0] = b1[0x01];
|
||||
out1[0x10* 4] = b1[0x05];
|
||||
out1[0x10* 8] = b1[0x03];
|
||||
out1[0x10*12] = b1[0x07];
|
||||
|
||||
b1[0x08] += b1[0x0C];
|
||||
out0[0x10*14] = b1[0x08];
|
||||
b1[0x0C] += b1[0x0a];
|
||||
out0[0x10*10] = b1[0x0C];
|
||||
b1[0x0A] += b1[0x0E];
|
||||
out0[0x10* 6] = b1[0x0A];
|
||||
b1[0x0E] += b1[0x09];
|
||||
out0[0x10* 2] = b1[0x0E];
|
||||
b1[0x09] += b1[0x0D];
|
||||
out1[0x10* 2] = b1[0x09];
|
||||
b1[0x0D] += b1[0x0B];
|
||||
out1[0x10* 6] = b1[0x0D];
|
||||
b1[0x0B] += b1[0x0F];
|
||||
out1[0x10*10] = b1[0x0B];
|
||||
out1[0x10*14] = b1[0x0F];
|
||||
|
||||
b1[0x18] += b1[0x1C];
|
||||
out0[0x10*15] = b1[0x10] + b1[0x18];
|
||||
out0[0x10*13] = b1[0x18] + b1[0x14];
|
||||
b1[0x1C] += b1[0x1a];
|
||||
out0[0x10*11] = b1[0x14] + b1[0x1C];
|
||||
out0[0x10* 9] = b1[0x1C] + b1[0x12];
|
||||
b1[0x1A] += b1[0x1E];
|
||||
out0[0x10* 7] = b1[0x12] + b1[0x1A];
|
||||
out0[0x10* 5] = b1[0x1A] + b1[0x16];
|
||||
b1[0x1E] += b1[0x19];
|
||||
out0[0x10* 3] = b1[0x16] + b1[0x1E];
|
||||
out0[0x10* 1] = b1[0x1E] + b1[0x11];
|
||||
b1[0x19] += b1[0x1D];
|
||||
out1[0x10* 1] = b1[0x11] + b1[0x19];
|
||||
out1[0x10* 3] = b1[0x19] + b1[0x15];
|
||||
b1[0x1D] += b1[0x1B];
|
||||
out1[0x10* 5] = b1[0x15] + b1[0x1D];
|
||||
out1[0x10* 7] = b1[0x1D] + b1[0x13];
|
||||
b1[0x1B] += b1[0x1F];
|
||||
out1[0x10* 9] = b1[0x13] + b1[0x1B];
|
||||
out1[0x10*11] = b1[0x1B] + b1[0x17];
|
||||
out1[0x10*13] = b1[0x17] + b1[0x1F];
|
||||
out1[0x10*15] = b1[0x1F];
|
||||
}
|
||||
|
||||
/*
|
||||
* the call via dct64 is a trick to force GCC to use
|
||||
* (new) registers for the b1,b2 pointer to the bufs[xx] field
|
||||
*/
|
||||
void dct64(real *a,real *b,real *c)
|
||||
{
|
||||
real bufs[0x40];
|
||||
dct64_1(a,b,bufs,bufs+0x20,c);
|
||||
}
|
||||
|
||||
153
project/jni/sdl_sound/decoders/mpglib/decode_i386.c
Normal file
153
project/jni/sdl_sound/decoders/mpglib/decode_i386.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Mpeg Layer-1,2,3 audio decoder
|
||||
* ------------------------------
|
||||
* copyright (c) 1995,1996,1997 by Michael Hipp, All rights reserved.
|
||||
* See also 'README'
|
||||
*
|
||||
* slighlty optimized for machines without autoincrement/decrement.
|
||||
* The performance is highly compiler dependend. Maybe
|
||||
* the decode.c version for 'normal' processor may be faster
|
||||
* even for Intel processors.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
#include "mpglib_sdlsound.h"
|
||||
|
||||
/* old WRITE_SAMPLE */
|
||||
#define WRITE_SAMPLE(samples,sum,clip) \
|
||||
if( (sum) > 32767.0) { *(samples) = 0x7fff; (clip)++; } \
|
||||
else if( (sum) < -32768.0) { *(samples) = -0x8000; (clip)++; } \
|
||||
else { *(samples) = sum; }
|
||||
|
||||
int synth_1to1_mono(real *bandPtr,unsigned char *samples,
|
||||
int *pnt, struct mpstr *mp)
|
||||
{
|
||||
short samples_tmp[64];
|
||||
short *tmp1 = samples_tmp;
|
||||
int i,ret;
|
||||
int pnt1 = 0;
|
||||
|
||||
ret = synth_1to1(bandPtr,0,(unsigned char *) samples_tmp,&pnt1,mp);
|
||||
samples += *pnt;
|
||||
|
||||
for(i=0;i<32;i++) {
|
||||
*( (short *) samples) = *tmp1;
|
||||
samples += 2;
|
||||
tmp1 += 2;
|
||||
}
|
||||
*pnt += 64;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int synth_1to1(real *bandPtr,int channel,unsigned char *out,
|
||||
int *pnt, struct mpstr *mp)
|
||||
{
|
||||
static const int step = 2;
|
||||
int bo;
|
||||
short *samples = (short *) (out + *pnt);
|
||||
|
||||
real *b0,(*buf)[0x110];
|
||||
int clip = 0;
|
||||
int bo1;
|
||||
|
||||
bo = mp->synth_bo;
|
||||
|
||||
if(!channel) {
|
||||
bo--;
|
||||
bo &= 0xf;
|
||||
buf = mp->synth_buffs[0];
|
||||
}
|
||||
else {
|
||||
samples++;
|
||||
buf = mp->synth_buffs[1];
|
||||
}
|
||||
|
||||
if(bo & 0x1) {
|
||||
b0 = buf[0];
|
||||
bo1 = bo;
|
||||
dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr);
|
||||
}
|
||||
else {
|
||||
b0 = buf[1];
|
||||
bo1 = bo+1;
|
||||
dct64(buf[0]+bo,buf[1]+bo+1,bandPtr);
|
||||
}
|
||||
|
||||
mp->synth_bo = bo;
|
||||
|
||||
{
|
||||
register int j;
|
||||
real *window = decwin + 16 - bo1;
|
||||
|
||||
for (j=16;j;j--,b0+=0x10,window+=0x20,samples+=step)
|
||||
{
|
||||
real sum;
|
||||
sum = window[0x0] * b0[0x0];
|
||||
sum -= window[0x1] * b0[0x1];
|
||||
sum += window[0x2] * b0[0x2];
|
||||
sum -= window[0x3] * b0[0x3];
|
||||
sum += window[0x4] * b0[0x4];
|
||||
sum -= window[0x5] * b0[0x5];
|
||||
sum += window[0x6] * b0[0x6];
|
||||
sum -= window[0x7] * b0[0x7];
|
||||
sum += window[0x8] * b0[0x8];
|
||||
sum -= window[0x9] * b0[0x9];
|
||||
sum += window[0xA] * b0[0xA];
|
||||
sum -= window[0xB] * b0[0xB];
|
||||
sum += window[0xC] * b0[0xC];
|
||||
sum -= window[0xD] * b0[0xD];
|
||||
sum += window[0xE] * b0[0xE];
|
||||
sum -= window[0xF] * b0[0xF];
|
||||
|
||||
WRITE_SAMPLE(samples,sum,clip);
|
||||
}
|
||||
|
||||
{
|
||||
real sum;
|
||||
sum = window[0x0] * b0[0x0];
|
||||
sum += window[0x2] * b0[0x2];
|
||||
sum += window[0x4] * b0[0x4];
|
||||
sum += window[0x6] * b0[0x6];
|
||||
sum += window[0x8] * b0[0x8];
|
||||
sum += window[0xA] * b0[0xA];
|
||||
sum += window[0xC] * b0[0xC];
|
||||
sum += window[0xE] * b0[0xE];
|
||||
WRITE_SAMPLE(samples,sum,clip);
|
||||
b0-=0x10,window-=0x20,samples+=step;
|
||||
}
|
||||
window += bo1<<1;
|
||||
|
||||
for (j=15;j;j--,b0-=0x10,window-=0x20,samples+=step)
|
||||
{
|
||||
real sum;
|
||||
sum = -window[-0x1] * b0[0x0];
|
||||
sum -= window[-0x2] * b0[0x1];
|
||||
sum -= window[-0x3] * b0[0x2];
|
||||
sum -= window[-0x4] * b0[0x3];
|
||||
sum -= window[-0x5] * b0[0x4];
|
||||
sum -= window[-0x6] * b0[0x5];
|
||||
sum -= window[-0x7] * b0[0x6];
|
||||
sum -= window[-0x8] * b0[0x7];
|
||||
sum -= window[-0x9] * b0[0x8];
|
||||
sum -= window[-0xA] * b0[0x9];
|
||||
sum -= window[-0xB] * b0[0xA];
|
||||
sum -= window[-0xC] * b0[0xB];
|
||||
sum -= window[-0xD] * b0[0xC];
|
||||
sum -= window[-0xE] * b0[0xD];
|
||||
sum -= window[-0xF] * b0[0xE];
|
||||
sum -= window[-0x0] * b0[0xF];
|
||||
|
||||
WRITE_SAMPLE(samples,sum,clip);
|
||||
}
|
||||
}
|
||||
*pnt += 128;
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
332
project/jni/sdl_sound/decoders/mpglib/huffman.h
Normal file
332
project/jni/sdl_sound/decoders/mpglib/huffman.h
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* huffman tables ... recalcualted to work with my optimzed
|
||||
* decoder scheme (MH)
|
||||
*
|
||||
* probably we could save a few bytes of memory, because the
|
||||
* smaller tables are often the part of a bigger table
|
||||
*/
|
||||
|
||||
struct newhuff
|
||||
{
|
||||
unsigned int linbits;
|
||||
short *table;
|
||||
};
|
||||
|
||||
static short tab0[] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
static short tab1[] =
|
||||
{
|
||||
-5, -3, -1, 17, 1, 16, 0
|
||||
};
|
||||
|
||||
static short tab2[] =
|
||||
{
|
||||
-15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1,
|
||||
16, 0
|
||||
};
|
||||
|
||||
static short tab3[] =
|
||||
{
|
||||
-13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1,
|
||||
1, 0
|
||||
};
|
||||
|
||||
static short tab5[] =
|
||||
{
|
||||
-29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19,
|
||||
3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab6[] =
|
||||
{
|
||||
-25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19,
|
||||
49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab7[] =
|
||||
{
|
||||
-69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83,
|
||||
-1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1,
|
||||
80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7,
|
||||
-3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18,
|
||||
-5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0
|
||||
};
|
||||
|
||||
static short tab8[] =
|
||||
{
|
||||
-65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83,
|
||||
-3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52,
|
||||
67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4,
|
||||
64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1,
|
||||
2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0
|
||||
};
|
||||
|
||||
static short tab9[] =
|
||||
{
|
||||
-63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1,
|
||||
84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67,
|
||||
-1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5,
|
||||
-3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2,
|
||||
18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0
|
||||
};
|
||||
|
||||
static short tab10[] =
|
||||
{
|
||||
-125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118,
|
||||
87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3,
|
||||
-1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1,
|
||||
100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23,
|
||||
-17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81,
|
||||
-1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7,
|
||||
-3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1,
|
||||
50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1,
|
||||
2, 32, 17, -1, 1, 16, 0
|
||||
};
|
||||
|
||||
static short tab11[] =
|
||||
{
|
||||
-121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117,
|
||||
-3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55,
|
||||
-1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114,
|
||||
-1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96,
|
||||
-1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38,
|
||||
6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1,
|
||||
36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50,
|
||||
-1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2,
|
||||
32, 17, -3, -1, 1, 16, 0
|
||||
};
|
||||
|
||||
static short tab12[] =
|
||||
{
|
||||
-115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87,
|
||||
117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115,
|
||||
85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7,
|
||||
112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5,
|
||||
-1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37,
|
||||
82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4,
|
||||
36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3,
|
||||
-1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1,
|
||||
2, 32, 0, 17, -1, 1, 16
|
||||
};
|
||||
|
||||
static short tab13[] =
|
||||
{
|
||||
-509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9,
|
||||
-7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238,
|
||||
207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1,
|
||||
236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249,
|
||||
234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158,
|
||||
-5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1,
|
||||
203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245,
|
||||
231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1,
|
||||
63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15,
|
||||
-5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1,
|
||||
200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1,
|
||||
240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1,
|
||||
46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3,
|
||||
-1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1,
|
||||
198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5,
|
||||
-1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167,
|
||||
151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76,
|
||||
196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137,
|
||||
28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106,
|
||||
-5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43,
|
||||
-1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178,
|
||||
-11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1,
|
||||
58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161,
|
||||
-3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88,
|
||||
-1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1,
|
||||
131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25,
|
||||
145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100,
|
||||
40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113,
|
||||
-1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38,
|
||||
-1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6,
|
||||
96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81,
|
||||
-7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11,
|
||||
-5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3,
|
||||
-1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab15[] =
|
||||
{
|
||||
-495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239,
|
||||
-1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237,
|
||||
191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3,
|
||||
-1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219,
|
||||
-3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173,
|
||||
-3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246,
|
||||
-3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9,
|
||||
-3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243,
|
||||
216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1,
|
||||
31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1,
|
||||
125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3,
|
||||
-1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5,
|
||||
-1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124,
|
||||
199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1,
|
||||
198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183,
|
||||
-5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76,
|
||||
-1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1,
|
||||
122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15,
|
||||
-7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106,
|
||||
-5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5,
|
||||
-1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74,
|
||||
-1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1,
|
||||
42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134,
|
||||
73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29,
|
||||
-13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7,
|
||||
-3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7,
|
||||
-3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86,
|
||||
-3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100,
|
||||
23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69,
|
||||
-1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9,
|
||||
-5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1,
|
||||
5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20,
|
||||
4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48,
|
||||
34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab16[] =
|
||||
{
|
||||
-509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223,
|
||||
253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3,
|
||||
-1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5,
|
||||
-3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19,
|
||||
-13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1,
|
||||
238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5,
|
||||
-1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125,
|
||||
94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13,
|
||||
-5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3,
|
||||
-1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186,
|
||||
-1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1,
|
||||
214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169,
|
||||
-5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213,
|
||||
-3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154,
|
||||
108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1,
|
||||
153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1,
|
||||
192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45,
|
||||
-1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107,
|
||||
-1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12,
|
||||
-1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1,
|
||||
178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74,
|
||||
164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33,
|
||||
-19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3,
|
||||
-1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147,
|
||||
-1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1,
|
||||
145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3,
|
||||
-1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1,
|
||||
8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3,
|
||||
-1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1,
|
||||
99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9,
|
||||
-5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33,
|
||||
-23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20,
|
||||
-5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1,
|
||||
3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab24[] =
|
||||
{
|
||||
-451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1,
|
||||
207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9,
|
||||
-5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79,
|
||||
244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31,
|
||||
240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1,
|
||||
236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3,
|
||||
-1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3,
|
||||
-1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235,
|
||||
-143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3,
|
||||
-1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9,
|
||||
-5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1,
|
||||
78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185,
|
||||
170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199,
|
||||
77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3,
|
||||
-1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3,
|
||||
-1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196,
|
||||
-3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1,
|
||||
167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1,
|
||||
137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10,
|
||||
26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9,
|
||||
144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165,
|
||||
27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135,
|
||||
-1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104,
|
||||
-1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3,
|
||||
-1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3,
|
||||
-1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7,
|
||||
-3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86,
|
||||
101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15,
|
||||
-7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84,
|
||||
-7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1,
|
||||
83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5,
|
||||
80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5,
|
||||
-1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1,
|
||||
3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab_c0[] =
|
||||
{
|
||||
-29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5,
|
||||
9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8,
|
||||
0
|
||||
};
|
||||
|
||||
static short tab_c1[] =
|
||||
{
|
||||
-15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9,
|
||||
8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct newhuff ht[] =
|
||||
{
|
||||
{ /* 0 */ 0 , tab0 } ,
|
||||
{ /* 2 */ 0 , tab1 } ,
|
||||
{ /* 3 */ 0 , tab2 } ,
|
||||
{ /* 3 */ 0 , tab3 } ,
|
||||
{ /* 0 */ 0 , tab0 } ,
|
||||
{ /* 4 */ 0 , tab5 } ,
|
||||
{ /* 4 */ 0 , tab6 } ,
|
||||
{ /* 6 */ 0 , tab7 } ,
|
||||
{ /* 6 */ 0 , tab8 } ,
|
||||
{ /* 6 */ 0 , tab9 } ,
|
||||
{ /* 8 */ 0 , tab10 } ,
|
||||
{ /* 8 */ 0 , tab11 } ,
|
||||
{ /* 8 */ 0 , tab12 } ,
|
||||
{ /* 16 */ 0 , tab13 } ,
|
||||
{ /* 0 */ 0 , tab0 } ,
|
||||
{ /* 16 */ 0 , tab15 } ,
|
||||
|
||||
{ /* 16 */ 1 , tab16 } ,
|
||||
{ /* 16 */ 2 , tab16 } ,
|
||||
{ /* 16 */ 3 , tab16 } ,
|
||||
{ /* 16 */ 4 , tab16 } ,
|
||||
{ /* 16 */ 6 , tab16 } ,
|
||||
{ /* 16 */ 8 , tab16 } ,
|
||||
{ /* 16 */ 10, tab16 } ,
|
||||
{ /* 16 */ 13, tab16 } ,
|
||||
{ /* 16 */ 4 , tab24 } ,
|
||||
{ /* 16 */ 5 , tab24 } ,
|
||||
{ /* 16 */ 6 , tab24 } ,
|
||||
{ /* 16 */ 7 , tab24 } ,
|
||||
{ /* 16 */ 8 , tab24 } ,
|
||||
{ /* 16 */ 9 , tab24 } ,
|
||||
{ /* 16 */ 11, tab24 } ,
|
||||
{ /* 16 */ 13, tab24 }
|
||||
};
|
||||
|
||||
static struct newhuff htc[] =
|
||||
{
|
||||
{ /* 1 , 1 , */ 0 , tab_c0 } ,
|
||||
{ /* 1 , 1 , */ 0 , tab_c1 }
|
||||
};
|
||||
|
||||
|
||||
243
project/jni/sdl_sound/decoders/mpglib/interface.c
Normal file
243
project/jni/sdl_sound/decoders/mpglib/interface.c
Normal file
@@ -0,0 +1,243 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
#include "mpglib_sdlsound.h"
|
||||
|
||||
|
||||
BOOL InitMP3(struct mpstr *mp)
|
||||
{
|
||||
static int init = 0;
|
||||
|
||||
memset(mp,0,sizeof(struct mpstr));
|
||||
|
||||
mp->framesize = 0;
|
||||
mp->fsizeold = -1;
|
||||
mp->bsize = 0;
|
||||
mp->head = mp->tail = NULL;
|
||||
mp->fr.single = -1;
|
||||
mp->bsnum = 0;
|
||||
mp->synth_bo = 1;
|
||||
|
||||
if(!init) {
|
||||
init = 1;
|
||||
make_decode_tables(32767);
|
||||
init_layer2();
|
||||
init_layer3(SBLIMIT);
|
||||
}
|
||||
|
||||
return !0;
|
||||
}
|
||||
|
||||
void ExitMP3(struct mpstr *mp)
|
||||
{
|
||||
struct buf *b,*bn;
|
||||
|
||||
b = mp->tail;
|
||||
while(b) {
|
||||
free(b->pnt);
|
||||
bn = b->next;
|
||||
free(b);
|
||||
b = bn;
|
||||
}
|
||||
}
|
||||
|
||||
static struct buf *addbuf(struct mpstr *mp,char *buf,int size)
|
||||
{
|
||||
struct buf *nbuf;
|
||||
|
||||
nbuf = malloc( sizeof(struct buf) );
|
||||
BAIL_IF_MACRO(!nbuf, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
nbuf->pnt = malloc(size);
|
||||
if(!nbuf->pnt) {
|
||||
free(nbuf);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
nbuf->size = size;
|
||||
memcpy(nbuf->pnt,buf,size);
|
||||
nbuf->next = NULL;
|
||||
nbuf->prev = mp->head;
|
||||
nbuf->pos = 0;
|
||||
|
||||
if(!mp->tail) {
|
||||
mp->tail = nbuf;
|
||||
}
|
||||
else {
|
||||
mp->head->next = nbuf;
|
||||
}
|
||||
|
||||
mp->head = nbuf;
|
||||
mp->bsize += size;
|
||||
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
static void remove_buf(struct mpstr *mp)
|
||||
{
|
||||
struct buf *buf = mp->tail;
|
||||
|
||||
mp->tail = buf->next;
|
||||
if(mp->tail)
|
||||
mp->tail->prev = NULL;
|
||||
else {
|
||||
mp->tail = mp->head = NULL;
|
||||
}
|
||||
|
||||
free(buf->pnt);
|
||||
free(buf);
|
||||
|
||||
}
|
||||
|
||||
static int read_buf_byte(struct mpstr *mp, unsigned long *retval)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = mp->tail->pos;
|
||||
while(pos >= mp->tail->size) {
|
||||
remove_buf(mp);
|
||||
pos = mp->tail->pos;
|
||||
if(!mp->tail) {
|
||||
BAIL_MACRO("MPGLIB: Short read in read_buf_byte()!", 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (retval != NULL)
|
||||
*retval = mp->tail->pnt[pos];
|
||||
|
||||
mp->bsize--;
|
||||
mp->tail->pos++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_head(struct mpstr *mp)
|
||||
{
|
||||
unsigned long val;
|
||||
unsigned long head;
|
||||
|
||||
if (!read_buf_byte(mp, &val))
|
||||
return 0;
|
||||
|
||||
head = val << 8;
|
||||
|
||||
if (!read_buf_byte(mp, &val))
|
||||
return 0;
|
||||
|
||||
head |= val;
|
||||
head <<= 8;
|
||||
|
||||
if (!read_buf_byte(mp, &val))
|
||||
return 0;
|
||||
|
||||
head |= val;
|
||||
head <<= 8;
|
||||
|
||||
if (!read_buf_byte(mp, &val))
|
||||
return 0;
|
||||
|
||||
head |= val;
|
||||
mp->header = head;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decodeMP3(struct mpstr *mp,char *in,int isize,char *out,
|
||||
int osize,int *done)
|
||||
{
|
||||
int len;
|
||||
|
||||
BAIL_IF_MACRO(osize < 4608, "MPGLIB: Output buffer too small", MP3_ERR);
|
||||
|
||||
if(in) {
|
||||
if(addbuf(mp,in,isize) == NULL) {
|
||||
return MP3_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* First decode header */
|
||||
if(mp->framesize == 0) {
|
||||
if(mp->bsize < 4) {
|
||||
return MP3_NEED_MORE;
|
||||
}
|
||||
|
||||
if (!read_head(mp))
|
||||
return MP3_ERR;
|
||||
|
||||
if (!decode_header(&mp->fr,mp->header))
|
||||
return MP3_ERR;
|
||||
|
||||
mp->framesize = mp->fr.framesize;
|
||||
}
|
||||
|
||||
if(mp->fr.framesize > mp->bsize)
|
||||
return MP3_NEED_MORE;
|
||||
|
||||
wordpointer = mp->bsspace[mp->bsnum] + 512;
|
||||
mp->bsnum = (mp->bsnum + 1) & 0x1;
|
||||
bitindex = 0;
|
||||
|
||||
len = 0;
|
||||
while(len < mp->framesize) {
|
||||
int nlen;
|
||||
int blen = mp->tail->size - mp->tail->pos;
|
||||
if( (mp->framesize - len) <= blen) {
|
||||
nlen = mp->framesize-len;
|
||||
}
|
||||
else {
|
||||
nlen = blen;
|
||||
}
|
||||
memcpy(wordpointer+len,mp->tail->pnt+mp->tail->pos,nlen);
|
||||
len += nlen;
|
||||
mp->tail->pos += nlen;
|
||||
mp->bsize -= nlen;
|
||||
if(mp->tail->pos == mp->tail->size) {
|
||||
remove_buf(mp);
|
||||
}
|
||||
}
|
||||
|
||||
*done = 0;
|
||||
if(mp->fr.error_protection)
|
||||
getbits(16);
|
||||
switch(mp->fr.lay) {
|
||||
case 1:
|
||||
do_layer1(&mp->fr,(unsigned char *) out,done,mp);
|
||||
break;
|
||||
case 2:
|
||||
do_layer2(&mp->fr,(unsigned char *) out,done,mp);
|
||||
break;
|
||||
case 3:
|
||||
do_layer3(&mp->fr,(unsigned char *) out,done,mp);
|
||||
break;
|
||||
}
|
||||
|
||||
mp->fsizeold = mp->framesize;
|
||||
mp->framesize = 0;
|
||||
|
||||
return MP3_OK;
|
||||
}
|
||||
|
||||
int set_pointer(long backstep, struct mpstr *mp)
|
||||
{
|
||||
unsigned char *bsbufold;
|
||||
if(mp->fsizeold < 0 && backstep > 0) {
|
||||
char err[128];
|
||||
snprintf(err, sizeof (err), "MPGLIB: Can't step back! %ld!", backstep);
|
||||
BAIL_MACRO(err, MP3_ERR);
|
||||
}
|
||||
bsbufold = mp->bsspace[mp->bsnum] + 512;
|
||||
wordpointer -= backstep;
|
||||
if (backstep)
|
||||
memcpy(wordpointer,bsbufold+mp->fsizeold-backstep,backstep);
|
||||
bitindex = 0;
|
||||
return MP3_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
160
project/jni/sdl_sound/decoders/mpglib/l2tables.h
Normal file
160
project/jni/sdl_sound/decoders/mpglib/l2tables.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Layer 2 Alloc tables ..
|
||||
* most other tables are calculated on program start (which is (of course)
|
||||
* not ISO-conform) ..
|
||||
* Layer-3 huffman table is in huffman.h
|
||||
*/
|
||||
|
||||
struct al_table
|
||||
{
|
||||
short bits;
|
||||
short d;
|
||||
};
|
||||
|
||||
struct al_table alloc_0[] = {
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767} };
|
||||
|
||||
struct al_table alloc_1[] = {
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511},
|
||||
{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767},
|
||||
{2,0},{5,3},{7,5},{16,-32767} };
|
||||
|
||||
struct al_table alloc_2[] = {
|
||||
{4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},
|
||||
{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},
|
||||
{4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},
|
||||
{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} };
|
||||
|
||||
struct al_table alloc_3[] = {
|
||||
{4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},
|
||||
{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},
|
||||
{4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},
|
||||
{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} };
|
||||
|
||||
struct al_table alloc_4[] = {
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},
|
||||
{4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},
|
||||
{9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9},
|
||||
{2,0},{5,3},{7,5},{10,9} };
|
||||
|
||||
148
project/jni/sdl_sound/decoders/mpglib/layer1.c
Normal file
148
project/jni/sdl_sound/decoders/mpglib/layer1.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Mpeg Layer-1 audio decoder
|
||||
* --------------------------
|
||||
* copyright (c) 1995 by Michael Hipp, All rights reserved. See also 'README'
|
||||
* near unoptimzed ...
|
||||
*
|
||||
* may have a few bugs after last optimization ...
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
|
||||
void I_step_one(unsigned int balloc[], unsigned int scale_index[2][SBLIMIT],struct frame *fr)
|
||||
{
|
||||
unsigned int *ba=balloc;
|
||||
unsigned int *sca = (unsigned int *) scale_index;
|
||||
|
||||
if(fr->stereo) {
|
||||
int i;
|
||||
int jsbound = fr->jsbound;
|
||||
for (i=0;i<jsbound;i++) {
|
||||
*ba++ = getbits(4);
|
||||
*ba++ = getbits(4);
|
||||
}
|
||||
for (i=jsbound;i<SBLIMIT;i++)
|
||||
*ba++ = getbits(4);
|
||||
|
||||
ba = balloc;
|
||||
|
||||
for (i=0;i<jsbound;i++) {
|
||||
if ((*ba++))
|
||||
*sca++ = getbits(6);
|
||||
if ((*ba++))
|
||||
*sca++ = getbits(6);
|
||||
}
|
||||
for (i=jsbound;i<SBLIMIT;i++)
|
||||
if ((*ba++)) {
|
||||
*sca++ = getbits(6);
|
||||
*sca++ = getbits(6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i=0;i<SBLIMIT;i++)
|
||||
*ba++ = getbits(4);
|
||||
ba = balloc;
|
||||
for (i=0;i<SBLIMIT;i++)
|
||||
if ((*ba++))
|
||||
*sca++ = getbits(6);
|
||||
}
|
||||
}
|
||||
|
||||
void I_step_two(real fraction[2][SBLIMIT],unsigned int balloc[2*SBLIMIT],
|
||||
unsigned int scale_index[2][SBLIMIT],struct frame *fr)
|
||||
{
|
||||
int i,n;
|
||||
int smpb[2*SBLIMIT]; /* values: 0-65535 */
|
||||
int *sample;
|
||||
register unsigned int *ba;
|
||||
register unsigned int *sca = (unsigned int *) scale_index;
|
||||
|
||||
if(fr->stereo) {
|
||||
int jsbound = fr->jsbound;
|
||||
register real *f0 = fraction[0];
|
||||
register real *f1 = fraction[1];
|
||||
ba = balloc;
|
||||
for (sample=smpb,i=0;i<jsbound;i++) {
|
||||
if ((n = *ba++))
|
||||
*sample++ = getbits(n+1);
|
||||
if ((n = *ba++))
|
||||
*sample++ = getbits(n+1);
|
||||
}
|
||||
for (i=jsbound;i<SBLIMIT;i++)
|
||||
if ((n = *ba++))
|
||||
*sample++ = getbits(n+1);
|
||||
|
||||
ba = balloc;
|
||||
for (sample=smpb,i=0;i<jsbound;i++) {
|
||||
if((n=*ba++))
|
||||
*f0++ = (real) ( ((-1)<<n) + (*sample++) + 1) * muls[n+1][*sca++];
|
||||
else
|
||||
*f0++ = 0.0;
|
||||
if((n=*ba++))
|
||||
*f1++ = (real) ( ((-1)<<n) + (*sample++) + 1) * muls[n+1][*sca++];
|
||||
else
|
||||
*f1++ = 0.0;
|
||||
}
|
||||
for (i=jsbound;i<SBLIMIT;i++) {
|
||||
if ((n=*ba++)) {
|
||||
real samp = ( ((-1)<<n) + (*sample++) + 1);
|
||||
*f0++ = samp * muls[n+1][*sca++];
|
||||
*f1++ = samp * muls[n+1][*sca++];
|
||||
}
|
||||
else
|
||||
*f0++ = *f1++ = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
register real *f0 = fraction[0];
|
||||
ba = balloc;
|
||||
for (sample=smpb,i=0;i<SBLIMIT;i++)
|
||||
if ((n = *ba++))
|
||||
*sample++ = getbits(n+1);
|
||||
ba = balloc;
|
||||
for (sample=smpb,i=0;i<SBLIMIT;i++) {
|
||||
if((n=*ba++))
|
||||
*f0++ = (real) ( ((-1)<<n) + (*sample++) + 1) * muls[n+1][*sca++];
|
||||
else
|
||||
*f0++ = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int do_layer1(struct frame *fr,unsigned char *pcm_sample,
|
||||
int *pcm_point,struct mpstr *mp)
|
||||
{
|
||||
int clip=0;
|
||||
int i,stereo = fr->stereo;
|
||||
unsigned int balloc[2*SBLIMIT];
|
||||
unsigned int scale_index[2][SBLIMIT];
|
||||
real fraction[2][SBLIMIT];
|
||||
int single = fr->single;
|
||||
|
||||
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext<<2)+4 : 32;
|
||||
|
||||
if(stereo == 1 || single == 3)
|
||||
single = 0;
|
||||
|
||||
I_step_one(balloc,scale_index,fr);
|
||||
|
||||
for (i=0;i<SCALE_BLOCK;i++)
|
||||
{
|
||||
I_step_two(fraction,balloc,scale_index,fr);
|
||||
|
||||
if(single >= 0) {
|
||||
clip += synth_1to1_mono( (real*)fraction[single],pcm_sample,pcm_point,mp);
|
||||
}
|
||||
else {
|
||||
int p1 = *pcm_point;
|
||||
clip += synth_1to1( (real*)fraction[0],0,pcm_sample,&p1,mp);
|
||||
clip += synth_1to1( (real*)fraction[1],1,pcm_sample,pcm_point,mp);
|
||||
}
|
||||
}
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
|
||||
289
project/jni/sdl_sound/decoders/mpglib/layer2.c
Normal file
289
project/jni/sdl_sound/decoders/mpglib/layer2.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Mpeg Layer-2 audio decoder
|
||||
* --------------------------
|
||||
* copyright (c) 1995 by Michael Hipp, All rights reserved. See also 'README'
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
#include "l2tables.h"
|
||||
|
||||
static int grp_3tab[32 * 3] = { 0, }; /* used: 27 */
|
||||
static int grp_5tab[128 * 3] = { 0, }; /* used: 125 */
|
||||
static int grp_9tab[1024 * 3] = { 0, }; /* used: 729 */
|
||||
|
||||
real muls[27][64]; /* also used by layer 1 */
|
||||
|
||||
void init_layer2(void)
|
||||
{
|
||||
static double mulmul[27] = {
|
||||
0.0 , -2.0/3.0 , 2.0/3.0 ,
|
||||
2.0/7.0 , 2.0/15.0 , 2.0/31.0, 2.0/63.0 , 2.0/127.0 , 2.0/255.0 ,
|
||||
2.0/511.0 , 2.0/1023.0 , 2.0/2047.0 , 2.0/4095.0 , 2.0/8191.0 ,
|
||||
2.0/16383.0 , 2.0/32767.0 , 2.0/65535.0 ,
|
||||
-4.0/5.0 , -2.0/5.0 , 2.0/5.0, 4.0/5.0 ,
|
||||
-8.0/9.0 , -4.0/9.0 , -2.0/9.0 , 2.0/9.0 , 4.0/9.0 , 8.0/9.0 };
|
||||
static int base[3][9] = {
|
||||
{ 1 , 0, 2 , } ,
|
||||
{ 17, 18, 0 , 19, 20 , } ,
|
||||
{ 21, 1, 22, 23, 0, 24, 25, 2, 26 } };
|
||||
int i,j,k,l,len;
|
||||
real *table;
|
||||
static int tablen[3] = { 3 , 5 , 9 };
|
||||
static int *itable,*tables[3] = { grp_3tab , grp_5tab , grp_9tab };
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
itable = tables[i];
|
||||
len = tablen[i];
|
||||
for(j=0;j<len;j++)
|
||||
for(k=0;k<len;k++)
|
||||
for(l=0;l<len;l++)
|
||||
{
|
||||
*itable++ = base[i][l];
|
||||
*itable++ = base[i][k];
|
||||
*itable++ = base[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for(k=0;k<27;k++)
|
||||
{
|
||||
double m=mulmul[k];
|
||||
table = muls[k];
|
||||
for(j=3,i=0;i<63;i++,j--)
|
||||
*table++ = m * pow(2.0,(double) j / 3.0);
|
||||
*table++ = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void II_step_one(unsigned int *bit_alloc,int *scale,struct frame *fr)
|
||||
{
|
||||
int stereo = fr->stereo-1;
|
||||
int sblimit = fr->II_sblimit;
|
||||
int jsbound = fr->jsbound;
|
||||
int sblimit2 = fr->II_sblimit<<stereo;
|
||||
struct al_table *alloc1 = fr->alloc;
|
||||
int i;
|
||||
static unsigned int scfsi_buf[64];
|
||||
unsigned int *scfsi,*bita;
|
||||
int sc,step;
|
||||
|
||||
bita = bit_alloc;
|
||||
if(stereo)
|
||||
{
|
||||
for (i=jsbound;i;i--,alloc1+=(1<<step))
|
||||
{
|
||||
*bita++ = (char) getbits(step=alloc1->bits);
|
||||
*bita++ = (char) getbits(step);
|
||||
}
|
||||
for (i=sblimit-jsbound;i;i--,alloc1+=(1<<step))
|
||||
{
|
||||
bita[0] = (char) getbits(step=alloc1->bits);
|
||||
bita[1] = bita[0];
|
||||
bita+=2;
|
||||
}
|
||||
bita = bit_alloc;
|
||||
scfsi=scfsi_buf;
|
||||
for (i=sblimit2;i;i--)
|
||||
if (*bita++)
|
||||
*scfsi++ = (char) getbits_fast(2);
|
||||
}
|
||||
else /* mono */
|
||||
{
|
||||
for (i=sblimit;i;i--,alloc1+=(1<<step))
|
||||
*bita++ = (char) getbits(step=alloc1->bits);
|
||||
bita = bit_alloc;
|
||||
scfsi=scfsi_buf;
|
||||
for (i=sblimit;i;i--)
|
||||
if (*bita++)
|
||||
*scfsi++ = (char) getbits_fast(2);
|
||||
}
|
||||
|
||||
bita = bit_alloc;
|
||||
scfsi=scfsi_buf;
|
||||
for (i=sblimit2;i;i--)
|
||||
if (*bita++)
|
||||
switch (*scfsi++)
|
||||
{
|
||||
case 0:
|
||||
*scale++ = getbits_fast(6);
|
||||
*scale++ = getbits_fast(6);
|
||||
*scale++ = getbits_fast(6);
|
||||
break;
|
||||
case 1 :
|
||||
*scale++ = sc = getbits_fast(6);
|
||||
*scale++ = sc;
|
||||
*scale++ = getbits_fast(6);
|
||||
break;
|
||||
case 2:
|
||||
*scale++ = sc = getbits_fast(6);
|
||||
*scale++ = sc;
|
||||
*scale++ = sc;
|
||||
break;
|
||||
default: /* case 3 */
|
||||
*scale++ = getbits_fast(6);
|
||||
*scale++ = sc = getbits_fast(6);
|
||||
*scale++ = sc;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void II_step_two(unsigned int *bit_alloc,real fraction[2][4][SBLIMIT],int *scale,struct frame *fr,int x1)
|
||||
{
|
||||
int i,j,k,ba;
|
||||
int stereo = fr->stereo;
|
||||
int sblimit = fr->II_sblimit;
|
||||
int jsbound = fr->jsbound;
|
||||
struct al_table *alloc2,*alloc1 = fr->alloc;
|
||||
unsigned int *bita=bit_alloc;
|
||||
int d1,step;
|
||||
|
||||
for (i=0;i<jsbound;i++,alloc1+=(1<<step))
|
||||
{
|
||||
step = alloc1->bits;
|
||||
for (j=0;j<stereo;j++)
|
||||
{
|
||||
if ( (ba=*bita++) )
|
||||
{
|
||||
k=(alloc2 = alloc1+ba)->bits;
|
||||
if( (d1=alloc2->d) < 0)
|
||||
{
|
||||
real cm=muls[k][scale[x1]];
|
||||
fraction[j][0][i] = ((real) ((int)getbits(k) + d1)) * cm;
|
||||
fraction[j][1][i] = ((real) ((int)getbits(k) + d1)) * cm;
|
||||
fraction[j][2][i] = ((real) ((int)getbits(k) + d1)) * cm;
|
||||
}
|
||||
else
|
||||
{
|
||||
static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab };
|
||||
unsigned int idx,*tab,m=scale[x1];
|
||||
idx = (unsigned int) getbits(k);
|
||||
tab = (unsigned int *) (table[d1] + idx + idx + idx);
|
||||
fraction[j][0][i] = muls[*tab++][m];
|
||||
fraction[j][1][i] = muls[*tab++][m];
|
||||
fraction[j][2][i] = muls[*tab][m];
|
||||
}
|
||||
scale+=3;
|
||||
}
|
||||
else
|
||||
fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=jsbound;i<sblimit;i++,alloc1+=(1<<step))
|
||||
{
|
||||
step = alloc1->bits;
|
||||
bita++; /* channel 1 and channel 2 bitalloc are the same */
|
||||
if ( (ba=*bita++) )
|
||||
{
|
||||
k=(alloc2 = alloc1+ba)->bits;
|
||||
if( (d1=alloc2->d) < 0)
|
||||
{
|
||||
real cm;
|
||||
cm=muls[k][scale[x1+3]];
|
||||
fraction[1][0][i] = (fraction[0][0][i] = (real) ((int)getbits(k) + d1) ) * cm;
|
||||
fraction[1][1][i] = (fraction[0][1][i] = (real) ((int)getbits(k) + d1) ) * cm;
|
||||
fraction[1][2][i] = (fraction[0][2][i] = (real) ((int)getbits(k) + d1) ) * cm;
|
||||
cm=muls[k][scale[x1]];
|
||||
fraction[0][0][i] *= cm; fraction[0][1][i] *= cm; fraction[0][2][i] *= cm;
|
||||
}
|
||||
else
|
||||
{
|
||||
static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab };
|
||||
unsigned int idx,*tab,m1,m2;
|
||||
m1 = scale[x1]; m2 = scale[x1+3];
|
||||
idx = (unsigned int) getbits(k);
|
||||
tab = (unsigned int *) (table[d1] + idx + idx + idx);
|
||||
fraction[0][0][i] = muls[*tab][m1]; fraction[1][0][i] = muls[*tab++][m2];
|
||||
fraction[0][1][i] = muls[*tab][m1]; fraction[1][1][i] = muls[*tab++][m2];
|
||||
fraction[0][2][i] = muls[*tab][m1]; fraction[1][2][i] = muls[*tab][m2];
|
||||
}
|
||||
scale+=6;
|
||||
}
|
||||
else {
|
||||
fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] =
|
||||
fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0;
|
||||
}
|
||||
/*
|
||||
should we use individual scalefac for channel 2 or
|
||||
is the current way the right one , where we just copy channel 1 to
|
||||
channel 2 ??
|
||||
The current 'strange' thing is, that we throw away the scalefac
|
||||
values for the second channel ...!!
|
||||
-> changed .. now we use the scalefac values of channel one !!
|
||||
*/
|
||||
}
|
||||
|
||||
for(i=sblimit;i<SBLIMIT;i++)
|
||||
for (j=0;j<stereo;j++)
|
||||
fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0;
|
||||
|
||||
}
|
||||
|
||||
static void II_select_table(struct frame *fr)
|
||||
{
|
||||
static int translate[3][2][16] =
|
||||
{ { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } ,
|
||||
{ 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } ,
|
||||
{ { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } ,
|
||||
{ 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } ,
|
||||
{ { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } ,
|
||||
{ 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } };
|
||||
|
||||
int table,sblim;
|
||||
static struct al_table *tables[5] =
|
||||
{ alloc_0, alloc_1, alloc_2, alloc_3 , alloc_4 };
|
||||
static int sblims[5] = { 27 , 30 , 8, 12 , 30 };
|
||||
|
||||
if(fr->lsf)
|
||||
table = 4;
|
||||
else
|
||||
table = translate[fr->sampling_frequency][2-fr->stereo][fr->bitrate_index];
|
||||
sblim = sblims[table];
|
||||
|
||||
fr->alloc = tables[table];
|
||||
fr->II_sblimit = sblim;
|
||||
}
|
||||
|
||||
int do_layer2(struct frame *fr,unsigned char *pcm_sample,
|
||||
int *pcm_point,struct mpstr *mp)
|
||||
{
|
||||
int clip=0;
|
||||
int i,j;
|
||||
int stereo = fr->stereo;
|
||||
real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */
|
||||
unsigned int bit_alloc[64];
|
||||
int scale[192];
|
||||
int single = fr->single;
|
||||
|
||||
II_select_table(fr);
|
||||
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
|
||||
(fr->mode_ext<<2)+4 : fr->II_sblimit;
|
||||
|
||||
if(stereo == 1 || single == 3)
|
||||
single = 0;
|
||||
|
||||
II_step_one(bit_alloc, scale, fr);
|
||||
|
||||
for (i=0;i<SCALE_BLOCK;i++)
|
||||
{
|
||||
II_step_two(bit_alloc,fraction,scale,fr,i>>2);
|
||||
for (j=0;j<3;j++) {
|
||||
if(single >= 0) {
|
||||
clip += synth_1to1_mono(fraction[0][j],pcm_sample,pcm_point,mp);
|
||||
}
|
||||
else {
|
||||
int p1 = *pcm_point;
|
||||
clip += synth_1to1(fraction[0][j],0,pcm_sample,&p1,mp);
|
||||
clip += synth_1to1(fraction[1][j],1,pcm_sample,pcm_point,mp);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
|
||||
2020
project/jni/sdl_sound/decoders/mpglib/layer3.c
Normal file
2020
project/jni/sdl_sound/decoders/mpglib/layer3.c
Normal file
File diff suppressed because it is too large
Load Diff
199
project/jni/sdl_sound/decoders/mpglib/mpg123_sdlsound.h
Normal file
199
project/jni/sdl_sound/decoders/mpglib/mpg123_sdlsound.h
Normal file
@@ -0,0 +1,199 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(WIN32) && !defined(macintosh) && !defined(_WIN32_WCE)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# undef WIN32
|
||||
# define WIN32
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(macintosh) || defined(_WIN32_WCE)
|
||||
|
||||
# define M_PI 3.14159265358979323846
|
||||
# define M_SQRT2 1.41421356237309504880
|
||||
# define REAL_IS_FLOAT
|
||||
# define NEW_DCT9
|
||||
|
||||
# define random rand
|
||||
# define srandom srand
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef REAL_IS_FLOAT
|
||||
# define real float
|
||||
#elif defined(REAL_IS_LONG_DOUBLE)
|
||||
# define real long double
|
||||
#else
|
||||
# define real double
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#elif ((defined _MSC_VER) || (defined __inline__))
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */
|
||||
#define AUDIOBUFSIZE 16384
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#define SBLIMIT 32
|
||||
#define SSLIMIT 18
|
||||
|
||||
#define SCALE_BLOCK 12
|
||||
|
||||
|
||||
#define MPG_MD_STEREO 0
|
||||
#define MPG_MD_JOINT_STEREO 1
|
||||
#define MPG_MD_DUAL_CHANNEL 2
|
||||
#define MPG_MD_MONO 3
|
||||
|
||||
#define MAXFRAMESIZE 1792
|
||||
|
||||
|
||||
/* Pre Shift fo 16 to 8 bit converter table */
|
||||
#define AUSHIFT (3)
|
||||
|
||||
struct frame {
|
||||
int stereo;
|
||||
int jsbound;
|
||||
int single;
|
||||
int lsf;
|
||||
int mpeg25;
|
||||
int header_change;
|
||||
int lay;
|
||||
int error_protection;
|
||||
int bitrate_index;
|
||||
int sampling_frequency;
|
||||
int padding;
|
||||
int extension;
|
||||
int mode;
|
||||
int mode_ext;
|
||||
int copyright;
|
||||
int original;
|
||||
int emphasis;
|
||||
int framesize; /* computed framesize */
|
||||
|
||||
/* layer2 stuff */
|
||||
int II_sblimit;
|
||||
void *alloc;
|
||||
};
|
||||
|
||||
struct parameter {
|
||||
int quiet; /* shut up! */
|
||||
int tryresync; /* resync stream after error */
|
||||
int verbose; /* verbose level */
|
||||
int checkrange;
|
||||
};
|
||||
|
||||
struct mpstr; /* forward declaration. */
|
||||
|
||||
extern unsigned int get1bit(void);
|
||||
extern unsigned int getbits(int);
|
||||
extern unsigned int getbits_fast(int);
|
||||
extern int set_pointer(long,struct mpstr *);
|
||||
|
||||
extern unsigned char *wordpointer;
|
||||
extern int bitindex;
|
||||
|
||||
extern void make_decode_tables(long scaleval);
|
||||
extern int do_layer3(struct frame *fr,unsigned char *,int *,struct mpstr *);
|
||||
extern int do_layer2(struct frame *fr,unsigned char *,int *,struct mpstr *);
|
||||
extern int do_layer1(struct frame *fr,unsigned char *,int *,struct mpstr *);
|
||||
extern int decode_header(struct frame *fr,unsigned long newhead);
|
||||
|
||||
|
||||
|
||||
struct gr_info_s {
|
||||
int scfsi;
|
||||
unsigned part2_3_length;
|
||||
unsigned big_values;
|
||||
unsigned scalefac_compress;
|
||||
unsigned block_type;
|
||||
unsigned mixed_block_flag;
|
||||
unsigned table_select[3];
|
||||
unsigned subblock_gain[3];
|
||||
unsigned maxband[3];
|
||||
unsigned maxbandl;
|
||||
unsigned maxb;
|
||||
unsigned region1start;
|
||||
unsigned region2start;
|
||||
unsigned preflag;
|
||||
unsigned scalefac_scale;
|
||||
unsigned count1table_select;
|
||||
real *full_gain[3];
|
||||
real *pow2gain;
|
||||
};
|
||||
|
||||
struct III_sideinfo
|
||||
{
|
||||
unsigned main_data_begin;
|
||||
unsigned private_bits;
|
||||
struct {
|
||||
struct gr_info_s gr[2];
|
||||
} ch[2];
|
||||
};
|
||||
|
||||
|
||||
extern int synth_1to1 (real *,int,unsigned char *,int *,struct mpstr *);
|
||||
extern int synth_1to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_1to1_mono (real *,unsigned char *,int *,struct mpstr *);
|
||||
extern int synth_1to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_1to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_1to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_2to1 (real *,int,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_2to1_mono (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_4to1 (real *,int,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_4to1_mono (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_ntom (real *,int,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_ntom_mono (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern void rewindNbits(int bits);
|
||||
extern int hsstell(void);
|
||||
extern int get_songlen(struct frame *fr,int no);
|
||||
|
||||
extern void init_layer3(int);
|
||||
extern void init_layer2(void);
|
||||
extern void make_decode_tables(long scale);
|
||||
extern void make_conv16to8_table(int);
|
||||
extern void dct64(real *,real *,real *);
|
||||
|
||||
extern void synth_ntom_set_step(long,long);
|
||||
|
||||
extern unsigned char *conv16to8;
|
||||
extern long mpglib_freqs[9];
|
||||
extern real muls[27][64];
|
||||
extern real decwin[512+32];
|
||||
extern real *pnts[5];
|
||||
|
||||
extern struct parameter param;
|
||||
|
||||
|
||||
243
project/jni/sdl_sound/decoders/mpglib/mpglib_common.c
Normal file
243
project/jni/sdl_sound/decoders/mpglib/mpglib_common.c
Normal file
@@ -0,0 +1,243 @@
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
|
||||
struct parameter param = { 1 , 1 , 0 , 0 };
|
||||
|
||||
int tabsel_123[2][3][16] = {
|
||||
{ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
|
||||
{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
|
||||
{0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
|
||||
|
||||
{ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }
|
||||
};
|
||||
|
||||
long mpglib_freqs[9] = { 44100, 48000, 32000,
|
||||
22050, 24000, 16000 ,
|
||||
11025 , 12000 , 8000 };
|
||||
|
||||
int bitindex;
|
||||
unsigned char *wordpointer;
|
||||
unsigned char *pcm_sample;
|
||||
int pcm_point = 0;
|
||||
|
||||
|
||||
#define HDRCMPMASK 0xfffffd00
|
||||
|
||||
#if 0
|
||||
int head_check(unsigned long head)
|
||||
{
|
||||
if( (head & 0xffe00000) != 0xffe00000)
|
||||
return FALSE;
|
||||
if(!((head>>17)&3))
|
||||
return FALSE;
|
||||
if( ((head>>12)&0xf) == 0xf)
|
||||
return FALSE;
|
||||
if( ((head>>10)&0x3) == 0x3 )
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* the code a header and write the information
|
||||
* into the frame structure
|
||||
*/
|
||||
int decode_header(struct frame *fr,unsigned long newhead)
|
||||
{
|
||||
if( newhead & (1<<20) ) {
|
||||
fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
|
||||
fr->mpeg25 = 0;
|
||||
}
|
||||
else {
|
||||
fr->lsf = 1;
|
||||
fr->mpeg25 = 1;
|
||||
}
|
||||
|
||||
fr->lay = 4-((newhead>>17)&3);
|
||||
if( ((newhead>>10)&0x3) == 0x3) {
|
||||
BAIL_MACRO("MPGLIB: Corrupted header", 0);
|
||||
}
|
||||
if(fr->mpeg25) {
|
||||
fr->sampling_frequency = 6 + ((newhead>>10)&0x3);
|
||||
}
|
||||
else
|
||||
fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3);
|
||||
fr->error_protection = ((newhead>>16)&0x1)^0x1;
|
||||
|
||||
if(fr->mpeg25) /* allow Bitrate change for 2.5 ... */
|
||||
fr->bitrate_index = ((newhead>>12)&0xf);
|
||||
|
||||
fr->bitrate_index = ((newhead>>12)&0xf);
|
||||
fr->padding = ((newhead>>9)&0x1);
|
||||
fr->extension = ((newhead>>8)&0x1);
|
||||
fr->mode = ((newhead>>6)&0x3);
|
||||
fr->mode_ext = ((newhead>>4)&0x3);
|
||||
fr->copyright = ((newhead>>3)&0x1);
|
||||
fr->original = ((newhead>>2)&0x1);
|
||||
fr->emphasis = newhead & 0x3;
|
||||
|
||||
fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
|
||||
|
||||
if(!fr->bitrate_index)
|
||||
{
|
||||
BAIL_MACRO("MPGLIB: Free format not supported.", 0);
|
||||
}
|
||||
|
||||
switch(fr->lay)
|
||||
{
|
||||
case 1:
|
||||
#ifdef LAYER1
|
||||
#if 0
|
||||
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
|
||||
(fr->mode_ext<<2)+4 : 32;
|
||||
#endif
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
|
||||
fr->framesize /= mpglib_freqs[fr->sampling_frequency];
|
||||
fr->framesize = ((fr->framesize+fr->padding)<<2)-4;
|
||||
#else
|
||||
__Sound_SetError("MPGLIB: Not supported!");
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
#ifdef LAYER2
|
||||
#if 0
|
||||
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
|
||||
(fr->mode_ext<<2)+4 : fr->II_sblimit;
|
||||
#endif
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
|
||||
fr->framesize /= mpglib_freqs[fr->sampling_frequency];
|
||||
fr->framesize += fr->padding - 4;
|
||||
#else
|
||||
__Sound_SetError("MPGLIB: Not supported!");
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
#if 0
|
||||
fr->do_layer = do_layer3;
|
||||
if(fr->lsf)
|
||||
ssize = (fr->stereo == 1) ? 9 : 17;
|
||||
else
|
||||
ssize = (fr->stereo == 1) ? 17 : 32;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if(fr->error_protection)
|
||||
ssize += 2;
|
||||
#endif
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
|
||||
fr->framesize /= mpglib_freqs[fr->sampling_frequency]<<(fr->lsf);
|
||||
fr->framesize = fr->framesize + fr->padding - 4;
|
||||
break;
|
||||
default:
|
||||
BAIL_MACRO("MPGLIB: Unknown layer type.", 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void print_header(struct frame *fr)
|
||||
{
|
||||
static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
|
||||
static char *layers[4] = { "Unknown" , "I", "II", "III" };
|
||||
|
||||
fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n",
|
||||
fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
|
||||
layers[fr->lay],mpglib_freqs[fr->sampling_frequency],
|
||||
modes[fr->mode],fr->mode_ext,fr->framesize+4);
|
||||
fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n",
|
||||
fr->stereo,fr->copyright?"Yes":"No",
|
||||
fr->original?"Yes":"No",fr->error_protection?"Yes":"No",
|
||||
fr->emphasis);
|
||||
fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n",
|
||||
tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension);
|
||||
}
|
||||
|
||||
void print_header_compact(struct frame *fr)
|
||||
{
|
||||
static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" };
|
||||
static char *layers[4] = { "Unknown" , "I", "II", "III" };
|
||||
|
||||
fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n",
|
||||
fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
|
||||
layers[fr->lay],
|
||||
tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
|
||||
mpglib_freqs[fr->sampling_frequency], modes[fr->mode]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned int getbits(int number_of_bits)
|
||||
{
|
||||
unsigned long rval;
|
||||
|
||||
if(!number_of_bits)
|
||||
return 0;
|
||||
|
||||
{
|
||||
rval = wordpointer[0];
|
||||
rval <<= 8;
|
||||
rval |= wordpointer[1];
|
||||
rval <<= 8;
|
||||
rval |= wordpointer[2];
|
||||
rval <<= bitindex;
|
||||
rval &= 0xffffff;
|
||||
|
||||
bitindex += number_of_bits;
|
||||
|
||||
rval >>= (24-number_of_bits);
|
||||
|
||||
wordpointer += (bitindex>>3);
|
||||
bitindex &= 7;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
unsigned int getbits_fast(int number_of_bits)
|
||||
{
|
||||
unsigned long rval;
|
||||
|
||||
{
|
||||
rval = wordpointer[0];
|
||||
rval <<= 8;
|
||||
rval |= wordpointer[1];
|
||||
rval <<= bitindex;
|
||||
rval &= 0xffff;
|
||||
bitindex += number_of_bits;
|
||||
|
||||
rval >>= (16-number_of_bits);
|
||||
|
||||
wordpointer += (bitindex>>3);
|
||||
bitindex &= 7;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
unsigned int get1bit(void)
|
||||
{
|
||||
unsigned char rval;
|
||||
rval = *wordpointer << bitindex;
|
||||
|
||||
bitindex++;
|
||||
wordpointer += (bitindex>>3);
|
||||
bitindex &= 7;
|
||||
|
||||
return rval>>7;
|
||||
}
|
||||
|
||||
|
||||
|
||||
63
project/jni/sdl_sound/decoders/mpglib/mpglib_sdlsound.h
Normal file
63
project/jni/sdl_sound/decoders/mpglib/mpglib_sdlsound.h
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
#ifndef _INCLUDE_MPGLIB_SDLSOUND_H_
|
||||
#define _INCLUDE_MPGLIB_SDLSOUND_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
struct buf {
|
||||
unsigned char *pnt;
|
||||
long size;
|
||||
long pos;
|
||||
struct buf *next;
|
||||
struct buf *prev;
|
||||
};
|
||||
|
||||
struct framebuf {
|
||||
struct buf *buf;
|
||||
long pos;
|
||||
struct frame *next;
|
||||
struct frame *prev;
|
||||
};
|
||||
|
||||
struct mpstr {
|
||||
struct buf *head,*tail;
|
||||
int bsize;
|
||||
int framesize;
|
||||
int fsizeold;
|
||||
struct frame fr;
|
||||
unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */
|
||||
real hybrid_block[2][2][SBLIMIT*SSLIMIT];
|
||||
int hybrid_blc[2];
|
||||
unsigned long header;
|
||||
int bsnum;
|
||||
real synth_buffs[2][2][0x110];
|
||||
int synth_bo;
|
||||
};
|
||||
|
||||
#ifndef BOOL
|
||||
#define BOOL int
|
||||
#endif
|
||||
|
||||
#define MP3_ERR -1
|
||||
#define MP3_OK 0
|
||||
#define MP3_NEED_MORE 1
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
BOOL InitMP3(struct mpstr *mp);
|
||||
int decodeMP3(struct mpstr *mp,char *inmemory,int inmemsize,
|
||||
char *outmemory,int outmemsize,int *done);
|
||||
void ExitMP3(struct mpstr *mp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
80
project/jni/sdl_sound/decoders/mpglib/tabinit.c
Normal file
80
project/jni/sdl_sound/decoders/mpglib/tabinit.c
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mpg123_sdlsound.h"
|
||||
|
||||
real decwin[512+32];
|
||||
static real cos64[16],cos32[8],cos16[4],cos8[2],cos4[1];
|
||||
real *pnts[] = { cos64,cos32,cos16,cos8,cos4 };
|
||||
|
||||
#if 0
|
||||
static unsigned char *conv16to8_buf = NULL;
|
||||
unsigned char *conv16to8;
|
||||
#endif
|
||||
|
||||
static long intwinbase[] = {
|
||||
0, -1, -1, -1, -1, -1, -1, -2, -2, -2,
|
||||
-2, -3, -3, -4, -4, -5, -5, -6, -7, -7,
|
||||
-8, -9, -10, -11, -13, -14, -16, -17, -19, -21,
|
||||
-24, -26, -29, -31, -35, -38, -41, -45, -49, -53,
|
||||
-58, -63, -68, -73, -79, -85, -91, -97, -104, -111,
|
||||
-117, -125, -132, -139, -147, -154, -161, -169, -176, -183,
|
||||
-190, -196, -202, -208, -213, -218, -222, -225, -227, -228,
|
||||
-228, -227, -224, -221, -215, -208, -200, -189, -177, -163,
|
||||
-146, -127, -106, -83, -57, -29, 2, 36, 72, 111,
|
||||
153, 197, 244, 294, 347, 401, 459, 519, 581, 645,
|
||||
711, 779, 848, 919, 991, 1064, 1137, 1210, 1283, 1356,
|
||||
1428, 1498, 1567, 1634, 1698, 1759, 1817, 1870, 1919, 1962,
|
||||
2001, 2032, 2057, 2075, 2085, 2087, 2080, 2063, 2037, 2000,
|
||||
1952, 1893, 1822, 1739, 1644, 1535, 1414, 1280, 1131, 970,
|
||||
794, 605, 402, 185, -45, -288, -545, -814, -1095, -1388,
|
||||
-1692, -2006, -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788,
|
||||
-5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, -7910, -8209,
|
||||
-8491, -8755, -8998, -9219, -9416, -9585, -9727, -9838, -9916, -9959,
|
||||
-9966, -9935, -9863, -9750, -9592, -9389, -9139, -8840, -8492, -8092,
|
||||
-7640, -7134, -6574, -5959, -5288, -4561, -3776, -2935, -2037, -1082,
|
||||
-70, 998, 2122, 3300, 4533, 5818, 7154, 8540, 9975, 11455,
|
||||
12980, 14548, 16155, 17799, 19478, 21189, 22929, 24694, 26482, 28289,
|
||||
30112, 31947, 33791, 35640, 37489, 39336, 41176, 43006, 44821, 46617,
|
||||
48390, 50137, 51853, 53534, 55178, 56778, 58333, 59838, 61289, 62684,
|
||||
64019, 65290, 66494, 67629, 68692, 69679, 70590, 71420, 72169, 72835,
|
||||
73415, 73908, 74313, 74630, 74856, 74992, 75038 };
|
||||
|
||||
void make_decode_tables(long scaleval)
|
||||
{
|
||||
int i,j,k,kr,divv;
|
||||
real *table,*costab;
|
||||
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
{
|
||||
kr=0x10>>i; divv=0x40>>i;
|
||||
costab = pnts[i];
|
||||
for(k=0;k<kr;k++)
|
||||
costab[k] = 1.0 / (2.0 * cos(M_PI * ((double) k * 2.0 + 1.0) / (double) divv));
|
||||
}
|
||||
|
||||
table = decwin;
|
||||
scaleval = -scaleval;
|
||||
for(i=0,j=0;i<256;i++,j++,table+=32)
|
||||
{
|
||||
if(table < decwin+512+16)
|
||||
table[16] = table[0] = (double) intwinbase[j] / 65536.0 * (double) scaleval;
|
||||
if(i % 32 == 31)
|
||||
table -= 1023;
|
||||
if(i % 64 == 63)
|
||||
scaleval = - scaleval;
|
||||
}
|
||||
|
||||
for( /* i=256 */ ;i<512;i++,j--,table+=32)
|
||||
{
|
||||
if(table < decwin+512+16)
|
||||
table[16] = table[0] = (double) intwinbase[j] / 65536.0 * (double) scaleval;
|
||||
if(i % 32 == 31)
|
||||
table -= 1023;
|
||||
if(i % 64 == 63)
|
||||
scaleval = - scaleval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
375
project/jni/sdl_sound/decoders/ogg.c
Normal file
375
project/jni/sdl_sound/decoders/ogg.c
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ogg Vorbis decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles .OGG audio files, and depends on libvorbisfile to
|
||||
* do the actual decoding work. libvorbisfile is part of libvorbis, which
|
||||
* is part of the Ogg Vorbis project.
|
||||
*
|
||||
* Ogg Vorbis: http://www.xiph.org/ogg/vorbis/
|
||||
* vorbisfile documentation: http://www.xiph.org/ogg/vorbis/doc/vorbisfile/
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_OGG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
|
||||
static int OGG_init(void);
|
||||
static void OGG_quit(void);
|
||||
static int OGG_open(Sound_Sample *sample, const char *ext);
|
||||
static void OGG_close(Sound_Sample *sample);
|
||||
static Uint32 OGG_read(Sound_Sample *sample);
|
||||
static int OGG_rewind(Sound_Sample *sample);
|
||||
static int OGG_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_ogg[] = { "OGG", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_OGG =
|
||||
{
|
||||
{
|
||||
extensions_ogg,
|
||||
"Ogg Vorbis audio through VorbisFile",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
OGG_init, /* init() method */
|
||||
OGG_quit, /* quit() method */
|
||||
OGG_open, /* open() method */
|
||||
OGG_close, /* close() method */
|
||||
OGG_read, /* read() method */
|
||||
OGG_rewind, /* rewind() method */
|
||||
OGG_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
static int OGG_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* OGG_init */
|
||||
|
||||
|
||||
static void OGG_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* OGG_quit */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* These are callbacks from vorbisfile that let them read data from
|
||||
* a RWops...
|
||||
*/
|
||||
|
||||
static size_t RWops_ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
return((size_t) SDL_RWread((SDL_RWops *) datasource, ptr, size, nmemb));
|
||||
} /* RWops_ogg_read */
|
||||
|
||||
static int RWops_ogg_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
return(SDL_RWseek((SDL_RWops *) datasource, offset, whence));
|
||||
} /* RWops_ogg_seek */
|
||||
|
||||
static int RWops_ogg_close(void *datasource)
|
||||
{
|
||||
/* do nothing; SDL_sound will delete the RWops at a higher level. */
|
||||
return(0); /* this is success in fclose(), so I guess that's okay. */
|
||||
} /* RWops_ogg_close */
|
||||
|
||||
static long RWops_ogg_tell(void *datasource)
|
||||
{
|
||||
return((long) SDL_RWtell((SDL_RWops *) datasource));
|
||||
} /* RWops_ogg_tell */
|
||||
|
||||
static const ov_callbacks RWops_ogg_callbacks =
|
||||
{
|
||||
RWops_ogg_read,
|
||||
RWops_ogg_seek,
|
||||
RWops_ogg_close,
|
||||
RWops_ogg_tell
|
||||
};
|
||||
|
||||
|
||||
/* Return a human readable version of an VorbisFile error code... */
|
||||
#if (defined DEBUG_CHATTER)
|
||||
static const char *ogg_error(int errnum)
|
||||
{
|
||||
switch(errnum)
|
||||
{
|
||||
case OV_EREAD:
|
||||
return("i/o error");
|
||||
case OV_ENOTVORBIS:
|
||||
return("not a vorbis file");
|
||||
case OV_EVERSION:
|
||||
return("Vorbis version mismatch");
|
||||
case OV_EBADHEADER:
|
||||
return("invalid Vorbis bitstream header");
|
||||
case OV_EFAULT:
|
||||
return("internal logic fault in Vorbis library");
|
||||
} /* switch */
|
||||
|
||||
return("unknown error");
|
||||
} /* ogg_error */
|
||||
#endif
|
||||
|
||||
static __inline__ void output_ogg_comments(OggVorbis_File *vf)
|
||||
{
|
||||
#if (defined DEBUG_CHATTER)
|
||||
int i;
|
||||
vorbis_comment *vc = ov_comment(vf, -1);
|
||||
|
||||
if (vc == NULL)
|
||||
return;
|
||||
|
||||
SNDDBG(("OGG: vendor == [%s].\n", vc->vendor));
|
||||
for (i = 0; i < vc->comments; i++)
|
||||
{
|
||||
SNDDBG(("OGG: user comment [%s].\n", vc->user_comments[i]));
|
||||
} /* for */
|
||||
#endif
|
||||
} /* output_ogg_comments */
|
||||
|
||||
|
||||
static int OGG_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
int rc;
|
||||
OggVorbis_File *vf;
|
||||
vorbis_info *info;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
vf = (OggVorbis_File *) malloc(sizeof (OggVorbis_File));
|
||||
BAIL_IF_MACRO(vf == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
rc = ov_open_callbacks(internal->rw, vf, NULL, 0, RWops_ogg_callbacks);
|
||||
if (rc != 0)
|
||||
{
|
||||
SNDDBG(("OGG: can't grok data. reason: [%s].\n", ogg_error(rc)));
|
||||
free(vf);
|
||||
BAIL_MACRO("OGG: Not valid Ogg Vorbis data.", 0);
|
||||
} /* if */
|
||||
|
||||
info = ov_info(vf, -1);
|
||||
if (info == NULL)
|
||||
{
|
||||
ov_clear(vf);
|
||||
free(vf);
|
||||
BAIL_MACRO("OGG: failed to retrieve bitstream info", 0);
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("OGG: Accepting data stream.\n"));
|
||||
|
||||
output_ogg_comments(vf);
|
||||
SNDDBG(("OGG: bitstream version == (%d).\n", info->version));
|
||||
SNDDBG(("OGG: bitstream channels == (%d).\n", info->channels));
|
||||
SNDDBG(("OGG: bitstream sampling rate == (%ld).\n", info->rate));
|
||||
SNDDBG(("OGG: seekable == {%s}.\n", ov_seekable(vf) ? "TRUE" : "FALSE"));
|
||||
SNDDBG(("OGG: number of logical bitstreams == (%ld).\n", ov_streams(vf)));
|
||||
SNDDBG(("OGG: serial number == (%ld).\n", ov_serialnumber(vf, -1)));
|
||||
SNDDBG(("OGG: total seconds of sample == (%f).\n", ov_time_total(vf, -1)));
|
||||
|
||||
internal->decoder_private = vf;
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
sample->actual.rate = (Uint32) info->rate;
|
||||
sample->actual.channels = (Uint8) info->channels;
|
||||
|
||||
/*
|
||||
* Since we might have more than one logical bitstream in the OGG file,
|
||||
* and these bitstreams may be in different formats, we might be
|
||||
* converting two or three times: once in vorbisfile, once again in
|
||||
* SDL_sound, and perhaps a third time to get it to the sound device's
|
||||
* format. That's wickedly inefficient.
|
||||
*
|
||||
* To combat this a little, if the user specified a desired format, we
|
||||
* claim that to be the "actual" format of the collection of logical
|
||||
* bitstreams. This means that VorbisFile will do a conversion as
|
||||
* necessary, and SDL_sound will not. If the user didn't specify a
|
||||
* desired format, then we pretend the "actual" format is something that
|
||||
* OGG files are apparently commonly encoded in.
|
||||
*/
|
||||
sample->actual.format = (sample->desired.format == 0) ?
|
||||
AUDIO_S16LSB : sample->desired.format;
|
||||
return(1);
|
||||
} /* OGG_open */
|
||||
|
||||
|
||||
static void OGG_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
|
||||
ov_clear(vf);
|
||||
free(vf);
|
||||
} /* OGG_close */
|
||||
|
||||
/* Note: According to the Vorbis documentation:
|
||||
* "ov_read() will decode at most one vorbis packet per invocation,
|
||||
* so the value returned will generally be less than length."
|
||||
* Due to this, for buffer sizes like 16384, SDL_Sound was always getting
|
||||
* an underfilled buffer and always setting the EAGAIN flag.
|
||||
* Since the SDL_Sound API implies that the entire buffer
|
||||
* should be filled unless EOF, additional code has been added
|
||||
* to this function to call ov_read() until the buffer is filled.
|
||||
* However, there may still be some corner cases where the buffer
|
||||
* cannot be entirely filled. So be aware.
|
||||
*/
|
||||
static Uint32 OGG_read(Sound_Sample *sample)
|
||||
{
|
||||
int rc;
|
||||
int bitstream;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
|
||||
|
||||
rc = ov_read(vf, internal->buffer, internal->buffer_size,
|
||||
((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
|
||||
((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
|
||||
((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
|
||||
&bitstream);
|
||||
|
||||
/* Make sure the read went smoothly... */
|
||||
if (rc == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
else if (rc < 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
|
||||
/* If the buffer isn't filled, keep trying to fill it
|
||||
* until no more data can be grabbed */
|
||||
else if ((Uint32) rc < internal->buffer_size)
|
||||
{
|
||||
/* Creating a pointer to the buffer that denotes where to start
|
||||
* writing new data. */
|
||||
Uint8* buffer_start_point = NULL;
|
||||
int total_bytes_read = rc;
|
||||
int bytes_remaining = internal->buffer_size - rc;
|
||||
|
||||
/* Keep grabbing data until something prevents
|
||||
* us from getting more. (Could be EOF,
|
||||
* packets are too large to fit in remaining
|
||||
* space, or an error.)
|
||||
*/
|
||||
while( (rc > 0) && (bytes_remaining > 0) )
|
||||
{
|
||||
/* Set buffer pointer to end of last write */
|
||||
/* All the messiness is to get rid of the warning for
|
||||
* dereferencing a void*
|
||||
*/
|
||||
buffer_start_point = &(((Uint8*)internal->buffer)[total_bytes_read]);
|
||||
rc = ov_read(vf, buffer_start_point, bytes_remaining,
|
||||
((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
|
||||
((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
|
||||
((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
|
||||
&bitstream);
|
||||
/* Make sure rc > 0 because we don't accidently want
|
||||
* to change the counters if there was an error
|
||||
*/
|
||||
if(rc > 0)
|
||||
{
|
||||
total_bytes_read += rc;
|
||||
bytes_remaining = bytes_remaining - rc;
|
||||
}
|
||||
}
|
||||
/* I think the minimum read size is 2, though I'm
|
||||
* not sure about this. (I've hit cases where I
|
||||
* couldn't read less than 4.) What I don't want to do is
|
||||
* accidently claim we hit EOF when the reason rc == 0
|
||||
* is because the requested amount of data was smaller
|
||||
* than the minimum packet size.
|
||||
* For now, I will be conservative
|
||||
* and not set the EOF flag, and let the next call to
|
||||
* this function figure it out.
|
||||
* I think the ERROR flag is safe to set because
|
||||
* it looks like OGG simply returns 0 if the
|
||||
* read size is too small.
|
||||
* And in most cases for sensible buffer sizes,
|
||||
* this fix will fill the buffer,
|
||||
* so we can set the EAGAIN flag without worrying
|
||||
* that it will always be set.
|
||||
*/
|
||||
if(rc < 0)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
}
|
||||
else if(rc == 0)
|
||||
{
|
||||
/* Do nothing for now until there is a better solution */
|
||||
/* sample->flags |= SOUND_SAMPLEFLAG_EOF; */
|
||||
}
|
||||
|
||||
/* Test for a buffer underrun. It should occur less frequently
|
||||
* now, but it still may happen and not necessarily mean
|
||||
* anything useful. */
|
||||
if ((Uint32) total_bytes_read < internal->buffer_size)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
}
|
||||
/* change rc to the total bytes read so function
|
||||
* can return the correct value.
|
||||
*/
|
||||
rc = total_bytes_read;
|
||||
}
|
||||
|
||||
return((Uint32) rc);
|
||||
} /* OGG_read */
|
||||
|
||||
|
||||
static int OGG_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
|
||||
|
||||
BAIL_IF_MACRO(ov_raw_seek(vf, 0) < 0, ERR_IO_ERROR, 0);
|
||||
return(1);
|
||||
} /* OGG_rewind */
|
||||
|
||||
|
||||
static int OGG_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
|
||||
double timepos = (((double) ms) / 1000.0);
|
||||
BAIL_IF_MACRO(ov_time_seek(vf, timepos) < 0, ERR_IO_ERROR, 0);
|
||||
return(1);
|
||||
} /* OGG_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_OGG */
|
||||
|
||||
|
||||
/* end of ogg.c ... */
|
||||
|
||||
591
project/jni/sdl_sound/decoders/quicktime.c
Normal file
591
project/jni/sdl_sound/decoders/quicktime.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* QuickTime decoder for sound formats that QuickTime supports.
|
||||
* April 28, 2002
|
||||
*
|
||||
* This driver handles .mov files with a sound track. In
|
||||
* theory, it could handle any format that QuickTime supports.
|
||||
* In practice, it may only handle a select few of these formats.
|
||||
*
|
||||
* It seems able to play back AIFF and other standard Mac formats.
|
||||
* Rewinding is not supported yet.
|
||||
*
|
||||
* The routine QT_create_data_ref() needs to be
|
||||
* tweaked to support different media types.
|
||||
* This code was originally written to get MP3 support,
|
||||
* as it turns out, this isn't possible using this method.
|
||||
*
|
||||
* The only way to get streaming MP3 support through QuickTime,
|
||||
* and hence support for SDL_RWops, is to write
|
||||
* a DataHandler component, which suddenly gets much more difficult :-(
|
||||
*
|
||||
* This file was written by Darrell Walisser (walisser@mac.com)
|
||||
* Portions have been borrowed from the "MP3Player" sample code,
|
||||
* courtesy of Apple.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_QUICKTIME
|
||||
#ifdef macintosh
|
||||
typedef long int32_t;
|
||||
# define OPAQUE_UPP_TYPES 0
|
||||
# include <QuickTime.h>
|
||||
#else
|
||||
# include <QuickTime/QuickTime.h>
|
||||
# include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int QT_init(void);
|
||||
static void QT_quit(void);
|
||||
static int QT_open(Sound_Sample *sample, const char *ext);
|
||||
static void QT_close(Sound_Sample *sample);
|
||||
static Uint32 QT_read(Sound_Sample *sample);
|
||||
static int QT_rewind(Sound_Sample *sample);
|
||||
static int QT_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
#define QT_MAX_INPUT_BUFFER (32*1024) /* Maximum size of internal buffer (internal->buffer_size) */
|
||||
|
||||
static const char *extensions_quicktime[] = { "mov", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_QuickTime =
|
||||
{
|
||||
{
|
||||
extensions_quicktime,
|
||||
"QuickTime format",
|
||||
"Darrell Walisser <dwaliss1@purdue.edu>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
QT_init, /* init() method */
|
||||
QT_quit, /* quit() method */
|
||||
QT_open, /* open() method */
|
||||
QT_close, /* close() method */
|
||||
QT_read, /* read() method */
|
||||
QT_rewind, /* rewind() method */
|
||||
QT_seek /* seek() method */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
ExtendedSoundComponentData compData;
|
||||
Handle hSource; /* source media buffer */
|
||||
Media sourceMedia; /* sound media identifier */
|
||||
TimeValue getMediaAtThisTime;
|
||||
TimeValue sourceDuration;
|
||||
Boolean isThereMoreSource;
|
||||
UInt32 maxBufferSize;
|
||||
|
||||
} SCFillBufferData, *SCFillBufferDataPtr;
|
||||
|
||||
typedef struct {
|
||||
|
||||
Movie movie;
|
||||
Track track;
|
||||
Media media;
|
||||
AudioFormatAtomPtr atom;
|
||||
SoundComponentData source_format;
|
||||
SoundComponentData dest_format;
|
||||
SoundConverter converter;
|
||||
SCFillBufferData buffer_data;
|
||||
SoundConverterFillBufferDataUPP fill_buffer_proc;
|
||||
|
||||
} qt_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This procedure creates a description of the raw data
|
||||
* read from SDL_RWops so that QuickTime can identify
|
||||
* the codec it needs to use to decompress it.
|
||||
*/
|
||||
static Handle QT_create_data_ref (const char *file_extension) {
|
||||
|
||||
Handle tmp_handle, data_ref;
|
||||
StringPtr file_name = "\p"; /* empty since we don't know the file name! */
|
||||
OSType file_type;
|
||||
StringPtr mime_type;
|
||||
long atoms[3];
|
||||
|
||||
/*
|
||||
if (__Sound_strcasecmp (file_extension, "mp3")==0) {
|
||||
file_type = 'MPEG';
|
||||
mime_type = "\pvideo/mpeg";
|
||||
}
|
||||
else {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if (__Sound_strcasecmp (file_extension, "mov") == 0) {
|
||||
|
||||
file_type = 'MooV';
|
||||
mime_type = "\pvideo/quicktime";
|
||||
}
|
||||
else {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmp_handle = NewHandle(0);
|
||||
assert (tmp_handle != NULL);
|
||||
assert (noErr == PtrToHand (&tmp_handle, &data_ref, sizeof(Handle)));
|
||||
assert (noErr == PtrAndHand (file_name, data_ref, file_name[0]+1));
|
||||
|
||||
atoms[0] = EndianU32_NtoB (sizeof(long) * 3);
|
||||
atoms[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
|
||||
atoms[2] = EndianU32_NtoB (file_type);
|
||||
|
||||
assert (noErr == PtrAndHand (atoms, data_ref, sizeof(long)*3));
|
||||
|
||||
atoms[0] = EndianU32_NtoB (sizeof(long)*2 + mime_type[0]+1);
|
||||
atoms[1] = EndianU32_NtoB (kDataRefExtensionMIMEType);
|
||||
|
||||
assert (noErr == PtrAndHand (atoms, data_ref, sizeof(long)*2));
|
||||
assert (noErr == PtrAndHand (mime_type, data_ref, mime_type[0]+1));
|
||||
|
||||
return data_ref;
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure is a hook for QuickTime to grab data from the
|
||||
* SDL_RWOps data structure when it needs it
|
||||
*/
|
||||
static pascal OSErr QT_get_movie_data_proc (long offset, long size,
|
||||
void *data, void *user_data)
|
||||
{
|
||||
SDL_RWops* rw = (SDL_RWops*)user_data;
|
||||
OSErr error;
|
||||
|
||||
if (offset == SDL_RWseek (rw, offset, SEEK_SET)) {
|
||||
|
||||
if (size == SDL_RWread (rw, data, 1, size)) {
|
||||
error = noErr;
|
||||
}
|
||||
else {
|
||||
error = notEnoughDataErr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = fileOffsetTooBigErr;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* * ----------------------------
|
||||
* SoundConverterFillBufferDataProc
|
||||
*
|
||||
* the callback routine that provides the source data for conversion -
|
||||
* it provides data by setting outData to a pointer to a properly
|
||||
* filled out ExtendedSoundComponentData structure
|
||||
*/
|
||||
static pascal Boolean QT_sound_converter_fill_buffer_data_proc (SoundComponentDataPtr *outData, void *inRefCon)
|
||||
{
|
||||
SCFillBufferDataPtr pFillData = (SCFillBufferDataPtr)inRefCon;
|
||||
|
||||
OSErr err = noErr;
|
||||
|
||||
/* if after getting the last chunk of data the total time is over
|
||||
* the duration, we're done
|
||||
*/
|
||||
if (pFillData->getMediaAtThisTime >= pFillData->sourceDuration) {
|
||||
pFillData->isThereMoreSource = false;
|
||||
pFillData->compData.desc.buffer = NULL;
|
||||
pFillData->compData.desc.sampleCount = 0;
|
||||
pFillData->compData.bufferSize = 0;
|
||||
}
|
||||
|
||||
if (pFillData->isThereMoreSource) {
|
||||
|
||||
long sourceBytesReturned;
|
||||
long numberOfSamples;
|
||||
TimeValue sourceReturnedTime, durationPerSample;
|
||||
|
||||
HUnlock(pFillData->hSource);
|
||||
|
||||
err = GetMediaSample
|
||||
(pFillData->sourceMedia,/* specifies the media for this operation */
|
||||
pFillData->hSource, /* function returns the sample data into this handle */
|
||||
pFillData->maxBufferSize, /* maximum number of bytes of sample data to be returned */
|
||||
&sourceBytesReturned, /* the number of bytes of sample data returned */
|
||||
pFillData->getMediaAtThisTime,/* starting time of the sample to
|
||||
be retrieved (must be in
|
||||
Media's TimeScale) */
|
||||
&sourceReturnedTime,/* indicates the actual time of the returned sample data */
|
||||
&durationPerSample, /* duration of each sample in the media */
|
||||
NULL, /* sample description corresponding to the returned sample data (NULL to ignore) */
|
||||
NULL, /* index value to the sample description that corresponds
|
||||
to the returned sample data (NULL to ignore) */
|
||||
0, /* maximum number of samples to be returned (0 to use a
|
||||
value that is appropriate for the media) */
|
||||
&numberOfSamples, /* number of samples it actually returned */
|
||||
NULL); /* flags that describe the sample (NULL to ignore) */
|
||||
|
||||
HLock(pFillData->hSource);
|
||||
|
||||
if ((noErr != err) || (sourceBytesReturned == 0)) {
|
||||
pFillData->isThereMoreSource = false;
|
||||
pFillData->compData.desc.buffer = NULL;
|
||||
pFillData->compData.desc.sampleCount = 0;
|
||||
|
||||
if ((err != noErr) && (sourceBytesReturned > 0))
|
||||
DebugStr("\pGetMediaSample - Failed in FillBufferDataProc");
|
||||
}
|
||||
|
||||
pFillData->getMediaAtThisTime = sourceReturnedTime + (durationPerSample * numberOfSamples);
|
||||
pFillData->compData.bufferSize = sourceBytesReturned;
|
||||
}
|
||||
|
||||
/* set outData to a properly filled out ExtendedSoundComponentData struct */
|
||||
*outData = (SoundComponentDataPtr)&pFillData->compData;
|
||||
|
||||
return (pFillData->isThereMoreSource);
|
||||
}
|
||||
|
||||
|
||||
static int QT_init_internal () {
|
||||
|
||||
OSErr error;
|
||||
|
||||
error = EnterMovies(); /* initialize the movie toolbox */
|
||||
|
||||
return (error == noErr);
|
||||
}
|
||||
|
||||
static void QT_quit_internal () {
|
||||
|
||||
ExitMovies();
|
||||
}
|
||||
|
||||
static qt_t* QT_open_internal (Sound_Sample *sample, const char *extension)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
qt_t *instance;
|
||||
OSErr error;
|
||||
Movie movie;
|
||||
Track sound_track;
|
||||
Media sound_track_media;
|
||||
AudioFormatAtomPtr source_sound_decomp_atom;
|
||||
|
||||
SoundDescriptionV1Handle source_sound_description;
|
||||
Handle source_sound_description_extension;
|
||||
Size source_sound_description_extension_size;
|
||||
Handle data_ref;
|
||||
|
||||
data_ref = QT_create_data_ref (extension);
|
||||
|
||||
/* create a movie that will read data using SDL_RWops */
|
||||
error = NewMovieFromUserProc
|
||||
(&movie,
|
||||
0,
|
||||
NULL,
|
||||
NewGetMovieUPP(QT_get_movie_data_proc),
|
||||
(void*) internal->rw,
|
||||
data_ref,
|
||||
'hndl');
|
||||
|
||||
if (error != noErr) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the first sound track of the movie; other tracks will be ignored */
|
||||
sound_track = GetMovieIndTrackType (movie, 1, SoundMediaType, movieTrackMediaType);
|
||||
if (sound_track == NULL) {
|
||||
|
||||
/* movie needs a sound track! */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get and return the sound track media */
|
||||
sound_track_media = GetTrackMedia (sound_track);
|
||||
if (sound_track_media == NULL) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create a description of the source sound so we can convert it later */
|
||||
source_sound_description = (SoundDescriptionV1Handle)NewHandle(0);
|
||||
assert (source_sound_description != NULL); /* out of memory */
|
||||
|
||||
GetMediaSampleDescription (sound_track_media, 1,
|
||||
(SampleDescriptionHandle)source_sound_description);
|
||||
error = GetMoviesError();
|
||||
if (error != noErr) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
source_sound_description_extension = NewHandle(0);
|
||||
assert (source_sound_description_extension != NULL); /* out of memory */
|
||||
|
||||
error = GetSoundDescriptionExtension ((SoundDescriptionHandle) source_sound_description,
|
||||
&source_sound_description_extension,
|
||||
siDecompressionParams);
|
||||
|
||||
if (error == noErr) {
|
||||
|
||||
/* copy extension to atom format description if we have an extension */
|
||||
|
||||
source_sound_description_extension_size =
|
||||
GetHandleSize (source_sound_description_extension);
|
||||
HLock (source_sound_description_extension);
|
||||
|
||||
source_sound_decomp_atom = (AudioFormatAtom*)
|
||||
NewPtr (source_sound_description_extension_size);
|
||||
assert (source_sound_decomp_atom != NULL); /* out of memory */
|
||||
|
||||
BlockMoveData (*source_sound_description_extension,
|
||||
source_sound_decomp_atom,
|
||||
source_sound_description_extension_size);
|
||||
|
||||
HUnlock (source_sound_description_extension);
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
source_sound_decomp_atom = NULL;
|
||||
}
|
||||
|
||||
instance = (qt_t*) malloc (sizeof(*instance));
|
||||
assert (instance != NULL); /* out of memory */
|
||||
|
||||
instance->movie = movie;
|
||||
instance->track = sound_track;
|
||||
instance->media = sound_track_media;
|
||||
instance->atom = source_sound_decomp_atom;
|
||||
|
||||
instance->source_format.flags = 0;
|
||||
instance->source_format.format = (*source_sound_description)->desc.dataFormat;
|
||||
instance->source_format.numChannels = (*source_sound_description)->desc.numChannels;
|
||||
instance->source_format.sampleSize = (*source_sound_description)->desc.sampleSize;
|
||||
instance->source_format.sampleRate = (*source_sound_description)->desc.sampleRate;
|
||||
instance->source_format.sampleCount = 0;
|
||||
instance->source_format.buffer = NULL;
|
||||
instance->source_format.reserved = 0;
|
||||
|
||||
instance->dest_format.flags = 0;
|
||||
instance->dest_format.format = kSoundNotCompressed;
|
||||
instance->dest_format.numChannels = (*source_sound_description)->desc.numChannels;
|
||||
instance->dest_format.sampleSize = (*source_sound_description)->desc.sampleSize;
|
||||
instance->dest_format.sampleRate = (*source_sound_description)->desc.sampleRate;
|
||||
instance->dest_format.sampleCount = 0;
|
||||
instance->dest_format.buffer = NULL;
|
||||
instance->dest_format.reserved = 0;
|
||||
|
||||
sample->actual.channels = (*source_sound_description)->desc.numChannels;
|
||||
sample->actual.rate = (*source_sound_description)->desc.sampleRate >> 16;
|
||||
|
||||
if ((*source_sound_description)->desc.sampleSize == 16) {
|
||||
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
}
|
||||
else if ((*source_sound_description)->desc.sampleSize == 8) {
|
||||
|
||||
sample->actual.format = AUDIO_U8;
|
||||
}
|
||||
else {
|
||||
|
||||
/* 24-bit or others... (which SDL can't handle) */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DisposeHandle (source_sound_description_extension);
|
||||
DisposeHandle ((Handle)source_sound_description);
|
||||
|
||||
/* This next code sets up the SoundConverter component */
|
||||
error = SoundConverterOpen (&instance->source_format, &instance->dest_format,
|
||||
&instance->converter);
|
||||
|
||||
if (error != noErr) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = SoundConverterSetInfo (instance->converter, siDecompressionParams,
|
||||
instance->atom);
|
||||
if (error == siUnknownInfoType) {
|
||||
|
||||
/* ignore */
|
||||
}
|
||||
else if (error != noErr) {
|
||||
|
||||
/* reall error */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = SoundConverterBeginConversion (instance->converter);
|
||||
if (error != noErr) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->buffer_data.sourceMedia = instance->media;
|
||||
instance->buffer_data.getMediaAtThisTime = 0;
|
||||
instance->buffer_data.sourceDuration = GetMediaDuration(instance->media);
|
||||
instance->buffer_data.isThereMoreSource = true;
|
||||
instance->buffer_data.maxBufferSize = QT_MAX_INPUT_BUFFER;
|
||||
/* allocate source media buffer */
|
||||
instance->buffer_data.hSource = NewHandle((long)instance->buffer_data.maxBufferSize);
|
||||
assert (instance->buffer_data.hSource != NULL); /* out of memory */
|
||||
|
||||
instance->buffer_data.compData.desc = instance->source_format;
|
||||
instance->buffer_data.compData.desc.buffer = (Byte *)*instance->buffer_data.hSource;
|
||||
instance->buffer_data.compData.desc.flags = kExtendedSoundData;
|
||||
instance->buffer_data.compData.recordSize = sizeof(ExtendedSoundComponentData);
|
||||
instance->buffer_data.compData.extendedFlags =
|
||||
kExtendedSoundSampleCountNotValid | kExtendedSoundBufferSizeValid;
|
||||
instance->buffer_data.compData.bufferSize = 0;
|
||||
|
||||
instance->fill_buffer_proc =
|
||||
NewSoundConverterFillBufferDataUPP (QT_sound_converter_fill_buffer_data_proc);
|
||||
|
||||
return (instance);
|
||||
|
||||
} /* QT_open_internal */
|
||||
|
||||
static void QT_close_internal (qt_t *instance)
|
||||
{
|
||||
|
||||
} /* QT_close_internal */
|
||||
|
||||
static Uint32 QT_read_internal(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
qt_t *instance = (qt_t*) internal->decoder_private;
|
||||
long output_bytes, output_frames, output_flags;
|
||||
OSErr error;
|
||||
|
||||
error = SoundConverterFillBuffer
|
||||
(instance->converter, /* a sound converter */
|
||||
instance->fill_buffer_proc, /* the callback UPP */
|
||||
&instance->buffer_data, /* refCon passed to FillDataProc */
|
||||
internal->buffer, /* the decompressed data 'play' buffer */
|
||||
internal->buffer_size, /* size of the 'play' buffer */
|
||||
&output_bytes, /* number of output bytes */
|
||||
&output_frames, /* number of output frames */
|
||||
&output_flags); /* fillbuffer retured advisor flags */
|
||||
|
||||
if (output_flags & kSoundConverterHasLeftOverData) {
|
||||
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
}
|
||||
else {
|
||||
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
}
|
||||
|
||||
if (error != noErr) {
|
||||
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
}
|
||||
|
||||
return (output_bytes);
|
||||
|
||||
} /* QT_read_internal */
|
||||
|
||||
static int QT_rewind_internal (Sound_Sample *sample)
|
||||
{
|
||||
|
||||
return 0;
|
||||
|
||||
} /* QT_rewind_internal */
|
||||
|
||||
|
||||
|
||||
static int QT_init(void)
|
||||
{
|
||||
return (QT_init_internal());
|
||||
|
||||
} /* QT_init */
|
||||
|
||||
static void QT_quit(void)
|
||||
{
|
||||
QT_quit_internal();
|
||||
|
||||
} /* QT_quit */
|
||||
|
||||
static int QT_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
qt_t *instance;
|
||||
|
||||
instance = QT_open_internal(sample, ext);
|
||||
internal->decoder_private = (void*)instance;
|
||||
|
||||
return(instance != NULL);
|
||||
|
||||
} /* QT_open */
|
||||
|
||||
|
||||
static void QT_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
qt_t *instance = (qt_t *) internal->decoder_private;
|
||||
|
||||
QT_close_internal (instance);
|
||||
|
||||
free (instance);
|
||||
|
||||
} /* QT_close */
|
||||
|
||||
|
||||
static Uint32 QT_read(Sound_Sample *sample)
|
||||
{
|
||||
return(QT_read_internal(sample));
|
||||
|
||||
} /* QT_read */
|
||||
|
||||
|
||||
static int QT_rewind(Sound_Sample *sample)
|
||||
{
|
||||
|
||||
return(QT_rewind_internal(sample));
|
||||
|
||||
} /* QT_rewind */
|
||||
|
||||
|
||||
static int QT_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
BAIL_MACRO("QUICKTIME: Seeking not implemented", 0);
|
||||
} /* QT_seek */
|
||||
|
||||
|
||||
#endif /* SOUND_SUPPORTS_QUICKTIME */
|
||||
|
||||
/* end of quicktime.c ... */
|
||||
|
||||
184
project/jni/sdl_sound/decoders/raw.c
Normal file
184
project/jni/sdl_sound/decoders/raw.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* RAW decoder for SDL_sound. This is as simple as it gets.
|
||||
*
|
||||
* This driver handles raw audio data. You must, regardless of where the
|
||||
* data is actually coming from, specify the string "RAW" in the extension
|
||||
* parameter of Sound_NewSample() (or, alternately, open a file with the
|
||||
* extension ".raw" in Sound_NewSampleFromFile()). The string is checked
|
||||
* case-insensitive. We need this check, because raw data, being raw, has
|
||||
* no headers or magic number we can use to determine if we should handle a
|
||||
* given file, so we needed some way to have this "decoder" discriminate.
|
||||
*
|
||||
* When calling Sound_NewSample*(), you must also specify a "desired"
|
||||
* audio format. The "actual" format will always match what you specify, so
|
||||
* there will be no conversion overhead, but these routines need to know how
|
||||
* to treat the bits, since it's all random garbage otherwise.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_RAW
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int RAW_init(void);
|
||||
static void RAW_quit(void);
|
||||
static int RAW_open(Sound_Sample *sample, const char *ext);
|
||||
static void RAW_close(Sound_Sample *sample);
|
||||
static Uint32 RAW_read(Sound_Sample *sample);
|
||||
static int RAW_rewind(Sound_Sample *sample);
|
||||
static int RAW_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_raw[] = { "RAW", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_RAW =
|
||||
{
|
||||
{
|
||||
extensions_raw,
|
||||
"Raw audio",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
RAW_init, /* init() method */
|
||||
RAW_quit, /* quit() method */
|
||||
RAW_open, /* open() method */
|
||||
RAW_close, /* close() method */
|
||||
RAW_read, /* read() method */
|
||||
RAW_rewind, /* rewind() method */
|
||||
RAW_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
static int RAW_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* RAW_init */
|
||||
|
||||
|
||||
static void RAW_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* RAW_quit */
|
||||
|
||||
|
||||
static int RAW_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
/*
|
||||
* We check this explicitly, since we have no other way to
|
||||
* determine whether we should handle this data or not.
|
||||
*/
|
||||
if (__Sound_strcasecmp(ext, "RAW") != 0)
|
||||
BAIL_MACRO("RAW: extension isn't explicitly \"RAW\".", 0);
|
||||
|
||||
/*
|
||||
* You must also specify a desired format, so we know how to
|
||||
* treat the bits that are otherwise binary garbage.
|
||||
*/
|
||||
if ( (sample->desired.channels < 1) ||
|
||||
(sample->desired.channels > 2) ||
|
||||
(sample->desired.rate == 0) ||
|
||||
(sample->desired.format == 0) )
|
||||
{
|
||||
BAIL_MACRO("RAW: invalid desired format.", 0);
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("RAW: Accepting data stream.\n"));
|
||||
|
||||
/*
|
||||
* We never convert raw samples; what you ask for is what you get.
|
||||
*/
|
||||
memcpy(&sample->actual, &sample->desired, sizeof (Sound_AudioInfo));
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* RAW_open */
|
||||
|
||||
|
||||
static void RAW_close(Sound_Sample *sample)
|
||||
{
|
||||
/* we don't allocate anything that we need to free. That's easy, eh? */
|
||||
} /* RAW_close */
|
||||
|
||||
|
||||
static Uint32 RAW_read(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
|
||||
/*
|
||||
* We don't actually do any decoding, so we read the raw data
|
||||
* directly into the internal buffer...
|
||||
*/
|
||||
retval = SDL_RWread(internal->rw, internal->buffer,
|
||||
1, internal->buffer_size);
|
||||
|
||||
/* Make sure the read went smoothly... */
|
||||
if (retval == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
else if (retval == -1)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
|
||||
/* (next call this EAGAIN may turn into an EOF or error.) */
|
||||
else if (retval < internal->buffer_size)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
|
||||
return(retval);
|
||||
} /* RAW_read */
|
||||
|
||||
|
||||
static int RAW_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
|
||||
return(1);
|
||||
} /* RAW_rewind */
|
||||
|
||||
|
||||
static int RAW_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
int pos = (int) __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int err = (SDL_RWseek(internal->rw, pos, SEEK_SET) != pos);
|
||||
BAIL_IF_MACRO(err, ERR_IO_ERROR, 0);
|
||||
return(1);
|
||||
} /* RAW_seek */
|
||||
|
||||
|
||||
#endif /* SOUND_SUPPORTS_RAW */
|
||||
|
||||
|
||||
/* end of raw.c ... */
|
||||
|
||||
1341
project/jni/sdl_sound/decoders/shn.c
Normal file
1341
project/jni/sdl_sound/decoders/shn.c
Normal file
File diff suppressed because it is too large
Load Diff
310
project/jni/sdl_sound/decoders/smpeg.c
Normal file
310
project/jni/sdl_sound/decoders/smpeg.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* MPEG-1 Layer 3, or simply, "MP3", decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles all those highly compressed songs you stole through
|
||||
* Napster. :) It depends on the SMPEG library for decoding, which can
|
||||
* be grabbed from: http://www.lokigames.com/development/smpeg.php3
|
||||
*
|
||||
* This should also be able to extract the audio stream from an MPEG movie.
|
||||
*
|
||||
* There is an alternative MP3 decoder available, called "mpglib", which
|
||||
* doesn't depend on external libraries (the decoder itself is part of
|
||||
* SDL_sound), and may be more efficient, but less flexible than SMPEG. YMMV.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_SMPEG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "smpeg.h"
|
||||
#include "extra_rwops.h"
|
||||
|
||||
|
||||
static int _SMPEG_init(void);
|
||||
static void _SMPEG_quit(void);
|
||||
static int _SMPEG_open(Sound_Sample *sample, const char *ext);
|
||||
static void _SMPEG_close(Sound_Sample *sample);
|
||||
static Uint32 _SMPEG_read(Sound_Sample *sample);
|
||||
static int _SMPEG_rewind(Sound_Sample *sample);
|
||||
static int _SMPEG_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_smpeg[] = { "MP3", "MPEG", "MPG", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_SMPEG =
|
||||
{
|
||||
{
|
||||
extensions_smpeg,
|
||||
"MPEG-1 Layer 3 audio through SMPEG",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/smpeg/"
|
||||
},
|
||||
|
||||
_SMPEG_init, /* init() method */
|
||||
_SMPEG_quit, /* quit() method */
|
||||
_SMPEG_open, /* open() method */
|
||||
_SMPEG_close, /* close() method */
|
||||
_SMPEG_read, /* read() method */
|
||||
_SMPEG_rewind, /* rewind() method */
|
||||
_SMPEG_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
static int _SMPEG_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* _SMPEG_init */
|
||||
|
||||
|
||||
static void _SMPEG_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* _SMPEG_quit */
|
||||
|
||||
|
||||
static __inline__ void output_version(void)
|
||||
{
|
||||
static int first_time = 1;
|
||||
|
||||
if (first_time)
|
||||
{
|
||||
SMPEG_version v;
|
||||
SMPEG_VERSION(&v);
|
||||
SNDDBG(("SMPEG: Compiled against SMPEG v%d.%d.%d.\n",
|
||||
v.major, v.minor, v.patch));
|
||||
first_time = 0;
|
||||
} /* if */
|
||||
} /* output_version */
|
||||
|
||||
|
||||
static int _SMPEG_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
SMPEG *smpeg;
|
||||
SMPEG_Info smpeg_info;
|
||||
SDL_AudioSpec spec;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *refCounter;
|
||||
const char *err = NULL;
|
||||
|
||||
output_version();
|
||||
|
||||
/*
|
||||
* If I understand things correctly, MP3 files don't really have any
|
||||
* magic header we can check for. The MP3 player is expected to just
|
||||
* pick the first thing that looks like a valid frame and start
|
||||
* playing from there.
|
||||
*
|
||||
* So here's what we do: If the caller insists that this is really
|
||||
* MP3 we'll take his word for it. Otherwise, use the same test as
|
||||
* SDL_mixer does and check if the stream starts with something that
|
||||
* looks like a frame.
|
||||
*
|
||||
* A frame begins with 11 bits of frame sync (all bits must be set),
|
||||
* followed by a two-bit MPEG Audio version ID:
|
||||
*
|
||||
* 00 - MPEG Version 2.5 (later extension of MPEG 2)
|
||||
* 01 - reserved
|
||||
* 10 - MPEG Version 2 (ISO/IEC 13818-3)
|
||||
* 11 - MPEG Version 1 (ISO/IEC 11172-3)
|
||||
*
|
||||
* Apparently we don't handle MPEG Version 2.5.
|
||||
*/
|
||||
if (__Sound_strcasecmp(ext, "MP3") != 0)
|
||||
{
|
||||
Uint8 mp3_magic[2];
|
||||
|
||||
if (SDL_RWread(internal->rw, mp3_magic, sizeof (mp3_magic), 1) != 1)
|
||||
BAIL_MACRO("SMPEG: Could not read MP3 magic.", 0);
|
||||
|
||||
if (mp3_magic[0] != 0xFF || (mp3_magic[1] & 0xF0) != 0xF0)
|
||||
BAIL_MACRO("SMPEG: Not an MP3 stream.", 0);
|
||||
|
||||
/* If the seek fails, we'll probably miss a frame, but oh well */
|
||||
SDL_RWseek(internal->rw, -sizeof (mp3_magic), SEEK_CUR);
|
||||
} /* if */
|
||||
|
||||
refCounter = RWops_RWRefCounter_new(internal->rw);
|
||||
if (refCounter == NULL)
|
||||
{
|
||||
SNDDBG(("SMPEG: Failed to create reference counting RWops.\n"));
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
/* replace original RWops. This is safe. Honest. :) */
|
||||
internal->rw = refCounter;
|
||||
|
||||
/*
|
||||
* increment the refcount, since SMPEG will nuke the RWops if it can't
|
||||
* accept the contained data...
|
||||
*/
|
||||
RWops_RWRefCounter_addRef(refCounter);
|
||||
smpeg = SMPEG_new_rwops(refCounter, &smpeg_info, 0);
|
||||
|
||||
err = SMPEG_error(smpeg);
|
||||
if (err != NULL)
|
||||
{
|
||||
__Sound_SetError(err); /* make a copy before SMPEG_delete()... */
|
||||
SMPEG_delete(smpeg);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (!smpeg_info.has_audio)
|
||||
{
|
||||
SMPEG_delete(smpeg);
|
||||
BAIL_MACRO("SMPEG: No audio stream found in data.", 0);
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("SMPEG: Accepting data stream.\n"));
|
||||
SNDDBG(("SMPEG: has_audio == {%s}.\n", smpeg_info.has_audio ? "TRUE" : "FALSE"));
|
||||
SNDDBG(("SMPEG: has_video == {%s}.\n", smpeg_info.has_video ? "TRUE" : "FALSE"));
|
||||
SNDDBG(("SMPEG: width == (%d).\n", smpeg_info.width));
|
||||
SNDDBG(("SMPEG: height == (%d).\n", smpeg_info.height));
|
||||
SNDDBG(("SMPEG: current_frame == (%d).\n", smpeg_info.current_frame));
|
||||
SNDDBG(("SMPEG: current_fps == (%f).\n", smpeg_info.current_fps));
|
||||
SNDDBG(("SMPEG: audio_string == [%s].\n", smpeg_info.audio_string));
|
||||
SNDDBG(("SMPEG: audio_current_frame == (%d).\n", smpeg_info.audio_current_frame));
|
||||
SNDDBG(("SMPEG: current_offset == (%d).\n", smpeg_info.current_offset));
|
||||
SNDDBG(("SMPEG: total_size == (%d).\n", smpeg_info.total_size));
|
||||
SNDDBG(("SMPEG: current_time == (%f).\n", smpeg_info.current_time));
|
||||
SNDDBG(("SMPEG: total_time == (%f).\n", smpeg_info.total_time));
|
||||
|
||||
SMPEG_enablevideo(smpeg, 0);
|
||||
SMPEG_enableaudio(smpeg, 1);
|
||||
SMPEG_loop(smpeg, 0);
|
||||
|
||||
SMPEG_wantedSpec(smpeg, &spec);
|
||||
|
||||
/*
|
||||
* One of the MP3s I tried wouldn't work unless I added this line
|
||||
* to tell SMPEG that yes, it may have the spec it wants.
|
||||
*/
|
||||
SMPEG_actualSpec(smpeg, &spec);
|
||||
sample->actual.format = spec.format;
|
||||
sample->actual.rate = spec.freq;
|
||||
sample->actual.channels = spec.channels;
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
internal->decoder_private = smpeg;
|
||||
|
||||
SMPEG_play(smpeg);
|
||||
return(1);
|
||||
} /* _SMPEG_open */
|
||||
|
||||
|
||||
static void _SMPEG_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SMPEG_delete((SMPEG *) internal->decoder_private);
|
||||
} /* _SMPEG_close */
|
||||
|
||||
|
||||
static Uint32 _SMPEG_read(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SMPEG *smpeg = (SMPEG *) internal->decoder_private;
|
||||
|
||||
/*
|
||||
* We have to clear the buffer because apparently SMPEG_playAudio()
|
||||
* will mix the decoded audio with whatever's already in it. Nasty.
|
||||
*/
|
||||
memset(internal->buffer, '\0', internal->buffer_size);
|
||||
retval = SMPEG_playAudio(smpeg, internal->buffer, internal->buffer_size);
|
||||
if (retval < internal->buffer_size)
|
||||
{
|
||||
char *errMsg = SMPEG_error(smpeg);
|
||||
if (errMsg == NULL)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
else
|
||||
{
|
||||
__Sound_SetError(errMsg);
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* _SMPEG_read */
|
||||
|
||||
|
||||
static int _SMPEG_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SMPEG *smpeg = (SMPEG *) internal->decoder_private;
|
||||
SMPEGstatus status;
|
||||
|
||||
/*
|
||||
* SMPEG_rewind() really means "stop and rewind", so we may have to
|
||||
* restart it afterwards.
|
||||
*/
|
||||
status = SMPEG_status(smpeg);
|
||||
SMPEG_rewind(smpeg);
|
||||
/* EW: I think SMPEG_play() has an independent and unrelated meaning
|
||||
* to the flag, "SMPEG_PLAYING". This is why the SMPEG_play() call
|
||||
* is done in the open() function even though the file is not yet
|
||||
* technically playing. I believe SMPEG_play() must always be active
|
||||
* because this seems to be what's causing the:
|
||||
* "Can't rewind after the file has finished playing once" problem,
|
||||
* because always recalling it here seems to make the problem go away.
|
||||
*/
|
||||
/*
|
||||
if (status == SMPEG_PLAYING)
|
||||
SMPEG_play(smpeg);
|
||||
*/
|
||||
SMPEG_play(smpeg);
|
||||
return(1);
|
||||
} /* _SMPEG_rewind */
|
||||
|
||||
|
||||
static int _SMPEG_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SMPEG *smpeg = (SMPEG *) internal->decoder_private;
|
||||
SMPEGstatus status;
|
||||
|
||||
/*
|
||||
* SMPEG_rewind() really means "stop and rewind", so we may have to
|
||||
* restart it afterwards.
|
||||
*/
|
||||
status = SMPEG_status(smpeg);
|
||||
SMPEG_rewind(smpeg);
|
||||
SMPEG_skip(smpeg, ((float) ms) / 1000.0);
|
||||
if (status == SMPEG_PLAYING)
|
||||
SMPEG_play(smpeg);
|
||||
return(1);
|
||||
} /* _SMPEG_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_SMPEG */
|
||||
|
||||
/* end of smpeg.c ... */
|
||||
|
||||
436
project/jni/sdl_sound/decoders/speex.c
Normal file
436
project/jni/sdl_sound/decoders/speex.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Speex decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles Speex audio data. Speex is a codec for speech that is
|
||||
* meant to be transmitted over narrowband network connections. Epic Games
|
||||
* estimates that their VoIP solution, built on top of Speex, uses around
|
||||
* 500 bytes per second or less to transmit relatively good sounding speech.
|
||||
*
|
||||
* This decoder processes the .spx files that the speexenc program produces.
|
||||
*
|
||||
* Speex isn't meant for general audio compression. Something like Ogg Vorbis
|
||||
* will give better results in that case.
|
||||
*
|
||||
* Further Speex information can be found at http://www.speex.org/
|
||||
*
|
||||
* This code is based on speexdec.c (see the Speex website).
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_SPEEX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
#include <speex/speex.h>
|
||||
#include <speex/speex_header.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int SPEEX_init(void);
|
||||
static void SPEEX_quit(void);
|
||||
static int SPEEX_open(Sound_Sample *sample, const char *ext);
|
||||
static void SPEEX_close(Sound_Sample *sample);
|
||||
static Uint32 SPEEX_read(Sound_Sample *sample);
|
||||
static int SPEEX_rewind(Sound_Sample *sample);
|
||||
static int SPEEX_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_speex[] = { "spx", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_SPEEX =
|
||||
{
|
||||
{
|
||||
extensions_speex,
|
||||
"SPEEX speech compression format",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
SPEEX_init, /* init() method */
|
||||
SPEEX_quit, /* quit() method */
|
||||
SPEEX_open, /* open() method */
|
||||
SPEEX_close, /* close() method */
|
||||
SPEEX_read, /* read() method */
|
||||
SPEEX_rewind, /* rewind() method */
|
||||
SPEEX_seek /* seek() method */
|
||||
};
|
||||
|
||||
#define SPEEX_USE_PERCEPTUAL_ENHANCER 1
|
||||
#define SPEEX_MAGIC 0x5367674F /* "OggS" in ASCII (littleendian) */
|
||||
#define SPEEX_OGG_BUFSIZE 200
|
||||
|
||||
/* this is what we store in our internal->decoder_private field... */
|
||||
typedef struct
|
||||
{
|
||||
ogg_sync_state oy;
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
ogg_stream_state os;
|
||||
void *state;
|
||||
SpeexBits bits;
|
||||
int header_count;
|
||||
int frame_size;
|
||||
int nframes;
|
||||
int frames_avail;
|
||||
float *decode_buf;
|
||||
int decode_total;
|
||||
int decode_pos;
|
||||
int have_ogg_packet;
|
||||
} speex_t;
|
||||
|
||||
|
||||
static int SPEEX_init(void)
|
||||
{
|
||||
return(1); /* no-op. */
|
||||
} /* SPEEX_init */
|
||||
|
||||
|
||||
static void SPEEX_quit(void)
|
||||
{
|
||||
/* no-op. */
|
||||
} /* SPEEX_quit */
|
||||
|
||||
|
||||
static int process_header(speex_t *speex, Sound_Sample *sample)
|
||||
{
|
||||
SpeexMode *mode;
|
||||
SpeexHeader *hptr;
|
||||
SpeexHeader header;
|
||||
int enh_enabled = SPEEX_USE_PERCEPTUAL_ENHANCER;
|
||||
int tmp;
|
||||
|
||||
hptr = speex_packet_to_header((char*) speex->op.packet, speex->op.bytes);
|
||||
BAIL_IF_MACRO(!hptr, "SPEEX: Cannot read header", 0);
|
||||
memcpy(&header, hptr, sizeof (SpeexHeader)); /* move to stack. */
|
||||
free(hptr); /* lame that this forces you to malloc... */
|
||||
|
||||
BAIL_IF_MACRO(header.mode >= SPEEX_NB_MODES, "SPEEX: Unknown mode", 0);
|
||||
BAIL_IF_MACRO(header.mode < 0, "SPEEX: Unknown mode", 0);
|
||||
mode = speex_mode_list[header.mode];
|
||||
BAIL_IF_MACRO(header.speex_version_id > 1, "SPEEX: Unknown version", 0);
|
||||
BAIL_IF_MACRO(mode->bitstream_version < header.mode_bitstream_version,
|
||||
"SPEEX: Unsupported bitstream version", 0);
|
||||
BAIL_IF_MACRO(mode->bitstream_version > header.mode_bitstream_version,
|
||||
"SPEEX: Unsupported bitstream version", 0);
|
||||
|
||||
speex->state = speex_decoder_init(mode);
|
||||
BAIL_IF_MACRO(!speex->state, "SPEEX: Decoder initialization error", 0);
|
||||
|
||||
speex_decoder_ctl(speex->state, SPEEX_SET_ENH, &enh_enabled);
|
||||
speex_decoder_ctl(speex->state, SPEEX_GET_FRAME_SIZE, &speex->frame_size);
|
||||
|
||||
speex->decode_buf = (float *) malloc(speex->frame_size * sizeof (float));
|
||||
BAIL_IF_MACRO(!speex->decode_buf, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
speex->nframes = header.frames_per_packet;
|
||||
if (!speex->nframes)
|
||||
speex->nframes = 1;
|
||||
|
||||
/* !!! FIXME: Write converters to match desired format.
|
||||
!!! FIXME: We have to convert from Float32 anyhow. */
|
||||
/* !!! FIXME: Is it a performance hit to alter sampling rate?
|
||||
!!! FIXME: If not, try to match desired rate. */
|
||||
/* !!! FIXME: We force mono output, but speexdec.c has code for stereo.
|
||||
!!! FIXME: Use that if sample->desired.channels == 2? */
|
||||
tmp = header.rate;
|
||||
speex_decoder_ctl(speex->state, SPEEX_SET_SAMPLING_RATE, &tmp);
|
||||
speex_decoder_ctl(speex->state, SPEEX_GET_SAMPLING_RATE, &tmp);
|
||||
sample->actual.rate = tmp;
|
||||
sample->actual.channels = 1;
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
|
||||
SNDDBG(("SPEEX: %dHz, mono, %svbr, %s mode.\n",
|
||||
(int) sample->actual.rate,
|
||||
header.vbr ? "" : "not ",
|
||||
mode->modeName));
|
||||
|
||||
/* plus 2: one for this header, one for the comment header. */
|
||||
speex->header_count = header.extra_headers + 2;
|
||||
return(1);
|
||||
} /* process_header */
|
||||
|
||||
|
||||
/* !!! FIXME: this code sucks. */
|
||||
static int SPEEX_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
int set_error_str = 1;
|
||||
int bitstream_initialized = 0;
|
||||
Uint8 *buffer = NULL;
|
||||
int packet_count = 0;
|
||||
speex_t *speex = NULL;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
Uint32 magic;
|
||||
|
||||
/* Quick rejection. */
|
||||
/*
|
||||
* !!! FIXME: If (ext) is .spx, ignore bad magic number and assume
|
||||
* !!! FIXME: this is a corrupted file...try to sync up further in
|
||||
* !!! FIXME: stream. But for general purposes we can't read the
|
||||
* !!! FIXME: whole RWops here in case it's not a Speex file at all.
|
||||
*/
|
||||
magic = SDL_ReadLE32(rw); /* make sure this is an ogg stream. */
|
||||
BAIL_IF_MACRO(magic != SPEEX_MAGIC, "SPEEX: Not a complete ogg stream", 0);
|
||||
BAIL_IF_MACRO(SDL_RWseek(rw, -4, SEEK_CUR) < 0, ERR_IO_ERROR, 0);
|
||||
|
||||
speex = (speex_t *) malloc(sizeof (speex_t));
|
||||
BAIL_IF_MACRO(speex == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(speex, '\0', sizeof (speex_t));
|
||||
|
||||
speex_bits_init(&speex->bits);
|
||||
if (ogg_sync_init(&speex->oy) != 0) goto speex_open_failed;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int rc;
|
||||
Uint8 *buffer = (Uint8*)ogg_sync_buffer(&speex->oy, SPEEX_OGG_BUFSIZE);
|
||||
if (buffer == NULL) goto speex_open_failed;
|
||||
rc = SDL_RWread(rw, buffer, 1, SPEEX_OGG_BUFSIZE);
|
||||
if (rc <= 0) goto speex_open_failed;
|
||||
if (ogg_sync_wrote(&speex->oy, rc) != 0) goto speex_open_failed;
|
||||
while (ogg_sync_pageout(&speex->oy, &speex->og) == 1)
|
||||
{
|
||||
if (!bitstream_initialized)
|
||||
{
|
||||
if (ogg_stream_init(&speex->os, ogg_page_serialno(&speex->og)))
|
||||
goto speex_open_failed;
|
||||
bitstream_initialized = 1;
|
||||
} /* if */
|
||||
|
||||
if (ogg_stream_pagein(&speex->os, &speex->og) != 0)
|
||||
goto speex_open_failed;
|
||||
|
||||
while (ogg_stream_packetout(&speex->os, &speex->op) == 1)
|
||||
{
|
||||
if (speex->op.e_o_s)
|
||||
goto speex_open_failed; /* end of stream already?! */
|
||||
|
||||
packet_count++;
|
||||
if (packet_count == 1) /* need speex header. */
|
||||
{
|
||||
if (!process_header(speex, sample))
|
||||
{
|
||||
set_error_str = 0; /* process_header will set error string. */
|
||||
goto speex_open_failed;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (packet_count > speex->header_count)
|
||||
{
|
||||
/* if you made it here, you're ready to get a waveform. */
|
||||
SNDDBG(("SPEEX: Accepting data stream.\n"));
|
||||
|
||||
/* sample->actual is configured in process_header()... */
|
||||
speex->have_ogg_packet = 1;
|
||||
sample->flags = SOUND_SAMPLEFLAG_NONE;
|
||||
internal->decoder_private = speex;
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
} /* while */
|
||||
|
||||
} /* while */
|
||||
|
||||
assert(0); /* shouldn't hit this point. */
|
||||
|
||||
speex_open_failed:
|
||||
if (speex != NULL)
|
||||
{
|
||||
if (speex->state != NULL)
|
||||
speex_decoder_destroy(speex->state);
|
||||
if (bitstream_initialized)
|
||||
ogg_stream_clear(&speex->os);
|
||||
speex_bits_destroy(&speex->bits);
|
||||
ogg_sync_clear(&speex->oy);
|
||||
free(speex->decode_buf);
|
||||
free(speex);
|
||||
} /* if */
|
||||
|
||||
if (set_error_str)
|
||||
BAIL_MACRO("SPEEX: decoding error", 0);
|
||||
|
||||
return(0);
|
||||
} /* SPEEX_open */
|
||||
|
||||
|
||||
static void SPEEX_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
speex_t *speex = (speex_t *) internal->decoder_private;
|
||||
speex_decoder_destroy(speex->state);
|
||||
ogg_stream_clear(&speex->os);
|
||||
speex_bits_destroy(&speex->bits);
|
||||
ogg_sync_clear(&speex->oy);
|
||||
free(speex->decode_buf);
|
||||
free(speex);
|
||||
} /* SPEEX_close */
|
||||
|
||||
|
||||
static Uint32 copy_from_decoded(speex_t *speex,
|
||||
Sound_SampleInternal *internal,
|
||||
Uint32 _cpypos)
|
||||
{
|
||||
/*
|
||||
* !!! FIXME: Obviously, this all needs to change if we allow for
|
||||
* !!! FIXME: more than mono, S16SYS data.
|
||||
*/
|
||||
Uint32 cpypos = _cpypos >> 1;
|
||||
Sint16 *dst = ((Sint16 *) internal->buffer) + cpypos;
|
||||
Sint16 *max;
|
||||
Uint32 maxoutput = (internal->buffer_size >> 1) - cpypos;
|
||||
Uint32 maxavail = speex->decode_total - speex->decode_pos;
|
||||
float *src = speex->decode_buf + speex->decode_pos;
|
||||
|
||||
if (maxavail < maxoutput)
|
||||
maxoutput = maxavail;
|
||||
|
||||
speex->decode_pos += maxoutput;
|
||||
cpypos += maxoutput;
|
||||
|
||||
for (max = dst + maxoutput; dst < max; dst++, src++)
|
||||
{
|
||||
/* !!! FIXME: This screams for vectorization. */
|
||||
register float f = *src;
|
||||
if (f > 32000.0f) /* eh, speexdec.c clamps like this, too. */
|
||||
f = 32000.0f;
|
||||
else if (f < -32000.0f)
|
||||
f = -32000.0f;
|
||||
*dst = (Sint16) (0.5f + f);
|
||||
} /* for */
|
||||
|
||||
return(cpypos << 1);
|
||||
} /* copy_from_decoded */
|
||||
|
||||
|
||||
/* !!! FIXME: this code sucks. */
|
||||
static Uint32 SPEEX_read(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval = 0;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
speex_t *speex = (speex_t *) internal->decoder_private;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
Uint8 *buffer;
|
||||
int rc;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* see if there's some already-decoded leftovers... */
|
||||
if (speex->decode_total != speex->decode_pos)
|
||||
{
|
||||
retval = copy_from_decoded(speex, internal, retval);
|
||||
if (retval >= internal->buffer_size)
|
||||
return(retval); /* whee. */
|
||||
} /* if */
|
||||
|
||||
/* okay, decoded buffer is spent. What else do we have? */
|
||||
speex->decode_total = speex->decode_pos = 0;
|
||||
|
||||
if (speex->frames_avail) /* have more frames to decode? */
|
||||
{
|
||||
rc = speex_decode(speex->state, &speex->bits, speex->decode_buf);
|
||||
if (rc < 0) goto speex_read_failed;
|
||||
if (speex_bits_remaining(&speex->bits) < 0) goto speex_read_failed;
|
||||
speex->frames_avail--;
|
||||
speex->decode_total = speex->frame_size;
|
||||
continue; /* go fill the output buffer... */
|
||||
} /* if */
|
||||
|
||||
/* need to get more speex frames from available ogg packets... */
|
||||
if (speex->have_ogg_packet)
|
||||
{
|
||||
speex_bits_read_from(&speex->bits,
|
||||
(char *) speex->op.packet,
|
||||
speex->op.bytes);
|
||||
|
||||
speex->frames_avail += speex->nframes;
|
||||
if (ogg_stream_packetout(&speex->os, &speex->op) <= 0)
|
||||
speex->have_ogg_packet = 0;
|
||||
continue; /* go decode these frames. */
|
||||
} /* if */
|
||||
|
||||
/* need to get more ogg packets from bitstream... */
|
||||
|
||||
if (speex->op.e_o_s) /* okay, we're really spent. */
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(retval);
|
||||
} /* if */
|
||||
|
||||
while ((!speex->op.e_o_s) && (!speex->have_ogg_packet))
|
||||
{
|
||||
buffer = (Uint8 *) ogg_sync_buffer(&speex->oy, SPEEX_OGG_BUFSIZE);
|
||||
if (buffer == NULL) goto speex_read_failed;
|
||||
rc = SDL_RWread(rw, buffer, 1, SPEEX_OGG_BUFSIZE);
|
||||
if (rc <= 0) goto speex_read_failed;
|
||||
if (ogg_sync_wrote(&speex->oy, rc) != 0) goto speex_read_failed;
|
||||
|
||||
/* got complete ogg page? */
|
||||
if (ogg_sync_pageout(&speex->oy, &speex->og) == 1)
|
||||
{
|
||||
if (ogg_stream_pagein(&speex->os, &speex->og) != 0)
|
||||
goto speex_read_failed;
|
||||
|
||||
/* got complete ogg packet? */
|
||||
if (ogg_stream_packetout(&speex->os, &speex->op) == 1)
|
||||
speex->have_ogg_packet = 1;
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* while */
|
||||
|
||||
assert(0); /* never hit this. Either return or goto speex_read_failed */
|
||||
|
||||
speex_read_failed:
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
/* !!! FIXME: "i/o error" is better in some situations. */
|
||||
BAIL_MACRO("SPEEX: Decoding error", retval);
|
||||
} /* SPEEX_read */
|
||||
|
||||
|
||||
static int SPEEX_rewind(Sound_Sample *sample)
|
||||
{
|
||||
/* !!! FIXME */ return(0);
|
||||
} /* SPEEX_rewind */
|
||||
|
||||
|
||||
static int SPEEX_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
/* !!! FIXME */ return(0);
|
||||
} /* SPEEX_seek */
|
||||
|
||||
|
||||
#endif /* SOUND_SUPPORTS_SPEEX */
|
||||
|
||||
/* end of speex.c ... */
|
||||
|
||||
77
project/jni/sdl_sound/decoders/timidity/CHANGES
Normal file
77
project/jni/sdl_sound/decoders/timidity/CHANGES
Normal file
@@ -0,0 +1,77 @@
|
||||
This version of TiMidity should contain all the fixes from the
|
||||
September 25 2003 SDL_mixer CVS snapshot. In addition, I've made some
|
||||
changes of my own, e.g.:
|
||||
|
||||
* All file access is done through SDL_RWops. This means the MIDI
|
||||
stream no longer has to be a file. (The config file and instruments
|
||||
still have to be though.)
|
||||
|
||||
* Replacing of TiMidity's endian-handling with SDL's.
|
||||
|
||||
* Removal of much unused or unnecessary code, such as
|
||||
|
||||
+ The "hooks" for putting a user interface onto TiMidity.
|
||||
+ The antialias filter. It wasn't active, and even at 4 kHz I
|
||||
couldn't hear any difference when activating it.
|
||||
+ Removed all traces of LOOKUP_HACK and LOOKUP_INTERPOLATION.
|
||||
According to the code comments they weren't very good anyway.
|
||||
("degrades sound quality noticeably"). I also removed the
|
||||
disclaimer about the "8-bit uLaw to 16-bit PCM and the 13-bit-PCM
|
||||
to 8-bit uLaw tables" disclaimer, since I believe those were the
|
||||
tables I removed.
|
||||
+ Removed LOOKUP_SINE since it was already commented out. I think we
|
||||
can count on our target audience having math co-processors
|
||||
nowadays.
|
||||
+ Removed USE_LDEXP since it wasn't being used and "it doesn't make
|
||||
much of a difference either way".
|
||||
+ Removed decompress hack from open_file() since it didn't look very
|
||||
portable.
|
||||
+ Removed heaps of unnecessary constants.
|
||||
+ Removed unused functions.
|
||||
+ Assume that LINEAR_INTERPOLATION is always used, so remove all
|
||||
code dealing with it not being so. It's not that I think the
|
||||
difference in audio quality is that great, but since it wouldn't
|
||||
compile without code changes I assume no one's used it for quite
|
||||
some time...
|
||||
+ Assume PRECALC_LOOPS is always defined. Judging by the comments it
|
||||
may not make much of a difference either way, so why maintain two
|
||||
versions of the same code?
|
||||
|
||||
* Moving several static globals into the MidiSong struct. This
|
||||
includes sample rate, formate, etc. which are now all per-song.
|
||||
|
||||
* Moved some typedefs (e.g. MidiSong) to timidity.h for easy inclusion
|
||||
into the MIDI decoder.
|
||||
|
||||
* Added free_pathlist().
|
||||
|
||||
* Replaced TiMidity's own 8, 16 and 32-bit types with SDL's.
|
||||
|
||||
* Made TiMidity look for its configuration file in both /etc and
|
||||
/usr/local/lib/timidity. (Windows version remains unchanged.)
|
||||
|
||||
* Timidity_PlaySome() now takes three arguments. A MidiSong, a decode
|
||||
buffer and decode buffer size in bytes. (MidiSong is a new argument,
|
||||
and buffer size used to be in samples.)
|
||||
|
||||
In addition, it will return the number of bytes decoded.
|
||||
|
||||
* Added Timidity_Exit().
|
||||
|
||||
* Removed Timidity_Stop() and Timidity_Active(). Stopping playback
|
||||
should be handled by SDL_sound, and Timidity_PlaySome() will return
|
||||
0 when the MIDI stream is finished.
|
||||
|
||||
* Modified the ToneBank stuff to allow some data to be shared between
|
||||
MidiSongs.
|
||||
|
||||
* The following files have been removed: controls.c, controls.h,
|
||||
filter.c, filter.h, sdl_a.c, sdl_c.c
|
||||
|
||||
* config.h has been renamed as options.h to avoid confusion with the
|
||||
automatically generated config.h for SDL_sound.
|
||||
|
||||
* Added support for loading DLS format instruments:
|
||||
Timidity_LoadDLS(), Timidity_FreeDLS(), Timidity_LoadDLSSong()
|
||||
|
||||
* Added Timidity_Init_NoConfig()
|
||||
519
project/jni/sdl_sound/decoders/timidity/COPYING
Normal file
519
project/jni/sdl_sound/decoders/timidity/COPYING
Normal file
@@ -0,0 +1,519 @@
|
||||
Please note that the included source from Timidity, the MIDI decoder, is also
|
||||
licensed under the following terms (GNU LGPL), but can also be used
|
||||
separately under the GNU GPL, or the Perl Artistic License. Those licensing
|
||||
terms are not reprinted here, but can be found on the web easily.
|
||||
|
||||
If you want to use SDL_sound under a closed-source license, please contact
|
||||
Ryan (icculus@icculus.org), and we can discuss an alternate license for
|
||||
money to be distributed between the contributors to this work, but I'd
|
||||
encourage you to abide by the LGPL, since the usual concern is whether you
|
||||
can use this library without releasing your own source code (you can).
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
100
project/jni/sdl_sound/decoders/timidity/FAQ
Normal file
100
project/jni/sdl_sound/decoders/timidity/FAQ
Normal file
@@ -0,0 +1,100 @@
|
||||
---------------------------*-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 enabled in options.h
|
||||
|
||||
- Recompile with an Intel-optimized gcc for a 5-15%
|
||||
performance increase.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
33
project/jni/sdl_sound/decoders/timidity/Makefile.am
Normal file
33
project/jni/sdl_sound/decoders/timidity/Makefile.am
Normal file
@@ -0,0 +1,33 @@
|
||||
if USE_TIMIDITY
|
||||
noinst_LTLIBRARIES = libtimidity.la
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
libtimidity_la_SOURCES = \
|
||||
common.c \
|
||||
common.h \
|
||||
dls1.h \
|
||||
dls2.h \
|
||||
instrum.c \
|
||||
instrum.h \
|
||||
instrum_dls.c \
|
||||
instrum_dls.h \
|
||||
mix.c \
|
||||
mix.h \
|
||||
options.h \
|
||||
output.c \
|
||||
output.h \
|
||||
playmidi.c \
|
||||
playmidi.h \
|
||||
readmidi.c \
|
||||
readmidi.h \
|
||||
resample.c \
|
||||
resample.h \
|
||||
tables.c \
|
||||
tables.h \
|
||||
timidity.c \
|
||||
timidity.h
|
||||
|
||||
EXTRA_DIST = CHANGES COPYING FAQ README TODO Makefile.testmidi testmidi.c
|
||||
|
||||
487
project/jni/sdl_sound/decoders/timidity/Makefile.in
Normal file
487
project/jni/sdl_sound/decoders/timidity/Makefile.in
Normal file
@@ -0,0 +1,487 @@
|
||||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ../..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = decoders/timidity
|
||||
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
COPYING TODO
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libtimidity_la_LIBADD =
|
||||
am_libtimidity_la_OBJECTS = common.lo instrum.lo instrum_dls.lo mix.lo \
|
||||
output.lo playmidi.lo readmidi.lo resample.lo tables.lo \
|
||||
timidity.lo
|
||||
libtimidity_la_OBJECTS = $(am_libtimidity_la_OBJECTS)
|
||||
@USE_TIMIDITY_TRUE@am_libtimidity_la_rpath =
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(libtimidity_la_SOURCES)
|
||||
DIST_SOURCES = $(libtimidity_la_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BINARY_AGE = @BINARY_AGE@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INTERFACE_AGE = @INTERFACE_AGE@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_AGE = @LT_AGE@
|
||||
LT_CURRENT = @LT_CURRENT@
|
||||
LT_RELEASE = @LT_RELEASE@
|
||||
LT_REVISION = @LT_REVISION@
|
||||
MAJOR_VERSION = @MAJOR_VERSION@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MICRO_VERSION = @MICRO_VERSION@
|
||||
MINOR_VERSION = @MINOR_VERSION@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
USE_MPGLIB_FALSE = @USE_MPGLIB_FALSE@
|
||||
USE_MPGLIB_TRUE = @USE_MPGLIB_TRUE@
|
||||
USE_PHYSICSFS_FALSE = @USE_PHYSICSFS_FALSE@
|
||||
USE_PHYSICSFS_TRUE = @USE_PHYSICSFS_TRUE@
|
||||
USE_TIMIDITY_FALSE = @USE_TIMIDITY_FALSE@
|
||||
USE_TIMIDITY_TRUE = @USE_TIMIDITY_TRUE@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
@USE_TIMIDITY_TRUE@noinst_LTLIBRARIES = libtimidity.la
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
libtimidity_la_SOURCES = \
|
||||
common.c \
|
||||
common.h \
|
||||
dls1.h \
|
||||
dls2.h \
|
||||
instrum.c \
|
||||
instrum.h \
|
||||
instrum_dls.c \
|
||||
instrum_dls.h \
|
||||
mix.c \
|
||||
mix.h \
|
||||
options.h \
|
||||
output.c \
|
||||
output.h \
|
||||
playmidi.c \
|
||||
playmidi.h \
|
||||
readmidi.c \
|
||||
readmidi.h \
|
||||
resample.c \
|
||||
resample.h \
|
||||
tables.c \
|
||||
tables.h \
|
||||
timidity.c \
|
||||
timidity.h
|
||||
|
||||
EXTRA_DIST = CHANGES COPYING FAQ README TODO Makefile.testmidi testmidi.c
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign decoders/timidity/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign decoders/timidity/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libtimidity.la: $(libtimidity_la_OBJECTS) $(libtimidity_la_DEPENDENCIES)
|
||||
$(LINK) $(am_libtimidity_la_rpath) $(libtimidity_la_LDFLAGS) $(libtimidity_la_OBJECTS) $(libtimidity_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrum.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrum_dls.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mix.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/playmidi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readmidi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resample.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timidity.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LTLIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLTLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am \
|
||||
uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
38
project/jni/sdl_sound/decoders/timidity/Makefile.testmidi
Normal file
38
project/jni/sdl_sound/decoders/timidity/Makefile.testmidi
Normal file
@@ -0,0 +1,38 @@
|
||||
# Silly test makefile
|
||||
|
||||
CC = gcc
|
||||
|
||||
# Standard SDL_sound debugging
|
||||
CFLAGS = -g -I../.. -ansi -pedantic -Wall `sdl-config --cflags` -DDEBUG_CHATTER
|
||||
LIBS = `sdl-config --libs`
|
||||
|
||||
# Electric Fence debugging
|
||||
# CFLAGS = -g -I../.. -ansi -pedantic -Wall `sdl-config --cflags`
|
||||
# LIBS = `sdl-config --libs` -lefence
|
||||
|
||||
OBJECTS = common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o \
|
||||
tables.o timidity.o testmidi.o
|
||||
|
||||
all: testmidi
|
||||
|
||||
testmidi: $(OBJECTS)
|
||||
$(CC) $(OBJECTS) $(CFLAGS) -o testmidi $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) testmidi *.o *~
|
||||
|
||||
common.o: common.c options.h common.h
|
||||
instrum.o: instrum.c timidity.h options.h common.h instrum.h resample.h \
|
||||
tables.h
|
||||
mix.o: mix.c timidity.h options.h instrum.h playmidi.h output.h tables.h \
|
||||
resample.h mix.h
|
||||
output.o: output.c options.h output.h
|
||||
playmidi.o: playmidi.c timidity.h options.h instrum.h playmidi.h output.h \
|
||||
mix.h tables.h
|
||||
readmidi.o: readmidi.c timidity.h common.h instrum.h playmidi.h
|
||||
resample.o: resample.c timidity.h options.h common.h instrum.h playmidi.h \
|
||||
tables.h resample.h
|
||||
tables.o: tables.c tables.h
|
||||
testmidi.o: testmidi.c common.h timidity.h
|
||||
timidity.o: timidity.c options.h common.h instrum.h playmidi.h readmidi.h \
|
||||
output.h timidity.h tables.h
|
||||
61
project/jni/sdl_sound/decoders/timidity/README
Normal file
61
project/jni/sdl_sound/decoders/timidity/README
Normal file
@@ -0,0 +1,61 @@
|
||||
[This version of timidity has been stripped for simplicity in porting to SDL,
|
||||
and then even further for SDL_sound]
|
||||
---------------------------------*-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
|
||||
|
||||
* The GNU General Public License can, as always, be found in the file
|
||||
"../COPYING".
|
||||
|
||||
* TiMidity requires sampled instruments (patches) to play MIDI files. You
|
||||
should get the file "timidity-lib-0.1.tar.gz" and unpack it in the same
|
||||
directory where you unpacked the source code archive. You'll want more
|
||||
patches later -- read the file "FAQ" for pointers.
|
||||
|
||||
* 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.]
|
||||
37
project/jni/sdl_sound/decoders/timidity/TODO
Normal file
37
project/jni/sdl_sound/decoders/timidity/TODO
Normal file
@@ -0,0 +1,37 @@
|
||||
* I don't like the indentation style at all, but for the most part
|
||||
I've left it alone.
|
||||
|
||||
* Much of the code looks ugly to me.
|
||||
|
||||
* The return value from SDL_RWread() is checked inconsistenly.
|
||||
|
||||
* Group the members of MidiSong into logical units, i.e. structs?
|
||||
|
||||
* The debug messages are probably a bit too noisy. I've removed one
|
||||
particularly annoying one, but...
|
||||
|
||||
Some of them should be turned into error messages instead.
|
||||
|
||||
* Can the instrument handling be made more efficient? At the moment
|
||||
different MidiSongs may separately load the same instrument.
|
||||
|
||||
Note that the MidiSong's audio format affects how the instrument is
|
||||
loaded, so it's not as easy as just letting all MidiSongs share tone
|
||||
and drum banks.
|
||||
|
||||
At the moment they do share the data that is simply read from the
|
||||
config file, but that's just a quick hack to avoid having to read
|
||||
the config file every time a MIDI song is loaded.
|
||||
|
||||
* Check if any of MidiStruct's members can safely be made into static
|
||||
globals again.
|
||||
|
||||
* TiMidity++ adds a number of undocumented (?) extensions to the
|
||||
configuration syntax. These are not implemented here. In particular,
|
||||
the "map" keyword used by the "eawpats".
|
||||
|
||||
* The other decoders generally only read as much of the file as is
|
||||
necessary. Could we do that in this decoder as well? (Currently it
|
||||
seems to convert the entire file into MIDI events first.)
|
||||
|
||||
* Can it be optimized?
|
||||
137
project/jni/sdl_sound/decoders/timidity/common.c
Normal file
137
project/jni/sdl_sound/decoders/timidity/common.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
common.c
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
|
||||
/* The paths in this list will be tried whenever we're reading a file */
|
||||
static PathList *pathlist = NULL; /* This is a linked list */
|
||||
|
||||
/* This is meant to find and open files for reading */
|
||||
SDL_RWops *open_file(char *name)
|
||||
{
|
||||
SDL_RWops *rw;
|
||||
|
||||
if (!name || !(*name))
|
||||
{
|
||||
SNDDBG(("Attempted to open nameless file.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First try the given name */
|
||||
|
||||
SNDDBG(("Trying to open %s\n", name));
|
||||
if ((rw = SDL_RWFromFile(name, "rb")))
|
||||
return rw;
|
||||
|
||||
if (name[0] != PATH_SEP)
|
||||
{
|
||||
char current_filename[1024];
|
||||
PathList *plp = pathlist;
|
||||
int l;
|
||||
|
||||
while (plp) /* Try along the path then */
|
||||
{
|
||||
*current_filename = 0;
|
||||
l = strlen(plp->path);
|
||||
if(l)
|
||||
{
|
||||
strcpy(current_filename, plp->path);
|
||||
if(current_filename[l - 1] != PATH_SEP)
|
||||
{
|
||||
current_filename[l] = PATH_SEP;
|
||||
current_filename[l + 1] = '\0';
|
||||
}
|
||||
}
|
||||
strcat(current_filename, name);
|
||||
SNDDBG(("Trying to open %s\n", current_filename));
|
||||
if ((rw = SDL_RWFromFile(current_filename, "rb")))
|
||||
return rw;
|
||||
plp = plp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing could be opened. */
|
||||
SNDDBG(("Could not open %s\n", name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This'll allocate memory or die. */
|
||||
void *safe_malloc(size_t count)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(count);
|
||||
if (p == NULL)
|
||||
SNDDBG(("Sorry. Couldn't malloc %d bytes.\n", count));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* This adds a directory to the path list */
|
||||
void add_to_pathlist(char *s)
|
||||
{
|
||||
PathList *plp = safe_malloc(sizeof(PathList));
|
||||
|
||||
if (plp == NULL)
|
||||
return;
|
||||
|
||||
plp->path = safe_malloc(strlen(s) + 1);
|
||||
if (plp->path == NULL)
|
||||
{
|
||||
free(plp);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(plp->path, s);
|
||||
plp->next = pathlist;
|
||||
pathlist = plp;
|
||||
}
|
||||
|
||||
void free_pathlist(void)
|
||||
{
|
||||
PathList *plp = pathlist;
|
||||
PathList *next;
|
||||
|
||||
while (plp)
|
||||
{
|
||||
next = plp->next;
|
||||
free(plp->path);
|
||||
free(plp);
|
||||
plp = next;
|
||||
}
|
||||
pathlist = NULL;
|
||||
}
|
||||
32
project/jni/sdl_sound/decoders/timidity/common.h
Normal file
32
project/jni/sdl_sound/decoders/timidity/common.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
common.h
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
void *next;
|
||||
} PathList;
|
||||
|
||||
extern SDL_RWops *open_file(char *name);
|
||||
extern void add_to_pathlist(char *s);
|
||||
extern void *safe_malloc(size_t count);
|
||||
extern void free_pathlist(void);
|
||||
266
project/jni/sdl_sound/decoders/timidity/dls1.h
Normal file
266
project/jni/sdl_sound/decoders/timidity/dls1.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/*==========================================================================;
|
||||
//
|
||||
// dls1.h
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Interface defines and structures for the Instrument Collection Form
|
||||
// RIFF DLS.
|
||||
//
|
||||
//
|
||||
// Written by Sonic Foundry 1996. Released for public use.
|
||||
//
|
||||
//=========================================================================*/
|
||||
|
||||
#ifndef _INC_DLS1
|
||||
#define _INC_DLS1
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// Layout of an instrument collection:
|
||||
//
|
||||
//
|
||||
// RIFF [] 'DLS ' [dlid,colh,INSTLIST,WAVEPOOL,INFOLIST]
|
||||
//
|
||||
// INSTLIST
|
||||
// LIST [] 'lins'
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
// LIST [] 'ins ' [dlid,insh,RGNLIST,ARTLIST,INFOLIST]
|
||||
//
|
||||
// RGNLIST
|
||||
// LIST [] 'lrgn'
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
// LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
|
||||
//
|
||||
// ARTLIST
|
||||
// LIST [] 'lart'
|
||||
// 'art1' level 1 Articulation connection graph
|
||||
// 'art2' level 2 Articulation connection graph
|
||||
// '3rd1' Possible 3rd party articulation structure 1
|
||||
// '3rd2' Possible 3rd party articulation structure 2 .... and so on
|
||||
//
|
||||
// WAVEPOOL
|
||||
// ptbl [] [pool table]
|
||||
// LIST [] 'wvpl'
|
||||
// [path],
|
||||
// [path],
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
// LIST [] 'wave' [dlid,RIFFWAVE]
|
||||
//
|
||||
// INFOLIST
|
||||
// LIST [] 'INFO'
|
||||
// 'icmt' 'One of those crazy comments.'
|
||||
// 'icop' 'Copyright (C) 1996 Sonic Foundry'
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// FOURCC's used in the DLS file
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define FOURCC_DLS mmioFOURCC('D','L','S',' ')
|
||||
#define FOURCC_DLID mmioFOURCC('d','l','i','d')
|
||||
#define FOURCC_COLH mmioFOURCC('c','o','l','h')
|
||||
#define FOURCC_WVPL mmioFOURCC('w','v','p','l')
|
||||
#define FOURCC_PTBL mmioFOURCC('p','t','b','l')
|
||||
#define FOURCC_PATH mmioFOURCC('p','a','t','h')
|
||||
#define FOURCC_wave mmioFOURCC('w','a','v','e')
|
||||
#define FOURCC_LINS mmioFOURCC('l','i','n','s')
|
||||
#define FOURCC_INS mmioFOURCC('i','n','s',' ')
|
||||
#define FOURCC_INSH mmioFOURCC('i','n','s','h')
|
||||
#define FOURCC_LRGN mmioFOURCC('l','r','g','n')
|
||||
#define FOURCC_RGN mmioFOURCC('r','g','n',' ')
|
||||
#define FOURCC_RGNH mmioFOURCC('r','g','n','h')
|
||||
#define FOURCC_LART mmioFOURCC('l','a','r','t')
|
||||
#define FOURCC_ART1 mmioFOURCC('a','r','t','1')
|
||||
#define FOURCC_WLNK mmioFOURCC('w','l','n','k')
|
||||
#define FOURCC_WSMP mmioFOURCC('w','s','m','p')
|
||||
#define FOURCC_VERS mmioFOURCC('v','e','r','s')
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Articulation connection graph definitions
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/* Generic Sources */
|
||||
#define CONN_SRC_NONE 0x0000
|
||||
#define CONN_SRC_LFO 0x0001
|
||||
#define CONN_SRC_KEYONVELOCITY 0x0002
|
||||
#define CONN_SRC_KEYNUMBER 0x0003
|
||||
#define CONN_SRC_EG1 0x0004
|
||||
#define CONN_SRC_EG2 0x0005
|
||||
#define CONN_SRC_PITCHWHEEL 0x0006
|
||||
|
||||
/* Midi Controllers 0-127 */
|
||||
#define CONN_SRC_CC1 0x0081
|
||||
#define CONN_SRC_CC7 0x0087
|
||||
#define CONN_SRC_CC10 0x008a
|
||||
#define CONN_SRC_CC11 0x008b
|
||||
|
||||
/* Generic Destinations */
|
||||
#define CONN_DST_NONE 0x0000
|
||||
#define CONN_DST_ATTENUATION 0x0001
|
||||
#define CONN_DST_PITCH 0x0003
|
||||
#define CONN_DST_PAN 0x0004
|
||||
|
||||
/* LFO Destinations */
|
||||
#define CONN_DST_LFO_FREQUENCY 0x0104
|
||||
#define CONN_DST_LFO_STARTDELAY 0x0105
|
||||
|
||||
/* EG1 Destinations */
|
||||
#define CONN_DST_EG1_ATTACKTIME 0x0206
|
||||
#define CONN_DST_EG1_DECAYTIME 0x0207
|
||||
#define CONN_DST_EG1_RELEASETIME 0x0209
|
||||
#define CONN_DST_EG1_SUSTAINLEVEL 0x020a
|
||||
|
||||
/* EG2 Destinations */
|
||||
#define CONN_DST_EG2_ATTACKTIME 0x030a
|
||||
#define CONN_DST_EG2_DECAYTIME 0x030b
|
||||
#define CONN_DST_EG2_RELEASETIME 0x030d
|
||||
#define CONN_DST_EG2_SUSTAINLEVEL 0x030e
|
||||
|
||||
#define CONN_TRN_NONE 0x0000
|
||||
#define CONN_TRN_CONCAVE 0x0001
|
||||
|
||||
typedef struct _DLSID {
|
||||
ULONG ulData1;
|
||||
USHORT usData2;
|
||||
USHORT usData3;
|
||||
BYTE abData4[8];
|
||||
} DLSID, FAR *LPDLSID;
|
||||
|
||||
typedef struct _DLSVERSION {
|
||||
DWORD dwVersionMS;
|
||||
DWORD dwVersionLS;
|
||||
} DLSVERSION, FAR *LPDLSVERSION;
|
||||
|
||||
|
||||
typedef struct _CONNECTION {
|
||||
USHORT usSource;
|
||||
USHORT usControl;
|
||||
USHORT usDestination;
|
||||
USHORT usTransform;
|
||||
LONG lScale;
|
||||
} CONNECTION, FAR *LPCONNECTION;
|
||||
|
||||
|
||||
/* Level 1 Articulation Data */
|
||||
|
||||
typedef struct _CONNECTIONLIST {
|
||||
ULONG cbSize; /* size of the connection list structure */
|
||||
ULONG cConnections; /* count of connections in the list */
|
||||
} CONNECTIONLIST, FAR *LPCONNECTIONLIST;
|
||||
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Generic type defines for regions and instruments
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
typedef struct _RGNRANGE {
|
||||
USHORT usLow;
|
||||
USHORT usHigh;
|
||||
} RGNRANGE, FAR * LPRGNRANGE;
|
||||
|
||||
#define F_INSTRUMENT_DRUMS 0x80000000
|
||||
|
||||
typedef struct _MIDILOCALE {
|
||||
ULONG ulBank;
|
||||
ULONG ulInstrument;
|
||||
} MIDILOCALE, FAR *LPMIDILOCALE;
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
// Header structures found in an DLS file for collection, instruments, and
|
||||
// regions.
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
|
||||
|
||||
typedef struct _RGNHEADER {
|
||||
RGNRANGE RangeKey; /* Key range */
|
||||
RGNRANGE RangeVelocity; /* Velocity Range */
|
||||
USHORT fusOptions; /* Synthesis options for this range */
|
||||
USHORT usKeyGroup; /* Key grouping for non simultaneous play */
|
||||
/* 0 = no group, 1 up is group */
|
||||
/* for Level 1 only groups 1-15 are allowed */
|
||||
} RGNHEADER, FAR *LPRGNHEADER;
|
||||
|
||||
typedef struct _INSTHEADER {
|
||||
ULONG cRegions; /* Count of regions in this instrument */
|
||||
MIDILOCALE Locale; /* Intended MIDI locale of this instrument */
|
||||
} INSTHEADER, FAR *LPINSTHEADER;
|
||||
|
||||
typedef struct _DLSHEADER {
|
||||
ULONG cInstruments; /* Count of instruments in the collection */
|
||||
} DLSHEADER, FAR *LPDLSHEADER;
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////////////
|
||||
// definitions for the Wave link structure
|
||||
////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/* **** For level 1 only WAVELINK_CHANNEL_MONO is valid **** */
|
||||
/* ulChannel allows for up to 32 channels of audio with each bit position */
|
||||
/* specifiying a channel of playback */
|
||||
|
||||
#define WAVELINK_CHANNEL_LEFT 0x0001l
|
||||
#define WAVELINK_CHANNEL_RIGHT 0x0002l
|
||||
|
||||
#define F_WAVELINK_PHASE_MASTER 0x0001
|
||||
|
||||
typedef struct _WAVELINK { /* any paths or links are stored right after struct */
|
||||
USHORT fusOptions; /* options flags for this wave */
|
||||
USHORT usPhaseGroup; /* Phase grouping for locking channels */
|
||||
ULONG ulChannel; /* channel placement */
|
||||
ULONG ulTableIndex; /* index into the wave pool table, 0 based */
|
||||
} WAVELINK, FAR *LPWAVELINK;
|
||||
|
||||
#define POOL_CUE_NULL 0xffffffffl
|
||||
|
||||
typedef struct _POOLCUE {
|
||||
ULONG ulOffset; /* Offset to the entry in the list */
|
||||
} POOLCUE, FAR *LPPOOLCUE;
|
||||
|
||||
typedef struct _POOLTABLE {
|
||||
ULONG cbSize; /* size of the pool table structure */
|
||||
ULONG cCues; /* count of cues in the list */
|
||||
} POOLTABLE, FAR *LPPOOLTABLE;
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////////////
|
||||
// Structures for the "wsmp" chunk
|
||||
////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#define F_WSMP_NO_TRUNCATION 0x0001l
|
||||
#define F_WSMP_NO_COMPRESSION 0x0002l
|
||||
|
||||
|
||||
typedef struct _rwsmp {
|
||||
ULONG cbSize;
|
||||
USHORT usUnityNote; /* MIDI Unity Playback Note */
|
||||
SHORT sFineTune; /* Fine Tune in log tuning */
|
||||
LONG lAttenuation; /* Overall Attenuation to be applied to data */
|
||||
ULONG fulOptions; /* Flag options */
|
||||
ULONG cSampleLoops; /* Count of Sample loops, 0 loops is one shot */
|
||||
} WSMPL, FAR *LPWSMPL;
|
||||
|
||||
|
||||
/* This loop type is a normal forward playing loop which is continually */
|
||||
/* played until the envelope reaches an off threshold in the release */
|
||||
/* portion of the volume envelope */
|
||||
|
||||
#define WLOOP_TYPE_FORWARD 0
|
||||
|
||||
typedef struct _rloop {
|
||||
ULONG cbSize;
|
||||
ULONG ulType; /* Loop Type */
|
||||
ULONG ulStart; /* Start of loop in samples */
|
||||
ULONG ulLength; /* Length of loop in samples */
|
||||
} WLOOP, FAR *LPWLOOP;
|
||||
|
||||
#endif /*_INC_DLS1 */
|
||||
130
project/jni/sdl_sound/decoders/timidity/dls2.h
Normal file
130
project/jni/sdl_sound/decoders/timidity/dls2.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
|
||||
dls2.h
|
||||
|
||||
Description:
|
||||
|
||||
Interface defines and structures for the DLS2 extensions of DLS.
|
||||
|
||||
|
||||
Written by Microsoft 1998. Released for public use.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_DLS2
|
||||
#define _INC_DLS2
|
||||
|
||||
/*
|
||||
FOURCC's used in the DLS2 file, in addition to DLS1 chunks
|
||||
*/
|
||||
|
||||
#define FOURCC_RGN2 mmioFOURCC('r','g','n','2')
|
||||
#define FOURCC_LAR2 mmioFOURCC('l','a','r','2')
|
||||
#define FOURCC_ART2 mmioFOURCC('a','r','t','2')
|
||||
#define FOURCC_CDL mmioFOURCC('c','d','l',' ')
|
||||
#define FOURCC_DLID mmioFOURCC('d','l','i','d')
|
||||
|
||||
/*
|
||||
Articulation connection graph definitions. These are in addition to
|
||||
the definitions in the DLS1 header.
|
||||
*/
|
||||
|
||||
/* Generic Sources (in addition to DLS1 sources. */
|
||||
#define CONN_SRC_POLYPRESSURE 0x0007 /* Polyphonic Pressure */
|
||||
#define CONN_SRC_CHANNELPRESSURE 0x0008 /* Channel Pressure */
|
||||
#define CONN_SRC_VIBRATO 0x0009 /* Vibrato LFO */
|
||||
#define CONN_SRC_MONOPRESSURE 0x000a /* MIDI Mono pressure */
|
||||
|
||||
|
||||
/* Midi Controllers */
|
||||
#define CONN_SRC_CC91 0x00db /* Reverb Send */
|
||||
#define CONN_SRC_CC93 0x00dd /* Chorus Send */
|
||||
|
||||
|
||||
/* Generic Destinations */
|
||||
#define CONN_DST_GAIN 0x0001 /* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */
|
||||
#define CONN_DST_KEYNUMBER 0x0005 /* Key Number Generator */
|
||||
|
||||
/* Audio Channel Output Destinations */
|
||||
#define CONN_DST_LEFT 0x0010 /* Left Channel Send */
|
||||
#define CONN_DST_RIGHT 0x0011 /* Right Channel Send */
|
||||
#define CONN_DST_CENTER 0x0012 /* Center Channel Send */
|
||||
#define CONN_DST_LEFTREAR 0x0013 /* Left Rear Channel Send */
|
||||
#define CONN_DST_RIGHTREAR 0x0014 /* Right Rear Channel Send */
|
||||
#define CONN_DST_LFE_CHANNEL 0x0015 /* LFE Channel Send */
|
||||
#define CONN_DST_CHORUS 0x0080 /* Chorus Send */
|
||||
#define CONN_DST_REVERB 0x0081 /* Reverb Send */
|
||||
|
||||
/* Vibrato LFO Destinations */
|
||||
#define CONN_DST_VIB_FREQUENCY 0x0114 /* Vibrato Frequency */
|
||||
#define CONN_DST_VIB_STARTDELAY 0x0115 /* Vibrato Start Delay */
|
||||
|
||||
/* EG1 Destinations */
|
||||
#define CONN_DST_EG1_DELAYTIME 0x020B /* EG1 Delay Time */
|
||||
#define CONN_DST_EG1_HOLDTIME 0x020C /* EG1 Hold Time */
|
||||
#define CONN_DST_EG1_SHUTDOWNTIME 0x020D /* EG1 Shutdown Time */
|
||||
|
||||
|
||||
/* EG2 Destinations */
|
||||
#define CONN_DST_EG2_DELAYTIME 0x030F /* EG2 Delay Time */
|
||||
#define CONN_DST_EG2_HOLDTIME 0x0310 /* EG2 Hold Time */
|
||||
|
||||
|
||||
/* Filter Destinations */
|
||||
#define CONN_DST_FILTER_CUTOFF 0x0500 /* Filter Cutoff Frequency */
|
||||
#define CONN_DST_FILTER_Q 0x0501 /* Filter Resonance */
|
||||
|
||||
|
||||
/* Transforms */
|
||||
#define CONN_TRN_CONVEX 0x0002 /* Convex Transform */
|
||||
#define CONN_TRN_SWITCH 0x0003 /* Switch Transform */
|
||||
|
||||
|
||||
/* Conditional chunk operators */
|
||||
#define DLS_CDL_AND 0x0001 /* X = X & Y */
|
||||
#define DLS_CDL_OR 0x0002 /* X = X | Y */
|
||||
#define DLS_CDL_XOR 0x0003 /* X = X ^ Y */
|
||||
#define DLS_CDL_ADD 0x0004 /* X = X + Y */
|
||||
#define DLS_CDL_SUBTRACT 0x0005 /* X = X - Y */
|
||||
#define DLS_CDL_MULTIPLY 0x0006 /* X = X * Y */
|
||||
#define DLS_CDL_DIVIDE 0x0007 /* X = X / Y */
|
||||
#define DLS_CDL_LOGICAL_AND 0x0008 /* X = X && Y */
|
||||
#define DLS_CDL_LOGICAL_OR 0x0009 /* X = X || Y */
|
||||
#define DLS_CDL_LT 0x000A /* X = (X < Y) */
|
||||
#define DLS_CDL_LE 0x000B /* X = (X <= Y) */
|
||||
#define DLS_CDL_GT 0x000C /* X = (X > Y) */
|
||||
#define DLS_CDL_GE 0x000D /* X = (X >= Y) */
|
||||
#define DLS_CDL_EQ 0x000E /* X = (X == Y) */
|
||||
#define DLS_CDL_NOT 0x000F /* X = !X */
|
||||
#define DLS_CDL_CONST 0x0010 /* 32-bit constant */
|
||||
#define DLS_CDL_QUERY 0x0011 /* 32-bit value returned from query */
|
||||
#define DLS_CDL_QUERYSUPPORTED 0x0012 /* Test to see if query is supported by synth */
|
||||
|
||||
/*
|
||||
Loop and release
|
||||
*/
|
||||
|
||||
#define WLOOP_TYPE_RELEASE 1
|
||||
|
||||
/*
|
||||
WaveLink chunk <wlnk-ck>
|
||||
*/
|
||||
|
||||
#define F_WAVELINK_MULTICHANNEL 0x0002
|
||||
|
||||
|
||||
/*
|
||||
DLSID queries for <cdl-ck>
|
||||
*/
|
||||
|
||||
DEFINE_GUID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
|
||||
DEFINE_GUID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
|
||||
DEFINE_GUID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
DEFINE_GUID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
DEFINE_GUID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
|
||||
|
||||
#endif /* _INC_DLS2 */
|
||||
623
project/jni/sdl_sound/decoders/timidity/instrum.c
Normal file
623
project/jni/sdl_sound/decoders/timidity/instrum.c
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.c
|
||||
|
||||
Code to load and unload GUS-compatible instrument patches.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "instrum_dls.h"
|
||||
#include "resample.h"
|
||||
#include "tables.h"
|
||||
|
||||
static void free_instrument(Instrument *ip)
|
||||
{
|
||||
Sample *sp;
|
||||
int i;
|
||||
if (!ip) return;
|
||||
for (i=0; i<ip->samples; i++)
|
||||
{
|
||||
sp=&(ip->sample[i]);
|
||||
free(sp->data);
|
||||
}
|
||||
free(ip->sample);
|
||||
free(ip);
|
||||
}
|
||||
|
||||
static void free_bank(MidiSong *song, int dr, int b)
|
||||
{
|
||||
int i;
|
||||
ToneBank *bank=((dr) ? song->drumset[b] : song->tonebank[b]);
|
||||
for (i=0; i<128; i++)
|
||||
if (bank->instrument[i])
|
||||
{
|
||||
/* Not that this could ever happen, of course */
|
||||
if (bank->instrument[i] != MAGIC_LOAD_INSTRUMENT)
|
||||
free_instrument(bank->instrument[i]);
|
||||
bank->instrument[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
static Sint32 convert_envelope_rate(MidiSong *song, Uint8 rate)
|
||||
{
|
||||
Sint32 r;
|
||||
|
||||
r = 3 - ((rate >> 6) & 0x3);
|
||||
r *= 3;
|
||||
r = (Sint32) (rate & 0x3f) << r; /* 6.9 fixed point */
|
||||
|
||||
/* 15.15 fixed point. */
|
||||
r = ((r * 44100) / song->rate) * song->control_ratio;
|
||||
|
||||
#ifdef FAST_DECAY
|
||||
return r << 10;
|
||||
#else
|
||||
return r << 9;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Sint32 convert_envelope_offset(Uint8 offset)
|
||||
{
|
||||
/* This is not too good... Can anyone tell me what these values mean?
|
||||
Are they GUS-style "exponential" volumes? And what does that mean? */
|
||||
|
||||
/* 15.15 fixed point */
|
||||
return offset << (7+15);
|
||||
}
|
||||
|
||||
static Sint32 convert_tremolo_sweep(MidiSong *song, Uint8 sweep)
|
||||
{
|
||||
if (!sweep)
|
||||
return 0;
|
||||
|
||||
return
|
||||
((song->control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
|
||||
(song->rate * sweep);
|
||||
}
|
||||
|
||||
static Sint32 convert_vibrato_sweep(MidiSong *song, Uint8 sweep,
|
||||
Sint32 vib_control_ratio)
|
||||
{
|
||||
if (!sweep)
|
||||
return 0;
|
||||
|
||||
return
|
||||
(Sint32) (FSCALE((double) (vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT)
|
||||
/ (double)(song->rate * sweep));
|
||||
|
||||
/* this was overflowing with seashore.pat
|
||||
|
||||
((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
|
||||
(song->rate * sweep); */
|
||||
}
|
||||
|
||||
static Sint32 convert_tremolo_rate(MidiSong *song, Uint8 rate)
|
||||
{
|
||||
return
|
||||
((SINE_CYCLE_LENGTH * song->control_ratio * rate) << RATE_SHIFT) /
|
||||
(TREMOLO_RATE_TUNING * song->rate);
|
||||
}
|
||||
|
||||
static Sint32 convert_vibrato_rate(MidiSong *song, Uint8 rate)
|
||||
{
|
||||
/* Return a suitable vibrato_control_ratio value */
|
||||
return
|
||||
(VIBRATO_RATE_TUNING * song->rate) /
|
||||
(rate * 2 * VIBRATO_SAMPLE_INCREMENTS);
|
||||
}
|
||||
|
||||
static void reverse_data(Sint16 *sp, Sint32 ls, Sint32 le)
|
||||
{
|
||||
Sint16 s, *ep=sp+le;
|
||||
sp+=ls;
|
||||
le-=ls;
|
||||
le/=2;
|
||||
while (le--)
|
||||
{
|
||||
s=*sp;
|
||||
*sp++=*ep;
|
||||
*ep--=s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If panning or note_to_use != -1, it will be used for all samples,
|
||||
instead of the sample-specific values in the instrument file.
|
||||
|
||||
For note_to_use, any value <0 or >127 will be forced to 0.
|
||||
|
||||
For other parameters, 1 means yes, 0 means no, other values are
|
||||
undefined.
|
||||
|
||||
TODO: do reverse loops right */
|
||||
static Instrument *load_instrument(MidiSong *song, char *name, int percussion,
|
||||
int panning, int amp, int note_to_use,
|
||||
int strip_loop, int strip_envelope,
|
||||
int strip_tail)
|
||||
{
|
||||
Instrument *ip;
|
||||
Sample *sp;
|
||||
SDL_RWops *rw;
|
||||
char tmp[1024];
|
||||
int i,j,noluck=0;
|
||||
static char *patch_ext[] = PATCH_EXT_LIST;
|
||||
|
||||
if (!name) return 0;
|
||||
|
||||
/* Open patch file */
|
||||
if ((rw=open_file(name)) == NULL)
|
||||
{
|
||||
noluck=1;
|
||||
/* Try with various extensions */
|
||||
for (i=0; patch_ext[i]; i++)
|
||||
{
|
||||
if (strlen(name)+strlen(patch_ext[i])<1024)
|
||||
{
|
||||
strcpy(tmp, name);
|
||||
strcat(tmp, patch_ext[i]);
|
||||
if ((rw=open_file(tmp)) != NULL)
|
||||
{
|
||||
noluck=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noluck)
|
||||
{
|
||||
SNDDBG(("Instrument `%s' can't be found.\n", name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
SNDDBG(("Loading instrument %s\n", tmp));
|
||||
|
||||
/* Read some headers and do cursory sanity checks. There are loads
|
||||
of magic offsets. This could be rewritten... */
|
||||
|
||||
if ((239 != SDL_RWread(rw, tmp, 1, 239)) ||
|
||||
(memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
|
||||
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
||||
differences are */
|
||||
{
|
||||
SNDDBG(("%s: not an instrument\n", name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers,
|
||||
0 means 1 */
|
||||
{
|
||||
SNDDBG(("Can't handle patches with %d instruments\n", tmp[82]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
||||
{
|
||||
SNDDBG(("Can't handle instruments with %d layers\n", tmp[151]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip=safe_malloc(sizeof(Instrument));
|
||||
ip->samples = tmp[198];
|
||||
ip->sample = safe_malloc(sizeof(Sample) * ip->samples);
|
||||
for (i=0; i<ip->samples; i++)
|
||||
{
|
||||
|
||||
Uint8 fractions;
|
||||
Sint32 tmplong;
|
||||
Uint16 tmpshort;
|
||||
Uint8 tmpchar;
|
||||
|
||||
#define READ_CHAR(thing) \
|
||||
if (1 != SDL_RWread(rw, &tmpchar, 1, 1)) goto fail; \
|
||||
thing = tmpchar;
|
||||
#define READ_SHORT(thing) \
|
||||
if (1 != SDL_RWread(rw, &tmpshort, 2, 1)) goto fail; \
|
||||
thing = SDL_SwapLE16(tmpshort);
|
||||
#define READ_LONG(thing) \
|
||||
if (1 != SDL_RWread(rw, &tmplong, 4, 1)) goto fail; \
|
||||
thing = SDL_SwapLE32(tmplong);
|
||||
|
||||
SDL_RWseek(rw, 7, SEEK_CUR); /* Skip the wave name */
|
||||
|
||||
if (1 != SDL_RWread(rw, &fractions, 1, 1))
|
||||
{
|
||||
fail:
|
||||
SNDDBG(("Error reading sample %d\n", i));
|
||||
for (j=0; j<i; j++)
|
||||
free(ip->sample[j].data);
|
||||
free(ip->sample);
|
||||
free(ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp=&(ip->sample[i]);
|
||||
|
||||
READ_LONG(sp->data_length);
|
||||
READ_LONG(sp->loop_start);
|
||||
READ_LONG(sp->loop_end);
|
||||
READ_SHORT(sp->sample_rate);
|
||||
READ_LONG(sp->low_freq);
|
||||
READ_LONG(sp->high_freq);
|
||||
READ_LONG(sp->root_freq);
|
||||
sp->low_vel = 0;
|
||||
sp->high_vel = 127;
|
||||
SDL_RWseek(rw, 2, SEEK_CUR); /* Why have a "root frequency" and then
|
||||
* "tuning"?? */
|
||||
|
||||
READ_CHAR(tmp[0]);
|
||||
|
||||
if (panning==-1)
|
||||
sp->panning = (tmp[0] * 8 + 4) & 0x7f;
|
||||
else
|
||||
sp->panning=(Uint8)(panning & 0x7F);
|
||||
|
||||
/* envelope, tremolo, and vibrato */
|
||||
if (18 != SDL_RWread(rw, tmp, 1, 18)) goto fail;
|
||||
|
||||
if (!tmp[13] || !tmp[14])
|
||||
{
|
||||
sp->tremolo_sweep_increment=
|
||||
sp->tremolo_phase_increment=sp->tremolo_depth=0;
|
||||
SNDDBG((" * no tremolo\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->tremolo_sweep_increment=convert_tremolo_sweep(song, tmp[12]);
|
||||
sp->tremolo_phase_increment=convert_tremolo_rate(song, tmp[13]);
|
||||
sp->tremolo_depth=tmp[14];
|
||||
SNDDBG((" * tremolo: sweep %d, phase %d, depth %d\n",
|
||||
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
||||
sp->tremolo_depth));
|
||||
}
|
||||
|
||||
if (!tmp[16] || !tmp[17])
|
||||
{
|
||||
sp->vibrato_sweep_increment=
|
||||
sp->vibrato_control_ratio=sp->vibrato_depth=0;
|
||||
SNDDBG((" * no vibrato\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->vibrato_control_ratio=convert_vibrato_rate(song, tmp[16]);
|
||||
sp->vibrato_sweep_increment=
|
||||
convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
||||
sp->vibrato_depth=tmp[17];
|
||||
SNDDBG((" * vibrato: sweep %d, ctl %d, depth %d\n",
|
||||
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
||||
sp->vibrato_depth));
|
||||
|
||||
}
|
||||
|
||||
READ_CHAR(sp->modes);
|
||||
|
||||
SDL_RWseek(rw, 40, SEEK_CUR); /* skip the useless scale frequency, scale
|
||||
factor (what's it mean?), and reserved
|
||||
space */
|
||||
|
||||
/* Mark this as a fixed-pitch instrument if such a deed is desired. */
|
||||
if (note_to_use!=-1)
|
||||
sp->note_to_use=(Uint8)(note_to_use);
|
||||
else
|
||||
sp->note_to_use=0;
|
||||
|
||||
/* seashore.pat in the Midia patch set has no Sustain. I don't
|
||||
understand why, and fixing it by adding the Sustain flag to
|
||||
all looped patches probably breaks something else. We do it
|
||||
anyway. */
|
||||
|
||||
if (sp->modes & MODES_LOOPING)
|
||||
sp->modes |= MODES_SUSTAIN;
|
||||
|
||||
/* Strip any loops and envelopes we're permitted to */
|
||||
if ((strip_loop==1) &&
|
||||
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING |
|
||||
MODES_PINGPONG | MODES_REVERSE)))
|
||||
{
|
||||
SNDDBG((" - Removing loop and/or sustain\n"));
|
||||
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING |
|
||||
MODES_PINGPONG | MODES_REVERSE);
|
||||
}
|
||||
|
||||
if (strip_envelope==1)
|
||||
{
|
||||
if (sp->modes & MODES_ENVELOPE)
|
||||
SNDDBG((" - Removing envelope\n"));
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
}
|
||||
else if (strip_envelope != 0)
|
||||
{
|
||||
/* Have to make a guess. */
|
||||
if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||||
{
|
||||
/* No loop? Then what's there to sustain? No envelope needed
|
||||
either... */
|
||||
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
||||
SNDDBG((" - No loop, removing sustain and envelope\n"));
|
||||
}
|
||||
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
||||
{
|
||||
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
||||
That's a weird envelope. Take it out. */
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
SNDDBG((" - Weirdness, removing envelope\n"));
|
||||
}
|
||||
else if (!(sp->modes & MODES_SUSTAIN))
|
||||
{
|
||||
/* No sustain? Then no envelope. I don't know if this is
|
||||
justified, but patches without sustain usually don't need the
|
||||
envelope either... at least the Gravis ones. They're mostly
|
||||
drums. I think. */
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
SNDDBG((" - No sustain, removing envelope\n"));
|
||||
}
|
||||
}
|
||||
|
||||
for (j=0; j<6; j++)
|
||||
{
|
||||
sp->envelope_rate[j]=
|
||||
convert_envelope_rate(song, tmp[j]);
|
||||
sp->envelope_offset[j]=
|
||||
convert_envelope_offset(tmp[6+j]);
|
||||
}
|
||||
|
||||
/* Then read the sample data */
|
||||
sp->data = safe_malloc(sp->data_length);
|
||||
if (1 != SDL_RWread(rw, sp->data, sp->data_length, 1))
|
||||
goto fail;
|
||||
|
||||
if (!(sp->modes & MODES_16BIT)) /* convert to 16-bit data */
|
||||
{
|
||||
Sint32 i=sp->data_length;
|
||||
Uint8 *cp=(Uint8 *)(sp->data);
|
||||
Uint16 *tmp,*new;
|
||||
tmp=new=safe_malloc(sp->data_length*2);
|
||||
while (i--)
|
||||
*tmp++ = (Uint16)(*cp++) << 8;
|
||||
cp=(Uint8 *)(sp->data);
|
||||
sp->data = (sample_t *)new;
|
||||
free(cp);
|
||||
sp->data_length *= 2;
|
||||
sp->loop_start *= 2;
|
||||
sp->loop_end *= 2;
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
else
|
||||
/* convert to machine byte order */
|
||||
{
|
||||
Sint32 i=sp->data_length/2;
|
||||
Sint16 *tmp=(Sint16 *)sp->data,s;
|
||||
while (i--)
|
||||
{
|
||||
s=SDL_SwapLE16(*tmp);
|
||||
*tmp++=s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
|
||||
{
|
||||
Sint32 i=sp->data_length/2;
|
||||
Sint16 *tmp=(Sint16 *)sp->data;
|
||||
while (i--)
|
||||
*tmp++ ^= 0x8000;
|
||||
}
|
||||
|
||||
/* Reverse reverse loops and pass them off as normal loops */
|
||||
if (sp->modes & MODES_REVERSE)
|
||||
{
|
||||
Sint32 t;
|
||||
/* The GUS apparently plays reverse loops by reversing the
|
||||
whole sample. We do the same because the GUS does not SUCK. */
|
||||
|
||||
SNDDBG(("Reverse loop in %s\n", name));
|
||||
reverse_data((Sint16 *)sp->data, 0, sp->data_length/2);
|
||||
|
||||
t=sp->loop_start;
|
||||
sp->loop_start=sp->data_length - sp->loop_end;
|
||||
sp->loop_end=sp->data_length - t;
|
||||
|
||||
sp->modes &= ~MODES_REVERSE;
|
||||
sp->modes |= MODES_LOOPING; /* just in case */
|
||||
}
|
||||
|
||||
#ifdef ADJUST_SAMPLE_VOLUMES
|
||||
if (amp!=-1)
|
||||
sp->volume=(float)((amp) / 100.0);
|
||||
else
|
||||
{
|
||||
/* Try to determine a volume scaling factor for the sample.
|
||||
This is a very crude adjustment, but things sound more
|
||||
balanced with it. Still, this should be a runtime option. */
|
||||
Sint32 i=sp->data_length/2;
|
||||
Sint16 maxamp=0,a;
|
||||
Sint16 *tmp=(Sint16 *)sp->data;
|
||||
while (i--)
|
||||
{
|
||||
a=*tmp++;
|
||||
if (a<0) a=-a;
|
||||
if (a>maxamp)
|
||||
maxamp=a;
|
||||
}
|
||||
sp->volume=(float)(32768.0 / maxamp);
|
||||
SNDDBG((" * volume comp: %f\n", sp->volume));
|
||||
}
|
||||
#else
|
||||
if (amp!=-1)
|
||||
sp->volume=(double)(amp) / 100.0;
|
||||
else
|
||||
sp->volume=1.0;
|
||||
#endif
|
||||
|
||||
sp->data_length /= 2; /* These are in bytes. Convert into samples. */
|
||||
sp->loop_start /= 2;
|
||||
sp->loop_end /= 2;
|
||||
|
||||
/* Then fractional samples */
|
||||
sp->data_length <<= FRACTION_BITS;
|
||||
sp->loop_start <<= FRACTION_BITS;
|
||||
sp->loop_end <<= FRACTION_BITS;
|
||||
|
||||
/* Adjust for fractional loop points. This is a guess. Does anyone
|
||||
know what "fractions" really stands for? */
|
||||
sp->loop_start |=
|
||||
(fractions & 0x0F) << (FRACTION_BITS-4);
|
||||
sp->loop_end |=
|
||||
((fractions>>4) & 0x0F) << (FRACTION_BITS-4);
|
||||
|
||||
/* If this instrument will always be played on the same note,
|
||||
and it's not looped, we can resample it now. */
|
||||
if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
|
||||
pre_resample(song, sp);
|
||||
|
||||
if (strip_tail==1)
|
||||
{
|
||||
/* Let's not really, just say we did. */
|
||||
SNDDBG((" - Stripping tail\n"));
|
||||
sp->data_length = sp->loop_end;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RWclose(rw);
|
||||
return ip;
|
||||
}
|
||||
|
||||
static int fill_bank(MidiSong *song, int dr, int b)
|
||||
{
|
||||
int i, errors=0;
|
||||
ToneBank *bank=((dr) ? song->drumset[b] : song->tonebank[b]);
|
||||
if (!bank)
|
||||
{
|
||||
SNDDBG(("Huh. Tried to load instruments in non-existent %s %d\n",
|
||||
(dr) ? "drumset" : "tone bank", b));
|
||||
return 0;
|
||||
}
|
||||
for (i=0; i<128; i++)
|
||||
{
|
||||
if (bank->instrument[i]==MAGIC_LOAD_INSTRUMENT)
|
||||
{
|
||||
bank->instrument[i]=load_instrument_dls(song, dr, b, i);
|
||||
if (bank->instrument[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(bank->tone[i].name))
|
||||
{
|
||||
SNDDBG(("No instrument mapped to %s %d, program %d%s\n",
|
||||
(dr)? "drum set" : "tone bank", b, i,
|
||||
(b!=0) ? "" : " - this instrument will not be heard"));
|
||||
if (b!=0)
|
||||
{
|
||||
/* Mark the corresponding instrument in the default
|
||||
bank / drumset for loading (if it isn't already) */
|
||||
if (!dr)
|
||||
{
|
||||
if (!(song->tonebank[0]->instrument[i]))
|
||||
song->tonebank[0]->instrument[i] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(song->drumset[0]->instrument[i]))
|
||||
song->drumset[0]->instrument[i] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
}
|
||||
bank->instrument[i] = 0;
|
||||
errors++;
|
||||
}
|
||||
else if (!(bank->instrument[i] =
|
||||
load_instrument(song,
|
||||
bank->tone[i].name,
|
||||
(dr) ? 1 : 0,
|
||||
bank->tone[i].pan,
|
||||
bank->tone[i].amp,
|
||||
(bank->tone[i].note!=-1) ?
|
||||
bank->tone[i].note :
|
||||
((dr) ? i : -1),
|
||||
(bank->tone[i].strip_loop!=-1) ?
|
||||
bank->tone[i].strip_loop :
|
||||
((dr) ? 1 : -1),
|
||||
(bank->tone[i].strip_envelope != -1) ?
|
||||
bank->tone[i].strip_envelope :
|
||||
((dr) ? 1 : -1),
|
||||
bank->tone[i].strip_tail )))
|
||||
{
|
||||
SNDDBG(("Couldn't load instrument %s (%s %d, program %d)\n",
|
||||
bank->tone[i].name,
|
||||
(dr)? "drum set" : "tone bank", b, i));
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int load_missing_instruments(MidiSong *song)
|
||||
{
|
||||
int i=128,errors=0;
|
||||
while (i--)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
errors+=fill_bank(song,0,i);
|
||||
if (song->drumset[i])
|
||||
errors+=fill_bank(song,1,i);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
void free_instruments(MidiSong *song)
|
||||
{
|
||||
int i=128;
|
||||
while(i--)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
free_bank(song, 0, i);
|
||||
if (song->drumset[i])
|
||||
free_bank(song, 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
int set_default_instrument(MidiSong *song, char *name)
|
||||
{
|
||||
Instrument *ip;
|
||||
if (!(ip=load_instrument(song, name, 0, -1, -1, -1, 0, 0, 0)))
|
||||
return -1;
|
||||
song->default_instrument = ip;
|
||||
song->default_program = SPECIAL_PROGRAM;
|
||||
return 0;
|
||||
}
|
||||
41
project/jni/sdl_sound/decoders/timidity/instrum.h
Normal file
41
project/jni/sdl_sound/decoders/timidity/instrum.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.h
|
||||
|
||||
*/
|
||||
|
||||
/* Bits in modes: */
|
||||
#define MODES_16BIT (1<<0)
|
||||
#define MODES_UNSIGNED (1<<1)
|
||||
#define MODES_LOOPING (1<<2)
|
||||
#define MODES_PINGPONG (1<<3)
|
||||
#define MODES_REVERSE (1<<4)
|
||||
#define MODES_SUSTAIN (1<<5)
|
||||
#define MODES_ENVELOPE (1<<6)
|
||||
|
||||
/* A hack to delay instrument loading until after reading the
|
||||
entire MIDI file. */
|
||||
#define MAGIC_LOAD_INSTRUMENT ((Instrument *) (-1))
|
||||
|
||||
#define SPECIAL_PROGRAM -1
|
||||
|
||||
extern int load_missing_instruments(MidiSong *song);
|
||||
extern void free_instruments(MidiSong *song);
|
||||
extern int set_default_instrument(MidiSong *song, char *name);
|
||||
1269
project/jni/sdl_sound/decoders/timidity/instrum_dls.c
Normal file
1269
project/jni/sdl_sound/decoders/timidity/instrum_dls.c
Normal file
File diff suppressed because it is too large
Load Diff
24
project/jni/sdl_sound/decoders/timidity/instrum_dls.h
Normal file
24
project/jni/sdl_sound/decoders/timidity/instrum_dls.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
instrum.h
|
||||
|
||||
*/
|
||||
|
||||
extern Instrument *load_instrument_dls(MidiSong *song, int drum, int bank, int instrument);
|
||||
573
project/jni/sdl_sound/decoders/timidity/mix.c
Normal file
573
project/jni/sdl_sound/decoders/timidity/mix.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
Suddenly, you realize that this program is free software; you get
|
||||
an overwhelming urge to redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received another copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
I bet they'll be amazed.
|
||||
|
||||
mix.c */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "options.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
#include "mix.h"
|
||||
|
||||
/* Returns 1 if envelope runs out */
|
||||
int recompute_envelope(MidiSong *song, int v)
|
||||
{
|
||||
int stage;
|
||||
|
||||
stage = song->voice[v].envelope_stage;
|
||||
|
||||
if (stage>5)
|
||||
{
|
||||
/* Envelope ran out. */
|
||||
song->voice[v].status = VOICE_FREE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
if (song->voice[v].status==VOICE_ON || song->voice[v].status==VOICE_SUSTAINED)
|
||||
{
|
||||
if (stage>2)
|
||||
{
|
||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||
song->voice[v].envelope_increment=0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
song->voice[v].envelope_stage=stage+1;
|
||||
|
||||
if (song->voice[v].envelope_volume==song->voice[v].sample->envelope_offset[stage])
|
||||
return recompute_envelope(song, v);
|
||||
song->voice[v].envelope_target = song->voice[v].sample->envelope_offset[stage];
|
||||
song->voice[v].envelope_increment = song->voice[v].sample->envelope_rate[stage];
|
||||
if (song->voice[v].envelope_target < song->voice[v].envelope_volume)
|
||||
song->voice[v].envelope_increment = -song->voice[v].envelope_increment;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apply_envelope_to_amp(MidiSong *song, int v)
|
||||
{
|
||||
float lamp = song->voice[v].left_amp, ramp;
|
||||
Sint32 la,ra;
|
||||
if (song->voice[v].panned == PANNED_MYSTERY)
|
||||
{
|
||||
ramp = song->voice[v].right_amp;
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
{
|
||||
lamp *= song->voice[v].tremolo_volume;
|
||||
ramp *= song->voice[v].tremolo_volume;
|
||||
}
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
ramp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
}
|
||||
|
||||
la = (Sint32)FSCALE(lamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE)
|
||||
la=MAX_AMP_VALUE;
|
||||
|
||||
ra = (Sint32)FSCALE(ramp,AMP_BITS);
|
||||
if (ra>MAX_AMP_VALUE)
|
||||
ra=MAX_AMP_VALUE;
|
||||
|
||||
song->voice[v].left_mix = la;
|
||||
song->voice[v].right_mix = ra;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
lamp *= song->voice[v].tremolo_volume;
|
||||
if (song->voice[v].sample->modes & MODES_ENVELOPE)
|
||||
lamp *= (float)vol_table[song->voice[v].envelope_volume>>23];
|
||||
|
||||
la = (Sint32)FSCALE(lamp,AMP_BITS);
|
||||
|
||||
if (la>MAX_AMP_VALUE)
|
||||
la=MAX_AMP_VALUE;
|
||||
|
||||
song->voice[v].left_mix = la;
|
||||
}
|
||||
}
|
||||
|
||||
static int update_envelope(MidiSong *song, int v)
|
||||
{
|
||||
song->voice[v].envelope_volume += song->voice[v].envelope_increment;
|
||||
/* Why is there no ^^ operator?? */
|
||||
if (((song->voice[v].envelope_increment < 0) &&
|
||||
(song->voice[v].envelope_volume <= song->voice[v].envelope_target)) ||
|
||||
((song->voice[v].envelope_increment > 0) &&
|
||||
(song->voice[v].envelope_volume >= song->voice[v].envelope_target)))
|
||||
{
|
||||
song->voice[v].envelope_volume = song->voice[v].envelope_target;
|
||||
if (recompute_envelope(song, v))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_tremolo(MidiSong *song, int v)
|
||||
{
|
||||
Sint32 depth = song->voice[v].sample->tremolo_depth << 7;
|
||||
|
||||
if (song->voice[v].tremolo_sweep)
|
||||
{
|
||||
/* Update sweep position */
|
||||
|
||||
song->voice[v].tremolo_sweep_position += song->voice[v].tremolo_sweep;
|
||||
if (song->voice[v].tremolo_sweep_position >= (1 << SWEEP_SHIFT))
|
||||
song->voice[v].tremolo_sweep=0; /* Swept to max amplitude */
|
||||
else
|
||||
{
|
||||
/* Need to adjust depth */
|
||||
depth *= song->voice[v].tremolo_sweep_position;
|
||||
depth >>= SWEEP_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
song->voice[v].tremolo_phase += song->voice[v].tremolo_phase_increment;
|
||||
|
||||
/* if (song->voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<<RATE_SHIFT))
|
||||
song->voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<<RATE_SHIFT; */
|
||||
|
||||
song->voice[v].tremolo_volume = (float)
|
||||
(1.0 - FSCALENEG((sine(song->voice[v].tremolo_phase >> RATE_SHIFT) + 1.0)
|
||||
* depth * TREMOLO_AMPLITUDE_TUNING,
|
||||
17));
|
||||
|
||||
/* I'm not sure about the +1.0 there -- it makes tremoloed voices'
|
||||
volumes on average the lower the higher the tremolo amplitude. */
|
||||
}
|
||||
|
||||
/* Returns 1 if the note died */
|
||||
static int update_signal(MidiSong *song, int v)
|
||||
{
|
||||
if (song->voice[v].envelope_increment && update_envelope(song, v))
|
||||
return 1;
|
||||
|
||||
if (song->voice[v].tremolo_phase_increment)
|
||||
update_tremolo(song, v);
|
||||
|
||||
apply_envelope_to_amp(song, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MIXATION(a) *lp++ += (a)*s;
|
||||
|
||||
static void mix_mystery_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
Voice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix,
|
||||
right=vp->right_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
right = vp->right_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
right = vp->right_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
Voice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
Voice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono_signal(MidiSong *song, sample_t *sp, Sint32 *lp, int v,
|
||||
int count)
|
||||
{
|
||||
Voice *vp = song->voice + v;
|
||||
final_volume_t
|
||||
left=vp->left_mix;
|
||||
int cc;
|
||||
sample_t s;
|
||||
|
||||
if (!(cc = vp->control_counter))
|
||||
{
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
|
||||
while (count)
|
||||
if (cc < count)
|
||||
{
|
||||
count -= cc;
|
||||
while (cc--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
cc = song->control_ratio;
|
||||
if (update_signal(song, v))
|
||||
return; /* Envelope ran out */
|
||||
left = vp->left_mix;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->control_counter = cc - count;
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mystery(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix,
|
||||
right = song->voice[v].right_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_center(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_single(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
|
||||
static void mix_mono(MidiSong *song, sample_t *sp, Sint32 *lp, int v, int count)
|
||||
{
|
||||
final_volume_t
|
||||
left = song->voice[v].left_mix;
|
||||
sample_t s;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
s = *sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ramp a note out in c samples */
|
||||
static void ramp_out(MidiSong *song, sample_t *sp, Sint32 *lp, int v, Sint32 c)
|
||||
{
|
||||
|
||||
/* should be final_volume_t, but Uint8 gives trouble. */
|
||||
Sint32 left, right, li, ri;
|
||||
|
||||
sample_t s=0; /* silly warning about uninitialized s */
|
||||
|
||||
/* Fix by James Caldwell */
|
||||
if ( c == 0 ) c = 1;
|
||||
|
||||
left=song->voice[v].left_mix;
|
||||
li=-(left/c);
|
||||
if (!li) li=-1;
|
||||
|
||||
/* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
|
||||
|
||||
if (!(song->encoding & PE_MONO))
|
||||
{
|
||||
if (song->voice[v].panned==PANNED_MYSTERY)
|
||||
{
|
||||
right=song->voice[v].right_mix;
|
||||
ri=-(right/c);
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
left=0;
|
||||
right += ri;
|
||||
if (right<0)
|
||||
right=0;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(right);
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_CENTER)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_LEFT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
else if (song->voice[v].panned==PANNED_RIGHT)
|
||||
{
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
lp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mono output. */
|
||||
while (c--)
|
||||
{
|
||||
left += li;
|
||||
if (left<0)
|
||||
return;
|
||||
s=*sp++;
|
||||
MIXATION(left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************** interface function ******************/
|
||||
|
||||
void mix_voice(MidiSong *song, Sint32 *buf, int v, Sint32 c)
|
||||
{
|
||||
Voice *vp = song->voice + v;
|
||||
sample_t *sp;
|
||||
if (vp->status==VOICE_DIE)
|
||||
{
|
||||
if (c>=MAX_DIE_TIME)
|
||||
c=MAX_DIE_TIME;
|
||||
sp=resample_voice(song, v, &c);
|
||||
ramp_out(song, sp, buf, v, c);
|
||||
vp->status=VOICE_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp=resample_voice(song, v, &c);
|
||||
if (song->encoding & PE_MONO)
|
||||
{
|
||||
/* Mono output. */
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mono_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_mono(song, sp, buf, v, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vp->panned == PANNED_MYSTERY)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_mystery_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_mystery(song, sp, buf, v, c);
|
||||
}
|
||||
else if (vp->panned == PANNED_CENTER)
|
||||
{
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_center_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_center(song, sp, buf, v, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's either full left or full right. In either case,
|
||||
every other sample is 0. Just get the offset right: */
|
||||
if (vp->panned == PANNED_RIGHT) buf++;
|
||||
|
||||
if (vp->envelope_increment || vp->tremolo_phase_increment)
|
||||
mix_single_signal(song, sp, buf, v, c);
|
||||
else
|
||||
mix_single(song, sp, buf, v, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
project/jni/sdl_sound/decoders/timidity/mix.h
Normal file
27
project/jni/sdl_sound/decoders/timidity/mix.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
In case you haven't heard, this program is free software;
|
||||
you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
mix.h
|
||||
|
||||
*/
|
||||
|
||||
extern void mix_voice(MidiSong *song, Sint32 *buf, int v, Sint32 c);
|
||||
extern int recompute_envelope(MidiSong *song, int v);
|
||||
extern void apply_envelope_to_amp(MidiSong *song, int v);
|
||||
113
project/jni/sdl_sound/decoders/timidity/options.h
Normal file
113
project/jni/sdl_sound/decoders/timidity/options.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* When a patch file can't be opened, one of these extensions is
|
||||
appended to the filename and the open is tried again.
|
||||
*/
|
||||
#define PATCH_EXT_LIST { ".pat", 0 }
|
||||
|
||||
/* Acoustic Grand Piano seems to be the usual default instrument. */
|
||||
#define DEFAULT_PROGRAM 0
|
||||
|
||||
/* 9 here is MIDI channel 10, which is the standard percussion channel.
|
||||
Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too.
|
||||
On the other hand, some files know that 16 is not a drum channel and
|
||||
try to play music on it. This is now a runtime option, so this isn't
|
||||
a critical choice anymore. */
|
||||
#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))
|
||||
|
||||
/* In percent. */
|
||||
#define DEFAULT_AMPLIFICATION 70
|
||||
|
||||
/* Default polyphony */
|
||||
#define DEFAULT_VOICES 32
|
||||
|
||||
/* 1000 here will give a control ratio of 22:1 with 22 kHz output.
|
||||
Higher CONTROLS_PER_SECOND values allow more accurate rendering
|
||||
of envelopes and tremolo. The cost is CPU time. */
|
||||
#define CONTROLS_PER_SECOND 1000
|
||||
|
||||
/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay
|
||||
faster) and sounds more like a GUS. There is now a command line
|
||||
option to toggle this as well. */
|
||||
#define FAST_DECAY
|
||||
|
||||
/* How many bits to use for the fractional part of sample positions.
|
||||
This affects tonal accuracy. The entire position counter must fit
|
||||
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
||||
a sample is 1048576 samples (2 megabytes in memory). The GUS gets
|
||||
by with just 9 bits and a little help from its friends...
|
||||
"The GUS does not SUCK!!!" -- a happy user :) */
|
||||
#define FRACTION_BITS 12
|
||||
|
||||
/* For some reason the sample volume is always set to maximum in all
|
||||
patch files. Define this for a crude adjustment that may help
|
||||
equalize instrument volumes. */
|
||||
#define ADJUST_SAMPLE_VOLUMES
|
||||
|
||||
/* The number of samples to use for ramping out a dying note. Affects
|
||||
click removal. */
|
||||
#define MAX_DIE_TIME 20
|
||||
|
||||
/**************************************************************************/
|
||||
/* Anything below this shouldn't need to be changed unless you're porting
|
||||
to a new machine with other than 32-bit, big-endian words. */
|
||||
/**************************************************************************/
|
||||
|
||||
/* change FRACTION_BITS above, not these */
|
||||
#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
|
||||
#define FRACTION_MASK (~ INTEGER_MASK)
|
||||
|
||||
/* This is enforced by some computations that must fit in an int */
|
||||
#define MAX_CONTROL_RATIO 255
|
||||
|
||||
#define MAX_AMPLIFICATION 800
|
||||
|
||||
/* The TiMidity configuration file */
|
||||
#define CONFIG_FILE "timidity.cfg"
|
||||
|
||||
/* These affect general volume */
|
||||
#define GUARD_BITS 3
|
||||
#define AMP_BITS (15-GUARD_BITS)
|
||||
|
||||
#define MAX_AMP_VALUE ((1<<(AMP_BITS+1))-1)
|
||||
|
||||
#define FSCALE(a,b) (float)((a) * (double)(1<<(b)))
|
||||
#define FSCALENEG(a,b) (float)((a) * (1.0L / (double)(1<<(b))))
|
||||
|
||||
/* Vibrato and tremolo Choices of the Day */
|
||||
#define SWEEP_TUNING 38
|
||||
#define VIBRATO_AMPLITUDE_TUNING 1.0L
|
||||
#define VIBRATO_RATE_TUNING 38
|
||||
#define TREMOLO_AMPLITUDE_TUNING 1.0L
|
||||
#define TREMOLO_RATE_TUNING 38
|
||||
|
||||
#define SWEEP_SHIFT 16
|
||||
#define RATE_SHIFT 5
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* The path separator (D.M.) */
|
||||
#ifdef WIN32
|
||||
# define PATH_SEP '\\'
|
||||
#else
|
||||
# define PATH_SEP '/'
|
||||
#endif
|
||||
116
project/jni/sdl_sound/decoders/timidity/output.c
Normal file
116
project/jni/sdl_sound/decoders/timidity/output.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
output.c
|
||||
|
||||
Audio output (to file / device) functions.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
|
||||
/*****************************************************************/
|
||||
/* Some functions to convert signed 32-bit data to other formats */
|
||||
|
||||
void s32tos8(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Sint8 *cp=(Sint8 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-8-GUARD_BITS);
|
||||
if (l>127) l=127;
|
||||
else if (l<-128) l=-128;
|
||||
*cp++ = (Sint8) (l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou8(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Uint8 *cp=(Uint8 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-8-GUARD_BITS);
|
||||
if (l>127) l=127;
|
||||
else if (l<-128) l=-128;
|
||||
*cp++ = 0x80 ^ ((Uint8) l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tos16(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Sint16 *sp=(Sint16 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = (Sint16)(l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Uint16 *sp=(Uint16 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = 0x8000 ^ (Uint16)(l);
|
||||
}
|
||||
}
|
||||
|
||||
void s32tos16x(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Sint16 *sp=(Sint16 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = SDL_Swap16((Sint16)(l));
|
||||
}
|
||||
}
|
||||
|
||||
void s32tou16x(void *dp, Sint32 *lp, Sint32 c)
|
||||
{
|
||||
Uint16 *sp=(Uint16 *)(dp);
|
||||
Sint32 l;
|
||||
while (c--)
|
||||
{
|
||||
l=(*lp++)>>(32-16-GUARD_BITS);
|
||||
if (l > 32767) l=32767;
|
||||
else if (l<-32768) l=-32768;
|
||||
*sp++ = SDL_Swap16(0x8000 ^ (Uint16)(l));
|
||||
}
|
||||
}
|
||||
56
project/jni/sdl_sound/decoders/timidity/output.h
Normal file
56
project/jni/sdl_sound/decoders/timidity/output.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
output.h
|
||||
|
||||
*/
|
||||
|
||||
/* Data format encoding bits */
|
||||
|
||||
#define PE_MONO 0x01 /* versus stereo */
|
||||
#define PE_SIGNED 0x02 /* versus unsigned */
|
||||
#define PE_16BIT 0x04 /* versus 8-bit */
|
||||
|
||||
/* Conversion functions -- These overwrite the Sint32 data in *lp with
|
||||
data in another format */
|
||||
|
||||
/* 8-bit signed and unsigned*/
|
||||
extern void s32tos8(void *dp, Sint32 *lp, Sint32 c);
|
||||
extern void s32tou8(void *dp, Sint32 *lp, Sint32 c);
|
||||
|
||||
/* 16-bit */
|
||||
extern void s32tos16(void *dp, Sint32 *lp, Sint32 c);
|
||||
extern void s32tou16(void *dp, Sint32 *lp, Sint32 c);
|
||||
|
||||
/* byte-exchanged 16-bit */
|
||||
extern void s32tos16x(void *dp, Sint32 *lp, Sint32 c);
|
||||
extern void s32tou16x(void *dp, Sint32 *lp, Sint32 c);
|
||||
|
||||
/* little-endian and big-endian specific */
|
||||
#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
|
||||
806
project/jni/sdl_sound/decoders/timidity/playmidi.c
Normal file
806
project/jni/sdl_sound/decoders/timidity/playmidi.c
Normal file
@@ -0,0 +1,806 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
playmidi.c -- random stuff in need of rearrangement
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "options.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "output.h"
|
||||
#include "mix.h"
|
||||
#include "tables.h"
|
||||
|
||||
static void adjust_amplification(MidiSong *song)
|
||||
{
|
||||
song->master_volume = (float)(song->amplification) / (float)100.0;
|
||||
}
|
||||
|
||||
static void reset_voices(MidiSong *song)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<MAX_VOICES; i++)
|
||||
song->voice[i].status=VOICE_FREE;
|
||||
}
|
||||
|
||||
/* Process the Reset All Controllers event */
|
||||
static void reset_controllers(MidiSong *song, int c)
|
||||
{
|
||||
song->channel[c].volume=90; /* Some standard says, although the SCC docs say 0. */
|
||||
song->channel[c].expression=127; /* SCC-1 does this. */
|
||||
song->channel[c].sustain=0;
|
||||
song->channel[c].pitchbend=0x2000;
|
||||
song->channel[c].pitchfactor=0; /* to be computed */
|
||||
}
|
||||
|
||||
static void reset_midi(MidiSong *song)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
reset_controllers(song, i);
|
||||
/* The rest of these are unaffected by the Reset All Controllers event */
|
||||
song->channel[i].program=song->default_program;
|
||||
song->channel[i].panning=NO_PANNING;
|
||||
song->channel[i].pitchsens=2;
|
||||
song->channel[i].bank=0; /* tone bank or drum set */
|
||||
}
|
||||
reset_voices(song);
|
||||
}
|
||||
|
||||
static void select_sample(MidiSong *song, int v, Instrument *ip, int vel)
|
||||
{
|
||||
Sint32 f, cdiff, diff;
|
||||
int s,i;
|
||||
Sample *sp, *closest;
|
||||
|
||||
s=ip->samples;
|
||||
sp=ip->sample;
|
||||
|
||||
if (s==1)
|
||||
{
|
||||
song->voice[v].sample=sp;
|
||||
return;
|
||||
}
|
||||
|
||||
f=song->voice[v].orig_frequency;
|
||||
for (i=0; i<s; i++)
|
||||
{
|
||||
if (sp->low_vel <= vel && sp->high_vel >= vel &&
|
||||
sp->low_freq <= f && sp->high_freq >= f)
|
||||
{
|
||||
song->voice[v].sample=sp;
|
||||
return;
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
|
||||
/*
|
||||
No suitable sample found! We'll select the sample whose root
|
||||
frequency is closest to the one we want. (Actually we should
|
||||
probably convert the low, high, and root frequencies to MIDI note
|
||||
values and compare those.) */
|
||||
|
||||
cdiff=0x7FFFFFFF;
|
||||
closest=sp=ip->sample;
|
||||
for(i=0; i<s; i++)
|
||||
{
|
||||
diff=sp->root_freq - f;
|
||||
if (diff<0) diff=-diff;
|
||||
if (diff<cdiff)
|
||||
{
|
||||
cdiff=diff;
|
||||
closest=sp;
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
song->voice[v].sample=closest;
|
||||
return;
|
||||
}
|
||||
|
||||
static void recompute_freq(MidiSong *song, int v)
|
||||
{
|
||||
int
|
||||
sign=(song->voice[v].sample_increment < 0), /* for bidirectional loops */
|
||||
pb=song->channel[song->voice[v].channel].pitchbend;
|
||||
double a;
|
||||
|
||||
if (!song->voice[v].sample->sample_rate)
|
||||
return;
|
||||
|
||||
if (song->voice[v].vibrato_control_ratio)
|
||||
{
|
||||
/* This instrument has vibrato. Invalidate any precomputed
|
||||
sample_increments. */
|
||||
|
||||
int i=VIBRATO_SAMPLE_INCREMENTS;
|
||||
while (i--)
|
||||
song->voice[v].vibrato_sample_increment[i]=0;
|
||||
}
|
||||
|
||||
if (pb==0x2000 || pb<0 || pb>0x3FFF)
|
||||
song->voice[v].frequency = song->voice[v].orig_frequency;
|
||||
else
|
||||
{
|
||||
pb-=0x2000;
|
||||
if (!(song->channel[song->voice[v].channel].pitchfactor))
|
||||
{
|
||||
/* Damn. Somebody bent the pitch. */
|
||||
Sint32 i=pb*song->channel[song->voice[v].channel].pitchsens;
|
||||
if (pb<0)
|
||||
i=-i;
|
||||
song->channel[song->voice[v].channel].pitchfactor=
|
||||
(float)(bend_fine[(i>>5) & 0xFF] * bend_coarse[i>>13]);
|
||||
}
|
||||
if (pb>0)
|
||||
song->voice[v].frequency=
|
||||
(Sint32)(song->channel[song->voice[v].channel].pitchfactor *
|
||||
(double)(song->voice[v].orig_frequency));
|
||||
else
|
||||
song->voice[v].frequency=
|
||||
(Sint32)((double)(song->voice[v].orig_frequency) /
|
||||
song->channel[song->voice[v].channel].pitchfactor);
|
||||
}
|
||||
|
||||
a = FSCALE(((double)(song->voice[v].sample->sample_rate) *
|
||||
(double)(song->voice[v].frequency)) /
|
||||
((double)(song->voice[v].sample->root_freq) *
|
||||
(double)(song->rate)),
|
||||
FRACTION_BITS);
|
||||
|
||||
if (sign)
|
||||
a = -a; /* need to preserve the loop direction */
|
||||
|
||||
song->voice[v].sample_increment = (Sint32)(a);
|
||||
}
|
||||
|
||||
static void recompute_amp(MidiSong *song, int v)
|
||||
{
|
||||
Sint32 tempamp;
|
||||
|
||||
/* TODO: use fscale */
|
||||
|
||||
tempamp= (song->voice[v].velocity *
|
||||
song->channel[song->voice[v].channel].volume *
|
||||
song->channel[song->voice[v].channel].expression); /* 21 bits */
|
||||
|
||||
if (!(song->encoding & PE_MONO))
|
||||
{
|
||||
if (song->voice[v].panning > 60 && song->voice[v].panning < 68)
|
||||
{
|
||||
song->voice[v].panned=PANNED_CENTER;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
21);
|
||||
}
|
||||
else if (song->voice[v].panning<5)
|
||||
{
|
||||
song->voice[v].panned = PANNED_LEFT;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
20);
|
||||
}
|
||||
else if (song->voice[v].panning>123)
|
||||
{
|
||||
song->voice[v].panned = PANNED_RIGHT;
|
||||
|
||||
song->voice[v].left_amp= /* left_amp will be used */
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
20);
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[v].panned = PANNED_MYSTERY;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
27);
|
||||
song->voice[v].right_amp = song->voice[v].left_amp * (song->voice[v].panning);
|
||||
song->voice[v].left_amp *= (float)(127 - song->voice[v].panning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[v].panned = PANNED_CENTER;
|
||||
|
||||
song->voice[v].left_amp=
|
||||
FSCALENEG((double)(tempamp) * song->voice[v].sample->volume * song->master_volume,
|
||||
21);
|
||||
}
|
||||
}
|
||||
|
||||
static void start_note(MidiSong *song, MidiEvent *e, int i)
|
||||
{
|
||||
Instrument *ip;
|
||||
int j;
|
||||
|
||||
if (ISDRUMCHANNEL(song, e->channel))
|
||||
{
|
||||
if (!(ip=song->drumset[song->channel[e->channel].bank]->instrument[e->a]))
|
||||
{
|
||||
if (!(ip=song->drumset[0]->instrument[e->a]))
|
||||
return; /* No instrument? Then we can't play. */
|
||||
}
|
||||
if (ip->samples != 1)
|
||||
{
|
||||
SNDDBG(("Strange: percussion instrument with %d samples!",
|
||||
ip->samples));
|
||||
}
|
||||
|
||||
if (ip->sample->note_to_use) /* Do we have a fixed pitch? */
|
||||
song->voice[i].orig_frequency = freq_table[(int)(ip->sample->note_to_use)];
|
||||
else
|
||||
song->voice[i].orig_frequency = freq_table[e->a & 0x7F];
|
||||
|
||||
/* drums are supposed to have only one sample */
|
||||
song->voice[i].sample = ip->sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (song->channel[e->channel].program == SPECIAL_PROGRAM)
|
||||
ip=song->default_instrument;
|
||||
else if (!(ip=song->tonebank[song->channel[e->channel].bank]->
|
||||
instrument[song->channel[e->channel].program]))
|
||||
{
|
||||
if (!(ip=song->tonebank[0]->instrument[song->channel[e->channel].program]))
|
||||
return; /* No instrument? Then we can't play. */
|
||||
}
|
||||
|
||||
if (ip->sample->note_to_use) /* Fixed-pitch instrument? */
|
||||
song->voice[i].orig_frequency = freq_table[(int)(ip->sample->note_to_use)];
|
||||
else
|
||||
song->voice[i].orig_frequency = freq_table[e->a & 0x7F];
|
||||
select_sample(song, i, ip, e->b);
|
||||
}
|
||||
|
||||
song->voice[i].status = VOICE_ON;
|
||||
song->voice[i].channel = e->channel;
|
||||
song->voice[i].note = e->a;
|
||||
song->voice[i].velocity = e->b;
|
||||
song->voice[i].sample_offset = 0;
|
||||
song->voice[i].sample_increment = 0; /* make sure it isn't negative */
|
||||
|
||||
song->voice[i].tremolo_phase = 0;
|
||||
song->voice[i].tremolo_phase_increment = song->voice[i].sample->tremolo_phase_increment;
|
||||
song->voice[i].tremolo_sweep = song->voice[i].sample->tremolo_sweep_increment;
|
||||
song->voice[i].tremolo_sweep_position = 0;
|
||||
|
||||
song->voice[i].vibrato_sweep = song->voice[i].sample->vibrato_sweep_increment;
|
||||
song->voice[i].vibrato_sweep_position = 0;
|
||||
song->voice[i].vibrato_control_ratio = song->voice[i].sample->vibrato_control_ratio;
|
||||
song->voice[i].vibrato_control_counter = song->voice[i].vibrato_phase = 0;
|
||||
for (j=0; j<VIBRATO_SAMPLE_INCREMENTS; j++)
|
||||
song->voice[i].vibrato_sample_increment[j] = 0;
|
||||
|
||||
if (song->channel[e->channel].panning != NO_PANNING)
|
||||
song->voice[i].panning = song->channel[e->channel].panning;
|
||||
else
|
||||
song->voice[i].panning = song->voice[i].sample->panning;
|
||||
|
||||
recompute_freq(song, i);
|
||||
recompute_amp(song, i);
|
||||
if (song->voice[i].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
/* Ramp up from 0 */
|
||||
song->voice[i].envelope_stage = 0;
|
||||
song->voice[i].envelope_volume = 0;
|
||||
song->voice[i].control_counter = 0;
|
||||
recompute_envelope(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
song->voice[i].envelope_increment = 0;
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void kill_note(MidiSong *song, int i)
|
||||
{
|
||||
song->voice[i].status = VOICE_DIE;
|
||||
}
|
||||
|
||||
/* Only one instance of a note can be playing on a single channel. */
|
||||
static void note_on(MidiSong *song)
|
||||
{
|
||||
int i = song->voices, lowest=-1;
|
||||
Sint32 lv=0x7FFFFFFF, v;
|
||||
MidiEvent *e = song->current_event;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
if (song->voice[i].status == VOICE_FREE)
|
||||
lowest=i; /* Can't get a lower volume than silence */
|
||||
else if (song->voice[i].channel==e->channel &&
|
||||
(song->voice[i].note==e->a || song->channel[song->voice[i].channel].mono))
|
||||
kill_note(song, i);
|
||||
}
|
||||
|
||||
if (lowest != -1)
|
||||
{
|
||||
/* Found a free voice. */
|
||||
start_note(song,e,lowest);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look for the decaying note with the lowest volume */
|
||||
i = song->voices;
|
||||
while (i--)
|
||||
{
|
||||
if ((song->voice[i].status != VOICE_ON) &&
|
||||
(song->voice[i].status != VOICE_DIE))
|
||||
{
|
||||
v = song->voice[i].left_mix;
|
||||
if ((song->voice[i].panned == PANNED_MYSTERY)
|
||||
&& (song->voice[i].right_mix > v))
|
||||
v = song->voice[i].right_mix;
|
||||
if (v<lv)
|
||||
{
|
||||
lv=v;
|
||||
lowest=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lowest != -1)
|
||||
{
|
||||
/* This can still cause a click, but if we had a free voice to
|
||||
spare for ramping down this note, we wouldn't need to kill it
|
||||
in the first place... Still, this needs to be fixed. Perhaps
|
||||
we could use a reserve of voices to play dying notes only. */
|
||||
|
||||
song->cut_notes++;
|
||||
song->voice[lowest].status=VOICE_FREE;
|
||||
start_note(song,e,lowest);
|
||||
}
|
||||
else
|
||||
song->lost_notes++;
|
||||
}
|
||||
|
||||
static void finish_note(MidiSong *song, int i)
|
||||
{
|
||||
if (song->voice[i].sample->modes & MODES_ENVELOPE)
|
||||
{
|
||||
/* We need to get the envelope out of Sustain stage */
|
||||
song->voice[i].envelope_stage = 3;
|
||||
song->voice[i].status = VOICE_OFF;
|
||||
recompute_envelope(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set status to OFF so resample_voice() will let this voice out
|
||||
of its loop, if any. In any case, this voice dies when it
|
||||
hits the end of its data (ofs>=data_length). */
|
||||
song->voice[i].status = VOICE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void note_off(MidiSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
MidiEvent *e = song->current_event;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == e->channel &&
|
||||
song->voice[i].note == e->a)
|
||||
{
|
||||
if (song->channel[e->channel].sustain)
|
||||
{
|
||||
song->voice[i].status = VOICE_SUSTAINED;
|
||||
}
|
||||
else
|
||||
finish_note(song, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the All Notes Off event */
|
||||
static void all_notes_off(MidiSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
SNDDBG(("All notes off on channel %d", c));
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == c)
|
||||
{
|
||||
if (song->channel[c].sustain)
|
||||
song->voice[i].status = VOICE_SUSTAINED;
|
||||
else
|
||||
finish_note(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the All Sounds Off event */
|
||||
static void all_sounds_off(MidiSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].channel == c &&
|
||||
song->voice[i].status != VOICE_FREE &&
|
||||
song->voice[i].status != VOICE_DIE)
|
||||
{
|
||||
kill_note(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_pressure(MidiSong *song)
|
||||
{
|
||||
MidiEvent *e = song->current_event;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_ON &&
|
||||
song->voice[i].channel == e->channel &&
|
||||
song->voice[i].note == e->a)
|
||||
{
|
||||
song->voice[i].velocity = e->b;
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_sustain(MidiSong *song)
|
||||
{
|
||||
int i = song->voices;
|
||||
int c = song->current_event->channel;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status == VOICE_SUSTAINED && song->voice[i].channel == c)
|
||||
finish_note(song, i);
|
||||
}
|
||||
|
||||
static void adjust_pitchbend(MidiSong *song)
|
||||
{
|
||||
int c = song->current_event->channel;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].status != VOICE_FREE && song->voice[i].channel == c)
|
||||
{
|
||||
recompute_freq(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_volume(MidiSong *song)
|
||||
{
|
||||
int c = song->current_event->channel;
|
||||
int i = song->voices;
|
||||
|
||||
while (i--)
|
||||
if (song->voice[i].channel == c &&
|
||||
(song->voice[i].status==VOICE_ON || song->voice[i].status==VOICE_SUSTAINED))
|
||||
{
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void seek_forward(MidiSong *song, Sint32 until_time)
|
||||
{
|
||||
reset_voices(song);
|
||||
while (song->current_event->time < until_time)
|
||||
{
|
||||
switch(song->current_event->type)
|
||||
{
|
||||
/* All notes stay off. Just handle the parameter changes. */
|
||||
|
||||
case ME_PITCH_SENS:
|
||||
song->channel[song->current_event->channel].pitchsens =
|
||||
song->current_event->a;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_PITCHWHEEL:
|
||||
song->channel[song->current_event->channel].pitchbend =
|
||||
song->current_event->a + song->current_event->b * 128;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_MAINVOLUME:
|
||||
song->channel[song->current_event->channel].volume =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_PAN:
|
||||
song->channel[song->current_event->channel].panning =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EXPRESSION:
|
||||
song->channel[song->current_event->channel].expression =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, song->current_event->channel))
|
||||
/* Change drum set */
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
else
|
||||
song->channel[song->current_event->channel].program =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_SUSTAIN:
|
||||
song->channel[song->current_event->channel].sustain =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_RESET_CONTROLLERS:
|
||||
reset_controllers(song, song->current_event->channel);
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EOT:
|
||||
song->current_sample = song->current_event->time;
|
||||
return;
|
||||
}
|
||||
song->current_event++;
|
||||
}
|
||||
/*song->current_sample=song->current_event->time;*/
|
||||
if (song->current_event != song->events)
|
||||
song->current_event--;
|
||||
song->current_sample=until_time;
|
||||
}
|
||||
|
||||
static void skip_to(MidiSong *song, Sint32 until_time)
|
||||
{
|
||||
if (song->current_sample > until_time)
|
||||
song->current_sample = 0;
|
||||
|
||||
reset_midi(song);
|
||||
song->buffered_count = 0;
|
||||
song->buffer_pointer = song->common_buffer;
|
||||
song->current_event = song->events;
|
||||
|
||||
if (until_time)
|
||||
seek_forward(song, until_time);
|
||||
}
|
||||
|
||||
static void do_compute_data(MidiSong *song, Sint32 count)
|
||||
{
|
||||
int i;
|
||||
memset(song->buffer_pointer, 0,
|
||||
(song->encoding & PE_MONO) ? (count * 4) : (count * 8));
|
||||
for (i = 0; i < song->voices; i++)
|
||||
{
|
||||
if(song->voice[i].status != VOICE_FREE)
|
||||
mix_voice(song, song->buffer_pointer, i, count);
|
||||
}
|
||||
song->current_sample += count;
|
||||
}
|
||||
|
||||
/* count=0 means flush remaining buffered data to output device, then
|
||||
flush the device itself */
|
||||
static void compute_data(MidiSong *song, void *stream, Sint32 count)
|
||||
{
|
||||
int channels;
|
||||
|
||||
if ( song->encoding & PE_MONO )
|
||||
channels = 1;
|
||||
else
|
||||
channels = 2;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
if (song->buffered_count)
|
||||
song->write(stream, song->common_buffer, channels * song->buffered_count);
|
||||
song->buffer_pointer = song->common_buffer;
|
||||
song->buffered_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while ((count + song->buffered_count) >= song->buffer_size)
|
||||
{
|
||||
do_compute_data(song, song->buffer_size - song->buffered_count);
|
||||
count -= song->buffer_size - song->buffered_count;
|
||||
song->write(stream, song->common_buffer, channels * song->buffer_size);
|
||||
song->buffer_pointer = song->common_buffer;
|
||||
song->buffered_count = 0;
|
||||
}
|
||||
if (count>0)
|
||||
{
|
||||
do_compute_data(song, count);
|
||||
song->buffered_count += count;
|
||||
song->buffer_pointer += (song->encoding & PE_MONO) ? count : count*2;
|
||||
}
|
||||
}
|
||||
|
||||
void Timidity_Start(MidiSong *song)
|
||||
{
|
||||
song->playing = 1;
|
||||
adjust_amplification(song);
|
||||
skip_to(song, 0);
|
||||
}
|
||||
|
||||
void Timidity_Seek(MidiSong *song, Uint32 ms)
|
||||
{
|
||||
skip_to(song, (ms * song->rate) / 1000);
|
||||
}
|
||||
|
||||
int Timidity_PlaySome(MidiSong *song, void *stream, Sint32 len)
|
||||
{
|
||||
Sint32 start_sample, end_sample, samples;
|
||||
int bytes_per_sample;
|
||||
|
||||
if (!song->playing)
|
||||
return 0;
|
||||
|
||||
bytes_per_sample =
|
||||
((song->encoding & PE_MONO) ? 1 : 2)
|
||||
* ((song->encoding & PE_16BIT) ? 2 : 1);
|
||||
samples = len / bytes_per_sample;
|
||||
|
||||
start_sample = song->current_sample;
|
||||
end_sample = song->current_sample+samples;
|
||||
while ( song->current_sample < end_sample ) {
|
||||
/* Handle all events that should happen at this time */
|
||||
while (song->current_event->time <= song->current_sample) {
|
||||
switch(song->current_event->type) {
|
||||
|
||||
/* Effects affecting a single note */
|
||||
|
||||
case ME_NOTEON:
|
||||
if (!(song->current_event->b)) /* Velocity 0? */
|
||||
note_off(song);
|
||||
else
|
||||
note_on(song);
|
||||
break;
|
||||
|
||||
case ME_NOTEOFF:
|
||||
note_off(song);
|
||||
break;
|
||||
|
||||
case ME_KEYPRESSURE:
|
||||
adjust_pressure(song);
|
||||
break;
|
||||
|
||||
/* Effects affecting a single channel */
|
||||
|
||||
case ME_PITCH_SENS:
|
||||
song->channel[song->current_event->channel].pitchsens =
|
||||
song->current_event->a;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
break;
|
||||
|
||||
case ME_PITCHWHEEL:
|
||||
song->channel[song->current_event->channel].pitchbend =
|
||||
song->current_event->a + song->current_event->b * 128;
|
||||
song->channel[song->current_event->channel].pitchfactor = 0;
|
||||
/* Adjust pitch for notes already playing */
|
||||
adjust_pitchbend(song);
|
||||
break;
|
||||
|
||||
case ME_MAINVOLUME:
|
||||
song->channel[song->current_event->channel].volume =
|
||||
song->current_event->a;
|
||||
adjust_volume(song);
|
||||
break;
|
||||
|
||||
case ME_PAN:
|
||||
song->channel[song->current_event->channel].panning =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EXPRESSION:
|
||||
song->channel[song->current_event->channel].expression =
|
||||
song->current_event->a;
|
||||
adjust_volume(song);
|
||||
break;
|
||||
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, song->current_event->channel)) {
|
||||
/* Change drum set */
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
}
|
||||
else
|
||||
song->channel[song->current_event->channel].program =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_SUSTAIN:
|
||||
song->channel[song->current_event->channel].sustain =
|
||||
song->current_event->a;
|
||||
if (!song->current_event->a)
|
||||
drop_sustain(song);
|
||||
break;
|
||||
|
||||
case ME_RESET_CONTROLLERS:
|
||||
reset_controllers(song, song->current_event->channel);
|
||||
break;
|
||||
|
||||
case ME_ALL_NOTES_OFF:
|
||||
all_notes_off(song);
|
||||
break;
|
||||
|
||||
case ME_ALL_SOUNDS_OFF:
|
||||
all_sounds_off(song);
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
song->channel[song->current_event->channel].bank =
|
||||
song->current_event->a;
|
||||
break;
|
||||
|
||||
case ME_EOT:
|
||||
/* Give the last notes a couple of seconds to decay */
|
||||
SNDDBG(("Playing time: ~%d seconds\n",
|
||||
song->current_sample/song->rate+2));
|
||||
SNDDBG(("Notes cut: %d\n", song->cut_notes));
|
||||
SNDDBG(("Notes lost totally: %d\n", song->lost_notes));
|
||||
song->playing = 0;
|
||||
return (song->current_sample - start_sample) * bytes_per_sample;
|
||||
}
|
||||
song->current_event++;
|
||||
}
|
||||
if (song->current_event->time > end_sample)
|
||||
compute_data(song, stream, end_sample-song->current_sample);
|
||||
else
|
||||
compute_data(song, stream, song->current_event->time-song->current_sample);
|
||||
}
|
||||
return samples * bytes_per_sample;
|
||||
}
|
||||
|
||||
void Timidity_SetVolume(MidiSong *song, int volume)
|
||||
{
|
||||
int i;
|
||||
if (volume > MAX_AMPLIFICATION)
|
||||
song->amplification = MAX_AMPLIFICATION;
|
||||
else
|
||||
if (volume < 0)
|
||||
song->amplification = 0;
|
||||
else
|
||||
song->amplification = volume;
|
||||
adjust_amplification(song);
|
||||
for (i = 0; i < song->voices; i++)
|
||||
if (song->voice[i].status != VOICE_FREE)
|
||||
{
|
||||
recompute_amp(song, i);
|
||||
apply_envelope_to_amp(song, i);
|
||||
}
|
||||
}
|
||||
64
project/jni/sdl_sound/decoders/timidity/playmidi.h
Normal file
64
project/jni/sdl_sound/decoders/timidity/playmidi.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
playmidi.h
|
||||
|
||||
*/
|
||||
|
||||
/* Midi events */
|
||||
#define ME_NONE 0
|
||||
#define ME_NOTEON 1
|
||||
#define ME_NOTEOFF 2
|
||||
#define ME_KEYPRESSURE 3
|
||||
#define ME_MAINVOLUME 4
|
||||
#define ME_PAN 5
|
||||
#define ME_SUSTAIN 6
|
||||
#define ME_EXPRESSION 7
|
||||
#define ME_PITCHWHEEL 8
|
||||
#define ME_PROGRAM 9
|
||||
#define ME_TEMPO 10
|
||||
#define ME_PITCH_SENS 11
|
||||
|
||||
#define ME_ALL_SOUNDS_OFF 12
|
||||
#define ME_RESET_CONTROLLERS 13
|
||||
#define ME_ALL_NOTES_OFF 14
|
||||
#define ME_TONE_BANK 15
|
||||
|
||||
#define ME_LYRIC 16
|
||||
|
||||
#define ME_EOT 99
|
||||
|
||||
/* Causes the instrument's default panning to be used. */
|
||||
#define NO_PANNING -1
|
||||
|
||||
/* Voice status options: */
|
||||
#define VOICE_FREE 0
|
||||
#define VOICE_ON 1
|
||||
#define VOICE_SUSTAINED 2
|
||||
#define VOICE_OFF 3
|
||||
#define VOICE_DIE 4
|
||||
|
||||
/* Voice panned options: */
|
||||
#define PANNED_MYSTERY 0
|
||||
#define PANNED_LEFT 1
|
||||
#define PANNED_RIGHT 2
|
||||
#define PANNED_CENTER 3
|
||||
/* Anything but PANNED_MYSTERY only uses the left volume */
|
||||
|
||||
#define ISDRUMCHANNEL(s, c) (((s)->drumchannels & (1<<(c))))
|
||||
584
project/jni/sdl_sound/decoders/timidity/readmidi.c
Normal file
584
project/jni/sdl_sound/decoders/timidity/readmidi.c
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
|
||||
/* Computes how many (fractional) samples one MIDI delta-time unit contains */
|
||||
static void compute_sample_increment(MidiSong *song, Sint32 tempo,
|
||||
Sint32 divisions)
|
||||
{
|
||||
double a;
|
||||
a = (double) (tempo) * (double) (song->rate) * (65536.0/1000000.0) /
|
||||
(double)(divisions);
|
||||
|
||||
song->sample_correction = (Sint32)(a) & 0xFFFF;
|
||||
song->sample_increment = (Sint32)(a) >> 16;
|
||||
|
||||
SNDDBG(("Samples per delta-t: %d (correction %d)",
|
||||
song->sample_increment, song->sample_correction));
|
||||
}
|
||||
|
||||
/* Read variable-length number (7 bits per byte, MSB first) */
|
||||
static Sint32 getvl(SDL_RWops *rw)
|
||||
{
|
||||
Sint32 l=0;
|
||||
Uint8 c;
|
||||
for (;;)
|
||||
{
|
||||
SDL_RWread(rw, &c, 1, 1);
|
||||
l += (c & 0x7f);
|
||||
if (!(c & 0x80)) return l;
|
||||
l<<=7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a string from the file, followed by a newline. Any non-ASCII
|
||||
or unprintable characters will be converted to periods. */
|
||||
static int dumpstring(SDL_RWops *rw, Sint32 len, char *label)
|
||||
{
|
||||
signed char *s=safe_malloc(len+1);
|
||||
if (len != (Sint32) SDL_RWread(rw, s, 1, len))
|
||||
{
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
s[len]='\0';
|
||||
while (len--)
|
||||
{
|
||||
if (s[len]<32)
|
||||
s[len]='.';
|
||||
}
|
||||
SNDDBG(("%s%s", label, s));
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MIDIEVENT(at,t,ch,pa,pb) \
|
||||
new=safe_malloc(sizeof(MidiEventList)); \
|
||||
new->event.time=at; new->event.type=t; new->event.channel=ch; \
|
||||
new->event.a=pa; new->event.b=pb; new->next=0;\
|
||||
return new;
|
||||
|
||||
#define MAGIC_EOT ((MidiEventList *)(-1))
|
||||
|
||||
/* Read a MIDI event, returning a freshly allocated element that can
|
||||
be linked to the event list */
|
||||
static MidiEventList *read_midi_event(MidiSong *song)
|
||||
{
|
||||
static Uint8 laststatus, lastchan;
|
||||
static Uint8 nrpn=0, rpn_msb[16], rpn_lsb[16]; /* one per channel */
|
||||
Uint8 me, type, a,b,c;
|
||||
Sint32 len;
|
||||
MidiEventList *new;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
song->at += getvl(song->rw);
|
||||
if (SDL_RWread(song->rw, &me, 1, 1) != 1)
|
||||
{
|
||||
SNDDBG(("read_midi_event: SDL_RWread() failure\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(me==0xF0 || me == 0xF7) /* SysEx event */
|
||||
{
|
||||
len=getvl(song->rw);
|
||||
SDL_RWseek(song->rw, len, SEEK_CUR);
|
||||
}
|
||||
else if(me==0xFF) /* Meta event */
|
||||
{
|
||||
SDL_RWread(song->rw, &type, 1, 1);
|
||||
len=getvl(song->rw);
|
||||
if (type>0 && type<16)
|
||||
{
|
||||
static char *label[]={
|
||||
"Text event: ", "Text: ", "Copyright: ", "Track name: ",
|
||||
"Instrument: ", "Lyric: ", "Marker: ", "Cue point: "};
|
||||
dumpstring(song->rw, len, label[(type>7) ? 0 : type]);
|
||||
}
|
||||
else
|
||||
switch(type)
|
||||
{
|
||||
case 0x2F: /* End of Track */
|
||||
return MAGIC_EOT;
|
||||
|
||||
case 0x51: /* Tempo */
|
||||
SDL_RWread(song->rw, &a, 1, 1);
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
SDL_RWread(song->rw, &c, 1, 1);
|
||||
MIDIEVENT(song->at, ME_TEMPO, c, a, b);
|
||||
|
||||
default:
|
||||
SNDDBG(("(Meta event type 0x%02x, length %d)\n", type, len));
|
||||
SDL_RWseek(song->rw, len, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a=me;
|
||||
if (a & 0x80) /* status byte */
|
||||
{
|
||||
lastchan=a & 0x0F;
|
||||
laststatus=(a>>4) & 0x07;
|
||||
SDL_RWread(song->rw, &a, 1, 1);
|
||||
a &= 0x7F;
|
||||
}
|
||||
switch(laststatus)
|
||||
{
|
||||
case 0: /* Note off */
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_NOTEOFF, lastchan, a,b);
|
||||
|
||||
case 1: /* Note on */
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_NOTEON, lastchan, a,b);
|
||||
|
||||
case 2: /* Key Pressure */
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_KEYPRESSURE, lastchan, a, b);
|
||||
|
||||
case 3: /* Control change */
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
{
|
||||
int control=255;
|
||||
switch(a)
|
||||
{
|
||||
case 7: control=ME_MAINVOLUME; break;
|
||||
case 10: control=ME_PAN; break;
|
||||
case 11: control=ME_EXPRESSION; break;
|
||||
case 64: control=ME_SUSTAIN; break;
|
||||
case 120: control=ME_ALL_SOUNDS_OFF; break;
|
||||
case 121: control=ME_RESET_CONTROLLERS; break;
|
||||
case 123: control=ME_ALL_NOTES_OFF; break;
|
||||
|
||||
/* These should be the SCC-1 tone bank switch
|
||||
commands. I don't know why there are two, or
|
||||
why the latter only allows switching to bank 0.
|
||||
Also, some MIDI files use 0 as some sort of
|
||||
continuous controller. This will cause lots of
|
||||
warnings about undefined tone banks. */
|
||||
case 0: control=ME_TONE_BANK; break;
|
||||
case 32:
|
||||
if (b!=0)
|
||||
SNDDBG(("(Strange: tone bank change 0x20%02x)\n", b));
|
||||
else
|
||||
control=ME_TONE_BANK;
|
||||
break;
|
||||
|
||||
case 100: nrpn=0; rpn_msb[lastchan]=b; break;
|
||||
case 101: nrpn=0; rpn_lsb[lastchan]=b; break;
|
||||
case 99: nrpn=1; rpn_msb[lastchan]=b; break;
|
||||
case 98: nrpn=1; rpn_lsb[lastchan]=b; break;
|
||||
|
||||
case 6:
|
||||
if (nrpn)
|
||||
{
|
||||
SNDDBG(("(Data entry (MSB) for NRPN %02x,%02x: %d)\n",
|
||||
rpn_msb[lastchan], rpn_lsb[lastchan], b));
|
||||
break;
|
||||
}
|
||||
|
||||
switch((rpn_msb[lastchan]<<8) | rpn_lsb[lastchan])
|
||||
{
|
||||
case 0x0000: /* Pitch bend sensitivity */
|
||||
control=ME_PITCH_SENS;
|
||||
break;
|
||||
|
||||
case 0x7F7F: /* RPN reset */
|
||||
/* reset pitch bend sensitivity to 2 */
|
||||
MIDIEVENT(song->at, ME_PITCH_SENS, lastchan, 2, 0);
|
||||
|
||||
default:
|
||||
SNDDBG(("(Data entry (MSB) for RPN %02x,%02x: %d)\n",
|
||||
rpn_msb[lastchan], rpn_lsb[lastchan], b));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SNDDBG(("(Control %d: %d)\n", a, b));
|
||||
break;
|
||||
}
|
||||
if (control != 255)
|
||||
{
|
||||
MIDIEVENT(song->at, control, lastchan, b, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* Program change */
|
||||
a &= 0x7f;
|
||||
MIDIEVENT(song->at, ME_PROGRAM, lastchan, a, 0);
|
||||
|
||||
case 5: /* Channel pressure - NOT IMPLEMENTED */
|
||||
break;
|
||||
|
||||
case 6: /* Pitch wheel */
|
||||
SDL_RWread(song->rw, &b, 1, 1);
|
||||
b &= 0x7F;
|
||||
MIDIEVENT(song->at, ME_PITCHWHEEL, lastchan, a, b);
|
||||
|
||||
default:
|
||||
SNDDBG(("*** Can't happen: status 0x%02X, channel 0x%02X\n",
|
||||
laststatus, lastchan));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
#undef MIDIEVENT
|
||||
|
||||
/* Read a midi track into the linked list, either merging with any previous
|
||||
tracks or appending to them. */
|
||||
static int read_track(MidiSong *song, int append)
|
||||
{
|
||||
MidiEventList *meep;
|
||||
MidiEventList *next, *new;
|
||||
Sint32 len;
|
||||
char tmp[4];
|
||||
|
||||
meep = song->evlist;
|
||||
if (append && meep)
|
||||
{
|
||||
/* find the last event in the list */
|
||||
for (; meep->next; meep=meep->next)
|
||||
;
|
||||
song->at = meep->event.time;
|
||||
}
|
||||
else
|
||||
song->at=0;
|
||||
|
||||
/* Check the formalities */
|
||||
|
||||
if (SDL_RWread(song->rw, tmp, 1, 4) != 4 || SDL_RWread(song->rw, &len, 4, 1) != 1)
|
||||
{
|
||||
SNDDBG(("Can't read track header.\n"));
|
||||
return -1;
|
||||
}
|
||||
len=SDL_SwapBE32(len);
|
||||
if (memcmp(tmp, "MTrk", 4))
|
||||
{
|
||||
SNDDBG(("Corrupt MIDI file.\n"));
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(new=read_midi_event(song))) /* Some kind of error */
|
||||
return -2;
|
||||
|
||||
if (new==MAGIC_EOT) /* End-of-track Hack. */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
next=meep->next;
|
||||
while (next && (next->event.time < new->event.time))
|
||||
{
|
||||
meep=next;
|
||||
next=meep->next;
|
||||
}
|
||||
|
||||
new->next=next;
|
||||
meep->next=new;
|
||||
|
||||
song->event_count++; /* Count the event. (About one?) */
|
||||
meep=new;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the linked event list from memory. */
|
||||
static void free_midi_list(MidiSong *song)
|
||||
{
|
||||
MidiEventList *meep, *next;
|
||||
if (!(meep = song->evlist)) return;
|
||||
while (meep)
|
||||
{
|
||||
next=meep->next;
|
||||
free(meep);
|
||||
meep=next;
|
||||
}
|
||||
song->evlist=0;
|
||||
}
|
||||
|
||||
/* Allocate an array of MidiEvents and fill it from the linked list of
|
||||
events, marking used instruments for loading. Convert event times to
|
||||
samples: handle tempo changes. Strip unnecessary events from the list.
|
||||
Free the linked list. */
|
||||
static MidiEvent *groom_list(MidiSong *song, Sint32 divisions,Sint32 *eventsp,
|
||||
Sint32 *samplesp)
|
||||
{
|
||||
MidiEvent *groomed_list, *lp;
|
||||
MidiEventList *meep;
|
||||
Sint32 i, our_event_count, tempo, skip_this_event, new_value;
|
||||
Sint32 sample_cum, samples_to_do, at, st, dt, counting_time;
|
||||
|
||||
int current_bank[16], current_set[16], current_program[16];
|
||||
/* Or should each bank have its own current program? */
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
current_bank[i]=0;
|
||||
current_set[i]=0;
|
||||
current_program[i]=song->default_program;
|
||||
}
|
||||
|
||||
tempo=500000;
|
||||
compute_sample_increment(song, tempo, divisions);
|
||||
|
||||
/* This may allocate a bit more than we need */
|
||||
groomed_list=lp=safe_malloc(sizeof(MidiEvent) * (song->event_count+1));
|
||||
meep=song->evlist;
|
||||
|
||||
our_event_count=0;
|
||||
st=at=sample_cum=0;
|
||||
counting_time=2; /* We strip any silence before the first NOTE ON. */
|
||||
|
||||
for (i = 0; i < song->event_count; i++)
|
||||
{
|
||||
skip_this_event=0;
|
||||
|
||||
if (meep->event.type==ME_TEMPO)
|
||||
{
|
||||
tempo=
|
||||
meep->event.channel + meep->event.b * 256 + meep->event.a * 65536;
|
||||
compute_sample_increment(song, tempo, divisions);
|
||||
skip_this_event=1;
|
||||
}
|
||||
else switch (meep->event.type)
|
||||
{
|
||||
case ME_PROGRAM:
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
if (song->drumset[meep->event.a]) /* Is this a defined drumset? */
|
||||
new_value=meep->event.a;
|
||||
else
|
||||
{
|
||||
SNDDBG(("Drum set %d is undefined\n", meep->event.a));
|
||||
new_value=meep->event.a=0;
|
||||
}
|
||||
if (current_set[meep->event.channel] != new_value)
|
||||
current_set[meep->event.channel]=new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_value=meep->event.a;
|
||||
if ((current_program[meep->event.channel] != SPECIAL_PROGRAM)
|
||||
&& (current_program[meep->event.channel] != new_value))
|
||||
current_program[meep->event.channel] = new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_NOTEON:
|
||||
if (counting_time)
|
||||
counting_time=1;
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
/* Mark this instrument to be loaded */
|
||||
if (!(song->drumset[current_set[meep->event.channel]]
|
||||
->instrument[meep->event.a]))
|
||||
song->drumset[current_set[meep->event.channel]]
|
||||
->instrument[meep->event.a] = MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_program[meep->event.channel]==SPECIAL_PROGRAM)
|
||||
break;
|
||||
/* Mark this instrument to be loaded */
|
||||
if (!(song->tonebank[current_bank[meep->event.channel]]
|
||||
->instrument[current_program[meep->event.channel]]))
|
||||
song->tonebank[current_bank[meep->event.channel]]
|
||||
->instrument[current_program[meep->event.channel]] =
|
||||
MAGIC_LOAD_INSTRUMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case ME_TONE_BANK:
|
||||
if (ISDRUMCHANNEL(song, meep->event.channel))
|
||||
{
|
||||
skip_this_event=1;
|
||||
break;
|
||||
}
|
||||
if (song->tonebank[meep->event.a]) /* Is this a defined tone bank? */
|
||||
new_value=meep->event.a;
|
||||
else
|
||||
{
|
||||
SNDDBG(("Tone bank %d is undefined\n", meep->event.a));
|
||||
new_value=meep->event.a=0;
|
||||
}
|
||||
if (current_bank[meep->event.channel]!=new_value)
|
||||
current_bank[meep->event.channel]=new_value;
|
||||
else
|
||||
skip_this_event=1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recompute time in samples*/
|
||||
if ((dt=meep->event.time - at) && !counting_time)
|
||||
{
|
||||
samples_to_do = song->sample_increment * dt;
|
||||
sample_cum += song->sample_correction * dt;
|
||||
if (sample_cum & 0xFFFF0000)
|
||||
{
|
||||
samples_to_do += ((sample_cum >> 16) & 0xFFFF);
|
||||
sample_cum &= 0x0000FFFF;
|
||||
}
|
||||
st += samples_to_do;
|
||||
}
|
||||
else if (counting_time==1) counting_time=0;
|
||||
if (!skip_this_event)
|
||||
{
|
||||
/* Add the event to the list */
|
||||
*lp=meep->event;
|
||||
lp->time=st;
|
||||
lp++;
|
||||
our_event_count++;
|
||||
}
|
||||
at=meep->event.time;
|
||||
meep=meep->next;
|
||||
}
|
||||
/* Add an End-of-Track event */
|
||||
lp->time=st;
|
||||
lp->type=ME_EOT;
|
||||
our_event_count++;
|
||||
free_midi_list(song);
|
||||
|
||||
*eventsp=our_event_count;
|
||||
*samplesp=st;
|
||||
return groomed_list;
|
||||
}
|
||||
|
||||
MidiEvent *read_midi_file(MidiSong *song, Sint32 *count, Sint32 *sp)
|
||||
{
|
||||
Sint32 len, divisions;
|
||||
Sint16 format, tracks, divisions_tmp;
|
||||
int i;
|
||||
char tmp[4];
|
||||
|
||||
song->event_count=0;
|
||||
song->at=0;
|
||||
song->evlist=0;
|
||||
|
||||
if (SDL_RWread(song->rw, tmp, 1, 4) != 4 || SDL_RWread(song->rw, &len, 4, 1) != 1)
|
||||
{
|
||||
SNDDBG(("Not a MIDI file!\n"));
|
||||
return 0;
|
||||
}
|
||||
len=SDL_SwapBE32(len);
|
||||
if (memcmp(tmp, "MThd", 4) || len < 6)
|
||||
{
|
||||
SNDDBG(("Not a MIDI file!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_RWread(song->rw, &format, 2, 1);
|
||||
SDL_RWread(song->rw, &tracks, 2, 1);
|
||||
SDL_RWread(song->rw, &divisions_tmp, 2, 1);
|
||||
format=SDL_SwapBE16(format);
|
||||
tracks=SDL_SwapBE16(tracks);
|
||||
divisions_tmp=SDL_SwapBE16(divisions_tmp);
|
||||
|
||||
if (divisions_tmp<0)
|
||||
{
|
||||
/* SMPTE time -- totally untested. Got a MIDI file that uses this? */
|
||||
divisions=
|
||||
(Sint32)(-(divisions_tmp/256)) * (Sint32)(divisions_tmp & 0xFF);
|
||||
}
|
||||
else divisions=(Sint32)(divisions_tmp);
|
||||
|
||||
if (len > 6)
|
||||
{
|
||||
SNDDBG(("MIDI file header size %u bytes", len));
|
||||
SDL_RWseek(song->rw, len-6, SEEK_CUR); /* skip the excess */
|
||||
}
|
||||
if (format<0 || format >2)
|
||||
{
|
||||
SNDDBG(("Unknown MIDI file format %d\n", format));
|
||||
return 0;
|
||||
}
|
||||
SNDDBG(("Format: %d Tracks: %d Divisions: %d\n",
|
||||
format, tracks, divisions));
|
||||
|
||||
/* Put a do-nothing event first in the list for easier processing */
|
||||
song->evlist=safe_malloc(sizeof(MidiEventList));
|
||||
song->evlist->event.time=0;
|
||||
song->evlist->event.type=ME_NONE;
|
||||
song->evlist->next=0;
|
||||
song->event_count++;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case 0:
|
||||
if (read_track(song, 0))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
for (i=0; i<tracks; i++)
|
||||
if (read_track(song, 0))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* We simply play the tracks sequentially */
|
||||
for (i=0; i<tracks; i++)
|
||||
if (read_track(song, 1))
|
||||
{
|
||||
free_midi_list(song);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return groom_list(song, divisions, count, sp);
|
||||
}
|
||||
24
project/jni/sdl_sound/decoders/timidity/readmidi.h
Normal file
24
project/jni/sdl_sound/decoders/timidity/readmidi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
readmidi.h
|
||||
|
||||
*/
|
||||
|
||||
extern MidiEvent *read_midi_file(MidiSong *song, Sint32 *count, Sint32 *sp);
|
||||
612
project/jni/sdl_sound/decoders/timidity/resample.c
Normal file
612
project/jni/sdl_sound/decoders/timidity/resample.c
Normal file
@@ -0,0 +1,612 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
resample.c
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "tables.h"
|
||||
#include "resample.h"
|
||||
|
||||
/*************** resampling with fixed increment *****************/
|
||||
|
||||
static sample_t *rs_plain(MidiSong *song, int v, Sint32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
sample_t v1, v2;
|
||||
Voice
|
||||
*vp=&(song->voice[v]);
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
Sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->data_length,
|
||||
count=*countptr;
|
||||
Sint32 i;
|
||||
|
||||
if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
|
||||
|
||||
/* Precalc how many times we should go through the loop.
|
||||
NOTE: Assumes that incr > 0 and that ofs <= le */
|
||||
i = (le - ofs) / incr + 1;
|
||||
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
|
||||
if (ofs >= le)
|
||||
{
|
||||
if (ofs == le)
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
vp->status=VOICE_FREE;
|
||||
*countptr-=count+1;
|
||||
}
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_loop(MidiSong *song, Voice *vp, Sint32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
sample_t v1, v2;
|
||||
Sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
Sint32 i;
|
||||
|
||||
while (count)
|
||||
{
|
||||
if (ofs >= le)
|
||||
/* NOTE: Assumes that ll > incr and that incr > 0. */
|
||||
ofs -= ll;
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = (le - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
}
|
||||
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_bidir(MidiSong *song, Voice *vp, Sint32 count)
|
||||
{
|
||||
sample_t v1, v2;
|
||||
Sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
Sint32
|
||||
le2 = le<<1,
|
||||
ls2 = ls<<1,
|
||||
i;
|
||||
/* Play normally until inside the loop region */
|
||||
|
||||
if (ofs <= ls)
|
||||
{
|
||||
/* NOTE: Assumes that incr > 0, which is NOT always the case
|
||||
when doing bidirectional looping. I have yet to see a case
|
||||
where both ofs <= ls AND incr < 0, however. */
|
||||
i = (ls - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
while(count)
|
||||
{
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
|
||||
if (i > count)
|
||||
{
|
||||
i = count;
|
||||
count = 0;
|
||||
}
|
||||
else count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (ofs>=le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
/*********************** vibrato versions ***************************/
|
||||
|
||||
/* We only need to compute one half of the vibrato sine cycle */
|
||||
static int vib_phase_to_inc_ptr(int phase)
|
||||
{
|
||||
if (phase < 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 Sint32 update_vibrato(MidiSong *song, Voice *vp, int sign)
|
||||
{
|
||||
Sint32 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)(song->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]=(Sint32) a;
|
||||
|
||||
if (sign)
|
||||
a = -a; /* need to preserve the loop direction */
|
||||
|
||||
return (Sint32) a;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_plain(MidiSong *song, int v, Sint32 *countptr)
|
||||
{
|
||||
|
||||
/* Play sample until end, then free the voice. */
|
||||
|
||||
sample_t v1, v2;
|
||||
Voice *vp=&(song->voice[v]);
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
Sint32
|
||||
le=vp->sample->data_length,
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
count=*countptr;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
|
||||
/* This has never been tested */
|
||||
|
||||
if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
|
||||
|
||||
while (count--)
|
||||
{
|
||||
if (!cc--)
|
||||
{
|
||||
cc=vp->vibrato_control_ratio;
|
||||
incr=update_vibrato(song, vp, 0);
|
||||
}
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
if (ofs >= le)
|
||||
{
|
||||
if (ofs == le)
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
vp->status=VOICE_FREE;
|
||||
*countptr-=count+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_loop(MidiSong *song, Voice *vp, Sint32 count)
|
||||
{
|
||||
|
||||
/* Play sample until end-of-loop, skip back and continue. */
|
||||
|
||||
sample_t v1, v2;
|
||||
Sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ll=le - vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
Sint32 i;
|
||||
int
|
||||
vibflag=0;
|
||||
|
||||
while (count)
|
||||
{
|
||||
/* Hopefully the loop is longer than an increment */
|
||||
if(ofs >= le)
|
||||
ofs -= ll;
|
||||
/* Precalc how many times to go through the loop, taking
|
||||
the vibrato control ratio into account this time. */
|
||||
i = (le - ofs) / incr + 1;
|
||||
if(i > count) i = count;
|
||||
if(i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while(i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if(vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, 0);
|
||||
vibflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
static sample_t *rs_vib_bidir(MidiSong *song, Voice *vp, Sint32 count)
|
||||
{
|
||||
sample_t v1, v2;
|
||||
Sint32
|
||||
ofs=vp->sample_offset,
|
||||
incr=vp->sample_increment,
|
||||
le=vp->sample->loop_end,
|
||||
ls=vp->sample->loop_start;
|
||||
sample_t
|
||||
*dest=song->resample_buffer,
|
||||
*src=vp->sample->data;
|
||||
int
|
||||
cc=vp->vibrato_control_counter;
|
||||
Sint32
|
||||
le2=le<<1,
|
||||
ls2=ls<<1,
|
||||
i;
|
||||
int
|
||||
vibflag = 0;
|
||||
|
||||
/* Play normally until inside the loop region */
|
||||
while (count && (ofs <= ls))
|
||||
{
|
||||
i = (ls - ofs) / incr + 1;
|
||||
if (i > count) i = count;
|
||||
if (i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, 0);
|
||||
vibflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then do the bidirectional looping */
|
||||
|
||||
while (count)
|
||||
{
|
||||
/* Precalc how many times we should go through the loop */
|
||||
i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
|
||||
if(i > count) i = count;
|
||||
if(i > cc)
|
||||
{
|
||||
i = cc;
|
||||
vibflag = 1;
|
||||
}
|
||||
else cc -= i;
|
||||
count -= i;
|
||||
while (i--)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS)+1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
ofs += incr;
|
||||
}
|
||||
if (vibflag)
|
||||
{
|
||||
cc = vp->vibrato_control_ratio;
|
||||
incr = update_vibrato(song, vp, (incr < 0));
|
||||
vibflag = 0;
|
||||
}
|
||||
if (ofs >= le)
|
||||
{
|
||||
/* fold the overshoot back in */
|
||||
ofs = le2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
else if (ofs <= ls)
|
||||
{
|
||||
ofs = ls2 - ofs;
|
||||
incr *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
vp->vibrato_control_counter=cc;
|
||||
vp->sample_increment=incr;
|
||||
vp->sample_offset=ofs; /* Update offset */
|
||||
return song->resample_buffer;
|
||||
}
|
||||
|
||||
sample_t *resample_voice(MidiSong *song, int v, Sint32 *countptr)
|
||||
{
|
||||
Sint32 ofs;
|
||||
Uint8 modes;
|
||||
Voice *vp=&(song->voice[v]);
|
||||
|
||||
if (!(vp->sample->sample_rate))
|
||||
{
|
||||
/* Pre-resampled data -- just update the offset and check if
|
||||
we're out of data. */
|
||||
ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use
|
||||
FRACTION_BITS here... */
|
||||
if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs)
|
||||
{
|
||||
/* Note finished. Free the voice. */
|
||||
vp->status = VOICE_FREE;
|
||||
|
||||
/* Let the caller know how much data we had left */
|
||||
*countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs;
|
||||
}
|
||||
else
|
||||
vp->sample_offset += *countptr << FRACTION_BITS;
|
||||
|
||||
return vp->sample->data+ofs;
|
||||
}
|
||||
|
||||
/* Need to resample. Use the proper function. */
|
||||
modes=vp->sample->modes;
|
||||
|
||||
if (vp->vibrato_control_ratio)
|
||||
{
|
||||
if ((modes & MODES_LOOPING) &&
|
||||
((modes & MODES_ENVELOPE) ||
|
||||
(vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
|
||||
{
|
||||
if (modes & MODES_PINGPONG)
|
||||
return rs_vib_bidir(song, vp, *countptr);
|
||||
else
|
||||
return rs_vib_loop(song, vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_vib_plain(song, v, countptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modes & MODES_LOOPING) &&
|
||||
((modes & MODES_ENVELOPE) ||
|
||||
(vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
|
||||
{
|
||||
if (modes & MODES_PINGPONG)
|
||||
return rs_bidir(song, vp, *countptr);
|
||||
else
|
||||
return rs_loop(song, vp, *countptr);
|
||||
}
|
||||
else
|
||||
return rs_plain(song, v, countptr);
|
||||
}
|
||||
}
|
||||
|
||||
void pre_resample(MidiSong *song, Sample *sp)
|
||||
{
|
||||
double a, xdiff;
|
||||
Sint32 incr, ofs, newlen, count;
|
||||
Sint16 *newdata, *dest, *src = (Sint16 *) sp->data;
|
||||
Sint16 v1, v2, v3, v4, *vptr;
|
||||
#ifdef DEBUG_CHATTER
|
||||
static const char note_name[12][3] =
|
||||
{
|
||||
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
||||
};
|
||||
#endif
|
||||
|
||||
SNDDBG((" * pre-resampling for note %d (%s%d)\n",
|
||||
sp->note_to_use,
|
||||
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12));
|
||||
|
||||
a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) /
|
||||
((double) (sp->root_freq) * song->rate);
|
||||
newlen = (Sint32)(sp->data_length / a);
|
||||
dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1));
|
||||
|
||||
count = (newlen >> FRACTION_BITS) - 1;
|
||||
ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
|
||||
|
||||
if (--count)
|
||||
*dest++ = src[0];
|
||||
|
||||
/* Since we're pre-processing and this doesn't have to be done in
|
||||
real-time, we go ahead and do the full sliding cubic interpolation. */
|
||||
while (--count)
|
||||
{
|
||||
vptr = src + (ofs >> FRACTION_BITS);
|
||||
/*
|
||||
* Electric Fence to the rescue: Accessing *(vptr - 1) is not a
|
||||
* good thing to do when vptr <= src. (TiMidity++ has a similar
|
||||
* safe-guard here.)
|
||||
*/
|
||||
v1 = (vptr == src) ? *vptr : *(vptr - 1);
|
||||
v2 = *vptr;
|
||||
v3 = *(vptr + 1);
|
||||
v4 = *(vptr + 2);
|
||||
xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);
|
||||
*dest++ = (Sint16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 +
|
||||
xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4))));
|
||||
ofs += incr;
|
||||
}
|
||||
|
||||
if (ofs & FRACTION_MASK)
|
||||
{
|
||||
v1 = src[ofs >> FRACTION_BITS];
|
||||
v2 = src[(ofs >> FRACTION_BITS) + 1];
|
||||
*dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
|
||||
}
|
||||
else
|
||||
*dest++ = src[ofs >> FRACTION_BITS];
|
||||
|
||||
sp->data_length = newlen;
|
||||
sp->loop_start = (Sint32)(sp->loop_start / a);
|
||||
sp->loop_end = (Sint32)(sp->loop_end / a);
|
||||
free(sp->data);
|
||||
sp->data = (sample_t *) newdata;
|
||||
sp->sample_rate = 0;
|
||||
}
|
||||
24
project/jni/sdl_sound/decoders/timidity/resample.h
Normal file
24
project/jni/sdl_sound/decoders/timidity/resample.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
resample.h
|
||||
*/
|
||||
|
||||
extern sample_t *resample_voice(MidiSong *song, int v, Sint32 *countptr);
|
||||
extern void pre_resample(MidiSong *song, Sample *sp);
|
||||
218
project/jni/sdl_sound/decoders/timidity/tables.c
Normal file
218
project/jni/sdl_sound/decoders/timidity/tables.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "tables.h"
|
||||
|
||||
const Sint32 freq_table[128]=
|
||||
{
|
||||
8176, 8662, 9177, 9723,
|
||||
10301, 10913, 11562, 12250,
|
||||
12978, 13750, 14568, 15434,
|
||||
|
||||
16352, 17324, 18354, 19445,
|
||||
20602, 21827, 23125, 24500,
|
||||
25957, 27500, 29135, 30868,
|
||||
|
||||
32703, 34648, 36708, 38891,
|
||||
41203, 43654, 46249, 48999,
|
||||
51913, 55000, 58270, 61735,
|
||||
|
||||
65406, 69296, 73416, 77782,
|
||||
82407, 87307, 92499, 97999,
|
||||
103826, 110000, 116541, 123471,
|
||||
|
||||
130813, 138591, 146832, 155563,
|
||||
164814, 174614, 184997, 195998,
|
||||
207652, 220000, 233082, 246942,
|
||||
|
||||
261626, 277183, 293665, 311127,
|
||||
329628, 349228, 369994, 391995,
|
||||
415305, 440000, 466164, 493883,
|
||||
|
||||
523251, 554365, 587330, 622254,
|
||||
659255, 698456, 739989, 783991,
|
||||
830609, 880000, 932328, 987767,
|
||||
|
||||
1046502, 1108731, 1174659, 1244508,
|
||||
1318510, 1396913, 1479978, 1567982,
|
||||
1661219, 1760000, 1864655, 1975533,
|
||||
|
||||
2093005, 2217461, 2349318, 2489016,
|
||||
2637020, 2793826, 2959955, 3135963,
|
||||
3322438, 3520000, 3729310, 3951066,
|
||||
|
||||
4186009, 4434922, 4698636, 4978032,
|
||||
5274041, 5587652, 5919911, 6271927,
|
||||
6644875, 7040000, 7458620, 7902133,
|
||||
|
||||
8372018, 8869844, 9397273, 9956063,
|
||||
10548082, 11175303, 11839822, 12543854
|
||||
};
|
||||
|
||||
/* v=2.^((x/127-1) * 6) */
|
||||
const double vol_table[128] =
|
||||
{
|
||||
0.015625, 0.016145143728351113, 0.016682602624583379, 0.017237953096759438,
|
||||
0.017811790741104401, 0.01840473098076444, 0.019017409725829021, 0.019650484055324921,
|
||||
0.020304632921913132, 0.020980557880044631, 0.021678983838355849, 0.02240065983711079,
|
||||
0.023146359851523596, 0.023916883621822989, 0.024713057510949051, 0.025535735390801884,
|
||||
0.026385799557992876, 0.027264161680080529, 0.028171763773305786, 0.029109579212875332,
|
||||
0.030078613776876421, 0.031079906724942836, 0.032114531912828696, 0.033183598944085631,
|
||||
0.034288254360078256, 0.035429682869614412, 0.036609108619508737, 0.037827796507442342,
|
||||
0.039087053538526394, 0.040388230227024875, 0.041732722044739302, 0.043121970917609151,
|
||||
0.044557466772132896, 0.046040749133268132, 0.047573408775524545, 0.049157089429020417,
|
||||
0.050793489542332405, 0.05248436410402918, 0.054231526524842463, 0.056036850582493913,
|
||||
0.057902272431264008, 0.059829792678457581, 0.061821478529993396, 0.063879466007418645,
|
||||
0.066005962238725971, 0.068203247825430205, 0.070473679288442961, 0.072819691595368496,
|
||||
0.075243800771931268, 0.077748606600335793, 0.080336795407452768, 0.083011142945821612,
|
||||
0.085774517370559328, 0.088629882315368294, 0.091580300070941839, 0.094628934869176312,
|
||||
0.097779056276712184, 0.10103404270144323, 0.1043973850157546, 0.1078726903003755,
|
||||
0.11146368571286204, 0.11517422248485852, 0.11900828005242428, 0.12296997032385605,
|
||||
0.12706354208958254, 0.13129338557886089, 0.13566403716816194, 0.14018018424629392,
|
||||
0.14484667024148207, 0.14966849981579558, 0.15465084423249356, 0.15979904690204472,
|
||||
0.16511862911277009, 0.17061529595225433, 0.17629494242587571, 0.18216365977901747,
|
||||
0.18822774202974024, 0.19449369271892172, 0.20096823188510385, 0.20765830327152621,
|
||||
0.21457108177307616, 0.22171398113114205, 0.2290946618846218, 0.23672103958561411,
|
||||
0.2446012932886038, 0.25274387432224471, 0.26115751535314891, 0.26985123975140174,
|
||||
0.27883437126784744, 0.28811654403352405, 0.29770771289197112, 0.30761816407549192,
|
||||
0.31785852623682015, 0.32843978184802081, 0.33937327897885317, 0.3506707434672246,
|
||||
0.36234429149478936, 0.37440644258117928, 0.38687013301080181, 0.39974872970660535,
|
||||
0.41305604456569134, 0.42680634927214656, 0.44101439060298442, 0.45569540624360722,
|
||||
0.47086514112975281, 0.48653986433345225, 0.50273638651110641, 0.51947207793239625,
|
||||
0.53676488710936021, 0.55463336004561792, 0.57309666012638816, 0.59217458867062556,
|
||||
0.61188760616732485, 0.63225685421876243, 0.65330417821421161, 0.67505215075844849,
|
||||
0.69752409588017272, 0.72074411404630734, 0.74473710800900605, 0.76952880951308478,
|
||||
0.79514580689252357, 0.82161557358563286, 0.84896649759946774, 0.87722791195508854,
|
||||
0.90643012614631979, 0.93660445864574493, 0.96778327049280244, 1
|
||||
};
|
||||
|
||||
const double bend_fine[256] = {
|
||||
1, 1.0002256593050698, 1.0004513695322617, 1.0006771306930664,
|
||||
1.0009029427989777, 1.0011288058614922, 1.0013547198921082, 1.0015806849023274,
|
||||
1.0018067009036538, 1.002032767907594, 1.0022588859256572, 1.0024850549693551,
|
||||
1.0027112750502025, 1.0029375461797159, 1.0031638683694153, 1.0033902416308227,
|
||||
1.0036166659754628, 1.0038431414148634, 1.0040696679605541, 1.0042962456240678,
|
||||
1.0045228744169397, 1.0047495543507072, 1.0049762854369111, 1.0052030676870944,
|
||||
1.0054299011128027, 1.0056567857255843, 1.00588372153699, 1.006110708558573,
|
||||
1.0063377468018897, 1.0065648362784985, 1.0067919769999607, 1.0070191689778405,
|
||||
1.0072464122237039, 1.0074737067491204, 1.0077010525656616, 1.0079284496849015,
|
||||
1.0081558981184175, 1.008383397877789, 1.008610948974598, 1.0088385514204294,
|
||||
1.0090662052268706, 1.0092939104055114, 1.0095216669679448, 1.0097494749257656,
|
||||
1.009977334290572, 1.0102052450739643, 1.0104332072875455, 1.0106612209429215,
|
||||
1.0108892860517005, 1.0111174026254934, 1.0113455706759138, 1.0115737902145781,
|
||||
1.0118020612531047, 1.0120303838031153, 1.0122587578762337, 1.012487183484087,
|
||||
1.0127156606383041, 1.0129441893505169, 1.0131727696323602, 1.0134014014954713,
|
||||
1.0136300849514894, 1.0138588200120575, 1.0140876066888203, 1.0143164449934257,
|
||||
1.0145453349375237, 1.0147742765327674, 1.0150032697908125, 1.0152323147233171,
|
||||
1.015461411341942, 1.0156905596583505, 1.0159197596842091, 1.0161490114311862,
|
||||
1.0163783149109531, 1.0166076701351838, 1.0168370771155553, 1.0170665358637463,
|
||||
1.0172960463914391, 1.0175256087103179, 1.0177552228320703, 1.0179848887683858,
|
||||
1.0182146065309567, 1.0184443761314785, 1.0186741975816487, 1.0189040708931674,
|
||||
1.0191339960777379, 1.0193639731470658, 1.0195940021128593, 1.0198240829868295,
|
||||
1.0200542157806898, 1.0202844005061564, 1.0205146371749483, 1.0207449257987866,
|
||||
1.0209752663893958, 1.0212056589585028, 1.0214361035178368, 1.0216666000791297,
|
||||
1.0218971486541166, 1.0221277492545349, 1.0223584018921241, 1.0225891065786274,
|
||||
1.0228198633257899, 1.0230506721453596, 1.023281533049087, 1.0235124460487257,
|
||||
1.0237434111560313, 1.0239744283827625, 1.0242054977406807, 1.0244366192415495,
|
||||
1.0246677928971357, 1.0248990187192082, 1.025130296719539, 1.0253616269099028,
|
||||
1.0255930093020766, 1.0258244439078401, 1.0260559307389761, 1.0262874698072693,
|
||||
1.0265190611245079, 1.0267507047024822, 1.0269824005529853, 1.027214148687813,
|
||||
1.0274459491187637, 1.0276778018576387, 1.0279097069162415, 1.0281416643063788,
|
||||
1.0283736740398595, 1.0286057361284953, 1.0288378505841009, 1.0290700174184932,
|
||||
1.0293022366434921, 1.0295345082709197, 1.0297668323126017, 1.0299992087803651,
|
||||
1.030231637686041, 1.0304641190414621, 1.0306966528584645, 1.0309292391488862,
|
||||
1.0311618779245688, 1.0313945691973556, 1.0316273129790936, 1.0318601092816313,
|
||||
1.0320929581168212, 1.0323258594965172, 1.0325588134325767, 1.0327918199368598,
|
||||
1.0330248790212284, 1.0332579906975481, 1.0334911549776868, 1.033724371873515,
|
||||
1.0339576413969056, 1.0341909635597348, 1.0344243383738811, 1.0346577658512259,
|
||||
1.034891246003653, 1.0351247788430489, 1.0353583643813031, 1.0355920026303078,
|
||||
1.0358256936019572, 1.0360594373081489, 1.0362932337607829, 1.0365270829717617,
|
||||
1.0367609849529913, 1.0369949397163791, 1.0372289472738365, 1.0374630076372766,
|
||||
1.0376971208186156, 1.0379312868297725, 1.0381655056826686, 1.0383997773892284,
|
||||
1.0386341019613787, 1.0388684794110492, 1.0391029097501721, 1.0393373929906822,
|
||||
1.0395719291445176, 1.0398065182236185, 1.0400411602399278, 1.0402758552053915,
|
||||
1.0405106031319582, 1.0407454040315787, 1.0409802579162071, 1.0412151647977996,
|
||||
1.0414501246883161, 1.0416851375997183, 1.0419202035439705, 1.0421553225330404,
|
||||
1.042390494578898, 1.042625719693516, 1.0428609978888699, 1.043096329176938,
|
||||
1.0433317135697009, 1.0435671510791424, 1.0438026417172486, 1.0440381854960086,
|
||||
1.0442737824274138, 1.044509432523459, 1.044745135796141, 1.0449808922574599,
|
||||
1.0452167019194181, 1.0454525647940205, 1.0456884808932754, 1.0459244502291931,
|
||||
1.0461604728137874, 1.0463965486590741, 1.046632677777072, 1.0468688601798024,
|
||||
1.0471050958792898, 1.047341384887561, 1.0475777272166455, 1.047814122878576,
|
||||
1.048050571885387, 1.0482870742491166, 1.0485236299818055, 1.0487602390954964,
|
||||
1.0489969016022356, 1.0492336175140715, 1.0494703868430555, 1.0497072096012419,
|
||||
1.0499440858006872, 1.0501810154534512, 1.050417998571596, 1.0506550351671864,
|
||||
1.0508921252522903, 1.0511292688389782, 1.0513664659393229, 1.0516037165654004,
|
||||
1.0518410207292894, 1.0520783784430709, 1.0523157897188296, 1.0525532545686513,
|
||||
1.0527907730046264, 1.0530283450388465, 1.0532659706834067, 1.0535036499504049,
|
||||
1.0537413828519411, 1.0539791694001188, 1.0542170096070436, 1.0544549034848243,
|
||||
1.0546928510455722, 1.0549308523014012, 1.0551689072644284, 1.0554070159467728,
|
||||
1.0556451783605572, 1.0558833945179062, 1.0561216644309479, 1.0563599881118126,
|
||||
1.0565983655726334, 1.0568367968255465, 1.0570752818826903, 1.0573138207562065,
|
||||
1.057552413458239, 1.0577910600009348, 1.0580297603964437, 1.058268514656918,
|
||||
1.0585073227945128, 1.0587461848213857, 1.058985100749698, 1.0592240705916123
|
||||
};
|
||||
|
||||
const double bend_coarse[128] = {
|
||||
1, 1.0594630943592953, 1.122462048309373, 1.189207115002721,
|
||||
1.2599210498948732, 1.3348398541700344, 1.4142135623730951, 1.4983070768766815,
|
||||
1.5874010519681994, 1.681792830507429, 1.7817974362806785, 1.8877486253633868,
|
||||
2, 2.1189261887185906, 2.244924096618746, 2.3784142300054421,
|
||||
2.5198420997897464, 2.6696797083400687, 2.8284271247461903, 2.996614153753363,
|
||||
3.1748021039363992, 3.363585661014858, 3.5635948725613571, 3.7754972507267741,
|
||||
4, 4.2378523774371812, 4.4898481932374912, 4.7568284600108841,
|
||||
5.0396841995794928, 5.3393594166801366, 5.6568542494923806, 5.993228307506727,
|
||||
6.3496042078727974, 6.727171322029716, 7.1271897451227151, 7.5509945014535473,
|
||||
8, 8.4757047548743625, 8.9796963864749824, 9.5136569200217682,
|
||||
10.079368399158986, 10.678718833360273, 11.313708498984761, 11.986456615013454,
|
||||
12.699208415745595, 13.454342644059432, 14.25437949024543, 15.101989002907095,
|
||||
16, 16.951409509748721, 17.959392772949972, 19.027313840043536,
|
||||
20.158736798317967, 21.357437666720553, 22.627416997969522, 23.972913230026901,
|
||||
25.398416831491197, 26.908685288118864, 28.508758980490853, 30.203978005814196,
|
||||
32, 33.902819019497443, 35.918785545899944, 38.054627680087073,
|
||||
40.317473596635935, 42.714875333441107, 45.254833995939045, 47.945826460053802,
|
||||
50.796833662982394, 53.817370576237728, 57.017517960981706, 60.407956011628393,
|
||||
64, 67.805638038994886, 71.837571091799887, 76.109255360174146,
|
||||
80.63494719327187, 85.429750666882214, 90.509667991878089, 95.891652920107603,
|
||||
101.59366732596479, 107.63474115247546, 114.03503592196341, 120.81591202325679,
|
||||
128, 135.61127607798977, 143.67514218359977, 152.21851072034829,
|
||||
161.26989438654374, 170.85950133376443, 181.01933598375618, 191.78330584021521,
|
||||
203.18733465192958, 215.26948230495091, 228.07007184392683, 241.63182404651357,
|
||||
256, 271.22255215597971, 287.35028436719938, 304.43702144069658,
|
||||
322.53978877308765, 341.71900266752868, 362.03867196751236, 383.56661168043064,
|
||||
406.37466930385892, 430.53896460990183, 456.14014368785394, 483.26364809302686,
|
||||
512, 542.44510431195943, 574.70056873439876, 608.87404288139317,
|
||||
645.0795775461753, 683.43800533505737, 724.07734393502471, 767.13322336086128,
|
||||
812.74933860771785, 861.07792921980365, 912.28028737570787, 966.52729618605372,
|
||||
1024, 1084.8902086239189, 1149.4011374687975, 1217.7480857627863,
|
||||
1290.1591550923506, 1366.8760106701147, 1448.1546878700494, 1534.2664467217226
|
||||
};
|
||||
30
project/jni/sdl_sound/decoders/timidity/tables.h
Normal file
30
project/jni/sdl_sound/decoders/timidity/tables.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
tables.h
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#define sine(x) (sin((2*PI/1024.0) * (x)))
|
||||
|
||||
#define SINE_CYCLE_LENGTH 1024
|
||||
extern const Sint32 freq_table[];
|
||||
extern const double vol_table[];
|
||||
extern const double bend_fine[];
|
||||
extern const double bend_coarse[];
|
||||
105
project/jni/sdl_sound/decoders/timidity/testmidi.c
Normal file
105
project/jni/sdl_sound/decoders/timidity/testmidi.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Program to test the TiMidity core, without having to worry about decoder
|
||||
* and/or playsound bugs. It's not meant to be robust or user-friendly.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "SDL.h"
|
||||
#include "timidity.h"
|
||||
|
||||
int done_flag = 0;
|
||||
MidiSong *song;
|
||||
|
||||
static void audio_callback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
if (Timidity_PlaySome(song, stream, len) == 0)
|
||||
done_flag = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_AudioSpec audio;
|
||||
SDL_RWops *rw;
|
||||
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
atexit(SDL_Quit);
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s midifile\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
audio.freq = 44100;
|
||||
audio.format = AUDIO_S16SYS;
|
||||
audio.channels = 2;
|
||||
audio.samples = 4096;
|
||||
audio.callback = audio_callback;
|
||||
|
||||
if (SDL_OpenAudio(&audio, NULL) < 0)
|
||||
{
|
||||
fprintf(stderr, "Couldn't open audio device. %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Timidity_Init() < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not initialise TiMidity.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rw = SDL_RWFromFile(argv[1], "rb");
|
||||
if (rw == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not create RWops from MIDI file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
song = Timidity_LoadSong(rw, &audio);
|
||||
SDL_RWclose(rw);
|
||||
|
||||
if (song == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not open MIDI file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Timidity_SetVolume(song, 100);
|
||||
Timidity_Start(song);
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
while (!done_flag)
|
||||
{
|
||||
SDL_Delay(10);
|
||||
}
|
||||
SDL_PauseAudio(1);
|
||||
Timidity_FreeSong(song);
|
||||
Timidity_Exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
602
project/jni/sdl_sound/decoders/timidity/timidity.c
Normal file
602
project/jni/sdl_sound/decoders/timidity/timidity.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
#include "timidity.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "instrum.h"
|
||||
#include "playmidi.h"
|
||||
#include "readmidi.h"
|
||||
#include "output.h"
|
||||
|
||||
#include "tables.h"
|
||||
|
||||
ToneBank *master_tonebank[128], *master_drumset[128];
|
||||
|
||||
static char def_instr_name[256] = "";
|
||||
|
||||
#define MAXWORDS 10
|
||||
|
||||
/* Quick-and-dirty fgets() replacement. */
|
||||
|
||||
static char *RWgets(SDL_RWops *rw, char *s, int size)
|
||||
{
|
||||
int num_read = 0;
|
||||
int newline = 0;
|
||||
|
||||
while (num_read < size && !newline)
|
||||
{
|
||||
if (SDL_RWread(rw, &s[num_read], 1, 1) != 1)
|
||||
break;
|
||||
|
||||
/* Unlike fgets(), don't store newline. Under Windows/DOS we'll
|
||||
* probably get an extra blank line for every line that's being
|
||||
* read, but that should be ok.
|
||||
*/
|
||||
if (s[num_read] == '\n' || s[num_read] == '\r')
|
||||
{
|
||||
s[num_read] = '\0';
|
||||
newline = 1;
|
||||
}
|
||||
|
||||
num_read++;
|
||||
}
|
||||
|
||||
s[num_read] = '\0';
|
||||
|
||||
return (num_read != 0) ? s : NULL;
|
||||
}
|
||||
|
||||
static int read_config_file(char *name)
|
||||
{
|
||||
SDL_RWops *rw;
|
||||
char tmp[1024], *w[MAXWORDS], *cp;
|
||||
ToneBank *bank=0;
|
||||
int i, j, k, line=0, words;
|
||||
static int rcf_count=0;
|
||||
|
||||
if (rcf_count>50)
|
||||
{
|
||||
SNDDBG(("Probable source loop in configuration files\n"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!(rw=open_file(name)))
|
||||
return -1;
|
||||
|
||||
while (RWgets(rw, tmp, sizeof(tmp)))
|
||||
{
|
||||
line++;
|
||||
w[words=0]=strtok(tmp, " \t\240");
|
||||
if (!w[0]) continue;
|
||||
|
||||
/* Originally the TiMidity++ extensions were prefixed like this */
|
||||
if (strcmp(w[0], "#extension") == 0)
|
||||
words = -1;
|
||||
else if (*w[0] == '#')
|
||||
continue;
|
||||
|
||||
while (w[words] && *w[words] != '#' && (words < MAXWORDS))
|
||||
w[++words]=strtok(0," \t\240");
|
||||
|
||||
/*
|
||||
* TiMidity++ adds a number of extensions to the config file format.
|
||||
* Many of them are completely irrelevant to SDL_sound, but at least
|
||||
* we shouldn't choke on them.
|
||||
*
|
||||
* Unfortunately the documentation for these extensions is often quite
|
||||
* vague, gramatically strange or completely absent.
|
||||
*/
|
||||
if (
|
||||
!strcmp(w[0], "comm") /* "comm" program second */
|
||||
|| !strcmp(w[0], "HTTPproxy") /* "HTTPproxy" hostname:port */
|
||||
|| !strcmp(w[0], "FTPproxy") /* "FTPproxy" hostname:port */
|
||||
|| !strcmp(w[0], "mailaddr") /* "mailaddr" your-mail-address */
|
||||
|| !strcmp(w[0], "opt") /* "opt" timidity-options */
|
||||
)
|
||||
{
|
||||
/*
|
||||
* + "comm" sets some kind of comment -- the documentation is too
|
||||
* vague for me to understand at this time.
|
||||
* + "HTTPproxy", "FTPproxy" and "mailaddr" are for reading data
|
||||
* over a network, rather than from the file system.
|
||||
* + "opt" specifies default options for TiMidity++.
|
||||
*
|
||||
* These are all quite useless for our version of TiMidity, so
|
||||
* they can safely remain no-ops.
|
||||
*/
|
||||
} else if (!strcmp(w[0], "timeout")) /* "timeout" program second */
|
||||
{
|
||||
/*
|
||||
* Specifies a timeout value of the program. A number of seconds
|
||||
* before TiMidity kills the note. This may be useful to implement
|
||||
* later, but I don't see any urgent need for it.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"timeout\" in TiMidity config.\n"));
|
||||
} else if (!strcmp(w[0], "copydrumset") /* "copydrumset" drumset */
|
||||
|| !strcmp(w[0], "copybank")) /* "copybank" bank */
|
||||
{
|
||||
/*
|
||||
* Copies all the settings of the specified drumset or bank to
|
||||
* the current drumset or bank. May be useful later, but not a
|
||||
* high priority.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"%s\" in TiMidity config.\n", w[0]));
|
||||
} else if (!strcmp(w[0], "undef")) /* "undef" progno */
|
||||
{
|
||||
/*
|
||||
* Undefines the tone "progno" of the current tone bank (or
|
||||
* drum set?). Not a high priority.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"undef\" in TiMidity config.\n"));
|
||||
} else if (!strcmp(w[0], "altassign")) /* "altassign" prog1 prog2 ... */
|
||||
{
|
||||
/*
|
||||
* Sets the alternate assign for drum set. Whatever that's
|
||||
* supposed to mean.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"altassign\" in TiMidity config.\n"));
|
||||
} else if (!strcmp(w[0], "soundfont")
|
||||
|| !strcmp(w[0], "font"))
|
||||
{
|
||||
/*
|
||||
* I can't find any documentation for these, but I guess they're
|
||||
* an alternative way of loading/unloading instruments.
|
||||
*
|
||||
* "soundfont" sf_file "remove"
|
||||
* "soundfont" sf_file ["order=" order] ["cutoff=" cutoff]
|
||||
* ["reso=" reso] ["amp=" amp]
|
||||
* "font" "exclude" bank preset keynote
|
||||
* "font" "order" order bank preset keynote
|
||||
*/
|
||||
SNDDBG(("FIXME: Implmement \"%s\" in TiMidity config.\n", w[0]));
|
||||
} else if (!strcmp(w[0], "progbase"))
|
||||
{
|
||||
/*
|
||||
* The documentation for this makes absolutely no sense to me, but
|
||||
* apparently it sets some sort of base offset for tone numbers.
|
||||
* Why anyone would want to do this is beyond me.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"progbase\" in TiMidity config.\n"));
|
||||
} else if (!strcmp(w[0], "map")) /* "map" name set1 elem1 set2 elem2 */
|
||||
{
|
||||
/*
|
||||
* This extension is the one we will need to implement, as it is
|
||||
* used by the "eawpats". Unfortunately I cannot find any
|
||||
* documentation whatsoever for it, but it looks like it's used
|
||||
* for remapping one instrument to another somehow.
|
||||
*/
|
||||
SNDDBG(("FIXME: Implement \"map\" in TiMidity config.\n"));
|
||||
}
|
||||
|
||||
/* Standard TiMidity config */
|
||||
|
||||
else if (!strcmp(w[0], "dir"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
SNDDBG(("%s: line %d: No directory given\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
for (i=1; i<words; i++)
|
||||
add_to_pathlist(w[i]);
|
||||
}
|
||||
else if (!strcmp(w[0], "source"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
SNDDBG(("%s: line %d: No file name given\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
for (i=1; i<words; i++)
|
||||
{
|
||||
rcf_count++;
|
||||
read_config_file(w[i]);
|
||||
rcf_count--;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(w[0], "default"))
|
||||
{
|
||||
if (words != 2)
|
||||
{
|
||||
SNDDBG(("%s: line %d: Must specify exactly one patch name\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
strncpy(def_instr_name, w[1], 255);
|
||||
def_instr_name[255]='\0';
|
||||
}
|
||||
else if (!strcmp(w[0], "drumset"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
SNDDBG(("%s: line %d: No drum set number given\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[1]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
SNDDBG(("%s: line %d: Drum set must be between 0 and 127\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
if (!master_drumset[i])
|
||||
{
|
||||
master_drumset[i] = safe_malloc(sizeof(ToneBank));
|
||||
memset(master_drumset[i], 0, sizeof(ToneBank));
|
||||
master_drumset[i]->tone = safe_malloc(128 * sizeof(ToneBankElement));
|
||||
memset(master_drumset[i]->tone, 0, 128 * sizeof(ToneBankElement));
|
||||
}
|
||||
bank=master_drumset[i];
|
||||
}
|
||||
else if (!strcmp(w[0], "bank"))
|
||||
{
|
||||
if (words < 2)
|
||||
{
|
||||
SNDDBG(("%s: line %d: No bank number given\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[1]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
SNDDBG(("%s: line %d: Tone bank must be between 0 and 127\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
if (!master_tonebank[i])
|
||||
{
|
||||
master_tonebank[i] = safe_malloc(sizeof(ToneBank));
|
||||
memset(master_tonebank[i], 0, sizeof(ToneBank));
|
||||
master_tonebank[i]->tone = safe_malloc(128 * sizeof(ToneBankElement));
|
||||
memset(master_tonebank[i]->tone, 0, 128 * sizeof(ToneBankElement));
|
||||
}
|
||||
bank=master_tonebank[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
|
||||
{
|
||||
SNDDBG(("%s: line %d: syntax error\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
i=atoi(w[0]);
|
||||
if (i<0 || i>127)
|
||||
{
|
||||
SNDDBG(("%s: line %d: Program must be between 0 and 127\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
if (!bank)
|
||||
{
|
||||
SNDDBG(("%s: line %d: Must specify tone bank or drum set before assignment\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
if (bank->tone[i].name)
|
||||
free(bank->tone[i].name);
|
||||
strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
|
||||
bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
|
||||
bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
|
||||
bank->tone[i].strip_tail=-1;
|
||||
|
||||
for (j=2; j<words; j++)
|
||||
{
|
||||
if (!(cp=strchr(w[j], '=')))
|
||||
{
|
||||
SNDDBG(("%s: line %d: bad patch option %s\n", name, line, w[j]));
|
||||
return -2;
|
||||
}
|
||||
*cp++=0;
|
||||
if (!strcmp(w[j], "amp"))
|
||||
{
|
||||
k=atoi(cp);
|
||||
if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
|
||||
{
|
||||
SNDDBG(("%s: line %d: amplification must be between 0 and %d\n",
|
||||
name, line, MAX_AMPLIFICATION));
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].amp=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "note"))
|
||||
{
|
||||
k=atoi(cp);
|
||||
if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
|
||||
{
|
||||
SNDDBG(("%s: line %d: note must be between 0 and 127\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].note=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "pan"))
|
||||
{
|
||||
if (!strcmp(cp, "center"))
|
||||
k=64;
|
||||
else if (!strcmp(cp, "left"))
|
||||
k=0;
|
||||
else if (!strcmp(cp, "right"))
|
||||
k=127;
|
||||
else
|
||||
k=((atoi(cp)+100) * 100) / 157;
|
||||
if ((k<0 || k>127) || (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
|
||||
{
|
||||
SNDDBG(("%s: line %d: panning must be left, right, center, or between -100 and 100\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
bank->tone[i].pan=k;
|
||||
}
|
||||
else if (!strcmp(w[j], "keep"))
|
||||
{
|
||||
if (!strcmp(cp, "env"))
|
||||
bank->tone[i].strip_envelope=0;
|
||||
else if (!strcmp(cp, "loop"))
|
||||
bank->tone[i].strip_loop=0;
|
||||
else
|
||||
{
|
||||
SNDDBG(("%s: line %d: keep must be env or loop\n", name, line));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(w[j], "strip"))
|
||||
{
|
||||
if (!strcmp(cp, "env"))
|
||||
bank->tone[i].strip_envelope=1;
|
||||
else if (!strcmp(cp, "loop"))
|
||||
bank->tone[i].strip_loop=1;
|
||||
else if (!strcmp(cp, "tail"))
|
||||
bank->tone[i].strip_tail=1;
|
||||
else
|
||||
{
|
||||
SNDDBG(("%s: line %d: strip must be env, loop, or tail\n",
|
||||
name, line));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SNDDBG(("%s: line %d: bad patch option %s\n", name, line, w[j]));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_RWclose(rw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Timidity_Init_NoConfig()
|
||||
{
|
||||
/* Allocate memory for the standard tonebank and drumset */
|
||||
master_tonebank[0] = safe_malloc(sizeof(ToneBank));
|
||||
memset(master_tonebank[0], 0, sizeof(ToneBank));
|
||||
master_tonebank[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
|
||||
memset(master_tonebank[0]->tone, 0, 128 * sizeof(ToneBankElement));
|
||||
|
||||
master_drumset[0] = safe_malloc(sizeof(ToneBank));
|
||||
memset(master_drumset[0], 0, sizeof(ToneBank));
|
||||
master_drumset[0]->tone = safe_malloc(128 * sizeof(ToneBankElement));
|
||||
memset(master_drumset[0]->tone, 0, 128 * sizeof(ToneBankElement));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Timidity_Init()
|
||||
{
|
||||
/* !!! FIXME: This may be ugly, but slightly less so than requiring the
|
||||
* default search path to have only one element. I think.
|
||||
*
|
||||
* We only need to include the likely locations for the config
|
||||
* file itself since that file should contain any other directory
|
||||
* that needs to be added to the search path.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
add_to_pathlist("\\TIMIDITY");
|
||||
#else
|
||||
add_to_pathlist("/usr/local/lib/timidity");
|
||||
add_to_pathlist("/etc");
|
||||
#endif
|
||||
|
||||
Timidity_Init_NoConfig();
|
||||
|
||||
return read_config_file(CONFIG_FILE);
|
||||
}
|
||||
|
||||
MidiSong *Timidity_LoadDLSSong(SDL_RWops *rw, DLS_Patches *patches, SDL_AudioSpec *audio)
|
||||
{
|
||||
MidiSong *song;
|
||||
Sint32 events;
|
||||
int i;
|
||||
|
||||
if (rw == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate memory for the song */
|
||||
song = (MidiSong *)safe_malloc(sizeof(*song));
|
||||
memset(song, 0, sizeof(*song));
|
||||
song->patches = patches;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (master_tonebank[i])
|
||||
{
|
||||
song->tonebank[i] = safe_malloc(sizeof(ToneBank));
|
||||
memset(song->tonebank[i], 0, sizeof(ToneBank));
|
||||
song->tonebank[i]->tone = master_tonebank[i]->tone;
|
||||
}
|
||||
if (master_drumset[i])
|
||||
{
|
||||
song->drumset[i] = safe_malloc(sizeof(ToneBank));
|
||||
memset(song->drumset[i], 0, sizeof(ToneBank));
|
||||
song->drumset[i]->tone = master_drumset[i]->tone;
|
||||
}
|
||||
}
|
||||
|
||||
song->amplification = DEFAULT_AMPLIFICATION;
|
||||
song->voices = DEFAULT_VOICES;
|
||||
song->drumchannels = DEFAULT_DRUMCHANNELS;
|
||||
|
||||
song->rw = rw;
|
||||
|
||||
song->rate = audio->freq;
|
||||
song->encoding = 0;
|
||||
if ((audio->format & 0xFF) == 16)
|
||||
song->encoding |= PE_16BIT;
|
||||
if (audio->format & 0x8000)
|
||||
song->encoding |= PE_SIGNED;
|
||||
if (audio->channels == 1)
|
||||
song->encoding |= PE_MONO;
|
||||
switch (audio->format) {
|
||||
case AUDIO_S8:
|
||||
song->write = s32tos8;
|
||||
break;
|
||||
case AUDIO_U8:
|
||||
song->write = s32tou8;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
song->write = s32tos16l;
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
song->write = s32tos16b;
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
song->write = s32tou16l;
|
||||
break;
|
||||
default:
|
||||
SNDDBG(("Unsupported audio format"));
|
||||
song->write = s32tou16l;
|
||||
break;
|
||||
}
|
||||
|
||||
song->buffer_size = audio->samples;
|
||||
song->resample_buffer = safe_malloc(audio->samples * sizeof(sample_t));
|
||||
song->common_buffer = safe_malloc(audio->samples * 2 * sizeof(Sint32));
|
||||
|
||||
song->control_ratio = audio->freq / CONTROLS_PER_SECOND;
|
||||
if (song->control_ratio < 1)
|
||||
song->control_ratio = 1;
|
||||
else if (song->control_ratio > MAX_CONTROL_RATIO)
|
||||
song->control_ratio = MAX_CONTROL_RATIO;
|
||||
|
||||
song->lost_notes = 0;
|
||||
song->cut_notes = 0;
|
||||
|
||||
song->events = read_midi_file(song, &events, &song->samples);
|
||||
|
||||
/* The RWops can safely be closed at this point, but let's make that the
|
||||
* responsibility of the caller.
|
||||
*/
|
||||
|
||||
/* Make sure everything is okay */
|
||||
if (!song->events) {
|
||||
free(song);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
song->default_instrument = 0;
|
||||
song->default_program = DEFAULT_PROGRAM;
|
||||
|
||||
if (*def_instr_name)
|
||||
set_default_instrument(song, def_instr_name);
|
||||
|
||||
load_missing_instruments(song);
|
||||
|
||||
return(song);
|
||||
}
|
||||
|
||||
MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio)
|
||||
{
|
||||
return Timidity_LoadDLSSong(rw, NULL, audio);
|
||||
}
|
||||
|
||||
void Timidity_FreeSong(MidiSong *song)
|
||||
{
|
||||
int i;
|
||||
|
||||
free_instruments(song);
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (song->tonebank[i])
|
||||
free(song->tonebank[i]);
|
||||
if (song->drumset[i])
|
||||
free(song->drumset[i]);
|
||||
}
|
||||
|
||||
free(song->common_buffer);
|
||||
free(song->resample_buffer);
|
||||
free(song->events);
|
||||
free(song);
|
||||
}
|
||||
|
||||
void Timidity_Exit(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (master_tonebank[i])
|
||||
{
|
||||
ToneBankElement *e = master_tonebank[i]->tone;
|
||||
if (e != NULL)
|
||||
{
|
||||
for (j = 0; j < 128; j++)
|
||||
{
|
||||
if (e[j].name != NULL)
|
||||
free(e[j].name);
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
free(master_tonebank[i]);
|
||||
}
|
||||
if (master_drumset[i])
|
||||
{
|
||||
ToneBankElement *e = master_drumset[i]->tone;
|
||||
if (e != NULL)
|
||||
{
|
||||
for (j = 0; j < 128; j++)
|
||||
{
|
||||
if (e[j].name != NULL)
|
||||
free(e[j].name);
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
free(master_drumset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free_pathlist();
|
||||
}
|
||||
176
project/jni/sdl_sound/decoders/timidity/timidity.h
Normal file
176
project/jni/sdl_sound/decoders/timidity/timidity.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
|
||||
TiMidity -- Experimental MIDI to WAVE converter
|
||||
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TIMIDITY_H
|
||||
#define TIMIDITY_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef Sint16 sample_t;
|
||||
typedef Sint32 final_volume_t;
|
||||
|
||||
#define VIBRATO_SAMPLE_INCREMENTS 32
|
||||
|
||||
/* Maximum polyphony. */
|
||||
#define MAX_VOICES 48
|
||||
|
||||
typedef struct {
|
||||
Sint32
|
||||
loop_start, loop_end, data_length,
|
||||
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
|
||||
Sint32
|
||||
envelope_rate[6], envelope_offset[6];
|
||||
float
|
||||
volume;
|
||||
sample_t *data;
|
||||
Sint32
|
||||
tremolo_sweep_increment, tremolo_phase_increment,
|
||||
vibrato_sweep_increment, vibrato_control_ratio;
|
||||
Uint8
|
||||
tremolo_depth, vibrato_depth,
|
||||
modes;
|
||||
Sint8
|
||||
panning, note_to_use;
|
||||
} Sample;
|
||||
|
||||
typedef struct {
|
||||
int
|
||||
bank, program, volume, sustain, panning, pitchbend, expression,
|
||||
mono, /* one note only on this channel -- not implemented yet */
|
||||
pitchsens;
|
||||
/* chorus, reverb... Coming soon to a 300-MHz, eight-way superscalar
|
||||
processor near you */
|
||||
float
|
||||
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||
} Channel;
|
||||
|
||||
typedef struct {
|
||||
Uint8
|
||||
status, channel, note, velocity;
|
||||
Sample *sample;
|
||||
Sint32
|
||||
orig_frequency, frequency,
|
||||
sample_offset, sample_increment,
|
||||
envelope_volume, envelope_target, envelope_increment,
|
||||
tremolo_sweep, tremolo_sweep_position,
|
||||
tremolo_phase, tremolo_phase_increment,
|
||||
vibrato_sweep, vibrato_sweep_position;
|
||||
|
||||
final_volume_t left_mix, right_mix;
|
||||
|
||||
float
|
||||
left_amp, right_amp, tremolo_volume;
|
||||
Sint32
|
||||
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
||||
int
|
||||
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
||||
envelope_stage, control_counter, panning, panned;
|
||||
|
||||
} Voice;
|
||||
|
||||
typedef struct {
|
||||
int samples;
|
||||
Sample *sample;
|
||||
} Instrument;
|
||||
|
||||
/* Shared data */
|
||||
typedef struct {
|
||||
char *name;
|
||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
||||
} ToneBankElement;
|
||||
|
||||
typedef struct {
|
||||
ToneBankElement *tone;
|
||||
Instrument *instrument[128];
|
||||
} ToneBank;
|
||||
|
||||
typedef struct {
|
||||
Sint32 time;
|
||||
Uint8 channel, type, a, b;
|
||||
} MidiEvent;
|
||||
|
||||
typedef struct {
|
||||
MidiEvent event;
|
||||
void *next;
|
||||
} MidiEventList;
|
||||
|
||||
struct _DLS_Data;
|
||||
typedef struct _DLS_Data DLS_Patches;
|
||||
|
||||
typedef struct {
|
||||
int playing;
|
||||
SDL_RWops *rw;
|
||||
Sint32 rate;
|
||||
Sint32 encoding;
|
||||
float master_volume;
|
||||
Sint32 amplification;
|
||||
DLS_Patches *patches;
|
||||
ToneBank *tonebank[128];
|
||||
ToneBank *drumset[128];
|
||||
Instrument *default_instrument;
|
||||
int default_program;
|
||||
void (*write)(void *dp, Sint32 *lp, Sint32 c);
|
||||
int buffer_size;
|
||||
sample_t *resample_buffer;
|
||||
Sint32 *common_buffer;
|
||||
Sint32 *buffer_pointer;
|
||||
/* These would both fit into 32 bits, but they are often added in
|
||||
large multiples, so it's simpler to have two roomy ints */
|
||||
/* samples per MIDI delta-t */
|
||||
Sint32 sample_increment;
|
||||
Sint32 sample_correction;
|
||||
Channel channel[16];
|
||||
Voice voice[MAX_VOICES];
|
||||
int voices;
|
||||
Sint32 drumchannels;
|
||||
Sint32 buffered_count;
|
||||
Sint32 control_ratio;
|
||||
Sint32 lost_notes;
|
||||
Sint32 cut_notes;
|
||||
Sint32 samples;
|
||||
MidiEvent *events;
|
||||
MidiEvent *current_event;
|
||||
MidiEventList *evlist;
|
||||
Sint32 current_sample;
|
||||
Sint32 event_count;
|
||||
Sint32 at;
|
||||
} MidiSong;
|
||||
|
||||
/* Some of these are not defined in timidity.c but are here for convenience */
|
||||
|
||||
extern int Timidity_Init(void);
|
||||
extern int Timidity_Init_NoConfig(void);
|
||||
extern void Timidity_SetVolume(MidiSong *song, int volume);
|
||||
extern int Timidity_PlaySome(MidiSong *song, void *stream, Sint32 len);
|
||||
extern DLS_Patches *Timidity_LoadDLS(SDL_RWops *rw);
|
||||
extern void Timidity_FreeDLS(DLS_Patches *patches);
|
||||
extern MidiSong *Timidity_LoadDLSSong(SDL_RWops *rw, DLS_Patches *patches, SDL_AudioSpec *audio);
|
||||
extern MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio);
|
||||
extern void Timidity_Start(MidiSong *song);
|
||||
extern void Timidity_Seek(MidiSong *song, Uint32 ms);
|
||||
extern void Timidity_FreeSong(MidiSong *song);
|
||||
extern void Timidity_Exit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* TIMIDITY_H */
|
||||
569
project/jni/sdl_sound/decoders/voc.c
Normal file
569
project/jni/sdl_sound/decoders/voc.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* VOC decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles Creative Labs VOC audio data...this is a legacy format,
|
||||
* but there's some game ports that could make use of such a decoder. Plus,
|
||||
* VOC is fairly straightforward to decode, so this is a more complex, but
|
||||
* still palatable example of an SDL_sound decoder. Y'know, in case the
|
||||
* RAW decoder didn't do it for you. :)
|
||||
*
|
||||
* This code was ripped from a decoder I had written for SDL_mixer, which was
|
||||
* largely ripped from sox v12.17.1's voc.c.
|
||||
*
|
||||
* SDL_mixer: http://www.libsdl.org/projects/SDL_mixer/
|
||||
* sox: http://www.freshmeat.net/projects/sox/
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_VOC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int VOC_init(void);
|
||||
static void VOC_quit(void);
|
||||
static int VOC_open(Sound_Sample *sample, const char *ext);
|
||||
static void VOC_close(Sound_Sample *sample);
|
||||
static Uint32 VOC_read(Sound_Sample *sample);
|
||||
static int VOC_rewind(Sound_Sample *sample);
|
||||
static int VOC_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_voc[] = { "VOC", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC =
|
||||
{
|
||||
{
|
||||
extensions_voc,
|
||||
"Creative Labs Voice format",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
VOC_init, /* init() method */
|
||||
VOC_quit, /* quit() method */
|
||||
VOC_open, /* open() method */
|
||||
VOC_close, /* close() method */
|
||||
VOC_read, /* read() method */
|
||||
VOC_rewind, /* rewind() method */
|
||||
VOC_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
/* 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 extended; /* Has an extended block been read? */
|
||||
Uint32 bufpos; /* byte position in internal->buffer. */
|
||||
Uint32 start_pos; /* offset to seek to in stream when rewinding. */
|
||||
int error; /* error condition (as opposed to EOF). */
|
||||
} 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_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* VOC_init */
|
||||
|
||||
|
||||
static void VOC_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* VOC_quit */
|
||||
|
||||
|
||||
static __inline__ int voc_readbytes(SDL_RWops *src, vs_t *v, void *p, int size)
|
||||
{
|
||||
if (SDL_RWread(src, p, size, 1) != 1)
|
||||
{
|
||||
v->error = 1;
|
||||
BAIL_MACRO("VOC: i/o error", 0);
|
||||
} /* if */
|
||||
|
||||
return(1);
|
||||
} /* voc_readbytes */
|
||||
|
||||
|
||||
static __inline__ int voc_check_header(SDL_RWops *src)
|
||||
{
|
||||
/* VOC magic header */
|
||||
Uint8 signature[20]; /* "Creative Voice File\032" */
|
||||
Uint16 datablockofs;
|
||||
vs_t v; /* dummy struct for voc_readbytes */
|
||||
|
||||
if (!voc_readbytes(src, &v, signature, sizeof (signature)))
|
||||
return(0);
|
||||
|
||||
if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0)
|
||||
{
|
||||
BAIL_MACRO("VOC: Wrong signature; not a VOC file.", 0);
|
||||
} /* if */
|
||||
|
||||
/* get the offset where the first datablock is located */
|
||||
if (!voc_readbytes(src, &v, &datablockofs, sizeof (Uint16)))
|
||||
return(0);
|
||||
|
||||
datablockofs = SDL_SwapLE16(datablockofs);
|
||||
|
||||
if (SDL_RWseek(src, datablockofs, SEEK_SET) != datablockofs)
|
||||
{
|
||||
BAIL_MACRO("VOC: Failed to seek to data block.", 0);
|
||||
} /* if */
|
||||
|
||||
return(1); /* success! */
|
||||
} /* voc_check_header */
|
||||
|
||||
|
||||
/* Read next block header, save info, leave position at start of data */
|
||||
static int voc_get_block(Sound_Sample *sample, vs_t *v)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *src = internal->rw;
|
||||
Uint8 bits24[3];
|
||||
Uint8 uc, block;
|
||||
Uint32 sblen;
|
||||
Uint16 new_rate_short;
|
||||
Uint32 new_rate_long;
|
||||
Uint8 trash[6];
|
||||
Uint16 period;
|
||||
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 (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return 0;
|
||||
|
||||
/* When DATA block preceeded by an EXTENDED */
|
||||
/* block, the DATA blocks rate value is invalid */
|
||||
if (!v->extended)
|
||||
{
|
||||
BAIL_IF_MACRO(uc == 0, "VOC: Sample rate is zero?", 0);
|
||||
|
||||
if ((v->rate != -1) && (uc != v->rate))
|
||||
BAIL_MACRO("VOC sample rate codes differ", 0);
|
||||
|
||||
v->rate = uc;
|
||||
v->channels = 1;
|
||||
sample->actual.rate = 1000000.0/(256 - v->rate);
|
||||
sample->actual.channels = 1;
|
||||
} /* if */
|
||||
|
||||
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return(0);
|
||||
|
||||
BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0);
|
||||
|
||||
v->extended = 0;
|
||||
v->rest = sblen - 2;
|
||||
v->size = ST_SIZE_BYTE;
|
||||
return 1;
|
||||
|
||||
case VOC_DATA_16:
|
||||
if (!voc_readbytes(src, v, &new_rate_long, sizeof (Uint32)))
|
||||
return 0;
|
||||
|
||||
new_rate_long = SDL_SwapLE32(new_rate_long);
|
||||
BAIL_IF_MACRO(!new_rate_long, "VOC: Sample rate is zero?", 0);
|
||||
|
||||
if ((v->rate != -1) && (new_rate_long != v->rate))
|
||||
BAIL_MACRO("VOC: sample rate codes differ", 0);
|
||||
|
||||
v->rate = new_rate_long;
|
||||
sample->actual.rate = new_rate_long;
|
||||
|
||||
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return 0;
|
||||
|
||||
switch (uc)
|
||||
{
|
||||
case 8: v->size = ST_SIZE_BYTE; break;
|
||||
case 16: v->size = ST_SIZE_WORD; break;
|
||||
default:
|
||||
BAIL_MACRO("VOC: unknown data size", 0);
|
||||
} /* switch */
|
||||
|
||||
if (!voc_readbytes(src, v, &v->channels, sizeof (Uint8)))
|
||||
return 0;
|
||||
|
||||
if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 6))
|
||||
return 0;
|
||||
|
||||
v->rest = sblen - 12;
|
||||
return 1;
|
||||
|
||||
case VOC_CONT:
|
||||
v->rest = sblen;
|
||||
return 1;
|
||||
|
||||
case VOC_SILENCE:
|
||||
if (!voc_readbytes(src, v, &period, sizeof (period)))
|
||||
return 0;
|
||||
|
||||
period = SDL_SwapLE16(period);
|
||||
|
||||
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return 0;
|
||||
|
||||
BAIL_IF_MACRO(uc == 0, "VOC: silence sample rate is zero", 0);
|
||||
|
||||
/*
|
||||
* Some silence-packed files have gratuitously
|
||||
* different sample rate codes in silence.
|
||||
* Adjust period.
|
||||
*/
|
||||
if ((v->rate != -1) && (uc != v->rate))
|
||||
period = (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 (!voc_readbytes(src, v, trash, sizeof (Uint8)))
|
||||
return 0;
|
||||
} /* for */
|
||||
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->extended = 1;
|
||||
if (!voc_readbytes(src, v, &new_rate_short, sizeof (Uint16)))
|
||||
return 0;
|
||||
|
||||
new_rate_short = SDL_SwapLE16(new_rate_short);
|
||||
BAIL_IF_MACRO(!new_rate_short, "VOC: sample rate is zero", 0);
|
||||
|
||||
if ((v->rate != -1) && (new_rate_short != v->rate))
|
||||
BAIL_MACRO("VOC: sample rate codes differ", 0);
|
||||
|
||||
v->rate = new_rate_short;
|
||||
|
||||
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return 0;
|
||||
|
||||
BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0);
|
||||
|
||||
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
|
||||
return 0;
|
||||
|
||||
if (uc)
|
||||
sample->actual.channels = 2; /* Stereo */
|
||||
|
||||
/* Needed number of channels before finishing
|
||||
compute for rate */
|
||||
sample->actual.rate =
|
||||
(256000000L/(65536L - v->rate)) / sample->actual.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 (!voc_readbytes(src, v, trash, sizeof (Uint8) * 2))
|
||||
return 0;
|
||||
|
||||
/* Falling! Falling! */
|
||||
|
||||
default: /* text block or other krapola. */
|
||||
for(i = 0; i < sblen; i++) /* skip repeat loops. */
|
||||
{
|
||||
if (!voc_readbytes(src, v, trash, sizeof (Uint8)))
|
||||
return 0;
|
||||
} /* for */
|
||||
|
||||
if (block == VOC_TEXT)
|
||||
continue; /* get next block */
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
return 1;
|
||||
} /* voc_get_block */
|
||||
|
||||
|
||||
static int voc_read_waveform(Sound_Sample *sample, int fill_buf, Uint32 max)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *src = internal->rw;
|
||||
vs_t *v = (vs_t *) internal->decoder_private;
|
||||
int done = 0;
|
||||
Uint8 silence = 0x80;
|
||||
Uint8 *buf = internal->buffer;
|
||||
|
||||
if (v->rest == 0)
|
||||
{
|
||||
if (!voc_get_block(sample, v))
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
if (v->rest == 0)
|
||||
return 0;
|
||||
|
||||
max = (v->rest < max) ? v->rest : max;
|
||||
|
||||
if (v->silent)
|
||||
{
|
||||
if (v->size == ST_SIZE_WORD)
|
||||
silence = 0x00;
|
||||
|
||||
/* Fill in silence */
|
||||
if (fill_buf)
|
||||
memset(buf + v->bufpos, silence, max);
|
||||
|
||||
done = max;
|
||||
v->rest -= done;
|
||||
} /* if */
|
||||
|
||||
else
|
||||
{
|
||||
if (fill_buf)
|
||||
{
|
||||
done = SDL_RWread(src, buf + v->bufpos, 1, max);
|
||||
if (done < max)
|
||||
{
|
||||
__Sound_SetError("VOC: i/o error");
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
else
|
||||
{
|
||||
int cur, rc;
|
||||
cur = SDL_RWtell(src);
|
||||
if (cur >= 0)
|
||||
{
|
||||
rc = SDL_RWseek(src, max, SEEK_CUR);
|
||||
if (rc >= 0)
|
||||
done = rc - cur;
|
||||
else
|
||||
{
|
||||
__Sound_SetError("VOC: seek error");
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
} /* else */
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
v->rest -= done;
|
||||
v->bufpos += done;
|
||||
} /* else */
|
||||
|
||||
return(done);
|
||||
} /* voc_read_waveform */
|
||||
|
||||
|
||||
static int VOC_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
vs_t *v = NULL;
|
||||
|
||||
if (!voc_check_header(internal->rw))
|
||||
return(0);
|
||||
|
||||
v = (vs_t *) malloc(sizeof (vs_t));
|
||||
BAIL_IF_MACRO(v == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(v, '\0', sizeof (vs_t));
|
||||
|
||||
v->start_pos = SDL_RWtell(internal->rw);
|
||||
v->rate = -1;
|
||||
if (!voc_get_block(sample, v))
|
||||
{
|
||||
free(v);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (v->rate == -1)
|
||||
{
|
||||
free(v);
|
||||
BAIL_MACRO("VOC: data had no sound!", 0);
|
||||
} /* if */
|
||||
|
||||
SNDDBG(("VOC: Accepting data stream.\n"));
|
||||
sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8;
|
||||
sample->actual.channels = v->channels;
|
||||
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
|
||||
internal->decoder_private = v;
|
||||
return(1);
|
||||
} /* VOC_open */
|
||||
|
||||
|
||||
static void VOC_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
free(internal->decoder_private);
|
||||
} /* VOC_close */
|
||||
|
||||
|
||||
static Uint32 VOC_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
vs_t *v = (vs_t *) internal->decoder_private;
|
||||
|
||||
v->bufpos = 0;
|
||||
while (v->bufpos < internal->buffer_size)
|
||||
{
|
||||
Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size);
|
||||
if (rc == 0)
|
||||
{
|
||||
sample->flags |= (v->error) ?
|
||||
SOUND_SAMPLEFLAG_ERROR :
|
||||
SOUND_SAMPLEFLAG_EOF;
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
if (!voc_get_block(sample, v))
|
||||
{
|
||||
sample->flags |= (v->error) ?
|
||||
SOUND_SAMPLEFLAG_ERROR :
|
||||
SOUND_SAMPLEFLAG_EOF;
|
||||
break;
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
return(v->bufpos);
|
||||
} /* VOC_read */
|
||||
|
||||
|
||||
static int VOC_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
vs_t *v = (vs_t *) internal->decoder_private;
|
||||
int rc = SDL_RWseek(internal->rw, v->start_pos, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != v->start_pos, ERR_IO_ERROR, 0);
|
||||
v->rest = 0;
|
||||
return(1);
|
||||
} /* VOC_rewind */
|
||||
|
||||
|
||||
static int VOC_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
/*
|
||||
* VOCs don't lend themselves well to seeking, since you have to
|
||||
* parse each section, which is an arbitrary size. The best we can do
|
||||
* is rewind, set a flag saying not to write the waveforms to a buffer,
|
||||
* and decode to the point that we want. Ugh. Fortunately, there's
|
||||
* really no such thing as a large VOC, due to the era and hardware that
|
||||
* spawned them, so even though this is inefficient, this is still a
|
||||
* relatively fast operation in most cases.
|
||||
*/
|
||||
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
vs_t *v = (vs_t *) internal->decoder_private;
|
||||
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int origpos = SDL_RWtell(internal->rw);
|
||||
int origrest = v->rest;
|
||||
|
||||
BAIL_IF_MACRO(!VOC_rewind(sample), NULL, 0);
|
||||
|
||||
v->bufpos = 0;
|
||||
|
||||
while (offset > 0)
|
||||
{
|
||||
Uint32 rc = voc_read_waveform(sample, 0, offset);
|
||||
if ( (rc == 0) || (!voc_get_block(sample, v)) )
|
||||
{
|
||||
SDL_RWseek(internal->rw, origpos, SEEK_SET);
|
||||
v->rest = origrest;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
offset -= rc;
|
||||
} /* while */
|
||||
|
||||
return(1);
|
||||
} /* VOC_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_VOC */
|
||||
|
||||
/* end of voc.c ... */
|
||||
800
project/jni/sdl_sound/decoders/wav.c
Normal file
800
project/jni/sdl_sound/decoders/wav.c
Normal file
@@ -0,0 +1,800 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* WAV decoder for SDL_sound.
|
||||
*
|
||||
* This driver handles Microsoft .WAVs, in as many of the thousands of
|
||||
* variations as we can.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_SUPPORTS_WAV
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_sound.h"
|
||||
|
||||
#define __SDL_SOUND_INTERNAL__
|
||||
#include "SDL_sound_internal.h"
|
||||
|
||||
static int WAV_init(void);
|
||||
static void WAV_quit(void);
|
||||
static int WAV_open(Sound_Sample *sample, const char *ext);
|
||||
static void WAV_close(Sound_Sample *sample);
|
||||
static Uint32 WAV_read(Sound_Sample *sample);
|
||||
static int WAV_rewind(Sound_Sample *sample);
|
||||
static int WAV_seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
static const char *extensions_wav[] = { "WAV", NULL };
|
||||
const Sound_DecoderFunctions __Sound_DecoderFunctions_WAV =
|
||||
{
|
||||
{
|
||||
extensions_wav,
|
||||
"Microsoft WAVE audio format",
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://www.icculus.org/SDL_sound/"
|
||||
},
|
||||
|
||||
WAV_init, /* init() method */
|
||||
WAV_quit, /* quit() method */
|
||||
WAV_open, /* open() method */
|
||||
WAV_close, /* close() method */
|
||||
WAV_read, /* read() method */
|
||||
WAV_rewind, /* rewind() method */
|
||||
WAV_seek /* seek() method */
|
||||
};
|
||||
|
||||
|
||||
/* Better than SDL_ReadLE16, since you can detect i/o errors... */
|
||||
static __inline__ int read_le16(SDL_RWops *rw, Uint16 *ui16)
|
||||
{
|
||||
int rc = SDL_RWread(rw, ui16, sizeof (Uint16), 1);
|
||||
BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
|
||||
*ui16 = SDL_SwapLE16(*ui16);
|
||||
return(1);
|
||||
} /* read_le16 */
|
||||
|
||||
|
||||
/* Better than SDL_ReadLE32, since you can detect i/o errors... */
|
||||
static __inline__ int read_le32(SDL_RWops *rw, Uint32 *ui32)
|
||||
{
|
||||
int rc = SDL_RWread(rw, ui32, sizeof (Uint32), 1);
|
||||
BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
|
||||
*ui32 = SDL_SwapLE32(*ui32);
|
||||
return(1);
|
||||
} /* read_le32 */
|
||||
|
||||
|
||||
/* This is just cleaner on the caller's end... */
|
||||
static __inline__ int read_uint8(SDL_RWops *rw, Uint8 *ui8)
|
||||
{
|
||||
int rc = SDL_RWread(rw, ui8, sizeof (Uint8), 1);
|
||||
BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
|
||||
return(1);
|
||||
} /* read_uint8 */
|
||||
|
||||
|
||||
/* Chunk management code... */
|
||||
|
||||
#define riffID 0x46464952 /* "RIFF", in ascii. */
|
||||
#define waveID 0x45564157 /* "WAVE", in ascii. */
|
||||
#define factID 0x74636166 /* "fact", in ascii. */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The FORMAT chunk... *
|
||||
*****************************************************************************/
|
||||
|
||||
#define fmtID 0x20746D66 /* "fmt ", in ascii. */
|
||||
|
||||
#define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */
|
||||
#define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Sint16 iCoef1;
|
||||
Sint16 iCoef2;
|
||||
} ADPCMCOEFSET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint8 bPredictor;
|
||||
Uint16 iDelta;
|
||||
Sint16 iSamp1;
|
||||
Sint16 iSamp2;
|
||||
} ADPCMBLOCKHEADER;
|
||||
|
||||
typedef struct S_WAV_FMT_T
|
||||
{
|
||||
Uint32 chunkID;
|
||||
Sint32 chunkSize;
|
||||
Sint16 wFormatTag;
|
||||
Uint16 wChannels;
|
||||
Uint32 dwSamplesPerSec;
|
||||
Uint32 dwAvgBytesPerSec;
|
||||
Uint16 wBlockAlign;
|
||||
Uint16 wBitsPerSample;
|
||||
|
||||
Uint32 next_chunk_offset;
|
||||
|
||||
Uint32 sample_frame_size;
|
||||
Uint32 data_starting_offset;
|
||||
Uint32 total_bytes;
|
||||
|
||||
void (*free)(struct S_WAV_FMT_T *fmt);
|
||||
Uint32 (*read_sample)(Sound_Sample *sample);
|
||||
int (*rewind_sample)(Sound_Sample *sample);
|
||||
int (*seek_sample)(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
Uint16 cbSize;
|
||||
Uint16 wSamplesPerBlock;
|
||||
Uint16 wNumCoef;
|
||||
ADPCMCOEFSET *aCoef;
|
||||
ADPCMBLOCKHEADER *blockheaders;
|
||||
Uint32 samples_left_in_block;
|
||||
int nibble_state;
|
||||
Sint8 nibble;
|
||||
} adpcm;
|
||||
|
||||
/* put other format-specific data here... */
|
||||
} fmt;
|
||||
} fmt_t;
|
||||
|
||||
|
||||
/*
|
||||
* Read in a fmt_t from disk. This makes this process safe regardless of
|
||||
* the processor's byte order or how the fmt_t structure is packed.
|
||||
* Note that the union "fmt" is not read in here; that is handled as
|
||||
* needed in the read_fmt_* functions.
|
||||
*/
|
||||
static int read_fmt_chunk(SDL_RWops *rw, fmt_t *fmt)
|
||||
{
|
||||
/* skip reading the chunk ID, since it was already read at this point... */
|
||||
fmt->chunkID = fmtID;
|
||||
|
||||
BAIL_IF_MACRO(!read_le32(rw, &fmt->chunkSize), NULL, 0);
|
||||
BAIL_IF_MACRO(fmt->chunkSize < 16, "WAV: Invalid chunk size", 0);
|
||||
fmt->next_chunk_offset = SDL_RWtell(rw) + fmt->chunkSize;
|
||||
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->wFormatTag), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->wChannels), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le32(rw, &fmt->dwSamplesPerSec), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le32(rw, &fmt->dwAvgBytesPerSec), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->wBlockAlign), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->wBitsPerSample), NULL, 0);
|
||||
|
||||
return(1);
|
||||
} /* read_fmt_chunk */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The DATA chunk... *
|
||||
*****************************************************************************/
|
||||
|
||||
#define dataID 0x61746164 /* "data", in ascii. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint32 chunkID;
|
||||
Sint32 chunkSize;
|
||||
/* Then, (chunkSize) bytes of waveform data... */
|
||||
} data_t;
|
||||
|
||||
|
||||
/*
|
||||
* Read in a data_t from disk. This makes this process safe regardless of
|
||||
* the processor's byte order or how the fmt_t structure is packed.
|
||||
*/
|
||||
static int read_data_chunk(SDL_RWops *rw, data_t *data)
|
||||
{
|
||||
/* skip reading the chunk ID, since it was already read at this point... */
|
||||
data->chunkID = dataID;
|
||||
BAIL_IF_MACRO(!read_le32(rw, &data->chunkSize), NULL, 0);
|
||||
return(1);
|
||||
} /* read_data_chunk */
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* this is what we store in our internal->decoder_private field... *
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fmt_t *fmt;
|
||||
Sint32 bytesLeft;
|
||||
} wav_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Normal, uncompressed waveform handler... *
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Sound_Decode() lands here for uncompressed WAVs...
|
||||
*/
|
||||
static Uint32 read_sample_fmt_normal(Sound_Sample *sample)
|
||||
{
|
||||
Uint32 retval;
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
Uint32 max = (internal->buffer_size < (Uint32) w->bytesLeft) ?
|
||||
internal->buffer_size : (Uint32) w->bytesLeft;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/*
|
||||
* We don't actually do any decoding, so we read the wav data
|
||||
* directly into the internal buffer...
|
||||
*/
|
||||
retval = SDL_RWread(internal->rw, internal->buffer, 1, max);
|
||||
|
||||
w->bytesLeft -= retval;
|
||||
|
||||
/* Make sure the read went smoothly... */
|
||||
if ((retval == 0) || (w->bytesLeft == 0))
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
|
||||
else if (retval == -1)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
|
||||
/* (next call this EAGAIN may turn into an EOF or error.) */
|
||||
else if (retval < internal->buffer_size)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
|
||||
|
||||
return(retval);
|
||||
} /* read_sample_fmt_normal */
|
||||
|
||||
|
||||
static int seek_sample_fmt_normal(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int pos = (int) (fmt->data_starting_offset + offset);
|
||||
int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
|
||||
w->bytesLeft = fmt->total_bytes - offset;
|
||||
return(1); /* success. */
|
||||
} /* seek_sample_fmt_normal */
|
||||
|
||||
|
||||
static int rewind_sample_fmt_normal(Sound_Sample *sample)
|
||||
{
|
||||
/* no-op. */
|
||||
return(1);
|
||||
} /* rewind_sample_fmt_normal */
|
||||
|
||||
|
||||
static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
|
||||
{
|
||||
/* (don't need to read more from the RWops...) */
|
||||
fmt->free = NULL;
|
||||
fmt->read_sample = read_sample_fmt_normal;
|
||||
fmt->rewind_sample = rewind_sample_fmt_normal;
|
||||
fmt->seek_sample = seek_sample_fmt_normal;
|
||||
return(1);
|
||||
} /* read_fmt_normal */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ADPCM compression handler... *
|
||||
*****************************************************************************/
|
||||
|
||||
#define FIXED_POINT_COEF_BASE 256
|
||||
#define FIXED_POINT_ADAPTION_BASE 256
|
||||
#define SMALLEST_ADPCM_DELTA 16
|
||||
|
||||
|
||||
static __inline__ int read_adpcm_block_headers(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
|
||||
int i;
|
||||
int max = fmt->wChannels;
|
||||
|
||||
if (w->bytesLeft < fmt->wBlockAlign)
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
w->bytesLeft -= fmt->wBlockAlign;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
BAIL_IF_MACRO(!read_uint8(rw, &headers[i].bPredictor), NULL, 0);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
BAIL_IF_MACRO(!read_le16(rw, &headers[i].iDelta), NULL, 0);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp1), NULL, 0);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp2), NULL, 0);
|
||||
|
||||
fmt->fmt.adpcm.samples_left_in_block = fmt->fmt.adpcm.wSamplesPerBlock;
|
||||
fmt->fmt.adpcm.nibble_state = 0;
|
||||
return(1);
|
||||
} /* read_adpcm_block_headers */
|
||||
|
||||
|
||||
static __inline__ void do_adpcm_nibble(Uint8 nib,
|
||||
ADPCMBLOCKHEADER *header,
|
||||
Sint32 lPredSamp)
|
||||
{
|
||||
static const Sint32 max_audioval = ((1<<(16-1))-1);
|
||||
static const Sint32 min_audioval = -(1<<(16-1));
|
||||
static const Sint32 AdaptionTable[] =
|
||||
{
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
|
||||
Sint32 lNewSamp;
|
||||
Sint32 delta;
|
||||
|
||||
if (nib & 0x08)
|
||||
lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10));
|
||||
else
|
||||
lNewSamp = lPredSamp + (header->iDelta * nib);
|
||||
|
||||
/* clamp value... */
|
||||
if (lNewSamp < min_audioval)
|
||||
lNewSamp = min_audioval;
|
||||
else if (lNewSamp > max_audioval)
|
||||
lNewSamp = max_audioval;
|
||||
|
||||
delta = ((Sint32) header->iDelta * AdaptionTable[nib]) /
|
||||
FIXED_POINT_ADAPTION_BASE;
|
||||
|
||||
if (delta < SMALLEST_ADPCM_DELTA)
|
||||
delta = SMALLEST_ADPCM_DELTA;
|
||||
|
||||
header->iDelta = delta;
|
||||
header->iSamp2 = header->iSamp1;
|
||||
header->iSamp1 = lNewSamp;
|
||||
} /* do_adpcm_nibble */
|
||||
|
||||
|
||||
static __inline__ int decode_adpcm_sample_frame(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
int i;
|
||||
int max = fmt->wChannels;
|
||||
Sint32 delta;
|
||||
Uint8 nib = fmt->fmt.adpcm.nibble;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
Uint8 byte;
|
||||
Sint16 iCoef1 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef1;
|
||||
Sint16 iCoef2 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef2;
|
||||
Sint32 lPredSamp = ((headers[i].iSamp1 * iCoef1) +
|
||||
(headers[i].iSamp2 * iCoef2)) /
|
||||
FIXED_POINT_COEF_BASE;
|
||||
|
||||
if (fmt->fmt.adpcm.nibble_state == 0)
|
||||
{
|
||||
BAIL_IF_MACRO(!read_uint8(rw, &nib), NULL, 0);
|
||||
fmt->fmt.adpcm.nibble_state = 1;
|
||||
do_adpcm_nibble(nib >> 4, &headers[i], lPredSamp);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
fmt->fmt.adpcm.nibble_state = 0;
|
||||
do_adpcm_nibble(nib & 0x0F, &headers[i], lPredSamp);
|
||||
} /* else */
|
||||
} /* for */
|
||||
|
||||
fmt->fmt.adpcm.nibble = nib;
|
||||
return(1);
|
||||
} /* decode_adpcm_sample_frame */
|
||||
|
||||
|
||||
static __inline__ void put_adpcm_sample_frame1(void *_buf, fmt_t *fmt)
|
||||
{
|
||||
Uint16 *buf = (Uint16 *) _buf;
|
||||
ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
|
||||
int i;
|
||||
for (i = 0; i < fmt->wChannels; i++)
|
||||
*(buf++) = headers[i].iSamp1;
|
||||
} /* put_adpcm_sample_frame1 */
|
||||
|
||||
|
||||
static __inline__ void put_adpcm_sample_frame2(void *_buf, fmt_t *fmt)
|
||||
{
|
||||
Uint16 *buf = (Uint16 *) _buf;
|
||||
ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
|
||||
int i;
|
||||
for (i = 0; i < fmt->wChannels; i++)
|
||||
*(buf++) = headers[i].iSamp2;
|
||||
} /* put_adpcm_sample_frame2 */
|
||||
|
||||
|
||||
/*
|
||||
* Sound_Decode() lands here for ADPCM-encoded WAVs...
|
||||
*/
|
||||
static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
Uint32 bw = 0;
|
||||
|
||||
while (bw < internal->buffer_size)
|
||||
{
|
||||
/* write ongoing sample frame before reading more data... */
|
||||
switch (fmt->fmt.adpcm.samples_left_in_block)
|
||||
{
|
||||
case 0: /* need to read a new block... */
|
||||
if (!read_adpcm_block_headers(sample))
|
||||
{
|
||||
if ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(bw);
|
||||
} /* if */
|
||||
|
||||
/* only write first sample frame for now. */
|
||||
put_adpcm_sample_frame2((Uint8 *) internal->buffer + bw, fmt);
|
||||
fmt->fmt.adpcm.samples_left_in_block--;
|
||||
bw += fmt->sample_frame_size;
|
||||
break;
|
||||
|
||||
case 1: /* output last sample frame of block... */
|
||||
put_adpcm_sample_frame1((Uint8 *) internal->buffer + bw, fmt);
|
||||
fmt->fmt.adpcm.samples_left_in_block--;
|
||||
bw += fmt->sample_frame_size;
|
||||
break;
|
||||
|
||||
default: /* output latest sample frame and read a new one... */
|
||||
put_adpcm_sample_frame1((Uint8 *) internal->buffer + bw, fmt);
|
||||
fmt->fmt.adpcm.samples_left_in_block--;
|
||||
bw += fmt->sample_frame_size;
|
||||
|
||||
if (!decode_adpcm_sample_frame(sample))
|
||||
{
|
||||
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
|
||||
return(bw);
|
||||
} /* if */
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
return(bw);
|
||||
} /* read_sample_fmt_adpcm */
|
||||
|
||||
|
||||
/*
|
||||
* Sound_FreeSample() lands here for ADPCM-encoded WAVs...
|
||||
*/
|
||||
static void free_fmt_adpcm(fmt_t *fmt)
|
||||
{
|
||||
if (fmt->fmt.adpcm.aCoef != NULL)
|
||||
free(fmt->fmt.adpcm.aCoef);
|
||||
|
||||
if (fmt->fmt.adpcm.blockheaders != NULL)
|
||||
free(fmt->fmt.adpcm.blockheaders);
|
||||
} /* free_fmt_adpcm */
|
||||
|
||||
|
||||
static int rewind_sample_fmt_adpcm(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
w->fmt->fmt.adpcm.samples_left_in_block = 0;
|
||||
return(1);
|
||||
} /* rewind_sample_fmt_adpcm */
|
||||
|
||||
|
||||
static int seek_sample_fmt_adpcm(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
Uint32 origsampsleft = fmt->fmt.adpcm.samples_left_in_block;
|
||||
int origpos = SDL_RWtell(internal->rw);
|
||||
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
|
||||
int bpb = (fmt->fmt.adpcm.wSamplesPerBlock * fmt->sample_frame_size);
|
||||
int skipsize = (offset / bpb) * fmt->wBlockAlign;
|
||||
int pos = skipsize + fmt->data_starting_offset;
|
||||
int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
|
||||
|
||||
/* The offset we need is in this block, so we need to decode to there. */
|
||||
skipsize += (offset % bpb);
|
||||
rc = (offset % bpb); /* bytes into this block we need to decode */
|
||||
if (!read_adpcm_block_headers(sample))
|
||||
{
|
||||
SDL_RWseek(internal->rw, origpos, SEEK_SET); /* try to make sane. */
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
/* first sample frame of block is a freebie. :) */
|
||||
fmt->fmt.adpcm.samples_left_in_block--;
|
||||
rc -= fmt->sample_frame_size;
|
||||
while (rc > 0)
|
||||
{
|
||||
if (!decode_adpcm_sample_frame(sample))
|
||||
{
|
||||
SDL_RWseek(internal->rw, origpos, SEEK_SET);
|
||||
fmt->fmt.adpcm.samples_left_in_block = origsampsleft;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
fmt->fmt.adpcm.samples_left_in_block--;
|
||||
rc -= fmt->sample_frame_size;
|
||||
} /* while */
|
||||
|
||||
w->bytesLeft = fmt->total_bytes - skipsize;
|
||||
return(1); /* success. */
|
||||
} /* seek_sample_fmt_adpcm */
|
||||
|
||||
|
||||
/*
|
||||
* Read in the adpcm-specific info from disk. This makes this process
|
||||
* safe regardless of the processor's byte order or how the fmt_t
|
||||
* structure is packed.
|
||||
*/
|
||||
static int read_fmt_adpcm(SDL_RWops *rw, fmt_t *fmt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm));
|
||||
fmt->free = free_fmt_adpcm;
|
||||
fmt->read_sample = read_sample_fmt_adpcm;
|
||||
fmt->rewind_sample = rewind_sample_fmt_adpcm;
|
||||
fmt->seek_sample = seek_sample_fmt_adpcm;
|
||||
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0);
|
||||
|
||||
/* fmt->free() is always called, so these malloc()s will be cleaned up. */
|
||||
|
||||
i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef;
|
||||
fmt->fmt.adpcm.aCoef = (ADPCMCOEFSET *) malloc(i);
|
||||
BAIL_IF_MACRO(fmt->fmt.adpcm.aCoef == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++)
|
||||
{
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.aCoef[i].iCoef1), NULL, 0);
|
||||
BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.aCoef[i].iCoef2), NULL, 0);
|
||||
} /* for */
|
||||
|
||||
i = sizeof (ADPCMBLOCKHEADER) * fmt->wChannels;
|
||||
fmt->fmt.adpcm.blockheaders = (ADPCMBLOCKHEADER *) malloc(i);
|
||||
BAIL_IF_MACRO(fmt->fmt.adpcm.blockheaders == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
return(1);
|
||||
} /* read_fmt_adpcm */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Everything else... *
|
||||
*****************************************************************************/
|
||||
|
||||
static int WAV_init(void)
|
||||
{
|
||||
return(1); /* always succeeds. */
|
||||
} /* WAV_init */
|
||||
|
||||
|
||||
static void WAV_quit(void)
|
||||
{
|
||||
/* it's a no-op. */
|
||||
} /* WAV_quit */
|
||||
|
||||
|
||||
static int read_fmt(SDL_RWops *rw, fmt_t *fmt)
|
||||
{
|
||||
/* if it's in this switch statement, we support the format. */
|
||||
switch (fmt->wFormatTag)
|
||||
{
|
||||
case FMT_NORMAL:
|
||||
SNDDBG(("WAV: Appears to be uncompressed audio.\n"));
|
||||
return(read_fmt_normal(rw, fmt));
|
||||
|
||||
case FMT_ADPCM:
|
||||
SNDDBG(("WAV: Appears to be ADPCM compressed audio.\n"));
|
||||
return(read_fmt_adpcm(rw, fmt));
|
||||
|
||||
/* add other types here. */
|
||||
|
||||
default:
|
||||
SNDDBG(("WAV: Format 0x%X is unknown.\n",
|
||||
(unsigned int) fmt->wFormatTag));
|
||||
BAIL_MACRO("WAV: Unsupported format", 0);
|
||||
} /* switch */
|
||||
|
||||
assert(0); /* shouldn't hit this point. */
|
||||
return(0);
|
||||
} /* read_fmt */
|
||||
|
||||
|
||||
/*
|
||||
* Locate a specific chunk in the WAVE file by ID...
|
||||
*/
|
||||
static int find_chunk(SDL_RWops *rw, Uint32 id)
|
||||
{
|
||||
Sint32 siz = 0;
|
||||
Uint32 _id = 0;
|
||||
Uint32 pos = SDL_RWtell(rw);
|
||||
|
||||
while (1)
|
||||
{
|
||||
BAIL_IF_MACRO(!read_le32(rw, &_id), NULL, 0);
|
||||
if (_id == id)
|
||||
return(1);
|
||||
|
||||
/* skip ahead and see what next chunk is... */
|
||||
BAIL_IF_MACRO(!read_le32(rw, &siz), NULL, 0);
|
||||
assert(siz >= 0);
|
||||
pos += (sizeof (Uint32) * 2) + siz;
|
||||
if (siz > 0)
|
||||
BAIL_IF_MACRO(SDL_RWseek(rw, pos, SEEK_SET) != pos, NULL, 0);
|
||||
} /* while */
|
||||
|
||||
return(0); /* shouldn't hit this, but just in case... */
|
||||
} /* find_chunk */
|
||||
|
||||
|
||||
static int WAV_open_internal(Sound_Sample *sample, const char *ext, fmt_t *fmt)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
SDL_RWops *rw = internal->rw;
|
||||
data_t d;
|
||||
wav_t *w;
|
||||
Uint32 pos;
|
||||
|
||||
BAIL_IF_MACRO(SDL_ReadLE32(rw) != riffID, "WAV: Not a RIFF file.", 0);
|
||||
SDL_ReadLE32(rw); /* throw the length away; we get this info later. */
|
||||
BAIL_IF_MACRO(SDL_ReadLE32(rw) != waveID, "WAV: Not a WAVE file.", 0);
|
||||
BAIL_IF_MACRO(!find_chunk(rw, fmtID), "WAV: No format chunk.", 0);
|
||||
BAIL_IF_MACRO(!read_fmt_chunk(rw, fmt), "WAV: Can't read format chunk.", 0);
|
||||
|
||||
sample->actual.channels = (Uint8) fmt->wChannels;
|
||||
sample->actual.rate = fmt->dwSamplesPerSec;
|
||||
if ((fmt->wBitsPerSample == 4) /*|| (fmt->wBitsPerSample == 0) */ )
|
||||
sample->actual.format = AUDIO_S16SYS;
|
||||
else if (fmt->wBitsPerSample == 8)
|
||||
sample->actual.format = AUDIO_U8;
|
||||
else if (fmt->wBitsPerSample == 16)
|
||||
sample->actual.format = AUDIO_S16LSB;
|
||||
else
|
||||
{
|
||||
SNDDBG(("WAV: %d bits per sample!?\n", (int) fmt->wBitsPerSample));
|
||||
BAIL_MACRO("WAV: Unsupported sample size.", 0);
|
||||
} /* else */
|
||||
|
||||
BAIL_IF_MACRO(!read_fmt(rw, fmt), NULL, 0);
|
||||
SDL_RWseek(rw, fmt->next_chunk_offset, SEEK_SET);
|
||||
BAIL_IF_MACRO(!find_chunk(rw, dataID), "WAV: No data chunk.", 0);
|
||||
BAIL_IF_MACRO(!read_data_chunk(rw, &d), "WAV: Can't read data chunk.", 0);
|
||||
|
||||
w = (wav_t *) malloc(sizeof(wav_t));
|
||||
BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
w->fmt = fmt;
|
||||
fmt->total_bytes = w->bytesLeft = d.chunkSize;
|
||||
fmt->data_starting_offset = SDL_RWtell(rw);
|
||||
fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) *
|
||||
sample->actual.channels );
|
||||
|
||||
internal->decoder_private = (void *) w;
|
||||
|
||||
sample->flags = SOUND_SAMPLEFLAG_NONE;
|
||||
if (fmt->seek_sample != NULL)
|
||||
sample->flags |= SOUND_SAMPLEFLAG_CANSEEK;
|
||||
|
||||
SNDDBG(("WAV: Accepting data stream.\n"));
|
||||
return(1); /* we'll handle this data. */
|
||||
} /* WAV_open_internal */
|
||||
|
||||
|
||||
static int WAV_open(Sound_Sample *sample, const char *ext)
|
||||
{
|
||||
int rc;
|
||||
|
||||
fmt_t *fmt = (fmt_t *) malloc(sizeof (fmt_t));
|
||||
BAIL_IF_MACRO(fmt == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(fmt, '\0', sizeof (fmt_t));
|
||||
|
||||
rc = WAV_open_internal(sample, ext, fmt);
|
||||
if (!rc)
|
||||
{
|
||||
if (fmt->free != NULL)
|
||||
fmt->free(fmt);
|
||||
free(fmt);
|
||||
} /* if */
|
||||
|
||||
return(rc);
|
||||
} /* WAV_open */
|
||||
|
||||
|
||||
static void WAV_close(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
|
||||
if (w->fmt->free != NULL)
|
||||
w->fmt->free(w->fmt);
|
||||
|
||||
free(w->fmt);
|
||||
free(w);
|
||||
} /* WAV_close */
|
||||
|
||||
|
||||
static Uint32 WAV_read(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
return(w->fmt->read_sample(sample));
|
||||
} /* WAV_read */
|
||||
|
||||
|
||||
static int WAV_rewind(Sound_Sample *sample)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
fmt_t *fmt = w->fmt;
|
||||
int rc = SDL_RWseek(internal->rw, fmt->data_starting_offset, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc != fmt->data_starting_offset, ERR_IO_ERROR, 0);
|
||||
w->bytesLeft = fmt->total_bytes;
|
||||
return(fmt->rewind_sample(sample));
|
||||
} /* WAV_rewind */
|
||||
|
||||
|
||||
static int WAV_seek(Sound_Sample *sample, Uint32 ms)
|
||||
{
|
||||
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
||||
wav_t *w = (wav_t *) internal->decoder_private;
|
||||
return(w->fmt->seek_sample(sample, ms));
|
||||
} /* WAV_seek */
|
||||
|
||||
#endif /* SOUND_SUPPORTS_WAV */
|
||||
|
||||
/* end of wav.c ... */
|
||||
|
||||
135
project/jni/sdl_sound/extra_rwops.c
Normal file
135
project/jni/sdl_sound/extra_rwops.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some extra RWops that are needed or are just handy to have.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "SDL.h"
|
||||
|
||||
|
||||
/*
|
||||
* The Reference Counter RWops...
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_RWops *rw; /* The actual RWops we're refcounting... */
|
||||
int refcount; /* The refcount; starts at 1. If goes to 0, delete. */
|
||||
} RWRefCounterData;
|
||||
|
||||
|
||||
/* Just pass through to the actual SDL_RWops's method... */
|
||||
static int refcounter_seek(SDL_RWops *rw, int offset, int whence)
|
||||
{
|
||||
RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
|
||||
return(data->rw->seek(data->rw, offset, whence));
|
||||
} /* refcounter_seek */
|
||||
|
||||
|
||||
/* Just pass through to the actual SDL_RWops's method... */
|
||||
static int refcounter_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
{
|
||||
RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
|
||||
return(data->rw->read(data->rw, ptr, size, maxnum));
|
||||
} /* refcounter_read */
|
||||
|
||||
|
||||
/* Just pass through to the actual SDL_RWops's method... */
|
||||
static int refcounter_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
{
|
||||
RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
|
||||
return(data->rw->write(data->rw, ptr, size, num));
|
||||
} /* refcounter_write */
|
||||
|
||||
|
||||
/*
|
||||
* Decrement the reference count. If there are no more references, pass
|
||||
* through to the actual SDL_RWops's method, and then clean ourselves up.
|
||||
*/
|
||||
static int refcounter_close(SDL_RWops *rw)
|
||||
{
|
||||
int retval = 0;
|
||||
RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
|
||||
data->refcount--;
|
||||
if (data->refcount <= 0)
|
||||
{
|
||||
retval = data->rw->close(data->rw);
|
||||
free(data);
|
||||
SDL_FreeRW(rw);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* refcounter_close */
|
||||
|
||||
|
||||
void RWops_RWRefCounter_addRef(SDL_RWops *rw)
|
||||
{
|
||||
RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
|
||||
data->refcount++;
|
||||
} /* RWops_RWRefCounter_addRef */
|
||||
|
||||
|
||||
SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
|
||||
if (rw == NULL)
|
||||
{
|
||||
SDL_SetError("NULL argument to RWops_RWRefCounter_new().");
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
retval = SDL_AllocRW();
|
||||
if (retval != NULL)
|
||||
{
|
||||
RWRefCounterData *data;
|
||||
data = (RWRefCounterData *) malloc(sizeof (RWRefCounterData));
|
||||
if (data == NULL)
|
||||
{
|
||||
SDL_SetError("Out of memory.");
|
||||
SDL_FreeRW(retval);
|
||||
retval = NULL;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
data->rw = rw;
|
||||
data->refcount = 1;
|
||||
retval->hidden.unknown.data1 = data;
|
||||
retval->seek = refcounter_seek;
|
||||
retval->read = refcounter_read;
|
||||
retval->write = refcounter_write;
|
||||
retval->close = refcounter_close;
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* RWops_RWRefCounter_new */
|
||||
|
||||
|
||||
/* end of extra_rwops.c ... */
|
||||
|
||||
|
||||
71
project/jni/sdl_sound/extra_rwops.h
Normal file
71
project/jni/sdl_sound/extra_rwops.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some extra RWops that are needed or are just handy to have.
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon. (icculus@icculus.org)
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_EXTRA_RWOPS_H_
|
||||
#define _INCLUDE_EXTRA_RWOPS_H_
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Reference Counter RWops...
|
||||
*
|
||||
* This wraps another RWops with a reference counter. When you create a
|
||||
* reference counter RWops, it sets a counter to one. Everytime you call
|
||||
* RWops_RWRefCounter_new(), that's RWops's counter increments by one.
|
||||
* Everytime you call that RWops's close() method, the counter decrements
|
||||
* by one. If the counter hits zero, the original RWops's close() method
|
||||
* is called, and the reference counting wrapper deletes itself. The read,
|
||||
* write, and seek methods just pass through to the original.
|
||||
*
|
||||
* This is handy if you have two libraries (in the original case, SDL_sound
|
||||
* and SMPEG), who both want an SDL_RWops, and both want to close it when
|
||||
* they are finished. This resolves that contention. The user creates a
|
||||
* RWops, passes it to SDL_sound, which wraps it in a reference counter and
|
||||
* increments the number of references, and passes the wrapped RWops to
|
||||
* SMPEG. SMPEG "closes" this wrapped RWops when the MP3 has finished
|
||||
* playing, and SDL_sound then closes it, too. This second closing removes
|
||||
* the last reference, and the RWops is smoothly destructed.
|
||||
*/
|
||||
|
||||
/* Return a SDL_RWops that is a reference counting wrapper of (rw). */
|
||||
SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw);
|
||||
|
||||
/* Increment a reference counting RWops's refcount by one. */
|
||||
void RWops_RWRefCounter_addRef(SDL_RWops *rw);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined _INCLUDE_EXTRA_RWOPS_H_ */
|
||||
|
||||
/* end of extra_rwops.h ... */
|
||||
|
||||
674
project/jni/sdl_sound/include/SDL_sound.h
Normal file
674
project/jni/sdl_sound/include/SDL_sound.h
Normal file
@@ -0,0 +1,674 @@
|
||||
/** \file SDL_sound.h */
|
||||
|
||||
/*
|
||||
* SDL_sound -- An abstract sound format decoding API.
|
||||
* Copyright (C) 2001 Ryan C. Gordon.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* \mainpage SDL_sound
|
||||
*
|
||||
* The latest version of SDL_sound can be found at:
|
||||
* http://icculus.org/SDL_sound/
|
||||
*
|
||||
* The basic gist of SDL_sound is that you use an SDL_RWops to get sound data
|
||||
* into this library, and SDL_sound will take that data, in one of several
|
||||
* popular formats, and decode it into raw waveform data in the format of
|
||||
* your choice. This gives you a nice abstraction for getting sound into your
|
||||
* game or application; just feed it to SDL_sound, and it will handle
|
||||
* decoding and converting, so you can just pass it to your SDL audio
|
||||
* callback (or whatever). Since it gets data from an SDL_RWops, you can get
|
||||
* the initial sound data from any number of sources: file, memory buffer,
|
||||
* network connection, etc.
|
||||
*
|
||||
* As the name implies, this library depends on SDL: Simple Directmedia Layer,
|
||||
* which is a powerful, free, and cross-platform multimedia library. It can
|
||||
* be found at http://www.libsdl.org/
|
||||
*
|
||||
* Support is in place or planned for the following sound formats:
|
||||
* - .WAV (Microsoft WAVfile RIFF data, internal.)
|
||||
* - .VOC (Creative Labs' Voice format, internal.)
|
||||
* - .MP3 (MPEG-1 Layer 3 support, via the SMPEG and mpglib libraries.)
|
||||
* - .MID (MIDI music converted to Waveform data, internal.)
|
||||
* - .MOD (MOD files, via MikMod and ModPlug.)
|
||||
* - .OGG (Ogg files, via Ogg Vorbis libraries.)
|
||||
* - .SPX (Speex files, via libspeex.)
|
||||
* - .SHN (Shorten files, internal.)
|
||||
* - .RAW (Raw sound data in any format, internal.)
|
||||
* - .AU (Sun's Audio format, internal.)
|
||||
* - .AIFF (Audio Interchange format, internal.)
|
||||
* - .FLAC (Lossless audio compression, via libFLAC.)
|
||||
*
|
||||
* (...and more to come...)
|
||||
*
|
||||
* Please see the file COPYING in the source's root directory.
|
||||
*
|
||||
* \author Ryan C. Gordon (icculus@icculus.org)
|
||||
* \author many others, please see CREDITS in the source's root directory.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDL_SOUND_H_
|
||||
#define _INCLUDE_SDL_SOUND_H_
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
|
||||
|
||||
#ifndef SDLCALL /* may not be defined with older SDL releases. */
|
||||
#define SDLCALL
|
||||
#endif
|
||||
|
||||
#ifdef SDL_SOUND_DLL_EXPORTS
|
||||
# define SNDDECLSPEC __declspec(dllexport)
|
||||
#else
|
||||
# define SNDDECLSPEC
|
||||
#endif
|
||||
|
||||
#define SOUND_VER_MAJOR 1
|
||||
#define SOUND_VER_MINOR 0
|
||||
#define SOUND_VER_PATCH 3
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \enum Sound_SampleFlags
|
||||
* \brief Flags that are used in a Sound_Sample to show various states.
|
||||
*
|
||||
* To use:
|
||||
* \code
|
||||
* if (sample->flags & SOUND_SAMPLEFLAG_ERROR) { dosomething(); }
|
||||
* \endcode
|
||||
*
|
||||
* \sa Sound_SampleNew
|
||||
* \sa Sound_SampleNewFromFile
|
||||
* \sa Sound_SampleDecode
|
||||
* \sa Sound_SampleDecodeAll
|
||||
* \sa Sound_SampleSeek
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SOUND_SAMPLEFLAG_NONE = 0, /**< No special attributes. */
|
||||
|
||||
/* these are set at sample creation time... */
|
||||
SOUND_SAMPLEFLAG_CANSEEK = 1, /**< Sample can seek to arbitrary points. */
|
||||
|
||||
/* these are set during decoding... */
|
||||
SOUND_SAMPLEFLAG_EOF = 1 << 29, /**< End of input stream. */
|
||||
SOUND_SAMPLEFLAG_ERROR = 1 << 30, /**< Unrecoverable error. */
|
||||
SOUND_SAMPLEFLAG_EAGAIN = 1 << 31 /**< Function would block, or temp error. */
|
||||
} Sound_SampleFlags;
|
||||
|
||||
|
||||
/**
|
||||
* \struct Sound_AudioInfo
|
||||
* \brief Information about an existing sample's format.
|
||||
*
|
||||
* These are the basics of a decoded sample's data structure: data format
|
||||
* (see AUDIO_U8 and friends in SDL_audio.h), number of channels, and sample
|
||||
* rate. If you need more explanation than that, you should stop developing
|
||||
* sound code right now.
|
||||
*
|
||||
* \sa Sound_SampleNew
|
||||
* \sa Sound_SampleNewFromFile
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Uint16 format; /**< Equivalent of SDL_AudioSpec.format. */
|
||||
Uint8 channels; /**< Number of sound channels. 1 == mono, 2 == stereo. */
|
||||
Uint32 rate; /**< Sample rate; frequency of sample points per second. */
|
||||
} Sound_AudioInfo;
|
||||
|
||||
|
||||
/**
|
||||
* \struct Sound_DecoderInfo
|
||||
* \brief Information about available soudn decoders.
|
||||
*
|
||||
* Each decoder sets up one of these structs, which can be retrieved via
|
||||
* the Sound_AvailableDecoders() function. EVERY FIELD IN THIS IS READ-ONLY.
|
||||
*
|
||||
* The extensions field is a NULL-terminated list of ASCIZ strings. You
|
||||
* should read it like this:
|
||||
*
|
||||
* \code
|
||||
* const char **ext;
|
||||
* for (ext = info->extensions; *ext != NULL; ext++) {
|
||||
* printf(" File extension \"%s\"\n", *ext);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \sa Sound_AvailableDecoders
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char **extensions; /**< File extensions, list ends with NULL. */
|
||||
const char *description; /**< Human readable description of decoder. */
|
||||
const char *author; /**< "Name Of Author \<email@emailhost.dom\>" */
|
||||
const char *url; /**< URL specific to this decoder. */
|
||||
} Sound_DecoderInfo;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \struct Sound_Sample
|
||||
* \brief Represents sound data in the process of being decoded.
|
||||
*
|
||||
* The Sound_Sample structure is the heart of SDL_sound. This holds
|
||||
* information about a source of sound data as it is being decoded.
|
||||
* EVERY FIELD IN THIS IS READ-ONLY. Please use the API functions to
|
||||
* change them.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void *opaque; /**< Internal use only. Don't touch. */
|
||||
const Sound_DecoderInfo *decoder; /**< Decoder used for this sample. */
|
||||
Sound_AudioInfo desired; /**< Desired audio format for conversion. */
|
||||
Sound_AudioInfo actual; /**< Actual audio format of sample. */
|
||||
void *buffer; /**< Decoded sound data lands in here. */
|
||||
Uint32 buffer_size; /**< Current size of (buffer), in bytes (Uint8). */
|
||||
Sound_SampleFlags flags; /**< Flags relating to this sample. */
|
||||
} Sound_Sample;
|
||||
|
||||
|
||||
/**
|
||||
* \struct Sound_Version
|
||||
* \brief Information the version of SDL_sound in use.
|
||||
*
|
||||
* Represents the library's version as three levels: major revision
|
||||
* (increments with massive changes, additions, and enhancements),
|
||||
* minor revision (increments with backwards-compatible changes to the
|
||||
* major revision), and patchlevel (increments with fixes to the minor
|
||||
* revision).
|
||||
*
|
||||
* \sa SOUND_VERSION
|
||||
* \sa Sound_GetLinkedVersion
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int major; /**< major revision */
|
||||
int minor; /**< minor revision */
|
||||
int patch; /**< patchlevel */
|
||||
} Sound_Version;
|
||||
|
||||
|
||||
/* functions and macros... */
|
||||
|
||||
/**
|
||||
* \def SOUND_VERSION(x)
|
||||
* \brief Macro to determine SDL_sound version program was compiled against.
|
||||
*
|
||||
* This macro fills in a Sound_Version structure with the version of the
|
||||
* library you compiled against. This is determined by what header the
|
||||
* compiler uses. Note that if you dynamically linked the library, you might
|
||||
* have a slightly newer or older version at runtime. That version can be
|
||||
* determined with Sound_GetLinkedVersion(), which, unlike SOUND_VERSION,
|
||||
* is not a macro.
|
||||
*
|
||||
* \param x A pointer to a Sound_Version struct to initialize.
|
||||
*
|
||||
* \sa Sound_Version
|
||||
* \sa Sound_GetLinkedVersion
|
||||
*/
|
||||
#define SOUND_VERSION(x) \
|
||||
{ \
|
||||
(x)->major = SOUND_VER_MAJOR; \
|
||||
(x)->minor = SOUND_VER_MINOR; \
|
||||
(x)->patch = SOUND_VER_PATCH; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \fn void Sound_GetLinkedVersion(Sound_Version *ver)
|
||||
* \brief Get the version of SDL_sound that is linked against your program.
|
||||
*
|
||||
* If you are using a shared library (DLL) version of SDL_sound, then it is
|
||||
* possible that it will be different than the version you compiled against.
|
||||
*
|
||||
* This is a real function; the macro SOUND_VERSION tells you what version
|
||||
* of SDL_sound you compiled against:
|
||||
*
|
||||
* \code
|
||||
* Sound_Version compiled;
|
||||
* Sound_Version linked;
|
||||
*
|
||||
* SOUND_VERSION(&compiled);
|
||||
* Sound_GetLinkedVersion(&linked);
|
||||
* printf("We compiled against SDL_sound version %d.%d.%d ...\n",
|
||||
* compiled.major, compiled.minor, compiled.patch);
|
||||
* printf("But we linked against SDL_sound version %d.%d.%d.\n",
|
||||
* linked.major, linked.minor, linked.patch);
|
||||
* \endcode
|
||||
*
|
||||
* This function may be called safely at any time, even before Sound_Init().
|
||||
*
|
||||
* \param ver Sound_Version structure to fill with shared library's version.
|
||||
*
|
||||
* \sa Sound_Version
|
||||
* \sa SOUND_VERSION
|
||||
*/
|
||||
SNDDECLSPEC void SDLCALL Sound_GetLinkedVersion(Sound_Version *ver);
|
||||
|
||||
|
||||
/**
|
||||
* \fn Sound_Init(void)
|
||||
* \brief Initialize SDL_sound.
|
||||
*
|
||||
* This must be called before any other SDL_sound function (except perhaps
|
||||
* Sound_GetLinkedVersion()). You should call SDL_Init() before calling this.
|
||||
* Sound_Init() will attempt to call SDL_Init(SDL_INIT_AUDIO), just in case.
|
||||
* This is a safe behaviour, but it may not configure SDL to your liking by
|
||||
* itself.
|
||||
*
|
||||
* \return nonzero on success, zero on error. Specifics of the
|
||||
* error can be gleaned from Sound_GetError().
|
||||
*
|
||||
* \sa Sound_Quit
|
||||
*/
|
||||
SNDDECLSPEC int SDLCALL Sound_Init(void);
|
||||
|
||||
|
||||
/**
|
||||
* \fn Sound_Quit(void)
|
||||
* \brief Shutdown SDL_sound.
|
||||
*
|
||||
* This closes any SDL_RWops that were being used as sound sources, and frees
|
||||
* any resources in use by SDL_sound.
|
||||
*
|
||||
* All Sound_Sample pointers you had prior to this call are INVALIDATED.
|
||||
*
|
||||
* Once successfully deinitialized, Sound_Init() can be called again to
|
||||
* restart the subsystem. All default API states are restored at this
|
||||
* point.
|
||||
*
|
||||
* You should call this BEFORE SDL_Quit(). This will NOT call SDL_Quit()
|
||||
* for you!
|
||||
*
|
||||
* \return nonzero on success, zero on error. Specifics of the error
|
||||
* can be gleaned from Sound_GetError(). If failure, state of
|
||||
* SDL_sound is undefined, and probably badly screwed up.
|
||||
*
|
||||
* \sa Sound_Init
|
||||
*/
|
||||
SNDDECLSPEC int SDLCALL Sound_Quit(void);
|
||||
|
||||
|
||||
/**
|
||||
* \fn const Sound_DecoderInfo **Sound_AvailableDecoders(void)
|
||||
* \brief Get a list of sound formats supported by this version of SDL_sound.
|
||||
*
|
||||
* This is for informational purposes only. Note that the extension listed is
|
||||
* merely convention: if we list "MP3", you can open an MPEG-1 Layer 3 audio
|
||||
* file with an extension of "XYZ", if you like. The file extensions are
|
||||
* informational, and only required as a hint to choosing the correct
|
||||
* decoder, since the sound data may not be coming from a file at all, thanks
|
||||
* to the abstraction that an SDL_RWops provides.
|
||||
*
|
||||
* The returned value is an array of pointers to Sound_DecoderInfo structures,
|
||||
* with a NULL entry to signify the end of the list:
|
||||
*
|
||||
* \code
|
||||
* Sound_DecoderInfo **i;
|
||||
*
|
||||
* for (i = Sound_AvailableDecoders(); *i != NULL; i++)
|
||||
* {
|
||||
* printf("Supported sound format: [%s], which is [%s].\n",
|
||||
* i->extension, i->description);
|
||||
* // ...and other fields...
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* The return values are pointers to static internal memory, and should
|
||||
* be considered READ ONLY, and never freed.
|
||||
*
|
||||
* \return READ ONLY Null-terminated array of READ ONLY structures.
|
||||
*
|
||||
* \sa Sound_DecoderInfo
|
||||
*/
|
||||
SNDDECLSPEC const Sound_DecoderInfo ** SDLCALL Sound_AvailableDecoders(void);
|
||||
|
||||
|
||||
/**
|
||||
* \fn const char *Sound_GetError(void)
|
||||
* \brief Get the last SDL_sound error message as a null-terminated string.
|
||||
*
|
||||
* This will be NULL if there's been no error since the last call to this
|
||||
* function. The pointer returned by this call points to an internal buffer,
|
||||
* and should not be deallocated. Each thread has a unique error state
|
||||
* associated with it, but each time a new error message is set, it will
|
||||
* overwrite the previous one associated with that thread. It is safe to call
|
||||
* this function at anytime, even before Sound_Init().
|
||||
*
|
||||
* \return READ ONLY string of last error message.
|
||||
*
|
||||
* \sa Sound_ClearError
|
||||
*/
|
||||
SNDDECLSPEC const char * SDLCALL Sound_GetError(void);
|
||||
|
||||
|
||||
/**
|
||||
* \fn void Sound_ClearError(void)
|
||||
* \brief Clear the current error message.
|
||||
*
|
||||
* The next call to Sound_GetError() after Sound_ClearError() will return NULL.
|
||||
*
|
||||
* \sa Sound_GetError
|
||||
*/
|
||||
SNDDECLSPEC void SDLCALL Sound_ClearError(void);
|
||||
|
||||
|
||||
/**
|
||||
* \fn Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, Sound_AudioInfo *desired, Uint32 bufferSize)
|
||||
* \brief Start decoding a new sound sample.
|
||||
*
|
||||
* The data is read via an SDL_RWops structure (see SDL_rwops.h in the SDL
|
||||
* include directory), so it may be coming from memory, disk, network stream,
|
||||
* etc. The (ext) parameter is merely a hint to determining the correct
|
||||
* decoder; if you specify, for example, "mp3" for an extension, and one of
|
||||
* the decoders lists that as a handled extension, then that decoder is given
|
||||
* first shot at trying to claim the data for decoding. If none of the
|
||||
* extensions match (or the extension is NULL), then every decoder examines
|
||||
* the data to determine if it can handle it, until one accepts it. In such a
|
||||
* case your SDL_RWops will need to be capable of rewinding to the start of
|
||||
* the stream.
|
||||
*
|
||||
* If no decoders can handle the data, a NULL value is returned, and a human
|
||||
* readable error message can be fetched from Sound_GetError().
|
||||
*
|
||||
* Optionally, a desired audio format can be specified. If the incoming data
|
||||
* is in a different format, SDL_sound will convert it to the desired format
|
||||
* on the fly. Note that this can be an expensive operation, so it may be
|
||||
* wise to convert data before you need to play it back, if possible, or
|
||||
* make sure your data is initially in the format that you need it in.
|
||||
* If you don't want to convert the data, you can specify NULL for a desired
|
||||
* format. The incoming format of the data, preconversion, can be found
|
||||
* in the Sound_Sample structure.
|
||||
*
|
||||
* Note that the raw sound data "decoder" needs you to specify both the
|
||||
* extension "RAW" and a "desired" format, or it will refuse to handle
|
||||
* the data. This is to prevent it from catching all formats unsupported
|
||||
* by the other decoders.
|
||||
*
|
||||
* Finally, specify an initial buffer size; this is the number of bytes that
|
||||
* will be allocated to store each read from the sound buffer. The more you
|
||||
* can safely allocate, the more decoding can be done in one block, but the
|
||||
* more resources you have to use up, and the longer each decoding call will
|
||||
* take. Note that different data formats require more or less space to
|
||||
* store. This buffer can be resized via Sound_SetBufferSize() ...
|
||||
*
|
||||
* The buffer size specified must be a multiple of the size of a single
|
||||
* sample point. So, if you want 16-bit, stereo samples, then your sample
|
||||
* point size is (2 channels * 16 bits), or 32 bits per sample, which is four
|
||||
* bytes. In such a case, you could specify 128 or 132 bytes for a buffer,
|
||||
* but not 129, 130, or 131 (although in reality, you'll want to specify a
|
||||
* MUCH larger buffer).
|
||||
*
|
||||
* When you are done with this Sound_Sample pointer, you can dispose of it
|
||||
* via Sound_FreeSample().
|
||||
*
|
||||
* You do not have to keep a reference to (rw) around. If this function
|
||||
* suceeds, it stores (rw) internally (and disposes of it during the call
|
||||
* to Sound_FreeSample()). If this function fails, it will dispose of the
|
||||
* SDL_RWops for you.
|
||||
*
|
||||
* \param rw SDL_RWops with sound data.
|
||||
* \param ext File extension normally associated with a data format.
|
||||
* Can usually be NULL.
|
||||
* \param desired Format to convert sound data into. Can usually be NULL,
|
||||
* if you don't need conversion.
|
||||
* \param bufferSize Size, in bytes, to allocate for the decoding buffer.
|
||||
* \return Sound_Sample pointer, which is used as a handle to several other
|
||||
* SDL_sound APIs. NULL on error. If error, use
|
||||
* Sound_GetError() to see what went wrong.
|
||||
*
|
||||
* \sa Sound_NewSampleFromFile
|
||||
* \sa Sound_SetBufferSize
|
||||
* \sa Sound_Decode
|
||||
* \sa Sound_DecodeAll
|
||||
* \sa Sound_Seek
|
||||
* \sa Sound_Rewind
|
||||
* \sa Sound_FreeSample
|
||||
*/
|
||||
SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSample(SDL_RWops *rw,
|
||||
const char *ext,
|
||||
Sound_AudioInfo *desired,
|
||||
Uint32 bufferSize);
|
||||
|
||||
/**
|
||||
* \fn Sound_Sample *Sound_NewSampleFromFile(const char *filename, Sound_AudioInfo *desired, Uint32 bufferSize)
|
||||
* \brief Start decoding a new sound sample from a file on disk.
|
||||
*
|
||||
* This is identical to Sound_NewSample(), but it creates an SDL_RWops for you
|
||||
* from the file located in (filename). Note that (filename) is specified in
|
||||
* platform-dependent notation. ("C:\\music\\mysong.mp3" on windows, and
|
||||
* "/home/icculus/music/mysong.mp3" or whatever on Unix, etc.)
|
||||
* Sound_NewSample()'s "ext" parameter is gleaned from the contents of
|
||||
* (filename).
|
||||
*
|
||||
* \param filename file containing sound data.
|
||||
* \param desired Format to convert sound data into. Can usually be NULL,
|
||||
* if you don't need conversion.
|
||||
* \param bufferSize size, in bytes, of initial read buffer.
|
||||
* \return Sound_Sample pointer, which is used as a handle to several other
|
||||
* SDL_sound APIs. NULL on error. If error, use
|
||||
* Sound_GetError() to see what went wrong.
|
||||
*
|
||||
* \sa Sound_NewSample
|
||||
* \sa Sound_SetBufferSize
|
||||
* \sa Sound_Decode
|
||||
* \sa Sound_DecodeAll
|
||||
* \sa Sound_Seek
|
||||
* \sa Sound_Rewind
|
||||
* \sa Sound_FreeSample
|
||||
*/
|
||||
SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromFile(const char *fname,
|
||||
Sound_AudioInfo *desired,
|
||||
Uint32 bufferSize);
|
||||
|
||||
/**
|
||||
* \fn void Sound_FreeSample(Sound_Sample *sample)
|
||||
* \brief Dispose of a Sound_Sample.
|
||||
*
|
||||
* This will also close/dispose of the SDL_RWops that was used at creation
|
||||
* time, so there's no need to keep a reference to that around.
|
||||
* The Sound_Sample pointer is invalid after this call, and will almost
|
||||
* certainly result in a crash if you attempt to keep using it.
|
||||
*
|
||||
* \param sample The Sound_Sample to delete.
|
||||
*
|
||||
* \sa Sound_NewSample
|
||||
* \sa Sound_NewSampleFromFile
|
||||
*/
|
||||
SNDDECLSPEC void SDLCALL Sound_FreeSample(Sound_Sample *sample);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int Sound_SetBufferSize(Sound_Sample *sample, Uint32 new_size)
|
||||
* \brief Change the current buffer size for a sample.
|
||||
*
|
||||
* If the buffer size could be changed, then the sample->buffer and
|
||||
* sample->buffer_size fields will reflect that. If they could not be
|
||||
* changed, then your original sample state is preserved. If the buffer is
|
||||
* shrinking, the data at the end of buffer is truncated. If the buffer is
|
||||
* growing, the contents of the new space at the end is undefined until you
|
||||
* decode more into it or initialize it yourself.
|
||||
*
|
||||
* The buffer size specified must be a multiple of the size of a single
|
||||
* sample point. So, if you want 16-bit, stereo samples, then your sample
|
||||
* point size is (2 channels * 16 bits), or 32 bits per sample, which is four
|
||||
* bytes. In such a case, you could specify 128 or 132 bytes for a buffer,
|
||||
* but not 129, 130, or 131 (although in reality, you'll want to specify a
|
||||
* MUCH larger buffer).
|
||||
*
|
||||
* \param sample The Sound_Sample whose buffer to modify.
|
||||
* \param new_size The desired size, in bytes, of the new buffer.
|
||||
* \return non-zero if buffer size changed, zero on failure.
|
||||
*
|
||||
* \sa Sound_Decode
|
||||
* \sa Sound_DecodeAll
|
||||
*/
|
||||
SNDDECLSPEC int SDLCALL Sound_SetBufferSize(Sound_Sample *sample,
|
||||
Uint32 new_size);
|
||||
|
||||
|
||||
/**
|
||||
* \fn Uint32 Sound_Decode(Sound_Sample *sample)
|
||||
* \brief Decode more of the sound data in a Sound_Sample.
|
||||
*
|
||||
* It will decode at most sample->buffer_size bytes into sample->buffer in the
|
||||
* desired format, and return the number of decoded bytes.
|
||||
* If sample->buffer_size bytes could not be decoded, then please refer to
|
||||
* sample->flags to determine if this was an end-of-stream or error condition.
|
||||
*
|
||||
* \param sample Do more decoding to this Sound_Sample.
|
||||
* \return number of bytes decoded into sample->buffer. If it is less than
|
||||
* sample->buffer_size, then you should check sample->flags to see
|
||||
* what the current state of the sample is (EOF, error, read again).
|
||||
*
|
||||
* \sa Sound_DecodeAll
|
||||
* \sa Sound_SetBufferSize
|
||||
* \sa Sound_Seek
|
||||
* \sa Sound_Rewind
|
||||
*/
|
||||
SNDDECLSPEC Uint32 SDLCALL Sound_Decode(Sound_Sample *sample);
|
||||
|
||||
|
||||
/**
|
||||
* \fn Uint32 Sound_DecodeAll(Sound_Sample *sample)
|
||||
* \brief Decode the remainder of the sound data in a Sound_Sample.
|
||||
*
|
||||
* This will dynamically allocate memory for the ENTIRE remaining sample.
|
||||
* sample->buffer_size and sample->buffer will be updated to reflect the
|
||||
* new buffer. Please refer to sample->flags to determine if the decoding
|
||||
* finished due to an End-of-stream or error condition.
|
||||
*
|
||||
* Be aware that sound data can take a large amount of memory, and that
|
||||
* this function may block for quite awhile while processing. Also note
|
||||
* that a streaming source (for example, from a SDL_RWops that is getting
|
||||
* fed from an Internet radio feed that doesn't end) may fill all available
|
||||
* memory before giving up...be sure to use this on finite sound sources
|
||||
* only!
|
||||
*
|
||||
* When decoding the sample in its entirety, the work is done one buffer at a
|
||||
* time. That is, sound is decoded in sample->buffer_size blocks, and
|
||||
* appended to a continually-growing buffer until the decoding completes.
|
||||
* That means that this function will need enough RAM to hold approximately
|
||||
* sample->buffer_size bytes plus the complete decoded sample at most. The
|
||||
* larger your buffer size, the less overhead this function needs, but beware
|
||||
* the possibility of paging to disk. Best to make this user-configurable if
|
||||
* the sample isn't specific and small.
|
||||
*
|
||||
* \param sample Do all decoding for this Sound_Sample.
|
||||
* \return number of bytes decoded into sample->buffer. You should check
|
||||
* sample->flags to see what the current state of the sample is
|
||||
* (EOF, error, read again).
|
||||
*
|
||||
* \sa Sound_Decode
|
||||
* \sa Sound_SetBufferSize
|
||||
*/
|
||||
SNDDECLSPEC Uint32 SDLCALL Sound_DecodeAll(Sound_Sample *sample);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int Sound_Rewind(Sound_Sample *sample)
|
||||
* \brief Rewind a sample to the start.
|
||||
*
|
||||
* Restart a sample at the start of its waveform data, as if newly
|
||||
* created with Sound_NewSample(). If successful, the next call to
|
||||
* Sound_Decode[All]() will give audio data from the earliest point
|
||||
* in the stream.
|
||||
*
|
||||
* Beware that this function will fail if the SDL_RWops that feeds the
|
||||
* decoder can not be rewound via it's seek method, but this can
|
||||
* theoretically be avoided by wrapping it in some sort of buffering
|
||||
* SDL_RWops.
|
||||
*
|
||||
* This function should ONLY fail if the RWops is not seekable, or
|
||||
* SDL_sound is not initialized. Both can be controlled by the application,
|
||||
* and thus, it is up to the developer's paranoia to dictate whether this
|
||||
* function's return value need be checked at all.
|
||||
*
|
||||
* If this function fails, the state of the sample is undefined, but it
|
||||
* is still safe to call Sound_FreeSample() to dispose of it.
|
||||
*
|
||||
* On success, ERROR, EOF, and EAGAIN are cleared from sample->flags. The
|
||||
* ERROR flag is set on error.
|
||||
*
|
||||
* \param sample The Sound_Sample to rewind.
|
||||
* \return nonzero on success, zero on error. Specifics of the
|
||||
* error can be gleaned from Sound_GetError().
|
||||
*
|
||||
* \sa Sound_Seek
|
||||
*/
|
||||
SNDDECLSPEC int SDLCALL Sound_Rewind(Sound_Sample *sample);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int Sound_Seek(Sound_Sample *sample, Uint32 ms)
|
||||
* \brief Seek to a different point in a sample.
|
||||
*
|
||||
* Reposition a sample's stream. If successful, the next call to
|
||||
* Sound_Decode[All]() will give audio data from the offset you
|
||||
* specified.
|
||||
*
|
||||
* The offset is specified in milliseconds from the start of the
|
||||
* sample.
|
||||
*
|
||||
* Beware that this function can fail for several reasons. If the
|
||||
* SDL_RWops that feeds the decoder can not seek, this call will almost
|
||||
* certainly fail, but this can theoretically be avoided by wrapping it
|
||||
* in some sort of buffering SDL_RWops. Some decoders can never seek,
|
||||
* others can only seek with certain files. The decoders will set a flag
|
||||
* in the sample at creation time to help you determine this.
|
||||
*
|
||||
* You should check sample->flags & SOUND_SAMPLEFLAG_CANSEEK
|
||||
* before attempting. Sound_Seek() reports failure immediately if this
|
||||
* flag isn't set. This function can still fail for other reasons if the
|
||||
* flag is set.
|
||||
*
|
||||
* This function can be emulated in the application with Sound_Rewind()
|
||||
* and predecoding a specific amount of the sample, but this can be
|
||||
* extremely inefficient. Sound_Seek() accelerates the seek on a
|
||||
* with decoder-specific code.
|
||||
*
|
||||
* If this function fails, the sample should continue to function as if
|
||||
* this call was never made. If there was an unrecoverable error,
|
||||
* sample->flags & SOUND_SAMPLEFLAG_ERROR will be set, which you regular
|
||||
* decoding loop can pick up.
|
||||
*
|
||||
* On success, ERROR, EOF, and EAGAIN are cleared from sample->flags.
|
||||
*
|
||||
* \param sample The Sound_Sample to seek.
|
||||
* \param ms The new position, in milliseconds from start of sample.
|
||||
* \return nonzero on success, zero on error. Specifics of the
|
||||
* error can be gleaned from Sound_GetError().
|
||||
*
|
||||
* \sa Sound_Rewind
|
||||
*/
|
||||
SNDDECLSPEC int SDLCALL Sound_Seek(Sound_Sample *sample, Uint32 ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined _INCLUDE_SDL_SOUND_H_ */
|
||||
|
||||
/* end of SDL_sound.h ... */
|
||||
|
||||
Reference in New Issue
Block a user