mirror of
https://github.com/holub/mame
synced 2025-06-21 19:56:53 +03:00
Make multipcm cache sample data on keyon, nw
This commit is contained in:
parent
96a3e2f005
commit
d7f7131a09
@ -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))
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user