LMMS
Loading...
Searching...
No Matches
Spc_Dsp.h
Go to the documentation of this file.
1// Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one)
2
3// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
4#ifndef SPC_DSP_H
5#define SPC_DSP_H
6
7#include "blargg_common.h"
8
9struct Spc_Dsp {
10public:
11// Setup
12
13 // Initializes DSP and has it use the 64K RAM provided
14 void init( void* ram_64k );
15
16 // Sets destination for output samples. If out is NULL or out_size is 0,
17 // doesn't generate any.
18 typedef short sample_t;
19 void set_output( sample_t* out, int out_size );
20
21 // Number of samples written to output since it was last set, always
22 // a multiple of 2. Undefined if more samples were generated than
23 // output buffer could hold.
24 int sample_count() const;
25
26// Emulation
27
28 // Resets DSP to power-on state
29 void reset();
30
31 // Emulates pressing reset switch on SNES
32 void soft_reset();
33
34 // Reads/writes DSP registers. For accuracy, you must first call spc_run_dsp()
35 // to catch the DSP up to present.
36 int read ( int addr ) const;
37 void write( int addr, int data );
38
39 // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
40 // a pair of samples is be generated.
41 void run( int clock_count );
42
43// Sound control
44
45 // Mutes voices corresponding to non-zero bits in mask (overrides VxVOL with 0).
46 // Reduces emulation accuracy.
47 enum { voice_count = 8 };
48 void mute_voices( int mask );
49
50 // If true, prevents channels and global volumes from being phase-negated
51 void disable_surround( bool disable = true );
52
53// State
54
55 // Resets DSP and uses supplied values to initialize registers
56 enum { register_count = 128 };
57 void load( uint8_t const regs [register_count] );
58
59// DSP register addresses
60
61 // Global registers
62 enum {
63 r_mvoll = 0x0C, r_mvolr = 0x1C,
64 r_evoll = 0x2C, r_evolr = 0x3C,
65 r_kon = 0x4C, r_koff = 0x5C,
66 r_flg = 0x6C, r_endx = 0x7C,
67 r_efb = 0x0D, r_pmon = 0x2D,
68 r_non = 0x3D, r_eon = 0x4D,
69 r_dir = 0x5D, r_esa = 0x6D,
70 r_edl = 0x7D,
71 r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
72 };
73
74 // Voice registers
75 enum {
76 v_voll = 0x00, v_volr = 0x01,
77 v_pitchl = 0x02, v_pitchh = 0x03,
78 v_srcn = 0x04, v_adsr0 = 0x05,
79 v_adsr1 = 0x06, v_gain = 0x07,
80 v_envx = 0x08, v_outx = 0x09
81 };
82
83public:
84 enum { extra_size = 16 };
85 sample_t* extra() { return m.extra; }
86 sample_t const* out_pos() const { return m.out; }
87public:
88 BLARGG_DISABLE_NOTHROW
89
90 enum { echo_hist_size = 8 };
91
93 enum { brr_buf_size = 12 };
94 struct voice_t
95 {
96 int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
97 int* buf_pos; // place in buffer where next samples will be decoded
98 int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
99 int brr_addr; // address of current BRR block
100 int brr_offset; // current decoding offset in BRR block
101 int kon_delay; // KON delay/current setup phase
103 int env; // current envelope level
104 int hidden_env; // used by GAIN mode 7, very obscure quirk
105 int volume [2]; // copy of volume from DSP registers, with surround disabled
106 int enabled; // -1 if enabled, 0 if muted
107 };
108private:
109 struct state_t
110 {
112
113 // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
115 int (*echo_hist_pos) [2]; // &echo_hist [0 to 7]
116
117 int every_other_sample; // toggles every sample
118 int kon; // KON value when last checked
119 int noise;
120 int echo_offset; // offset from ESA in echo buffer
121 int echo_length; // number of bytes that echo_offset will stop at
122 int phase; // next clock cycle to run (0-31)
123 unsigned counters [4];
124
127
129
130 unsigned* counter_select [32];
131
132 // non-emulation state
133 uint8_t* ram; // 64K shared RAM between DSP and SMP
140 };
142
143 void init_counter();
144 void run_counter( int );
145 void soft_reset_common();
146 void write_outline( int addr, int data );
147 void update_voice_vol( int addr );
148};
149
150#include <assert.h>
151
152inline int Spc_Dsp::sample_count() const { return m.out - m.out_begin; }
153
154inline int Spc_Dsp::read( int addr ) const
155{
156 assert( (unsigned) addr < register_count );
157 return m.regs [addr];
158}
159
160inline void Spc_Dsp::update_voice_vol( int addr )
161{
162 int l = (int8_t) m.regs [addr + v_voll];
163 int r = (int8_t) m.regs [addr + v_volr];
164
165 if ( l * r < m.surround_threshold )
166 {
167 // signs differ, so negate those that are negative
168 l ^= l >> 7;
169 r ^= r >> 7;
170 }
171
172 voice_t& v = m.voices [addr >> 4];
173 int enabled = v.enabled;
174 v.volume [0] = l & enabled;
175 v.volume [1] = r & enabled;
176}
177
178inline void Spc_Dsp::write( int addr, int data )
179{
180 assert( (unsigned) addr < register_count );
181
182 m.regs [addr] = (uint8_t) data;
183 int low = addr & 0x0F;
184 if ( low < 0x2 ) // voice volumes
185 {
186 update_voice_vol( low ^ addr );
187 }
188 else if ( low == 0xC )
189 {
190 if ( addr == r_kon )
191 m.new_kon = (uint8_t) data;
192
193 if ( addr == r_endx ) // always cleared, regardless of data written
194 m.regs [r_endx] = 0;
195 }
196}
197
198inline void Spc_Dsp::disable_surround( bool disable )
199{
200 m.surround_threshold = disable ? 0 : -0x4000;
201}
202
203#define SPC_NO_COPY_STATE_FUNCS 1
204
205#define SPC_LESS_ACCURATE 1
206
207#endif
assert(0)
static const unsigned long mask[]
Definition bitwise.c:31
int * l
Definition inflate.c:1579
unsigned v[N_MAX]
Definition inflate.c:1584
JSAMPIMAGE data
Definition jpeglib.h:945
float out
Definition lilv_test.c:1461
unsigned char uint8_t
Definition mid.cpp:98
signed char int8_t
Definition mid.cpp:95
Definition Spc_Dsp.h:110
sample_t * out_end
Definition Spc_Dsp.h:137
int(* echo_hist_pos)[2]
Definition Spc_Dsp.h:115
sample_t * out
Definition Spc_Dsp.h:136
int surround_threshold
Definition Spc_Dsp.h:135
int new_kon
Definition Spc_Dsp.h:125
sample_t extra[extra_size]
Definition Spc_Dsp.h:139
int mute_mask
Definition Spc_Dsp.h:134
uint8_t * ram
Definition Spc_Dsp.h:133
voice_t voices[voice_count]
Definition Spc_Dsp.h:128
unsigned counters[4]
Definition Spc_Dsp.h:123
int every_other_sample
Definition Spc_Dsp.h:117
int kon
Definition Spc_Dsp.h:118
sample_t * out_begin
Definition Spc_Dsp.h:138
unsigned * counter_select[32]
Definition Spc_Dsp.h:130
int phase
Definition Spc_Dsp.h:122
int t_koff
Definition Spc_Dsp.h:126
int echo_hist[echo_hist_size *2][2]
Definition Spc_Dsp.h:114
int echo_length
Definition Spc_Dsp.h:121
int noise
Definition Spc_Dsp.h:119
uint8_t regs[register_count]
Definition Spc_Dsp.h:111
int echo_offset
Definition Spc_Dsp.h:120
Definition Spc_Dsp.h:95
env_mode_t env_mode
Definition Spc_Dsp.h:102
int volume[2]
Definition Spc_Dsp.h:105
int enabled
Definition Spc_Dsp.h:106
int hidden_env
Definition Spc_Dsp.h:104
int interp_pos
Definition Spc_Dsp.h:98
int brr_addr
Definition Spc_Dsp.h:99
int * buf_pos
Definition Spc_Dsp.h:97
int env
Definition Spc_Dsp.h:103
int buf[brr_buf_size *2]
Definition Spc_Dsp.h:96
int kon_delay
Definition Spc_Dsp.h:101
int brr_offset
Definition Spc_Dsp.h:100
Definition Spc_Dsp.h:9
sample_t const * out_pos() const
Definition Spc_Dsp.h:86
void soft_reset_common()
Definition Spc_Dsp.cpp:666
void disable_surround(bool disable=true)
Definition Spc_Dsp.h:198
void run(int clock_count)
Definition Spc_Dsp.cpp:186
@ echo_hist_size
Definition Spc_Dsp.h:90
void update_voice_vol(int addr)
Definition Spc_Dsp.h:160
int sample_count() const
Definition Spc_Dsp.h:152
@ v_voll
Definition Spc_Dsp.h:76
@ v_adsr0
Definition Spc_Dsp.h:78
@ v_envx
Definition Spc_Dsp.h:80
@ v_pitchl
Definition Spc_Dsp.h:77
@ v_srcn
Definition Spc_Dsp.h:78
@ v_pitchh
Definition Spc_Dsp.h:77
@ v_outx
Definition Spc_Dsp.h:80
@ v_volr
Definition Spc_Dsp.h:76
@ v_gain
Definition Spc_Dsp.h:79
@ v_adsr1
Definition Spc_Dsp.h:79
@ extra_size
Definition Spc_Dsp.h:84
@ brr_buf_size
Definition Spc_Dsp.h:93
void set_output(sample_t *out, int out_size)
Definition Spc_Dsp.cpp:76
state_t m
Definition Spc_Dsp.h:141
int read(int addr) const
Definition Spc_Dsp.h:154
void write(int addr, int data)
Definition Spc_Dsp.h:178
sample_t * extra()
Definition Spc_Dsp.h:85
void soft_reset()
Definition Spc_Dsp.cpp:679
void mute_voices(int mask)
Definition Spc_Dsp.cpp:632
void write_outline(int addr, int data)
@ r_koff
Definition Spc_Dsp.h:65
@ r_pmon
Definition Spc_Dsp.h:67
@ r_evolr
Definition Spc_Dsp.h:64
@ r_flg
Definition Spc_Dsp.h:66
@ r_efb
Definition Spc_Dsp.h:67
@ r_mvoll
Definition Spc_Dsp.h:63
@ r_endx
Definition Spc_Dsp.h:66
@ r_edl
Definition Spc_Dsp.h:70
@ r_fir
Definition Spc_Dsp.h:71
@ r_evoll
Definition Spc_Dsp.h:64
@ r_esa
Definition Spc_Dsp.h:69
@ r_eon
Definition Spc_Dsp.h:68
@ r_kon
Definition Spc_Dsp.h:65
@ r_dir
Definition Spc_Dsp.h:69
@ r_mvolr
Definition Spc_Dsp.h:63
@ r_non
Definition Spc_Dsp.h:68
@ voice_count
Definition Spc_Dsp.h:47
void load(uint8_t const regs[register_count])
Definition Spc_Dsp.cpp:685
@ register_count
Definition Spc_Dsp.h:56
env_mode_t
Definition Spc_Dsp.h:92
@ env_attack
Definition Spc_Dsp.h:92
@ env_decay
Definition Spc_Dsp.h:92
@ env_release
Definition Spc_Dsp.h:92
@ env_sustain
Definition Spc_Dsp.h:92
void run_counter(int)
Definition Spc_Dsp.cpp:172
void init_counter()
Definition Spc_Dsp.cpp:153
short sample_t
Definition Spc_Dsp.h:18
void reset()
Definition Spc_Dsp.cpp:704
int r
Definition crypt.c:458
ZCONST uch * init
Definition extract.c:2392
typedef int(UZ_EXP MsgFn)()