summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/sound/okim9810.h
blob: 823a8e25f595d396cb54d1d3a1598dd8412c4fac (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
160
161
162
163
/***************************************************************************

    okim9810.h

    OKI MSM9810 ADCPM(2) sound chip.

    Notes:
    The master clock frequency for this chip can range from 3.5MHz to 4.5Mhz.
      The typical oscillator is a 4.096Mhz crystal.

***************************************************************************/

#pragma once

#ifndef __OKIM9810_H__
#define __OKIM9810_H__

#include "okiadpcm.h"


//**************************************************************************
//  CONSTANTS
//**************************************************************************

enum
{
	OKIM9810_ADPCM_PLAYBACK = 0,
	OKIM9810_ADPCM2_PLAYBACK = 1,
	OKIM9810_STRAIGHT8_PLAYBACK = 2,
	OKIM9810_NONLINEAR8_PLAYBACK = 3
};

enum
{
	OKIM9810_SECONDARY_FILTER = 0,
	OKIM9810_PRIMARY_FILTER = 1,
	OKIM9810_NO_FILTER = 2,
	OKIM9810_NO_FILTER2 = 3
};

enum
{
	OKIM9810_OUTPUT_TO_DIRECT_DAC = 0,
	OKIM9810_OUTPUT_TO_VOLTAGE_FOLLOWER = 1
};


//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_OKIM9810_ADD(_tag, _clock) \
	MCFG_DEVICE_ADD(_tag, OKIM9810, _clock)

#define MCFG_OKIM9810_REPLACE(_tag, _clock) \
	MCFG_DEVICE_REPLACE(_tag, OKIM9810, _clock)



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


// ======================> okim9810_device

class okim9810_device : public device_t,
						public device_sound_interface,
						public device_memory_interface
{
public:
	// construction/destruction
	okim9810_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	UINT8 read_status();
	void write_TMP_register(UINT8 command);
	void write_command(UINT8 command);

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );
	DECLARE_WRITE8_MEMBER( write_TMP_register );

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

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

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

	// a single voice
	class okim_voice
	{
	public:
		okim_voice();
		void generate_audio(direct_read_data &direct,
							stream_sample_t **buffers,
							int samples,
							const UINT8 global_volume,
							const UINT32 clock,
							const UINT8 filter_type);

		// computes volume scale from 3 volume numbers
		UINT8 volume_scale(const UINT8 global_volume,
							const UINT8 channel_volume,
							const UINT8 pan_volume) const;

		oki_adpcm_state m_adpcm;    // current ADPCM state
		oki_adpcm2_state m_adpcm2;  // current ADPCM2 state
		UINT8   m_playbackAlgo;     // current playback method
		bool    m_looping;
		UINT8   m_startFlags;
		UINT8   m_endFlags;
		offs_t  m_base_offset;      // pointer to the base memory location
		UINT32  m_count;            // total samples to play
		UINT32  m_samplingFreq;     // voice sampling frequency

		bool    m_playing;          // playback state
		UINT32  m_sample;           // current sample number

		UINT8   m_channel_volume;   // volume index set with the CVOL command
		UINT8   m_pan_volume_left;  // volume index set with the PAN command
		UINT8   m_pan_volume_right; // volume index set with the PAN command

		INT32   m_startSample;      // interpolation state - sample to interpolate from
		INT32   m_endSample;        // interpolation state - sample to interpolate to
		UINT32  m_interpSampleNum;  // interpolation state - fraction between start & end

		static const UINT8 s_volume_table[16];
	};

	okim_voice *get_voice(int which);
	
	// internal state
	const address_space_config  m_space_config;

	sound_stream* m_stream;
	direct_read_data* m_direct;

	UINT8 m_TMP_register;

	UINT8 m_global_volume;      // volume index set with the OPT command
	UINT8 m_filter_type;        // interpolation filter type set with the OPT command
	UINT8 m_output_level;       // flag stating if a voltage follower is connected

	static const int OKIM9810_VOICES = 8;
	okim_voice m_voice[OKIM9810_VOICES];

	static const UINT32 s_sampling_freq_table[16];
};


// device type definition
extern const device_type OKIM9810;



#endif // __OKIM9810_H__