summaryrefslogtreecommitdiff
path: root/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h')
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h152
1 files changed, 152 insertions, 0 deletions
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h
new file mode 100644
index 00000000..36492275
--- /dev/null
+++ b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h
@@ -0,0 +1,152 @@
+// Super Nintendo (SNES) SPC DSP emulator
+
+// Game_Music_Emu 0.5.2
+#ifndef SPC_DSP_H
+#define SPC_DSP_H
+
+#include "blargg_common.h"
+
+class Spc_Dsp {
+ typedef BOOST::int8_t int8_t;
+ typedef BOOST::uint8_t uint8_t;
+public:
+
+ // Keeps pointer to 64K ram
+ Spc_Dsp( uint8_t* ram );
+
+ // Mute voice n if bit n (1 << n) of mask is clear.
+ enum { voice_count = 8 };
+ void mute_voices( int mask );
+
+ // Clear state and silence everything.
+ void reset();
+
+ // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped to
+ // the 16-bit sample range.
+ void set_gain( double );
+
+ // If true, prevent channels and global volumes from being phase-negated
+ void disable_surround( bool disable );
+
+ // Read/write register 'n', where n ranges from 0 to register_count - 1.
+ enum { register_count = 128 };
+ int read ( int n );
+ void write( int n, int );
+
+ // Run DSP for 'count' samples. Write resulting samples to 'buf' if not NULL.
+ void run( long count, short* buf = NULL );
+
+
+// End of public interface
+private:
+
+ struct raw_voice_t {
+ int8_t left_vol;
+ int8_t right_vol;
+ uint8_t rate [2];
+ uint8_t waveform;
+ uint8_t adsr [2]; // envelope rates for attack, decay, and sustain
+ uint8_t gain; // envelope gain (if not using ADSR)
+ int8_t envx; // current envelope level
+ int8_t outx; // current sample
+ int8_t unused [6];
+ };
+
+ struct globals_t {
+ int8_t unused1 [12];
+ int8_t left_volume; // 0C Main Volume Left (-.7)
+ int8_t echo_feedback; // 0D Echo Feedback (-.7)
+ int8_t unused2 [14];
+ int8_t right_volume; // 1C Main Volume Right (-.7)
+ int8_t unused3 [15];
+ int8_t left_echo_volume; // 2C Echo Volume Left (-.7)
+ uint8_t pitch_mods; // 2D Pitch Modulation on/off for each voice
+ int8_t unused4 [14];
+ int8_t right_echo_volume; // 3C Echo Volume Right (-.7)
+ uint8_t noise_enables; // 3D Noise output on/off for each voice
+ int8_t unused5 [14];
+ uint8_t key_ons; // 4C Key On for each voice
+ uint8_t echo_ons; // 4D Echo on/off for each voice
+ int8_t unused6 [14];
+ uint8_t key_offs; // 5C key off for each voice (instantiates release mode)
+ uint8_t wave_page; // 5D source directory (wave table offsets)
+ int8_t unused7 [14];
+ uint8_t flags; // 6C flags and noise freq
+ uint8_t echo_page; // 6D
+ int8_t unused8 [14];
+ uint8_t wave_ended; // 7C
+ uint8_t echo_delay; // 7D ms >> 4
+ char unused9 [2];
+ };
+
+ union {
+ raw_voice_t voice [voice_count];
+ uint8_t reg [register_count];
+ globals_t g;
+ };
+
+ uint8_t* const ram;
+
+ // Cache of echo FIR values for faster access
+ short fir_coeff [voice_count];
+
+ // fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code
+ short fir_buf [16] [2];
+ int fir_offset; // (0 to 7)
+
+ enum { emu_gain_bits = 8 };
+ int emu_gain;
+
+ int keyed_on; // 8-bits for 8 voices
+ int keys;
+
+ int echo_ptr;
+ int noise_amp;
+ int noise;
+ int noise_count;
+
+ int surround_threshold;
+
+ static BOOST::int16_t const gauss [];
+
+ enum state_t {
+ state_attack,
+ state_decay,
+ state_sustain,
+ state_release
+ };
+
+ struct voice_t {
+ short volume [2];
+ short fraction;// 12-bit fractional position
+ short interp3; // most recent four decoded samples
+ short interp2;
+ short interp1;
+ short interp0;
+ short block_remain; // number of nybbles remaining in current block
+ unsigned short addr;
+ short block_header; // header byte from current block
+ short envcnt;
+ short envx;
+ short on_cnt;
+ short enabled; // 7 if enabled, 31 if disabled
+ short envstate;
+ short unused; // pad to power of 2
+ };
+
+ voice_t voice_state [voice_count];
+
+ int clock_envelope( int );
+};
+
+inline void Spc_Dsp::disable_surround( bool disable ) { surround_threshold = disable ? 0 : -0x7FFF; }
+
+inline void Spc_Dsp::set_gain( double v ) { emu_gain = (int) (v * (1 << emu_gain_bits)); }
+
+inline int Spc_Dsp::read( int i )
+{
+ assert( (unsigned) i < register_count );
+ return reg [i];
+}
+
+#endif