mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			376 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			376 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
Game_Music_Emu 0.6.2
 | 
						|
--------------------
 | 
						|
Author     : Shay Green <gblargg@gmail.com>
 | 
						|
Maintainer : Michael Pyne <mpyne@purinchu.net>
 | 
						|
Website    : https://bitbucket.org/mpyne/game-music-emu/
 | 
						|
Source     : https://bitbucket.org/mpyne/game-music-emu/
 | 
						|
License    : GNU Lesser General Public License (LGPL), see LICENSE.txt
 | 
						|
 | 
						|
Contents
 | 
						|
--------
 | 
						|
* Overview
 | 
						|
* Error handling
 | 
						|
* Emulator types
 | 
						|
* M3U playlist support
 | 
						|
* Information fields
 | 
						|
* Track length
 | 
						|
* Loading file data
 | 
						|
* Sound parameters
 | 
						|
* VGM/GYM YM2413 & YM2612 FM sound
 | 
						|
* Modular construction
 | 
						|
* Obscure features
 | 
						|
* Solving problems
 | 
						|
* Thanks
 | 
						|
 | 
						|
 | 
						|
Overview
 | 
						|
--------
 | 
						|
This library can open game music files, play tracks, and read game and
 | 
						|
track information tags. To play a game music file, do the following:
 | 
						|
 | 
						|
* Open the file with gme_open_file()
 | 
						|
* Start a track with gme_start_track();
 | 
						|
* Generate samples as needed with gme_play()
 | 
						|
* Play samples through speaker using your operating system
 | 
						|
* Delete emulator when done with gme_delete()
 | 
						|
 | 
						|
Your code must arrange for the generated samples to be played through
 | 
						|
the computer's speaker using whatever method your operating system
 | 
						|
requires.
 | 
						|
 | 
						|
There are many additional features available; you can:
 | 
						|
 | 
						|
* Determine of the type of a music file without opening it with
 | 
						|
gme_identify_*()
 | 
						|
* Load just the file's information tags with gme_info_only
 | 
						|
* Load from a block of memory rather than a file with gme_load_data()
 | 
						|
* Arrange for a fade-out at a particular time with gme_set_fade
 | 
						|
* Find when a track has ended with gme_track_ended()
 | 
						|
* Seek to a new time in the track with gme_seek()
 | 
						|
* Load an extended m3u playlist with gme_load_m3u()
 | 
						|
* Get a list of the voices (channels) and mute them individually with
 | 
						|
gme_voice_names() and gme_mute_voice()
 | 
						|
* Change the playback tempo without affecting pitch with gme_set_tempo()
 | 
						|
* Adjust treble/bass equalization with gme_set_equalizer()
 | 
						|
* Associate your own data with an emulator and later get it back with
 | 
						|
gme_set_user_data()
 | 
						|
* Register a function of yours to be called back when the emulator is
 | 
						|
deleted with gme_set_user_cleanup()
 | 
						|
 | 
						|
Refer to gme.h for a comprehensive summary of features.
 | 
						|
 | 
						|
 | 
						|
Error handling
 | 
						|
--------------
 | 
						|
Functions which can fail have a return type of gme_err_t, which is a
 | 
						|
pointer to an error string (const char*). If a function is successful it
 | 
						|
returns NULL. Errors that you can easily avoid are checked with debug
 | 
						|
assertions; gme_err_t return values are only used for genuine run-time
 | 
						|
errors that can't be easily predicted in advance (out of memory, I/O
 | 
						|
errors, incompatible file data). Your code should check all error
 | 
						|
values.
 | 
						|
 | 
						|
When loading a music file in the wrong emulator or trying to load a
 | 
						|
non-music file, gme_wrong_file_type is returned. You can check for this
 | 
						|
error in C++ like this:
 | 
						|
 | 
						|
	gme_err_t err = gme_open_file( path, &emu );
 | 
						|
	if ( err == gme_wrong_file_type )
 | 
						|
		...
 | 
						|
 | 
						|
To check for minor problems, call gme_warning() to get a string
 | 
						|
describing the last warning. Your player should allow the user some way
 | 
						|
of knowing when this is the case, since these minor errors could affect
 | 
						|
playback. Without this information the user can't solve problems as
 | 
						|
well. When playing a track, gme_warning() returns minor playback-related
 | 
						|
problems (major playback problems end the track immediately and set the
 | 
						|
warning string).
 | 
						|
 | 
						|
 | 
						|
Emulator types
 | 
						|
--------------
 | 
						|
The library includes several game music emulators that each support a
 | 
						|
