summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/snes_snd.h
blob: 2808b5f95f463fcb0268c457e75d0c7706b36ef7 (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
// license:LGPL-2.1+
// copyright-holders:R. Belmont, Brad Martin
/*****************************************************************************
 *
 * audio/snes_spc.h
 *
 ****************************************************************************/

#ifndef MAME_AUDIO_SNES_SND_H
#define MAME_AUDIO_SNES_SND_H


/***************************************************************************
 TYPE DEFINITIONS
 ***************************************************************************/

class snes_sound_device : public device_t, public device_sound_interface
{
public:
	snes_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 32'000);

	void set_volume(int volume);

	DECLARE_READ8_MEMBER( spc_io_r );
	DECLARE_READ8_MEMBER( spc_ram_r );
	DECLARE_READ8_MEMBER( spc_port_out );
	DECLARE_WRITE8_MEMBER( spc_io_w );
	DECLARE_WRITE8_MEMBER( spc_ram_w );
	DECLARE_WRITE8_MEMBER( spc_port_in );

//  uint8_t *spc_get_ram() { return m_ram; }

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	// sound stream update overrides
	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

private:
	enum class env_state_t32 : u8
	{
		ATTACK,
		DECAY,
		SUSTAIN,
		RELEASE
	};


	static constexpr unsigned SNES_SPCRAM_SIZE = 0x10000;


	struct voice_state_type                      /* Voice state type             */
	{
		uint16_t        mem_ptr;        /* Sample data memory pointer   */
		int             end;            /* End or loop after block      */
		int             envcnt;         /* Counts to envelope update    */
		env_state_t32   envstate;       /* Current envelope state       */
		int             envx;           /* Last env height (0-0x7FFF)   */
		int             filter;         /* Last header's filter         */
		int             half;           /* Active nybble of BRR         */
		int             header_cnt;     /* Bytes before new header (0-8)*/
		int             mixfrac;        /* Fractional part of smpl pstn */
		int             on_cnt;         /* Is it time to turn on yet?   */
		int             pitch;          /* Sample pitch (4096->32000Hz) */
		int             range;          /* Last header's range          */
		uint32_t        samp_id;        /* Sample ID#                   */
		int             sampptr;        /* Where in sampbuf we are      */
		int32_t         smp1;           /* Last sample (for BRR filter) */
		int32_t         smp2;           /* Second-to-last sample decoded*/
		short           sampbuf[4];   /* Buffer for Gaussian interp   */
	};

	struct src_dir_type                      /* Source directory entry       */
	{
		uint16_t  vptr;           /* Ptr to start of sample data  */
		uint16_t  lptr;           /* Loop pointer in sample data  */
	};


	DECLARE_READ8_MEMBER(dsp_io_r);
	DECLARE_WRITE8_MEMBER(dsp_io_w);
//  TIMER_CALLBACK_MEMBER(spc_timer);
	void dsp_reset();
	void dsp_update(short *sound_ptr);
	int advance_envelope(int v);
	void state_register();

	// internal state
	std::unique_ptr<uint8_t[]>                   m_ram;
	sound_stream            *m_channel;
	uint8_t                 m_dsp_regs[256];      /* DSP registers */
	uint8_t                 m_ipl_region[64];     /* SPC top 64 bytes */

	int                     m_keyed_on;
	int                     m_keys;               /* 8-bits for 8 voices */
	voice_state_type        m_voice_state[8];

	/* Noise stuff */
	int                     m_noise_cnt;
	int                     m_noise_lev;

	/* These are for the FIR echo filter */
#ifndef NO_ECHO
	short                   m_fir_lbuf[8];
	short                   m_fir_rbuf[8];
	int                     m_fir_ptr;
	int                     m_echo_ptr;
#endif

	enum
	{
		TIMER_TICK_ID = 1
	};
	/* timers */
	emu_timer                 *m_tick_timer;
	bool                      m_timer_enabled[3];
	uint16_t                  m_counter[3];
	uint8_t                   m_subcounter[3];
	inline void update_timer_tick(uint8_t which);

	/* IO ports */
	uint8_t                   m_port_in[4];         /* SPC input ports */
	uint8_t                   m_port_out[4];        /* SPC output ports */

	uint16_t                  m_TnDIV[3]; /**< Timer N Divider */
};

DECLARE_DEVICE_TYPE(SNES_SOUND, snes_sound_device)


#endif // MAME_AUDIO_SNES_SND_H