1 // license:BSD-3-Clause
2 // copyright-holders:superctr, Valley Bell
3 /***************************************************************************
4 
5   Capcom QSound DL-1425 (HLE)
6   ===========================
7 
8   Driver by superctr with thanks to Valley Bell.
9 
10   Based on disassembled DSP code.
11 
12   Links:
13   https://siliconpr0n.org/map/capcom/dl-1425
14 
15 ***************************************************************************/
16 
17 #include "emu.h"
18 #include "qsoundhle.h"
19 
20 #include <algorithm>
21 #include <limits>
22 
23 // device type definition
24 DEFINE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device, "qsound_hle", "QSound (HLE)")
25 
26 // DSP internal ROM region
ROM_START(qsound_hle)27 ROM_START( qsound_hle )
28 	ROM_REGION16_LE( 0x2000, "dsp", 0 )
29 	// removing WORD_SWAP from original definition
30 	ROM_LOAD16_WORD( "dl-1425.bin", 0x0000, 0x2000, CRC(d6cf5ef5) SHA1(555f50fe5cdf127619da7d854c03f4a244a0c501) )
31 	ROM_IGNORE( 0x4000 )
32 ROM_END
33 
34 //**************************************************************************
35 //  LIVE DEVICE
36 //**************************************************************************
37 
38 //-------------------------------------------------
39 //  qsound_hle_device - constructor
40 //-------------------------------------------------
41 
42 qsound_hle_device::qsound_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
43 	: device_t(mconfig, QSOUND_HLE, tag, owner, clock)
44 	, device_sound_interface(mconfig, *this)
45 	, device_rom_interface(mconfig, *this)
46 	, m_stream(nullptr)
47 	, m_dsp_rom(*this, "dsp")
48 	, m_data_latch(0)
49 {
50 }
51 
52 //-------------------------------------------------
53 //  rom_bank_updated - the rom bank has changed
54 //-------------------------------------------------
55 
rom_bank_updated()56 void qsound_hle_device::rom_bank_updated()
57 {
58 	m_stream->update();
59 }
60 
61 //-------------------------------------------------
62 //  device_start - device-specific startup
63 //-------------------------------------------------
64 
device_start()65 void qsound_hle_device::device_start()
66 {
67 	m_stream = stream_alloc(0, 2, clock() / 2 / 1248); // DSP program uses 1248 machine cycles per iteration
68 
69 	init_register_map();
70 
71 	// state save
72 	// PCM registers
73 	// PCM voices
74 	save_item(STRUCT_MEMBER(m_voice, m_bank));
75 	save_item(STRUCT_MEMBER(m_voice, m_addr));
76 	save_item(STRUCT_MEMBER(m_voice, m_phase));
77 	save_item(STRUCT_MEMBER(m_voice, m_rate));
78 	save_item(STRUCT_MEMBER(m_voice, m_loop_len));
79 	save_item(STRUCT_MEMBER(m_voice, m_end_addr));
80 	save_item(STRUCT_MEMBER(m_voice, m_volume));
81 	save_item(STRUCT_MEMBER(m_voice, m_echo));
82 
83 	// ADPCM voices
84 	save_item(STRUCT_MEMBER(m_adpcm, m_start_addr));
85 	save_item(STRUCT_MEMBER(m_adpcm, m_end_addr));
86 	save_item(STRUCT_MEMBER(m_adpcm, m_bank));
87 	save_item(STRUCT_MEMBER(m_adpcm, m_volume));
88 	save_item(STRUCT_MEMBER(m_adpcm, m_flag));
89 	save_item(STRUCT_MEMBER(m_adpcm, m_cur_vol));
90 	save_item(STRUCT_MEMBER(m_adpcm, m_step_size));
91 	save_item(STRUCT_MEMBER(m_adpcm, m_cur_addr));
92 
93 	// PCM voices
94 	save_item(NAME(m_voice_pan));
95 
96 	// QSound registers
97 	save_item(NAME(m_echo.m_end_pos));
98 	save_item(NAME(m_echo.m_feedback));
99 	save_item(NAME(m_echo.m_length));
100 	save_item(NAME(m_echo.m_last_sample));
101 	save_item(NAME(m_echo.m_delay_line));
102 	save_item(NAME(m_echo.m_delay_pos));
103 
104 	// left, right
105 	save_item(STRUCT_MEMBER(m_filter, m_tap_count));
106 	save_item(STRUCT_MEMBER(m_filter, m_delay_pos));
107 	save_item(STRUCT_MEMBER(m_filter, m_table_pos));
108 	save_item(STRUCT_MEMBER(m_filter, m_taps));
109 	save_item(STRUCT_MEMBER(m_filter, m_delay_line));
110 
111 	save_item(STRUCT_MEMBER(m_alt_filter, m_tap_count));
112 	save_item(STRUCT_MEMBER(m_alt_filter, m_delay_pos));
113 	save_item(STRUCT_MEMBER(m_alt_filter, m_table_pos));
114 	save_item(STRUCT_MEMBER(m_alt_filter, m_taps));
115 	save_item(STRUCT_MEMBER(m_alt_filter, m_delay_line));
116 
117 	save_item(STRUCT_MEMBER(m_wet, m_delay));
118 	save_item(STRUCT_MEMBER(m_wet, m_volume));
119 	save_item(STRUCT_MEMBER(m_wet, m_write_pos));
120 	save_item(STRUCT_MEMBER(m_wet, m_read_pos));
121 	save_item(STRUCT_MEMBER(m_wet, m_delay_line));
122 
123 	save_item(STRUCT_MEMBER(m_dry, m_delay));
124 	save_item(STRUCT_MEMBER(m_dry, m_volume));
125 	save_item(STRUCT_MEMBER(m_dry, m_write_pos));
126 	save_item(STRUCT_MEMBER(m_dry, m_read_pos));
127 	save_item(STRUCT_MEMBER(m_dry, m_delay_line));
128 
129 	save_item(NAME(m_state));
130 	save_item(NAME(m_next_state));
131 	save_item(NAME(m_delay_update));
132 	save_item(NAME(m_state_counter));
133 	save_item(NAME(m_ready_flag));
134 	save_item(NAME(m_data_latch));
135 	save_item(NAME(m_out));
136 }
137 
138 //-------------------------------------------------
139 //  rom_region - return a pointer to the device's
140 //  internal ROM region
141 //-------------------------------------------------
142 
device_rom_region() const143 const tiny_rom_entry *qsound_hle_device::device_rom_region() const
144 {
145 	return ROM_NAME( qsound_hle );
146 }
147 
148 //-------------------------------------------------
149 //  device_reset - device-specific reset
150 //-------------------------------------------------
151 
device_reset()152 void qsound_hle_device::device_reset()
153 {
154 	m_ready_flag = 0;
155 	m_out[0] = m_out[1] = 0;
156 	m_state = STATE_BOOT;
157 	m_state_counter = 0;
158 }
159 
160 //-------------------------------------------------
161 //  sound_stream_update - handle a stream update
162 //-------------------------------------------------
163 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)164 void qsound_hle_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
165 {
166 	for (int i = 0; i < outputs[0].samples(); i ++)
167 	{
168 		update_sample();
169 		outputs[0].put_int(i, m_out[0], 32768);
170 		outputs[1].put_int(i, m_out[1], 32768);
171 	}
172 }
173 
174 
qsound_w(offs_t offset,uint8_t data)175 void qsound_hle_device::qsound_w(offs_t offset, uint8_t data)
176 {
177 	switch (offset)
178 	{
179 		case 0:
180 			m_data_latch = (m_data_latch & 0x00ff) | (data << 8);
181 			break;
182 
183 		case 1:
184 			m_data_latch = (m_data_latch & 0xff00) | data;
185 			break;
186 
187 		case 2:
188 			m_stream->update();
189 			write_data(data, m_data_latch);
190 			break;
191 
192 		default:
193 			logerror("%s: qsound_w %d = %02x\n", machine().describe_context(), offset, data);
194 			break;
195 	}
196 }
197 
198 
qsound_r()199 uint8_t qsound_hle_device::qsound_r()
200 {
201 	// ready bit (0x00 = busy, 0x80 == ready)
202 	m_stream->update();
203 	return m_ready_flag;
204 }
205 
206 
write_data(uint8_t address,uint16_t data)207 void qsound_hle_device::write_data(uint8_t address, uint16_t data)
208 {
209 	uint16_t *destination = m_register_map[address];
210 	if (destination)
211 		*destination = data;
212 	m_ready_flag = 0;
213 }
214 
init_register_map()215 void qsound_hle_device::init_register_map()
216 {
217 	// unused registers
218 	std::fill(std::begin(m_register_map), std::end(m_register_map), nullptr);
219 
220 	// PCM registers
221 	for (int i = 0; i < 16; i++) // PCM voices
222 	{
223 		m_register_map[(i << 3) + 0] = (uint16_t*)&m_voice[(i + 1) % 16].m_bank; // Bank applies to the next channel
224 		m_register_map[(i << 3) + 1] = (uint16_t*)&m_voice[i].m_addr; // Current sample position and start position.
225 		m_register_map[(i << 3) + 2] = (uint16_t*)&m_voice[i].m_rate; // 4.12 fixed point decimal.
226 		m_register_map[(i << 3) + 3] = (uint16_t*)&m_voice[i].m_phase;
227 		m_register_map[(i << 3) + 4] = (uint16_t*)&m_voice[i].m_loop_len;
228 		m_register_map[(i << 3) + 5] = (uint16_t*)&m_voice[i].m_end_addr;
229 		m_register_map[(i << 3) + 6] = (uint16_t*)&m_voice[i].m_volume;
230 		m_register_map[(i << 3) + 7] = nullptr; // unused
231 		m_register_map[i + 0x80] = (uint16_t*)&m_voice_pan[i];
232 		m_register_map[i + 0xba] = (uint16_t*)&m_voice[i].m_echo;
233 	}
234 
235 	// ADPCM registers
236 	for (int i = 0; i < 3; i++) // ADPCM voices
237 	{
238 		// ADPCM sample rate is fixed to 8khz. (one channel is updated every third sample)
239 		m_register_map[(i << 2) + 0xca] = (uint16_t*)&m_adpcm[i].m_start_addr;
240 		m_register_map[(i << 2) + 0xcb] = (uint16_t*)&m_adpcm[i].m_end_addr;
241 		m_register_map[(i << 2) + 0xcc] = (uint16_t*)&m_adpcm[i].m_bank;
242 		m_register_map[(i << 2) + 0xcd] = (uint16_t*)&m_adpcm[i].m_volume;
243 		m_register_map[i + 0xd6] = (uint16_t*)&m_adpcm[i].m_flag; // non-zero to start ADPCM playback
244 		m_register_map[i + 0x90] = (uint16_t*)&m_voice_pan[16 + i];
245 	}
246 
247 	// QSound registers
248 	m_register_map[0x93] = (uint16_t*)&m_echo.m_feedback;
249 	m_register_map[0xd9] = (uint16_t*)&m_echo.m_end_pos;
250 	m_register_map[0xe2] = (uint16_t*)&m_delay_update; // non-zero to update delays
251 	m_register_map[0xe3] = (uint16_t*)&m_next_state;
252 	for (int i = 0; i < 2; i++)  // left, right
253 	{
254 		// Wet
255 		m_register_map[(i << 1) + 0xda] = (uint16_t*)&m_filter[i].m_table_pos;
256 		m_register_map[(i << 1) + 0xde] = (uint16_t*)&m_wet[i].m_delay;
257 		m_register_map[(i << 1) + 0xe4] = (uint16_t*)&m_wet[i].m_volume;
258 		// Dry
259 		m_register_map[(i << 1) + 0xdb] = (uint16_t*)&m_alt_filter[i].m_table_pos;
260 		m_register_map[(i << 1) + 0xdf] = (uint16_t*)&m_dry[i].m_delay;
261 		m_register_map[(i << 1) + 0xe5] = (uint16_t*)&m_dry[i].m_volume;
262 	}
263 }
264 
read_sample(uint16_t bank,uint16_t address)265 int16_t qsound_hle_device::read_sample(uint16_t bank, uint16_t address)
266 {
267 	bank &= 0x7FFF;
268 	const uint32_t rom_addr = (bank << 16) | (address << 0);
269 	const uint8_t sample_data = read_byte(rom_addr);
270 	return (int16_t)(sample_data << 8); // bit0-7 is tied to ground
271 }
272 
273 /********************************************************************/
274 
275 // updates one DSP sample
update_sample()276 void qsound_hle_device::update_sample()
277 {
278 	switch (m_state)
279 	{
280 		default:
281 		case STATE_INIT1:
282 		case STATE_INIT2:
283 			return state_init();
284 		case STATE_REFRESH1:
285 			return state_refresh_filter_1();
286 		case STATE_REFRESH2:
287 			return state_refresh_filter_2();
288 		case STATE_NORMAL1:
289 		case STATE_NORMAL2:
290 			return state_normal_update();
291 	}
292 }
293 
294 // Initialization routine
state_init()295 void qsound_hle_device::state_init()
296 {
297 	int mode = (m_state == STATE_INIT2) ? 1 : 0;
298 
299 	// we're busy for 4 samples, including the filter refresh.
300 	if (m_state_counter >= 2)
301 	{
302 		m_state_counter = 0;
303 		m_state = m_next_state;
304 		return;
305 	}
306 	else if (m_state_counter == 1)
307 	{
308 		m_state_counter++;
309 		return;
310 	}
311 
312 	std::fill(std::begin(m_voice), std::end(m_voice), qsound_voice());
313 	std::fill(std::begin(m_adpcm), std::end(m_adpcm), qsound_adpcm());
314 	std::fill(std::begin(m_filter), std::end(m_filter), qsound_fir());
315 	std::fill(std::begin(m_alt_filter), std::end(m_alt_filter), qsound_fir());
316 	std::fill(std::begin(m_wet), std::end(m_wet), qsound_delay());
317 	std::fill(std::begin(m_dry), std::end(m_dry), qsound_delay());
318 	m_echo = qsound_echo();
319 
320 	for (int i = 0; i < 19; i++)
321 	{
322 		m_voice_pan[i] = DATA_PAN_TAB + 0x10;
323 		m_voice_output[i] = 0;
324 	}
325 
326 	for (int i = 0; i < 16; i++)
327 		m_voice[i].m_bank = 0x8000;
328 	for (int i = 0; i < 3; i++)
329 		m_adpcm[i].m_bank = 0x8000;
330 
331 	if (mode == 0)
332 	{
333 		// mode 1
334 		m_wet[0].m_delay = 0;
335 		m_dry[0].m_delay = 46;
336 		m_wet[1].m_delay = 0;
337 		m_dry[1].m_delay = 48;
338 		m_filter[0].m_table_pos = DATA_FILTER_TAB + (FILTER_ENTRY_SIZE*1);
339 		m_filter[1].m_table_pos = DATA_FILTER_TAB + (FILTER_ENTRY_SIZE*2);
340 		m_echo.m_end_pos = DELAY_BASE_OFFSET + 6;
341 		m_next_state = STATE_REFRESH1;
342 	}
343 	else
344 	{
345 		// mode 2
346 		m_wet[0].m_delay = 1;
347 		m_dry[0].m_delay = 0;
348 		m_wet[1].m_delay = 0;
349 		m_dry[1].m_delay = 0;
350 		m_filter[0].m_table_pos = 0xf73;
351 		m_filter[1].m_table_pos = 0xfa4;
352 		m_alt_filter[0].m_table_pos = 0xf73;
353 		m_alt_filter[1].m_table_pos = 0xfa4;
354 		m_echo.m_end_pos = DELAY_BASE_OFFSET2 + 6;
355 		m_next_state = STATE_REFRESH2;
356 	}
357 
358 	m_wet[0].m_volume = 0x3fff;
359 	m_dry[0].m_volume = 0x3fff;
360 	m_wet[1].m_volume = 0x3fff;
361 	m_dry[1].m_volume = 0x3fff;
362 
363 	m_delay_update = 1;
364 	m_ready_flag = 0;
365 	m_state_counter = 1;
366 }
367 
368 // Updates filter parameters for mode 1
state_refresh_filter_1()369 void qsound_hle_device::state_refresh_filter_1()
370 {
371 	for (int ch = 0; ch < 2; ch++)
372 	{
373 		m_filter[ch].m_delay_pos = 0;
374 		m_filter[ch].m_tap_count = 95;
375 
376 		for (int i = 0; i < 95; i++)
377 			m_filter[ch].m_taps[i] = read_dsp_rom(m_filter[ch].m_table_pos + i);
378 	}
379 
380 	m_state = m_next_state = STATE_NORMAL1;
381 }
382 
383 // Updates filter parameters for mode 2
state_refresh_filter_2()384 void qsound_hle_device::state_refresh_filter_2()
385 {
386 	for (int ch = 0; ch < 2; ch++)
387 	{
388 		m_filter[ch].m_delay_pos = 0;
389 		m_filter[ch].m_tap_count = 45;
390 
391 		for (int i = 0; i < 45; i++)
392 			m_filter[ch].m_taps[i] = (int16_t)read_dsp_rom(m_filter[ch].m_table_pos + i);
393 
394 		m_alt_filter[ch].m_delay_pos = 0;
395 		m_alt_filter[ch].m_tap_count = 44;
396 
397 		for (int i = 0; i < 44; i++)
398 			m_alt_filter[ch].m_taps[i] = (int16_t)read_dsp_rom(m_alt_filter[ch].m_table_pos + i);
399 	}
400 
401 	m_state = m_next_state = STATE_NORMAL2;
402 }
403 
404 // Updates a PCM voice. There are 16 voices, each are updated every sample
405 // with full rate and volume control.
update(qsound_hle_device & dsp,int32_t * echo_out)406 int16_t qsound_hle_device::qsound_voice::update(qsound_hle_device &dsp, int32_t *echo_out)
407 {
408 	// Read sample from rom and apply volume
409 	const int16_t output = (m_volume * dsp.read_sample(m_bank, m_addr)) >> 14;
410 
411 	*echo_out += (output * m_echo) << 2;
412 
413 	// Add delta to the phase and loop back if required
414 	int32_t new_phase = m_rate + ((m_addr << 12) | (m_phase >> 4));
415 
416 	if ((new_phase >> 12) >= m_end_addr)
417 		new_phase -= (m_loop_len << 12);
418 
419 	new_phase = std::min<int32_t>(std::max<int32_t>(new_phase, -0x8000000), 0x7FFFFFF);
420 	m_addr = new_phase >> 12;
421 	m_phase = (new_phase << 4)&0xffff;
422 
423 	return output;
424 }
425 
426 // Updates an ADPCM voice. There are 3 voices, one is updated every sample
427 // (effectively making the ADPCM rate 1/3 of the master sample rate), and
428 // volume is set when starting samples only.
429 // The ADPCM algorithm is supposedly similar to Yamaha ADPCM. It also seems
430 // like Capcom never used it, so this was not emulated in the earlier QSound
431 // emulators.
update(qsound_hle_device & dsp,int16_t curr_sample,int nibble)432 int16_t qsound_hle_device::qsound_adpcm::update(qsound_hle_device &dsp, int16_t curr_sample, int nibble)
433 {
434 	int8_t step;
435 	if (!nibble)
436 	{
437 		// Mute voice when it reaches the end address.
438 		if (m_cur_addr == m_end_addr)
439 			m_cur_vol = 0;
440 
441 		// Playback start flag
442 		if (m_flag)
443 		{
444 			curr_sample = 0;
445 			m_flag = 0;
446 			m_step_size = 10;
447 			m_cur_vol = m_volume;
448 			m_cur_addr = m_start_addr;
449 		}
450 
451 		// get top nibble
452 		step = dsp.read_sample(m_bank, m_cur_addr) >> 8;
453 	}
454 	else
455 	{
456 		// get bottom nibble
457 		step = dsp.read_sample(m_bank, m_cur_addr++) >> 4;
458 	}
459 
460 	// shift with sign extend
461 	step >>= 4;
462 
463 	// delta = (0.5 + abs(step)) * m_step_size
464 	int32_t delta = ((1 + abs(step << 1)) * m_step_size) >> 1;
465 	if (step <= 0)
466 		delta = -delta;
467 	delta += curr_sample;
468 	delta = std::min<int32_t>(std::max<int32_t>(delta, -32768), 32767);
469 
470 	m_step_size = (dsp.read_dsp_rom(DATA_ADPCM_TAB + 8 + step) * m_step_size) >> 6;
471 	m_step_size = std::min<int16_t>(std::max<int16_t>(m_step_size, 1), 2000);
472 
473 	return (delta * m_cur_vol) >> 16;
474 }
475 
476 // The echo effect is pretty simple. A moving average filter is used on
477 // the output from the delay line to smooth samples over time.
apply(int32_t input)478 int16_t qsound_hle_device::qsound_echo::apply(int32_t input)
479 {
480 	// get average of last 2 samples from the delay line
481 	int32_t old_sample = m_delay_line[m_delay_pos];
482 	const int32_t last_sample = m_last_sample;
483 	m_last_sample = old_sample;
484 	old_sample = (old_sample + last_sample) >> 1;
485 
486 	// add current sample to the delay line
487 	int32_t new_sample = input + ((old_sample * m_feedback) << 2);
488 	m_delay_line[m_delay_pos++] = new_sample >> 16;
489 
490 	if (m_delay_pos >= m_length)
491 		m_delay_pos = 0;
492 
493 	return old_sample;
494 }
495 
496 // Process a sample update
state_normal_update()497 void qsound_hle_device::state_normal_update()
498 {
499 	m_ready_flag = 0x80;
500 
501 	// recalculate echo length
502 	if (m_state == STATE_NORMAL2)
503 		m_echo.m_length = m_echo.m_end_pos - DELAY_BASE_OFFSET2;
504 	else
505 		m_echo.m_length = m_echo.m_end_pos - DELAY_BASE_OFFSET;
506 
507 	m_echo.m_length = std::min<int16_t>(std::max<int16_t>(m_echo.m_length, 0), 1024);
508 
509 	// update PCM voices
510 	int32_t echo_input = 0;
511 	for (int i = 0; i < 16; i++)
512 		m_voice_output[i] = m_voice[i].update(*this, &echo_input);
513 
514 	// update ADPCM voices (one every third sample)
515 	const int adpcm_voice = m_state_counter % 3;
516 	m_voice_output[16 + adpcm_voice] = m_adpcm[adpcm_voice].update(*this, m_voice_output[16 + adpcm_voice], m_state_counter / 3);
517 
518 	int16_t echo_output = m_echo.apply(echo_input);
519 
520 	// now, we do the magic stuff
521 	for (int ch = 0; ch < 2; ch++)
522 	{
523 		// Echo is output on the unfiltered component of the left channel and
524 		// the filtered component of the right channel.
525 		int32_t wet = (ch == 1) ? echo_output << 14 : 0;
526 		int32_t dry = (ch == 0) ? echo_output << 14 : 0;
527 
528 		for (int i = 0; i < 19; i++)
529 		{
530 			uint16_t pan_index = m_voice_pan[i] + (ch * PAN_TABLE_CH_OFFSET);
531 
532 			// Apply different volume tables on the dry and wet inputs.
533 			dry -= (m_voice_output[i] * (int16_t)read_dsp_rom(pan_index + PAN_TABLE_DRY));
534 			wet -= (m_voice_output[i] * (int16_t)read_dsp_rom(pan_index + PAN_TABLE_WET));
535 		}
536 		// Saturate accumulated voices
537 		dry = (std::min<int32_t>(std::max<int32_t>(dry, -0x1fffffff), 0x1fffffff)) << 2;
538 		wet = (std::min<int32_t>(std::max<int32_t>(wet, -0x1fffffff), 0x1fffffff)) << 2;
539 
540 		// Apply FIR filter on 'wet' input
541 		wet = m_filter[ch].apply(wet >> 16);
542 
543 		// in mode 2, we do this on the 'dry' input too
544 		if (m_state == STATE_NORMAL2)
545 			dry = m_alt_filter[ch].apply(dry >> 16);
546 
547 		// output goes through a delay line and attenuation
548 		int32_t output = (m_wet[ch].apply(wet) + m_dry[ch].apply(dry));
549 
550 		// DSP round function
551 		output = (output + 0x2000) & ~0x3fff;
552 		m_out[ch] = (std::min<int32_t>(std::max<int32_t>(output >> 14, -0x7fff), 0x7fff));
553 
554 		if (m_delay_update)
555 		{
556 			m_wet[ch].update();
557 			m_dry[ch].update();
558 		}
559 	}
560 
561 	m_delay_update = 0;
562 
563 	// after 6 samples, the next state is executed.
564 	m_state_counter++;
565 	if (m_state_counter > 5)
566 	{
567 		m_state_counter = 0;
568 		m_state = m_next_state;
569 	}
570 }
571 
572 // Apply the FIR filter used as the Q1 transfer function
apply(int16_t input)573 int32_t qsound_hle_device::qsound_fir::apply(int16_t input)
574 {
575 	int32_t output = 0, tap = 0;
576 	for (; tap < (m_tap_count - 1); tap++)
577 	{
578 		output -= (m_taps[tap] * m_delay_line[m_delay_pos++]) << 2;
579 
580 		if (m_delay_pos >= m_tap_count - 1)
581 			m_delay_pos = 0;
582 	}
583 
584 	output -= (m_taps[tap] * input) << 2;
585 
586 	m_delay_line[m_delay_pos++] = input;
587 	if (m_delay_pos >= m_tap_count - 1)
588 		m_delay_pos = 0;
589 
590 	return output;
591 }
592 
593 // Apply delay line and component volume
apply(const int32_t input)594 int32_t qsound_hle_device::qsound_delay::apply(const int32_t input)
595 {
596 	m_delay_line[m_write_pos++] = input >> 16;
597 	if (m_write_pos >= 51)
598 		m_write_pos = 0;
599 
600 	const int32_t output = m_delay_line[m_read_pos++] * m_volume;
601 	if (m_read_pos >= 51)
602 		m_read_pos = 0;
603 
604 	return output;
605 }
606 
607 // Update the delay read position to match new delay length
update()608 void qsound_hle_device::qsound_delay::update()
609 {
610 	const int16_t new_read_pos = (m_write_pos - m_delay) % 51;
611 	if (new_read_pos < 0)
612 		m_read_pos = new_read_pos + 51;
613 	else
614 		m_read_pos = new_read_pos;
615 }
616