1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     samples.c
6 
7     Sound device for sample playback.
8 
9 ****************************************************************************
10 
11     Playback of pre-recorded samples. Used for high-level simulation of
12     discrete sound circuits where proper low-level simulation isn't
13     available.  Also used for tape loops and similar.
14 
15     Current limitations
16       - Only supports single channel samples!
17 
18     Considerations
19       - Maybe this should be part of the presentation layer
20         (artwork etc.) with samples specified in .lay files instead of
21         in drivers?
22 
23 ***************************************************************************/
24 
25 #include "emu.h"
26 #include "samples.h"
27 
28 #include "emuopts.h"
29 
30 #include "flac.h"
31 
32 
33 //**************************************************************************
34 //  GLOBAL VARIABLES
35 //**************************************************************************
36 
37 // device type definition
38 DEFINE_DEVICE_TYPE(SAMPLES, samples_device, "samples", "Samples")
39 
40 
41 
42 //**************************************************************************
43 //  LIVE DEVICE
44 //**************************************************************************
45 
46 //-------------------------------------------------
47 //  samples_device - constructors
48 //-------------------------------------------------
49 
samples_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)50 samples_device::samples_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
51 	: samples_device(mconfig, SAMPLES, tag, owner, clock)
52 {
53 }
54 
samples_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)55 samples_device::samples_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
56 	: device_t(mconfig, type, tag, owner, clock)
57 	, device_sound_interface(mconfig, *this)
58 	, m_channels(0)
59 	, m_names(nullptr)
60 	, m_samples_start_cb(*this)
61 {
62 }
63 
64 
65 //**************************************************************************
66 //  PUBLIC INTERFACE
67 //**************************************************************************
68 
69 //-------------------------------------------------
70 //  start - start playing a loaded sample
71 //-------------------------------------------------
72 
start(uint8_t channel,uint32_t samplenum,bool loop)73 void samples_device::start(uint8_t channel, uint32_t samplenum, bool loop)
74 {
75 	// if samples are disabled, just return quietly
76 	if (m_sample.empty())
77 		return;
78 
79 	assert(samplenum < m_sample.size());
80 	assert(channel < m_channels);
81 
82 	// force an update before we start
83 	channel_t &chan = m_channel[channel];
84 	chan.stream->update();
85 
86 	// update the parameters
87 	sample_t &sample = m_sample[samplenum];
88 	chan.source = (sample.data.size() > 0) ? &sample.data[0] : nullptr;
89 	chan.source_num = (chan.source_len > 0) ? samplenum : -1;
90 	chan.source_len = sample.data.size();
91 	chan.pos = 0;
92 	chan.basefreq = sample.frequency;
93 	chan.curfreq = sample.frequency;
94 	chan.loop = loop;
95 }
96 
97 
98 //-------------------------------------------------
99 //  start_raw - start playing an externally
100 //  provided sample
101 //-------------------------------------------------
102 
start_raw(uint8_t channel,const int16_t * sampledata,uint32_t samples,uint32_t frequency,bool loop)103 void samples_device::start_raw(uint8_t channel, const int16_t *sampledata, uint32_t samples, uint32_t frequency, bool loop)
104 {
105 	assert(channel < m_channels);
106 
107 	// force an update before we start
108 	channel_t &chan = m_channel[channel];
109 	chan.stream->update();
110 
111 	// update the parameters
112 	chan.source = sampledata;
113 	chan.source_num = -1;
114 	chan.source_len = samples;
115 	chan.pos = 0;
116 	chan.basefreq = frequency;
117 	chan.curfreq = frequency;
118 	chan.loop = loop;
119 }
120 
121 
122 //-------------------------------------------------
123 //  set_frequency - set the playback frequency of
124 //  a sample
125 //-------------------------------------------------
126 
set_frequency(uint8_t channel,uint32_t freq)127 void samples_device::set_frequency(uint8_t channel, uint32_t freq)
128 {
129 	assert(channel < m_channels);
130 
131 	// force an update before we start
132 	channel_t &chan = m_channel[channel];
133 	chan.stream->update();
134 	chan.curfreq = freq;
135 }
136 
137 
138 //-------------------------------------------------
139 //  set_volume - set the playback volume of a
140 //  sample
141 //-------------------------------------------------
142 
set_volume(uint8_t channel,float volume)143 void samples_device::set_volume(uint8_t channel, float volume)
144 {
145 	assert(channel < m_channels);
146 
147 	// force an update before we start
148 	set_output_gain(channel, volume);
149 }
150 
151 
152 //-------------------------------------------------
153 //  pause - pause playback on a channel
154 //-------------------------------------------------
155 
pause(uint8_t channel,bool pause)156 void samples_device::pause(uint8_t channel, bool pause)
157 {
158 	assert(channel < m_channels);
159 
160 	// force an update before we start
161 	channel_t &chan = m_channel[channel];
162 	chan.paused = pause;
163 }
164 
165 
166 //-------------------------------------------------
167 //  stop - stop playback on a channel
168 //-------------------------------------------------
169 
stop(uint8_t channel)170 void samples_device::stop(uint8_t channel)
171 {
172 	assert(channel < m_channels);
173 
174 	// force an update before we start
175 	channel_t &chan = m_channel[channel];
176 	chan.source = nullptr;
177 	chan.source_num = -1;
178 }
179 
180 
181 //-------------------------------------------------
182 //  stop_all - stop playback on all channels
183 //-------------------------------------------------
184 
stop_all()185 void samples_device::stop_all()
186 {
187 	// just iterate over channels and stop them
188 	for (uint8_t channel = 0; channel < m_channels; channel++)
189 		stop(channel);
190 }
191 
192 
193 //-------------------------------------------------
194 //  base_frequency - return the base frequency of
195 //  a channel being played
196 //-------------------------------------------------
197 
base_frequency(uint8_t channel) const198 uint32_t samples_device::base_frequency(uint8_t channel) const
199 {
200 	assert(channel < m_channels);
201 	return m_channel[channel].basefreq;
202 }
203 
204 
205 //-------------------------------------------------
206 //  playing - return true if a sample is still
207 //  playing on the given channel
208 //-------------------------------------------------
209 
playing(uint8_t channel) const210 bool samples_device::playing(uint8_t channel) const
211 {
212 	assert(channel < m_channels);
213 
214 	// force an update before we start
215 	const channel_t &chan = m_channel[channel];
216 	chan.stream->update();
217 	return (chan.source != nullptr);
218 }
219 
220 
221 
222 //**************************************************************************
223 //  DEVICE INTERFACE
224 //**************************************************************************
225 
226 //-------------------------------------------------
227 //  device_start - handle device startup
228 //-------------------------------------------------
229 
device_start()230 void samples_device::device_start()
231 {
232 	// read audio samples
233 	load_samples();
234 
235 	// allocate channels
236 	m_channel.resize(m_channels);
237 	for (int channel = 0; channel < m_channels; channel++)
238 	{
239 		// initialize channel
240 		channel_t &chan = m_channel[channel];
241 		chan.stream = stream_alloc(0, 1, SAMPLE_RATE_OUTPUT_ADAPTIVE);
242 		chan.source = nullptr;
243 		chan.source_num = -1;
244 		chan.pos = 0;
245 		chan.loop = 0;
246 		chan.paused = 0;
247 
248 		// register with the save state system
249 		save_item(NAME(chan.source_num), channel);
250 		save_item(NAME(chan.source_len), channel);
251 		save_item(NAME(chan.pos), channel);
252 		save_item(NAME(chan.loop), channel);
253 		save_item(NAME(chan.paused), channel);
254 	}
255 
256 	// initialize any custom handlers
257 	m_samples_start_cb.resolve();
258 
259 	if (!m_samples_start_cb.isnull())
260 		m_samples_start_cb();
261 }
262 
263 
264 //-------------------------------------------------
265 //  device_reset - handle device reset
266 //-------------------------------------------------
267 
device_reset()268 void samples_device::device_reset()
269 {
270 	stop_all();
271 }
272 
273 
274 //-------------------------------------------------
275 //  device_post_load - handle updating after a
276 //  restore
277 //-------------------------------------------------
278 
device_post_load()279 void samples_device::device_post_load()
280 {
281 	// loop over channels
282 	for (int channel = 0; channel < m_channels; channel++)
283 	{
284 		// attach any samples that were loaded and playing
285 		channel_t &chan = m_channel[channel];
286 		if (chan.source_num >= 0 && chan.source_num < m_sample.size())
287 		{
288 			sample_t &sample = m_sample[chan.source_num];
289 			chan.source = &sample.data[0];
290 			chan.source_len = sample.data.size();
291 			if (sample.data.empty())
292 				chan.source_num = -1;
293 		}
294 
295 		// validate the position against the length in case the sample is smaller
296 		double endpos = chan.source_len;
297 		if (chan.source != nullptr && chan.pos >= endpos)
298 		{
299 			if (chan.loop)
300 			{
301 				double posfloor = floor(chan.pos);
302 				chan.pos -= posfloor;
303 				chan.pos += double(int32_t(posfloor) % chan.source_len);
304 			}
305 			else
306 			{
307 				chan.source = nullptr;
308 				chan.source_num = -1;
309 			}
310 		}
311 	}
312 }
313 
314 
315 //-------------------------------------------------
316 //  sound_stream_update - update a sound stream
317 //-------------------------------------------------
318 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)319 void samples_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
320 {
321 	// find the channel with this stream
322 	constexpr stream_buffer::sample_t sample_scale = 1.0 / 32768.0;
323 	for (int channel = 0; channel < m_channels; channel++)
324 		if (&stream == m_channel[channel].stream)
325 		{
326 			channel_t &chan = m_channel[channel];
327 			auto &buffer = outputs[0];
328 
329 			// process if we still have a source and we're not paused
330 			if (chan.source != nullptr && !chan.paused)
331 			{
332 				// load some info locally
333 				double step = double(chan.curfreq) / double(buffer.sample_rate());
334 				double endpos = chan.source_len;
335 				const int16_t *sample = chan.source;
336 
337 				for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
338 				{
339 					// do a linear interp on the sample
340 					double pos_floor = floor(chan.pos);
341 					double frac = chan.pos - pos_floor;
342 					int32_t ipos = int32_t(pos_floor);
343 
344 					stream_buffer::sample_t sample1 = stream_buffer::sample_t(sample[ipos++]);
345 					stream_buffer::sample_t sample2 = stream_buffer::sample_t(sample[(ipos + 1) % chan.source_len]);
346 					buffer.put(sampindex, sample_scale * ((1.0 - frac) * sample1 + frac * sample2));
347 
348 					// advance
349 					chan.pos += step;
350 
351 					// handle looping/ending
352 					if (chan.pos >= endpos)
353 					{
354 						if (chan.loop)
355 							chan.pos -= endpos;
356 						else
357 						{
358 							chan.source = nullptr;
359 							chan.source_num = -1;
360 							buffer.fill(0, sampindex);
361 							break;
362 						}
363 					}
364 				}
365 			}
366 			else
367 				buffer.fill(0);
368 			break;
369 		}
370 }
371 
372 
373 
374 //**************************************************************************
375 //  INTERNAL HELPERS
376 //**************************************************************************
377 
378 //-------------------------------------------------
379 //  read_sample - read a WAV or FLAC file as a
380 //  sample
381 //-------------------------------------------------
382 
read_sample(emu_file & file,sample_t & sample)383 bool samples_device::read_sample(emu_file &file, sample_t &sample)
384 {
385 	// read the core header and make sure it's a proper file
386 	uint8_t buf[4];
387 	uint32_t offset = file.read(buf, 4);
388 	if (offset < 4)
389 	{
390 		osd_printf_warning("Unable to read %s, 0-byte file?\n", file.filename());
391 		return false;
392 	}
393 
394 	// look for the appropriate RIFF tag
395 	if (memcmp(&buf[0], "RIFF", 4) == 0)
396 		return read_wav_sample(file, sample);
397 	else if (memcmp(&buf[0], "fLaC", 4) == 0)
398 		return read_flac_sample(file, sample);
399 
400 	// if nothing appropriate, emit a warning
401 	osd_printf_warning("Unable to read %s, corrupt file?\n", file.filename());
402 	return false;
403 }
404 
405 
406 //-------------------------------------------------
407 //  read_wav_sample - read a WAV file as a sample
408 //-------------------------------------------------
409 
read_wav_sample(emu_file & file,sample_t & sample)410 bool samples_device::read_wav_sample(emu_file &file, sample_t &sample)
411 {
412 	// we already read the opening 'RIFF' tag
413 	uint32_t offset = 4;
414 
415 	// get the total size
416 	uint32_t filesize;
417 	offset += file.read(&filesize, 4);
418 	if (offset < 8)
419 	{
420 		osd_printf_warning("Unexpected size offset %u (%s)\n", offset, file.filename());
421 		return false;
422 	}
423 	filesize = little_endianize_int32(filesize);
424 
425 	// read the RIFF file type and make sure it's a WAVE file
426 	char buf[32];
427 	offset += file.read(buf, 4);
428 	if (offset < 12)
429 	{
430 		osd_printf_warning("Unexpected WAVE offset %u (%s)\n", offset, file.filename());
431 		return false;
432 	}
433 	if (memcmp(&buf[0], "WAVE", 4) != 0)
434 	{
435 		osd_printf_warning("Could not find WAVE header (%s)\n", file.filename());
436 		return false;
437 	}
438 
439 	// seek until we find a format tag
440 	uint32_t length;
441 	while (1)
442 	{
443 		offset += file.read(buf, 4);
444 		offset += file.read(&length, 4);
445 		length = little_endianize_int32(length);
446 		if (memcmp(&buf[0], "fmt ", 4) == 0)
447 			break;
448 
449 		// seek to the next block
450 		file.seek(length, SEEK_CUR);
451 		offset += length;
452 		if (offset >= filesize)
453 		{
454 			osd_printf_warning("Could not find fmt tag (%s)\n", file.filename());
455 			return false;
456 		}
457 	}
458 
459 	// read the format -- make sure it is PCM
460 	uint16_t temp16;
461 	offset += file.read(&temp16, 2);
462 	temp16 = little_endianize_int16(temp16);
463 	if (temp16 != 1)
464 	{
465 		osd_printf_warning("unsupported format %u - only PCM is supported (%s)\n", temp16, file.filename());
466 		return false;
467 	}
468 
469 	// number of channels -- only mono is supported
470 	offset += file.read(&temp16, 2);
471 	temp16 = little_endianize_int16(temp16);
472 	if (temp16 != 1)
473 	{
474 		osd_printf_warning("unsupported number of channels %u - only mono is supported (%s)\n", temp16, file.filename());
475 		return false;
476 	}
477 
478 	// sample rate
479 	uint32_t rate;
480 	offset += file.read(&rate, 4);
481 	rate = little_endianize_int32(rate);
482 
483 	// bytes/second and block alignment are ignored
484 	offset += file.read(buf, 6);
485 
486 	// bits/sample
487 	uint16_t bits;
488 	offset += file.read(&bits, 2);
489 	bits = little_endianize_int16(bits);
490 	if (bits != 8 && bits != 16)
491 	{
492 		osd_printf_warning("unsupported bits/sample %u - only 8 and 16 are supported (%s)\n", bits, file.filename());
493 		return false;
494 	}
495 
496 	// seek past any extra data
497 	file.seek(length - 16, SEEK_CUR);
498 	offset += length - 16;
499 
500 	// seek until we find a data tag
501 	while (1)
502 	{
503 		offset += file.read(buf, 4);
504 		offset += file.read(&length, 4);
505 		length = little_endianize_int32(length);
506 		if (memcmp(&buf[0], "data", 4) == 0)
507 			break;
508 
509 		// seek to the next block
510 		file.seek(length, SEEK_CUR);
511 		offset += length;
512 		if (offset >= filesize)
513 		{
514 			osd_printf_warning("Could not find data tag (%s)\n", file.filename());
515 			return false;
516 		}
517 	}
518 
519 	// if there was a 0 length data block, we're done
520 	if (length == 0)
521 	{
522 		osd_printf_warning("empty data block (%s)\n", file.filename());
523 		return false;
524 	}
525 
526 	// fill in the sample data
527 	sample.frequency = rate;
528 
529 	// read the data in
530 	if (bits == 8)
531 	{
532 		sample.data.resize(length);
533 		file.read(&sample.data[0], length);
534 
535 		// convert 8-bit data to signed samples
536 		uint8_t *tempptr = reinterpret_cast<uint8_t *>(&sample.data[0]);
537 		for (int32_t sindex = length - 1; sindex >= 0; sindex--)
538 			sample.data[sindex] = int8_t(tempptr[sindex] ^ 0x80) * 256;
539 	}
540 	else
541 	{
542 		// 16-bit data is fine as-is
543 		sample.data.resize(length / 2);
544 		file.read(&sample.data[0], length);
545 
546 		// swap high/low on big-endian systems
547 		if (ENDIANNESS_NATIVE != ENDIANNESS_LITTLE)
548 			for (uint32_t sindex = 0; sindex < length / 2; sindex++)
549 				sample.data[sindex] = little_endianize_int16(sample.data[sindex]);
550 	}
551 	return true;
552 }
553 
554 
555 //-------------------------------------------------
556 //  read_flac_sample - read a FLAC file as a sample
557 //-------------------------------------------------
558 
read_flac_sample(emu_file & file,sample_t & sample)559 bool samples_device::read_flac_sample(emu_file &file, sample_t &sample)
560 {
561 	// seek back to the start of the file
562 	file.seek(0, SEEK_SET);
563 
564 	// create the FLAC decoder and fill in the sample data
565 	flac_decoder decoder((util::core_file &)file);
566 	sample.frequency = decoder.sample_rate();
567 
568 	// error if more than 1 channel or not 16bpp
569 	if (decoder.channels() != 1)
570 		return false;
571 	if (decoder.bits_per_sample() != 16)
572 		return false;
573 
574 	// resize the array and read
575 	sample.data.resize(decoder.total_samples());
576 	if (!decoder.decode_interleaved(&sample.data[0], sample.data.size()))
577 		return false;
578 
579 	// finish up and clean up
580 	decoder.finish();
581 	return true;
582 }
583 
584 
585 //-------------------------------------------------
586 //  load_samples - load all the samples in our
587 //  attached interface
588 //  Returns true when all samples were successfully read, else false
589 //-------------------------------------------------
590 
load_samples()591 bool samples_device::load_samples()
592 {
593 	bool ok = true;
594 	// if the user doesn't want to use samples, bail
595 	if (!machine().options().samples())
596 		return false;
597 
598 	// iterate over ourself
599 	const std::string &basename = machine().basename();
600 	samples_iterator iter(*this);
601 	const char *altbasename = iter.altbasename();
602 
603 	// pre-size the array
604 	m_sample.resize(iter.count());
605 
606 	// load the samples
607 	int index = 0;
608 	for (const char *samplename = iter.first(); samplename != nullptr; index++, samplename = iter.next())
609 	{
610 		// attempt to open as FLAC first
611 		emu_file file(machine().options().sample_path(), OPEN_FLAG_READ);
612 		osd_file::error filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.flac", basename, samplename));
613 		if (filerr != osd_file::error::NONE && altbasename != nullptr)
614 			filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.flac", altbasename, samplename));
615 
616 		// if not, try as WAV
617 		if (filerr != osd_file::error::NONE)
618 			filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.wav", basename, samplename));
619 		if (filerr != osd_file::error::NONE && altbasename != nullptr)
620 			filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.wav", altbasename, samplename));
621 
622 		// if opened, read it
623 		if (filerr == osd_file::error::NONE)
624 			read_sample(file, m_sample[index]);
625 		else if (filerr == osd_file::error::NOT_FOUND)
626 		{
627 			logerror("%s: Sample '%s' NOT FOUND\n", tag(), samplename);
628 			ok = false;
629 		}
630 	}
631 	return ok;
632 }
633