Make multipcm cache sample data on keyon, nw

This commit is contained in:
therealmogminer@gmail.com 2016-08-18 18:12:50 +02:00
parent 96a3e2f005
commit d7f7131a09
2 changed files with 48 additions and 46 deletions

View File

@ -74,6 +74,23 @@ const INT32 multipcm_device::VALUE_TO_CHANNEL[32] =
const UINT32 multipcm_device::TL_SHIFT = 12;
const UINT32 multipcm_device::EG_SHIFT = 16;
void multipcm_device::init_sample(sample_t *sample, UINT32 index)
{
UINT32 address = index * 12;
sample->m_start = (read_byte(address) << 16) | (read_byte(address + 1) << 8) | read_byte(address + 2);
sample->m_loop = (read_byte(address + 3) << 8) | read_byte(address + 4);
sample->m_end = 0xffff - ((read_byte(address + 5) << 8) | read_byte(address + 6));
sample->m_attack_reg = (read_byte(address + 8) >> 4) & 0xf;
sample->m_decay1_reg = read_byte(address + 8) & 0xf;
sample->m_decay2_reg = read_byte(address + 9) & 0xf;
sample->m_decay_level = (read_byte(address + 9) >> 4) & 0xf;
sample->m_release_reg = read_byte(address + 10) & 0xf;
sample->m_key_rate_scale = (read_byte(address + 10) >> 4) & 0xf;
sample->m_lfo_vibrato_reg = read_byte(address + 7);
sample->m_lfo_amplitude_reg = read_byte(address + 11) & 0xf;
}
INT32 multipcm_device::envelope_generator_update(slot_t *slot)
{
switch(slot->m_envelope_gen.m_state)
@ -149,20 +166,20 @@ void multipcm_device::envelope_generator_calc(slot_t *slot)
}
INT32 rate;
if (slot->m_sample->key_rate_scale() != 0xf)
if (slot->m_sample.m_key_rate_scale != 0xf)
{
rate = (octave + slot->m_sample->key_rate_scale()) * 2 + ((slot->m_regs[3] >> 3) & 1);
rate = (octave + slot->m_sample.m_key_rate_scale) * 2 + ((slot->m_regs[3] >> 3) & 1);
}
else
{
rate = 0;
}
slot->m_envelope_gen.m_attack_rate = get_rate(m_attack_step, rate, slot->m_sample->attack_reg());
slot->m_envelope_gen.m_decay1_rate = get_rate(m_decay_release_step, rate, slot->m_sample->decay1_reg());
slot->m_envelope_gen.m_decay2_rate = get_rate(m_decay_release_step, rate, slot->m_sample->decay2_reg());
slot->m_envelope_gen.m_release_rate = get_rate(m_decay_release_step, rate, slot->m_sample->release_reg());
slot->m_envelope_gen.m_decay_level = 0xf - slot->m_sample->decay_level();
slot->m_envelope_gen.m_attack_rate = get_rate(m_attack_step, rate, slot->m_sample.m_attack_reg);
slot->m_envelope_gen.m_decay1_rate = get_rate(m_decay_release_step, rate, slot->m_sample.m_decay1_reg);
slot->m_envelope_gen.m_decay2_rate = get_rate(m_decay_release_step, rate, slot->m_sample.m_decay2_reg);
slot->m_envelope_gen.m_release_rate = get_rate(m_decay_release_step, rate, slot->m_sample.m_release_reg);
slot->m_envelope_gen.m_decay_level = 0xf - slot->m_sample.m_decay_level;
}
@ -316,9 +333,10 @@ void multipcm_device::write_slot(slot_t *slot, INT32 reg, UINT8 data)
{
//according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
//the game should never change the sample while playing.
sample_t &sample = m_samples[slot->m_regs[1]];
write_slot(slot, 6, sample.lfo_vibrato_reg());
write_slot(slot, 7, sample.lfo_amplitude_reg());
sample_t sample;
init_sample(&sample, slot->m_regs[1]);
write_slot(slot, 6, sample.m_lfo_vibrato_reg);
write_slot(slot, 7, sample.m_lfo_amplitude_reg);
break;
}
case 2: //Pitch
@ -341,9 +359,9 @@ void multipcm_device::write_slot(slot_t *slot, INT32 reg, UINT8 data)
case 4: //KeyOn/Off (and more?)
if (data & 0x80) //KeyOn
{
slot->m_sample = &m_samples[slot->m_regs[1]];
init_sample(&slot->m_sample, slot->m_regs[1]);
slot->m_playing = true;
slot->m_base = slot->m_sample->start();
slot->m_base = slot->m_sample.m_start;
slot->m_offset = 0;
slot->m_prev_sample = 0;
slot->m_total_level = slot->m_dest_total_level << TL_SHIFT;
@ -369,7 +387,7 @@ void multipcm_device::write_slot(slot_t *slot, INT32 reg, UINT8 data)
{
if (slot->m_playing)
{
if (slot->m_sample->release_reg() != 0xf)
if (slot->m_sample.m_release_reg != 0xf)
{
slot->m_envelope_gen.m_state = RELEASE;
}
@ -453,7 +471,6 @@ multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag,
device_sound_interface(mconfig, *this),
device_rom_interface(mconfig, *this, 24),
m_stream(nullptr),
m_samples(nullptr),
m_slots(nullptr),
m_cur_slot(0),
m_address(0),
@ -584,13 +601,6 @@ void multipcm_device::device_start()
m_linear_to_exp_volume[i] = value_to_fixed(TL_SHIFT, exp_volume);
}
// Samples
m_samples = auto_alloc_array_clear(machine(), sample_t, 0x200);
for(INT32 sample = 0; sample < 512; ++sample)
{
m_samples[sample].init(sample, this);
}
save_item(NAME(m_cur_slot));
save_item(NAME(m_address));
save_item(NAME(m_bank_left));
@ -685,9 +695,9 @@ void multipcm_device::sound_stream_update(sound_stream &stream, stream_sample_t
}
slot->m_offset += step;
if (slot->m_offset >= (slot->m_sample->end() << TL_SHIFT))
if (slot->m_offset >= (slot->m_sample.m_end << TL_SHIFT))
{
slot->m_offset = slot->m_sample->loop() << TL_SHIFT;
slot->m_offset = slot->m_sample.m_loop << TL_SHIFT;
}
if (adr ^ (slot->m_offset >> TL_SHIFT))

View File

@ -27,28 +27,19 @@ protected:
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private:
class sample_t
struct sample_t
{
public:
sample_t() { }
void init(UINT32 index, multipcm_device* rom) { m_address = index * 12; m_rom = rom; }
UINT32 start() { return (m_rom->read_byte(m_address) << 16) | (m_rom->read_byte(m_address + 1) << 8) | m_rom->read_byte(m_address + 2); }
UINT32 loop() { return (m_rom->read_byte(m_address + 3) << 8) | m_rom->read_byte(m_address + 4); }
UINT32 end() { return 0xffff - ((m_rom->read_byte(m_address + 5) << 8) | m_rom->read_byte(m_address + 6)); }
UINT8 attack_reg() { return (m_rom->read_byte(m_address + 8) >> 4) & 0xf; }
UINT8 decay1_reg() { return m_rom->read_byte(m_address + 8) & 0xf; }
UINT8 decay2_reg() { return m_rom->read_byte(m_address + 9) & 0xf; }
UINT8 decay_level() { return (m_rom->read_byte(m_address + 9) >> 4) & 0xf; }
UINT8 release_reg() { return m_rom->read_byte(m_address + 10) & 0xf; }
UINT8 key_rate_scale() { return (m_rom->read_byte(m_address + 10) >> 4) & 0xf; }
UINT8 lfo_vibrato_reg() { return m_rom->read_byte(m_address + 7); }
UINT8 lfo_amplitude_reg() { return m_rom->read_byte(m_address + 11) & 0xf; }
private:
UINT32 m_address;
multipcm_device* m_rom;
UINT32 m_start;
UINT32 m_loop;
UINT32 m_end;
UINT8 m_attack_reg;
UINT8 m_decay1_reg;
UINT8 m_decay2_reg;
UINT8 m_decay_level;
UINT8 m_release_reg;
UINT8 m_key_rate_scale;
UINT8 m_lfo_vibrato_reg;
UINT8 m_lfo_amplitude_reg;
};
enum state_t
@ -85,7 +76,7 @@ private:
UINT8 m_slot_index;
UINT8 m_regs[8];
bool m_playing;
sample_t *m_sample;
sample_t m_sample;
UINT32 m_base;
UINT32 m_offset;
UINT32 m_step;
@ -101,7 +92,6 @@ private:
// internal state
sound_stream *m_stream;
sample_t *m_samples; // Max 512 samples
slot_t *m_slots;
UINT32 m_cur_slot;
UINT32 m_address;
@ -125,6 +115,8 @@ private:
UINT32 value_to_fixed(const UINT32 bits, const float value);
void init_sample(sample_t *sample, UINT32 index);
// Internal LFO functions
void lfo_init();
void lfo_compute_step(lfo_t *lfo, UINT32 lfo_frequency, UINT32 LFOS, INT32 amplitude_lfo);