// license:BSD-3-Clause
// copyright-holders:Miguel Angel Horna
#ifndef MAME_SOUND_MULTIPCM_H
#define MAME_SOUND_MULTIPCM_H
#pragma once
class multipcm_device : public device_t,
public device_sound_interface,
public device_rom_interface
{
public:
multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_clock_changed() override;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
// device_rom_interface overrides
virtual void rom_bank_updated() override;
private:
struct sample_t
{
uint32_t m_start;
uint32_t m_loop;
uint32_t m_end;
uint8_t m_attack_reg;
uint8_t m_decay1_reg;
uint8_t m_decay2_reg;
uint8_t m_decay_level;
uint8_t m_release_reg;
uint8_t m_key_rate_scale;
uint8_t m_lfo_vibrato_reg;
uint8_t m_lfo_amplitude_reg;
};
enum class state_t : u8
{
ATTACK,
DECAY1,
DECAY2,
RELEASE
};
struct envelope_gen_t
{
int32_t m_volume;
state_t m_state;
int32_t step;
//step vals
int32_t m_attack_rate; // Attack
int32_t m_decay1_rate; // Decay1
int32_t m_decay2_rate; // Decay2
int32_t m_release_rate; // Release
int32_t m_decay_level; // Decay level
};
struct lfo_t
{
uint16_t m_phase;
uint32_t m_phase_step;
int32_t *m_table;
int32_t *m_scale;
};
struct slot_t
{
uint8_t m_slot_index;
uint8_t m_regs[8];
bool m_playing;
sample_t m_sample;
uint32_t m_base;
uint32_t m_offset;
uint32_t m_step;
uint32_t m_pan;
uint32_t m_total_level;
uint32_t m_dest_total_level;
int32_t m_total_level_step;
int32_t m_prev_sample;
envelope_gen_t m_envelope_gen;
lfo_t m_pitch_lfo; // Pitch lfo
lfo_t m_amplitude_lfo; // AM lfo
};
// internal state
sound_stream *m_stream;
slot_t *m_slots;
uint32_t m_cur_slot;
uint32_t m_address;
float m_rate;
uint32_t *m_attack_step;
uint32_t *m_decay_release_step; // Envelope step tables
uint32_t *m_freq_step_table; // Frequency step table
int32_t *m_left_pan_table;
int32_t *m_right_pan_table;
int32_t *m_linear_to_exp_volume;
int32_t *m_total_level_steps;
int32_t *m_pitch_table;
int32_t **m_pitch_scale_tables;
int32_t *m_amplitude_table;
int32_t **m_amplitude_scale_tables;
uint32_t value_to_fixed(const uint32_t bits, const float value);
void init_sample(sample_t *sample, uint32_t index);
// Internal LFO functions
void lfo_init();
void lfo_compute_step(lfo_t *lfo, uint32_t lfo_frequency, uint32_t LFOS, int32_t amplitude_lfo);
int32_t pitch_lfo_step(lfo_t *lfo);
int32_t amplitude_lfo_step(lfo_t *lfo);
// Internal envelope functions
int32_t envelope_generator_update(slot_t *slot);
void envelope_generator_calc(slot_t *slot);
uint32_t get_rate(uint32_t *steps, uint32_t rate, uint32_t val);
void write_slot(slot_t *slot, int32_t reg, uint8_t data);
int16_t clamp_to_int16(int32_t value);
static constexpr uint32_t TL_SHIFT = 12;
static const int32_t VALUE_TO_CHANNEL[32];
static constexpr uint32_t EG_SHIFT = 16;
static const double BASE_TIMES[64];
static constexpr uint32_t LFO_SHIFT = 8;
static const float LFO_FREQ[8];
static const float PHASE_SCALE_LIMIT[8];
static const float AMPLITUDE_SCALE_LIMIT[8];
};
DECLARE_DEVICE_TYPE(MULTIPCM, multipcm_device)
#endif // MAME_SOUND_MULTIPCM_H