different file type. Each is identified by a gme_type_t constant defined
 | 
						|
in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
 | 
						|
gme_open_file() or gme_open_data(), the library does the work of
 | 
						|
determining the file type and creating an appropriate emulator. If you
 | 
						|
want more control over this process, read on.
 | 
						|
 | 
						|
There are two basic ways to identify a game music file's type: look at
 | 
						|
its file extension, or read the header data. The library includes
 | 
						|
functions to help with both methods. The first is preferable because it
 | 
						|
is fast and the most common way to identify files. Sometimes the
 | 
						|
extension is lost or wrong, so the header must be read.
 | 
						|
 | 
						|
Use gme_identify_extension() to find the correct game music type based
 | 
						|
on a filename. To identify a file based on its extension and header
 | 
						|
contents, use gme_identify_file(). If you read the header data yourself,
 | 
						|
use gme_identify_header().
 | 
						|
 | 
						|
If you want to remove support for some music types to reduce your
 | 
						|
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
 | 
						|
support just NSF and GBS, use this:
 | 
						|
 | 
						|
	#define GME_TYPE_LIST \
 | 
						|
		gme_nsf_type,\
 | 
						|
		gme_gbs_type
 | 
						|
 | 
						|
 | 
						|
M3U playlist support
 | 
						|
--------------------
 | 
						|
The library supports playlists in an extended m3u format with
 | 
						|
gme_load_m3u() to give track names and times to multi-song formats: AY,
 | 
						|
GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
 | 
						|
itself is not well-defined so some m3u files won't work properly
 | 
						|
(particularly those provided with KSS files). Only m3u files referencing
 | 
						|
a single file are supported; your code must handle m3u files covering
 | 
						|
more than one game music file, though it can use the built-in m3u
 | 
						|
parsing provided by the library.
 | 
						|
 | 
						|
 | 
						|
Information fields
 | 
						|
------------------
 | 
						|
Support is provided for the various text fields and length information
 | 
						|
in a file with gme_track_info(). If you just need track information for
 | 
						|
a file (for example, building a playlist), use gme_new_info() in place
 | 
						|
of gme_new_emu(), load the file normally, then you can access the track
 | 
						|
count and info, but nothing else.
 | 
						|
 | 
						|
             M3U  VGM  GYM  SPC  SAP  NSFE  NSF  AY  GBS  HES  KSS
 | 
						|
             -------------------------------------------------------
 | 
						|
Track Count | *    *    *    *    *    *    *    *    *
 | 
						|
            |
 | 
						|
System      |      *    *    *    *    *    *    *    *    *    *
 | 
						|
            |
 | 
						|
Game        |      *    *    *         *    *         *    *
 | 
						|
            |
 | 
						|
Song        | *    *    *    *    *    *         *
 | 
						|
            |
 | 
						|
Author      |      *         *    *    *    *    *    *    *
 | 
						|
            |
 | 
						|
Copyright   |      *    *    *    *    *    *         *    *
 | 
						|
            |
 | 
						|
Comment     |      *    *    *                   *
 | 
						|
            |
 | 
						|
Dumper      |      *    *    *         *
 | 
						|
            |
 | 
						|
Length      | *    *    *    *    *    *
 | 
						|
            |
 | 
						|
Intro Length| *    *    *
 | 
						|
            |
 | 
						|
Loop Length | *    *    *
 | 
						|
 | 
						|
As listed above, the HES and KSS file formats don't include a track
 | 
						|
count, and tracks are often scattered over the 0-255 range, so an m3u
 | 
						|
playlist for these is a must.
 | 
						|
 | 
						|
Unavailable text fields are set to an empty string and times to -1. Your
 | 
						|
code should be prepared for any combination of available and unavailable
 | 
						|
fields, as a particular music file might not use all of the supported
 | 
						|
fields listed above.
 | 
						|
 | 
						|
Currently text fields are truncated to 255 characters. Obscure fields of
 | 
						|
some formats are not currently decoded; contact me if you want one
 | 
						|
added.
 | 
						|
 | 
						|
 | 
						|
Track length
 | 
						|
------------
 | 
						|
The library leaves it up to you as to when to stop playing a track. You
 | 
						|
can ask for available length information and then tell the library what
 | 
						|
time it should start fading the track with gme_set_fade(). By default it
 | 
						|
also continually checks for 6 or more seconds of silence to mark the end
 | 
						|
of a track. Here is a reasonable algorithm you can use to decide how
 | 
						|
long to play a track:
 | 
						|
 | 
						|
