summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/multipcm.h
blob: 6ea22c5e3e84f7252edce091ae04b4c71c0f217e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// 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();
	virtual void device_start();

	// sound stream update overrides
	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);

	// device_memory_interface overrides
	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;

	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();
	INT32 lfo_float_to_fixed(const float value);
	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__ */