1 // license:BSD-3-Clause
2 // copyright-holders:Krzysztof Strzecha
3 /***************************************************************************
4 
5   audio/dai_snd.c
6 
7   Functions to emulate sound hardware of DAI Personal Computer
8 
9   Krzysztof Strzecha
10 
11 ****************************************************************************/
12 
13 #include "emu.h"
14 #include "dai_snd.h"
15 
16 // device type definition
17 DEFINE_DEVICE_TYPE(DAI_SOUND, dai_sound_device, "dai_sound", "DAI Custom Sound")
18 
19 
20 //-------------------------------------------------
21 //  dai_sound_device - constructor
22 //-------------------------------------------------
23 
dai_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)24 dai_sound_device::dai_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
25 	: device_t(mconfig, DAI_SOUND, tag, owner, clock)
26 	, device_sound_interface(mconfig, *this)
27 {
28 }
29 
30 //-------------------------------------------------
31 //  device_start - device-specific startup
32 //-------------------------------------------------
33 
device_start()34 void dai_sound_device::device_start()
35 {
36 	m_mixer_channel = stream_alloc(0, 2, machine().sample_rate());
37 }
38 
39 //-------------------------------------------------
40 //  device_reset - device-specific reset
41 //-------------------------------------------------
42 
device_reset()43 void dai_sound_device::device_reset()
44 {
45 	memset(m_dai_input, 0, sizeof(m_dai_input));
46 	memset(m_osc_volume, 0, sizeof(m_osc_volume));
47 	m_noise_volume = 0;
48 }
49 
50 
51 //-------------------------------------------------
52 //  channels 0/1/2 volume table
53 //-------------------------------------------------
54 
55 const uint16_t dai_sound_device::s_osc_volume_table[] = {
56 	   0,  500, 1000, 1500,
57 	2000, 2500, 3000, 3500,
58 	4000, 4500, 5000, 5500,
59 	6000, 6500, 7000, 7500
60 };
61 
62 //-------------------------------------------------
63 //  noise volume table
64 //-------------------------------------------------
65 
66 const uint16_t dai_sound_device::s_noise_volume_table[] = {
67 	   0,    0,    0,    0,
68 	   0,    0,    0,    0,
69 	 500, 1000, 1500, 2000,
70 	2500, 3000, 3500, 4000
71 };
72 
73 
74 //-------------------------------------------------
75 //  set_volume
76 //-------------------------------------------------
77 
set_volume(offs_t offset,uint8_t data)78 void dai_sound_device::set_volume(offs_t offset, uint8_t data)
79 {
80 	m_mixer_channel->update();
81 
82 	switch (offset & 1)
83 	{
84 	case 0x00:
85 		m_osc_volume[0] = data&0x0f;
86 		m_osc_volume[1] = (data&0xf0)>>4;
87 		break;
88 
89 	case 0x01:
90 		m_osc_volume[2] = data&0x0f;
91 		m_noise_volume = (data&0xf0)>>4;
92 	}
93 }
94 
95 //-------------------------------------------------
96 //  PIT callbacks
97 //-------------------------------------------------
98 
WRITE_LINE_MEMBER(dai_sound_device::set_input_ch0)99 WRITE_LINE_MEMBER(dai_sound_device::set_input_ch0)
100 {
101 	m_mixer_channel->update();
102 	m_dai_input[0] = state;
103 }
104 
WRITE_LINE_MEMBER(dai_sound_device::set_input_ch1)105 WRITE_LINE_MEMBER(dai_sound_device::set_input_ch1)
106 {
107 	m_mixer_channel->update();
108 	m_dai_input[1] = state;
109 }
110 
WRITE_LINE_MEMBER(dai_sound_device::set_input_ch2)111 WRITE_LINE_MEMBER(dai_sound_device::set_input_ch2)
112 {
113 	m_mixer_channel->update();
114 	m_dai_input[2] = state;
115 }
116 
117 //-------------------------------------------------
118 //  sound_stream_update - handle update requests for
119 //  our sound stream
120 //-------------------------------------------------
121 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)122 void dai_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
123 {
124 	auto &sample_left = outputs[0];
125 	auto &sample_right = outputs[1];
126 
127 	int16_t channel_0_signal = m_dai_input[0] ? s_osc_volume_table[m_osc_volume[0]] : -s_osc_volume_table[m_osc_volume[0]];
128 	int16_t channel_1_signal = m_dai_input[1] ? s_osc_volume_table[m_osc_volume[1]] : -s_osc_volume_table[m_osc_volume[1]];
129 	int16_t channel_2_signal = m_dai_input[2] ? s_osc_volume_table[m_osc_volume[2]] : -s_osc_volume_table[m_osc_volume[2]];
130 
131 	for (int sampindex = 0; sampindex < sample_left.samples(); sampindex++)
132 	{
133 		int16_t noise = machine().rand()&0x01 ? s_noise_volume_table[m_noise_volume] : -s_noise_volume_table[m_noise_volume];
134 
135 		/* channel 0 + channel 1 + noise */
136 		sample_left.put_int(sampindex, channel_0_signal + channel_1_signal + noise, 32768);
137 
138 		/* channel 1 + channel 2 + noise */
139 		sample_right.put_int(sampindex, channel_1_signal + channel_2_signal + noise, 32768);
140 	}
141 }
142