* If the track length is > 0, use it
 | 
						|
* If the loop length > 0, play for intro + loop * 2
 | 
						|
* Otherwise, default to 2.5 minutes (150000 msec)
 | 
						|
 | 
						|
If you want to play a track longer than normal, be sure the loop length
 | 
						|
isn't zero. See Music_Player.cpp around line 145 for example code.
 | 
						|
 | 
						|
By default, the library skips silence at the beginning of a track. It
 | 
						|
also continually checks for the end of a non-looping track by watching
 | 
						|
for 6 seconds of unbroken silence. When doing this is scans *ahead* by
 | 
						|
several seconds so it can report the end of the track after only one
 | 
						|
second of silence has actually played. This feature can be disabled with
 | 
						|
gme_ignore_silence().
 | 
						|
 | 
						|
 | 
						|
Loading file data
 | 
						|
-----------------
 | 
						|
The library allows file data to be loaded in many different ways. All
 | 
						|
load functions return an error which you should check. The following
 | 
						|
examples assume these variables:
 | 
						|
 | 
						|
	Music_Emu* emu;
 | 
						|
	gme_err_t error;
 | 
						|
 | 
						|
If you're letting the library determine a file's type, you can use
 | 
						|
either gme_open_file() or gme_open_data():
 | 
						|
	
 | 
						|
	error = gme_open_file( pathname, &emu );
 | 
						|
	error = gme_open_data( pointer, size, &emu );
 | 
						|
 | 
						|
If you're manually determining file type and using used gme_new_emu() to
 | 
						|
create an emulator, you can use the following methods of loading:
 | 
						|
 | 
						|
* From a block of memory:
 | 
						|
 | 
						|
	error = gme_load_data( emu, pointer, size );
 | 
						|
 | 
						|
* Have library call your function to read data:
 | 
						|
 | 
						|
	gme_err_t my_read( void* my_data, void* out, long count )
 | 
						|
	{
 | 
						|
		// code that reads 'count' bytes into 'out' buffer
 | 
						|
		// and return 0 if no error
 | 
						|
	}
 | 
						|
	
 | 
						|
	error = gme_load_custom( emu, my_read, file_size, my_data );
 | 
						|
 | 
						|
 | 
						|
Sound parameters
 | 
						|
----------------
 | 
						|
All emulators support an arbitrary output sampling rate. A rate of 44100
 | 
						|
Hz should work well on most systems. Since band-limited synthesis is
 | 
						|
used, a sampling rate above 48000 Hz is not necessary and will actually
 | 
						|
reduce sound quality and performance.
 | 
						|
 | 
						|
All emulators also support adjustable gain, mainly for the purpose of
 | 
						|
getting consistent volume between different music formats and avoiding
 | 
						|
excessive modulation. The gain can only be set *before* setting the
 | 
						|
emulator's sampling rate, so it's not useful as a general volume
 | 
						|
control. The default gains of emulators are set so that they give
 | 
						|
generally similar volumes, though some soundtracks are significantly
 | 
						|
louder or quieter than normal.
 | 
						|
 | 
						|
Some emulators support adjustable treble and bass frequency equalization
 | 
						|
