2007-10-11 23:11:58 +00:00
|
|
|
// Super Nintendo SPC music file emulator
|
|
|
|
|
2013-09-28 03:24:23 +00:00
|
|
|
// Game_Music_Emu $vers
|
2007-10-11 23:11:58 +00:00
|
|
|
#ifndef SPC_EMU_H
|
|
|
|
#define SPC_EMU_H
|
|
|
|
|
|
|
|
#include "Music_Emu.h"
|
|
|
|
#include "Snes_Spc.h"
|
2013-09-28 03:24:23 +00:00
|
|
|
#include "Spc_Filter.h"
|
|
|
|
|
|
|
|
#if GME_SPC_FAST_RESAMPLER
|
|
|
|
#include "Upsampler.h"
|
|
|
|
typedef Upsampler Spc_Emu_Resampler;
|
|
|
|
#else
|
|
|
|
#include "Fir_Resampler.h"
|
|
|
|
typedef Fir_Resampler<24> Spc_Emu_Resampler;
|
|
|
|
#endif
|
2007-10-11 23:11:58 +00:00
|
|
|
|
|
|
|
class Spc_Emu : public Music_Emu {
|
|
|
|
public:
|
|
|
|
// The Super Nintendo hardware samples at 32kHz. Other sample rates are
|
|
|
|
// handled by resampling the 32kHz output; emulation accuracy is not affected.
|
|
|
|
enum { native_sample_rate = 32000 };
|
|
|
|
|
2013-09-28 03:24:23 +00:00
|
|
|
// Disables annoying pseudo-surround effect some music uses
|
|
|
|
void disable_surround( bool disable = true ) { apu.disable_surround( disable ); }
|
|
|
|
|
|
|
|
// Enables gaussian, cubic or sinc interpolation
|
|
|
|
void interpolation_level( int level = 0 ) { apu.interpolation_level( level ); }
|
|
|
|
|
|
|
|
Snes_Spc const* get_apu() const;
|
|
|
|
Snes_Spc * get_apu();
|
|
|
|
|
2007-10-11 23:11:58 +00:00
|
|
|
// SPC file header
|
|
|
|
struct header_t
|
|
|
|
{
|
2013-09-28 03:24:23 +00:00
|
|
|
enum { size = 0x100 };
|
|
|
|
|
|
|
|
char tag [35];
|
2007-10-11 23:11:58 +00:00
|
|
|
byte format;
|
|
|
|
byte version;
|
2013-09-28 03:24:23 +00:00
|
|
|
byte pc [ 2];
|
2007-10-11 23:11:58 +00:00
|
|
|
byte a, x, y, psw, sp;
|
2013-09-28 03:24:23 +00:00
|
|
|
byte unused [ 2];
|
|
|
|
char song [32];
|
|
|
|
char game [32];
|
|
|
|
char dumper [16];
|
|
|
|
char comment [32];
|
|
|
|
byte date [11];
|
|
|
|
byte len_secs [ 3];
|
|
|
|
byte fade_msec [ 4];
|
|
|
|
char author [32]; // sometimes first char should be skipped (see official SPC spec)
|
2007-10-11 23:11:58 +00:00
|
|
|
byte mute_mask;
|
|
|
|
byte emulator;
|
2013-09-28 03:24:23 +00:00
|
|
|
byte unused2 [46];
|
2007-10-11 23:11:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Header for currently loaded file
|
2013-09-28 03:24:23 +00:00
|
|
|
header_t const& header() const { return *(header_t const*) file_begin(); }
|
|
|
|
|
|
|
|
blargg_err_t hash_( Hash_Function& ) const;
|
2007-10-11 23:11:58 +00:00
|
|
|
|
2013-09-28 03:24:23 +00:00
|
|
|
static gme_type_t static_type() { return gme_spc_type; }
|
2007-10-11 23:11:58 +00:00
|
|
|
|
2013-09-28 03:24:23 +00:00
|
|
|
// Implementation
|
2007-10-11 23:11:58 +00:00
|
|
|
public:
|
|
|
|
Spc_Emu();
|
|
|
|
~Spc_Emu();
|
2013-09-28 03:24:23 +00:00
|
|
|
|
2007-10-11 23:11:58 +00:00
|
|
|
protected:
|
2013-09-28 03:24:23 +00:00
|
|
|
virtual blargg_err_t load_mem_( byte const [], int );
|
|
|
|
virtual blargg_err_t track_info_( track_info_t*, int track ) const;
|
|
|
|
virtual blargg_err_t set_sample_rate_( int );
|
|
|
|
virtual blargg_err_t start_track_( int );
|
|
|
|
virtual blargg_err_t play_( int, sample_t [] );
|
|
|
|
virtual blargg_err_t skip_( int );
|
|
|
|
virtual void mute_voices_( int );
|
|
|
|
virtual void set_tempo_( double );
|
|
|
|
|
2007-10-11 23:11:58 +00:00
|
|
|
private:
|
2013-09-28 03:24:23 +00:00
|
|
|
Spc_Emu_Resampler resampler;
|
|
|
|
Spc_Filter filter;
|
2007-10-11 23:11:58 +00:00
|
|
|
Snes_Spc apu;
|
2013-09-28 03:24:23 +00:00
|
|
|
|
|
|
|
byte const* trailer_() const;
|
|
|
|
int trailer_size_() const;
|
|
|
|
blargg_err_t play_and_filter( int count, sample_t out [] );
|
2007-10-11 23:11:58 +00:00
|
|
|
};
|
|
|
|
|
2013-09-28 03:24:23 +00:00
|
|
|
inline Snes_Spc const* Spc_Emu::get_apu() const { return &apu; }
|
|
|
|
inline Snes_Spc * Spc_Emu::get_apu() { return &apu; }
|
2007-10-11 23:11:58 +00:00
|
|
|
|
|
|
|
#endif
|