173 lines
3.5 KiB
C++
Executable File
173 lines
3.5 KiB
C++
Executable File
class aDSP : public DSP {
|
|
private:
|
|
uint8 dspram[128];
|
|
uint8 *spcram;
|
|
|
|
uint32 dsp_counter;
|
|
|
|
enum { BRR_END = 1, BRR_LOOP = 2 };
|
|
|
|
uint8 readb (uint16 addr);
|
|
uint16 readw (uint16 addr);
|
|
void writeb(uint16 addr, uint8 data);
|
|
void writew(uint16 addr, uint16 data);
|
|
|
|
public:
|
|
static const uint16 rate_table[32];
|
|
static const int16 gaussian_table[512];
|
|
|
|
enum EnvelopeStates {
|
|
ATTACK,
|
|
DECAY,
|
|
SUSTAIN,
|
|
RELEASE,
|
|
SILENCE
|
|
};
|
|
|
|
enum EnvelopeModes {
|
|
DIRECT,
|
|
LINEAR_DEC,
|
|
EXP_DEC,
|
|
LINEAR_INC,
|
|
BENT_INC,
|
|
|
|
FAST_ATTACK,
|
|
RELEASE_DEC
|
|
};
|
|
|
|
private:
|
|
struct Status {
|
|
//$0c,$1c
|
|
int8 MVOLL, MVOLR;
|
|
//$2c,$3c
|
|
int8 EVOLL, EVOLR;
|
|
//$4c,$5c
|
|
uint8 KON, KOFF;
|
|
//$6c
|
|
uint8 FLG;
|
|
//$7c
|
|
uint8 ENDX;
|
|
//$0d
|
|
int8 EFB;
|
|
//$2d,$3d,$4d
|
|
uint8 PMON, NON, EON;
|
|
//$5d
|
|
uint8 DIR;
|
|
//$6d,$7d
|
|
uint8 ESA, EDL;
|
|
|
|
//$xf
|
|
int8 FIR[8];
|
|
|
|
//internal variables
|
|
uint8 kon, esa;
|
|
|
|
int16 noise_ctr, noise_rate;
|
|
uint16 noise_sample;
|
|
|
|
uint16 echo_index, echo_length;
|
|
int16 fir_buffer[2][8];
|
|
uint8 fir_buffer_index;
|
|
|
|
//functions
|
|
bool soft_reset() { return !!(FLG & 0x80); }
|
|
bool mute() { return !!(FLG & 0x40); }
|
|
bool echo_write() { return !(FLG & 0x20); }
|
|
} status;
|
|
|
|
struct Voice {
|
|
//$x0-$x1
|
|
int8 VOLL, VOLR;
|
|
//$x2-$x3
|
|
int16 PITCH;
|
|
//$x4
|
|
uint8 SRCN;
|
|
//$x5-$x7
|
|
uint8 ADSR1, ADSR2, GAIN;
|
|
//$x8-$x9
|
|
uint8 ENVX, OUTX;
|
|
|
|
//internal variables
|
|
int16 pitch_ctr;
|
|
|
|
int8 brr_index;
|
|
uint16 brr_ptr;
|
|
uint8 brr_header;
|
|
bool brr_looped;
|
|
|
|
int16 brr_data[4];
|
|
uint8 brr_data_index;
|
|
|
|
int16 envx;
|
|
uint16 env_ctr, env_rate, env_sustain;
|
|
enum EnvelopeStates env_state;
|
|
enum EnvelopeModes env_mode;
|
|
|
|
int16 outx;
|
|
|
|
//functions
|
|
int16 pitch_rate() { return PITCH & 0x3fff; }
|
|
|
|
uint8 brr_header_shift() { return brr_header >> 4; }
|
|
uint8 brr_header_filter() { return (brr_header >> 2) & 3; }
|
|
uint8 brr_header_flags() { return brr_header & 3; }
|
|
|
|
bool ADSR_enabled() { return !!(ADSR1 & 0x80); }
|
|
uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; }
|
|
uint8 ADSR_attack() { return ADSR1 & 15; }
|
|
uint8 ADSR_sus_level() { return ADSR2 >> 5; }
|
|
uint8 ADSR_sus_rate() { return ADSR2 & 31; }
|
|
|
|
void AdjustEnvelope() {
|
|
if(env_state == SILENCE) {
|
|
env_mode = DIRECT;
|
|
env_rate = 0;
|
|
envx = 0;
|
|
} else if(env_state == RELEASE) {
|
|
env_mode = RELEASE_DEC;
|
|
env_rate = 0x7800;
|
|
} else if(ADSR_enabled()) {
|
|
switch(env_state) {
|
|
case ATTACK:
|
|
env_rate = rate_table[(ADSR_attack() << 1) + 1];
|
|
env_mode = (env_rate == 0x7800) ? FAST_ATTACK : LINEAR_INC;
|
|
break;
|
|
case DECAY:
|
|
env_rate = rate_table[(ADSR_decay() << 1) + 0x10];
|
|
env_mode = EXP_DEC;
|
|
break;
|
|
case SUSTAIN:
|
|
env_rate = rate_table[ADSR_sus_rate()];
|
|
env_mode = (env_rate == 0) ? DIRECT : EXP_DEC;
|
|
break;
|
|
}
|
|
} else if(GAIN & 0x80) {
|
|
switch(GAIN & 0x60) {
|
|
case 0x00: env_mode = LINEAR_DEC; break;
|
|
case 0x20: env_mode = EXP_DEC; break;
|
|
case 0x40: env_mode = LINEAR_INC; break;
|
|
case 0x60: env_mode = BENT_INC; break;
|
|
}
|
|
env_rate = rate_table[GAIN & 0x1f];
|
|
} else {
|
|
env_mode = DIRECT;
|
|
env_rate = 0;
|
|
envx = (GAIN & 0x7f) << 4;
|
|
}
|
|
}
|
|
} voice[8];
|
|
|
|
public:
|
|
void enter();
|
|
void run();
|
|
|
|
uint8 read (uint8 addr);
|
|
void write(uint8 addr, uint8 data);
|
|
|
|
void power();
|
|
void reset();
|
|
|
|
aDSP();
|
|
~aDSP();
|
|
};
|