1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
4 * streaming ADPCM driver
7 * Library to transcode from an ADPCM source to raw PCM.
8 * Written by Buffoni Mirko in 08/06/97
9 * References: various sources and documents.
12 * modified to use an automatically selected oversampling factor
13 * for the current sample rate
16 * separate MSM5205 emulator form adpcm.c and some fix
19 * added basic support for the MSM6585
31 Data is streamed from a CPU by means of a clock generated on the chip.
33 A reset signal is set high or low to determine whether playback (and interrupts) are occurring.
35 MSM6585: is an upgraded MSM5205 voice synth IC.
37 More precise internal DA converter
38 Built in low-pass filter
39 Expanded sampling frequency
41 Differences between MSM6585 & MSM5205:
44 Master clock frequency 640kHz 384kHz
45 Sampling frequency 4k/8k/16k/32kHz 4k/6k/8kHz
46 ADPCM bit length 4-bit 3-bit/4-bit
47 DA converter 12-bit 10-bit
48 Low-pass filter -40dB/oct N/A
49 Overflow prevent circuit Included N/A
51 Timer callback at VCLK low edge on MSM5205 (at rising edge on MSM6585)
54 - lowpass filter for MSM6585
58 void MSM5205::initialize()
61 // m_mod_clock = clock();
62 // m_vclk_cb.resolve();
64 /* compute the difference tables */
67 /* stream system initialize */
68 // m_stream = machine().sound().stream_alloc(*this, 0, 1, clock());
69 // m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(msm5205_device::vclk_callback), this));
73 //-------------------------------------------------
74 // device_reset - device-specific reset
75 //-------------------------------------------------
86 /* initialize clock */
87 change_clock_w(m_mod_clock);
89 /* timer and bitwidth set */
98 /* step size index shift table */
99 static const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
102 * Compute the difference table
105 void MSM5205::compute_tables()
107 /* nibble to bit map */
108 static const int nbl2bit[16][4] =
110 { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},
111 { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},
112 {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
113 {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
118 /* loop over all possible steps */
119 for (step = 0; step <= 48; step++)
121 /* compute the step value */
122 int stepval = (int)floor (16.0 * pow (11.0 / 10.0, (double)step));
124 /* loop over all nibbles and compute the difference */
125 for (nib = 0; nib < 16; nib++)
127 m_diff_lookup[step*16 + nib] = nbl2bit[nib][0] *
128 (stepval * nbl2bit[nib][1] +
129 stepval/2 * nbl2bit[nib][2] +
130 stepval/4 * nbl2bit[nib][3] +
136 /* timer callback at VCLK low edge on MSM5205 (at rising edge on MSM6585) */
137 void MSM5205::event_callback(int event_id, int err)
139 if(event_id == EVENT_TIMER)
144 /* callback user handler and latch next data */
145 // if (!m_vclk_cb.isnull())
147 write_signals(&m_vclk_cb, 0xffffffff);
149 /* reset check at last hiedge of VCLK */
158 /* !! MSM5205 has internal 12bit decoding, signal width is 0 to 8191 !! */
160 new_signal = m_signal + m_diff_lookup[m_step * 16 + (val & 15)];
162 if (new_signal > 2047) new_signal = 2047;
163 else if (new_signal < -2048) new_signal = -2048;
165 m_step += index_shift[val & 7];
167 if (m_step > 48) m_step = 48;
168 else if (m_step < 0) m_step = 0;
171 /* update when signal changed */
172 if( m_signal != new_signal)
174 // m_stream->update();
175 m_signal = new_signal;
183 * Handle an update of the vclk status of a chip (1 is reset ON, 0 is reset OFF)
184 * This function can use selector = MSM5205_SEX only
186 void MSM5205::vclk_w(int vclk)
188 if (m_prescaler != 0)
190 // logerror("error: msm5205_vclk_w() called with chip = '%s', but VCLK selected master mode\n", this->device().tag());
198 // vclk_callback(this, 0);
199 event_callback(EVENT_TIMER, 0);
205 * Handle an update of the reset status of a chip (1 is reset ON, 0 is reset OFF)
208 void MSM5205::reset_w(int reset)
212 set_realtime_render(this, (m_reset == 0));
216 * Handle an update of the data to the chip
219 void MSM5205::data_w(int data)
223 m_data = data & 0x0f;
225 m_data = (data & 0x07) << 1; /* unknown */
229 * Handle a change of the selector
232 void MSM5205::playmode_w(int select)
234 static const int prescaler_table[2][4] =
239 int prescaler = prescaler_table[(select >> 3) & 1][select & 3];
240 int bitwidth = (select & 4) ? 4 : 3;
242 if (m_prescaler != prescaler)
245 // m_stream->update();
248 m_prescaler = prescaler;
253 // attotime period = attotime::from_hz(m_mod_clock) * prescaler;
254 // m_timer->adjust(period, 0, period);
255 double period = 1000000.0 / m_mod_clock * prescaler;
257 cancel_event(this, m_timer);
259 register_event(this, EVENT_TIMER, period, true, &m_timer);
263 // m_timer->adjust(attotime::never);
265 cancel_event(this, m_timer);
271 if (m_bitwidth != bitwidth)
274 // m_stream->update();
275 m_bitwidth = bitwidth;
280 void MSM5205::set_volume(int volume)
283 volume_m = (int)(1024.0 * (max(0, min(100, volume)) / 100.0));
286 void MSM5205::change_clock_w(int32_t clock)
290 if (m_prescaler != 0) {
292 double period = 1000000.0 / m_mod_clock * m_prescaler;
294 cancel_event(this, m_timer);
296 register_event(this, EVENT_TIMER, period, true, &m_timer);
300 cancel_event(this, m_timer);
307 //-------------------------------------------------
308 // sound_stream_update - handle a stream update
309 //-------------------------------------------------
311 void MSM5205::mix(int32_t* buffer, int cnt)
313 /* if this voice is active */
316 int32_t val = apply_volume(m_signal * 16, volume_m);
317 int32_t val_l = apply_volume(val, volume_l);
318 int32_t val_r = apply_volume(val, volume_r);
320 for(int i = 0; i < cnt; i++)
322 *buffer++ += val_l; // L
323 *buffer++ += val_r; // R
328 void MSM5205::set_volume(int ch, int decibel_l, int decibel_r)
330 volume_l = decibel_to_volume(decibel_l);
331 volume_r = decibel_to_volume(decibel_r);
334 #define STATE_VERSION 1
336 bool MSM5205::process_state(FILEIO* state_fio, bool loading)
338 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
341 if(!state_fio->StateCheckInt32(this_device_id)) {
344 state_fio->StateInt32(m_mod_clock);
345 state_fio->StateInt32(m_timer);
346 state_fio->StateInt32(m_data);
347 state_fio->StateInt32(m_vclk);
348 state_fio->StateInt32(m_reset);
349 state_fio->StateInt32(m_prescaler);
350 state_fio->StateInt32(m_bitwidth);
351 state_fio->StateInt32(m_signal);
352 state_fio->StateInt32(m_step);
353 state_fio->StateInt32(m_select);
354 state_fio->StateInt32(volume_m);