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.
 | 