(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
 | 
						|
Parameters are specified using gme_equalizer_t eq = { treble_dB,
 | 
						|
bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
 | 
						|
normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
 | 
						|
for an extra crisp sound. Bass_freq sets the frequency where bass
 | 
						|
response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
 | 
						|
and 15000 Hz removes all bass. For example, the following makes the
 | 
						|
sound extra-crisp but lacking bass:
 | 
						|
 | 
						|
	gme_equalizer_t eq = { 5.0, 1000 };
 | 
						|
	gme_set_equalizer( music_emu, &eq );
 | 
						|
 | 
						|
Each emulator's equalization defaults to approximate the particular
 | 
						|
console's sound quality; this default can be determined by calling
 | 
						|
equalizer() just after creating the emulator. The Music_Emu::tv_eq
 | 
						|
profile gives sound as if coming from a TV speaker, and some emulators
 | 
						|
include other profiles for different versions of the system. For
 | 
						|
example, to use Famicom sound equalization with the NSF emulator, do the
 | 
						|
following:
 | 
						|
 | 
						|
	music_emu->set_equalizer( Nsf_Emu::famicom_eq );
 | 
						|
 | 
						|
 | 
						|
VGM/GYM YM2413 & YM2612 FM sound
 | 
						|
--------------------------------
 | 
						|
The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
 | 
						|
chip emulator based on the Gens project. Because this has some
 | 
						|
inaccuracies, other YM2612 emulators can be used in its place by
 | 
						|
re-implementing the interface in YM2612_Emu.h. Available on my website
 | 
						|
is a modified version of MAME's YM2612 emulator, which sounds better in
 | 
						|
some ways and whose author is still making improvements.
 | 
						|
 | 
						|
VGM music files using the YM2413 FM sound chip are also supported, but a
 | 
						|
YM2413 emulator isn't included with the library due to technical
 | 
						|
reasons. I have put one of the available YM2413 emulators on my website
 | 
						|
that can be used directly.
 | 
						|
 | 
						|
 | 
						|
Modular construction
 | 
						|
--------------------
 | 
						|
The library is made of many fairly independent modules. If you're using
 | 
						|
only one music file emulator, you can eliminate many of the library
 | 
						|
sources from your program. Refer to the files list in readme.txt to get
 | 
						|
a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
 | 
						|
(see "Emulator types" above). Post to the forum if you'd like me to put
 | 
						|
together a smaller version for a particular use, as this only takes me a
 | 
						|
few minutes to do.
 | 
						|
 | 
						|
If you want to use one of the individual sound chip emulators (or CPU
 | 
						|
cores) in your own console emulator, first check the libraries page on
 | 
						|
my website since I have released several of them as stand alone
 | 
						|
libraries with included documentation and examples on their use. If you
 | 
						|
don't find it as a standalone library, contact me and I'll consider
 | 
						|
separating it.
 | 
						|
 | 
						|
The "classic" sound chips use my Blip_Buffer library, which greatly
 | 
						|
simplifies their implementation and efficiently handles band-limited
 | 
						|
synthesis. It is also available as a stand alone library with
 | 
						|
documentation and many examples.
 | 
						|
 | 
						|
 | 
						|
Obscure features
 | 
						|
----------------
 | 
						|
The library's flexibility allows many possibilities. Contact me if you
 | 
						|
want help implementing ideas or removing limitations.
 | 
						|
 | 
						|
* Uses no global/static variables, allowing multiple instances of any
 | 
						|
emulator. This is useful in a music player if you want to allow
 | 
						|
simultaneous recording or scanning of other tracks while one is already
 | 
						|
playing. This will also be useful if your platform disallows global
 | 
						|
data.
 | 
						|
 | 
						|
* Emulators that support a custom sound buffer can have *every* voice
 | 
						|
routed to a different Blip_Buffer, allowing custom processing on each
 | 
						|
voice. For example you could record a Game Boy track as a 4-channel
 | 
						|
sound file.
 | 
						|
 | 
						|
* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
 | 
						|
synthesis on "classic" emulators, which might help on some really old
 | 
						|
processors. This significantly lowers sound quality and prevents treble
 | 
						|
equalization. Try this if your platform's processor isn't fast enough
 | 
						|
for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
 | 
						|
processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
 | 
						|
the quality loss.
 | 
						|
 | 
						|
 | 
						|
Solving problems
 | 
						|
----------------
 | 
						|
If you're having problems, try the following:
 | 
						|
 | 
						|
* If you're getting garbled sound, try this simple siren generator in
 | 
						|
place of your call to play(). This will quickly tell whether the problem
 | 
						|
is in the library or in your code.
 | 
						|
 | 
						|
	static void play_siren( long count, short* out )
 | 
						|
	{
 | 
						|
		static double a, a2;
 | 
						|
		while ( count-- )
 | 
						|
			*out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
 | 
						|
	}
 | 
						|
 | 
						|
* Enable debugging support in your environment. This enables assertions
 | 
						|
and other run-time checks.
 | 
						|
 | 
						|
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
 | 
						|
bad code.
 | 
						|
 | 
						|
* If multiple threads are being used, ensure that only one at a time is
 | 
						|
accessing a given set of objects from the library. This library is not
 | 
						|
in general thread-safe, though independent objects can be used in
 | 
						|
separate threads.
 | 
						|
 | 
						|
* If all else fails, see if the demos work.
 | 
						|
 | 
						|
 | 
						|
Thanks
 | 
						|
------
 | 
						|
Big thanks to Chris Moeller (kode54) for help with library testing and
 | 
						|
feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
 | 
						|
for original work on openspc++ that was used when developing Spc_Emu.
 | 
						|
Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
 | 
						|
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
 | 
						|
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
 | 
						|
and giving feedback for the library in their respective game music
 | 
						|
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
 | 
						|
library into a public repository and get its interface more stable for use
 | 
						|
in shared libraries.
 |