// license:BSD-3-Clause
// copyright-holders:Miguel Angel Horna
#pragma once
#ifndef __MULTIPCM_H__
#define __MULTIPCM_H__
class multipcm_device : public device_t,
public device_sound_interface,
public device_memory_interface
{
public:
multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~multipcm_device() {}
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
void set_bank(UINT32 leftoffs, UINT32 rightoffs);
protected:
// device-level overrides
virtual void device_config_complete() override;
virtual void device_start() 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_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override;
const address_space_config m_space_config;
private:
struct sample_t
{
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
{
ATTACK,
DECAY1,
DECAY2,
RELEASE
};
struct envelope_gen_t
{
INT32 m_volume;
state_t m_state;
INT32 step;
//step vals
INT32 m_attack_rate; // Attack
INT32 m_decay1_rate; // Decay1
INT32 m_decay2_rate; // Decay2
INT32 m_release_rate; // Release
INT32 m_decay_level; // Decay level
};
struct lfo_t
{
UINT16 m_phase;
UINT32 m_phase_step;
INT32 *m_table;
INT32 *m_scale;
};
struct slot_t
{
UINT8 m_slot_index;
UINT8 m_regs[8];
bool m_playing;
sample_t *m_sample;
UINT32 m_base;
UINT32 m_offset;
UINT32 m_step;
UINT32 m_pan;
UINT32 m_total_level;
UINT32 m_dest_total_level;
INT32 m_total_level_step;
INT32 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;
sample_t *m_samples; // Max 512 samples
slot_t *m_slots;
UINT32 m_cur_slot;
UINT32 m_address;
UINT32 m_bank_right;
UINT32 m_bank_left;
float m_rate;
UINT32 *m_attack_step;
UINT32 *m_decay_release_step; // Envelope step tables
UINT32 *m_freq_step_table; // Frequency step table
direct_read_data *m_direct;
INT32 *m_left_pan_table;
INT32 *m_right_pan_table;
INT32 *m_linear_to_exp_volume;
INT32 *m_total_level_steps;
INT32 *m_pitch_table;
INT32 **m_pitch_scale_tables;
INT32 *m_amplitude_table;
INT32 **m_amplitude_scale_tables;
UINT32 value_to_fixed(const UINT32 bits, const float value);
// Internal LFO functions
void lfo_init();
void lfo_compute_step(lfo_t *lfo, UINT32 lfo_frequency, UINT32 LFOS, INT32 amplitude_lfo);
INT32 pitch_lfo_step(lfo_t *lfo);
INT32 amplitude_lfo_step(lfo_t *lfo);
// Internal envelope functions
INT32 envelope_generator_update(slot_t *slot);
void envelope_generator_calc(slot_t *slot);
UINT32 get_rate(UINT32 *steps, UINT32 rate, UINT32 val);
void write_slot(slot_t *slot, INT32 reg, UINT8 data);
INT16 clamp_to_int16(INT32 value);
static const UINT32 TL_SHIFT;
static const INT32 VALUE_TO_CHANNEL[32];
static const UINT32 EG_SHIFT;
static const double BASE_TIMES[64];
static const UINT32 LFO_SHIFT;
static const float LFO_FREQ[8];
static const float PHASE_SCALE_LIMIT[8];
static const float AMPLITUDE_SCALE_LIMIT[8];
};
extern const device_type MULTIPCM;
#endif /* __MULTIPCM_H__ */