1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4
5 sound.cpp
6
7 Core sound functions and definitions.
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "speaker.h"
13 #include "emuopts.h"
14 #include "osdepend.h"
15 #include "config.h"
16 #include "wavwrite.h"
17
18
19
20 //**************************************************************************
21 // DEBUGGING
22 //**************************************************************************
23
24 #define VERBOSE (0)
25
26 #define VPRINTF(x) do { if (VERBOSE) osd_printf_debug x; } while (0)
27
28 #define LOG_OUTPUT_WAV (0)
29
30
31
32 //**************************************************************************
33 // CONSTANTS
34 //**************************************************************************
35
36
37
38 //**************************************************************************
39 // GLOBAL VARIABLES
40 //**************************************************************************
41
42 const attotime sound_manager::STREAMS_UPDATE_ATTOTIME = attotime::from_hz(STREAMS_UPDATE_FREQUENCY);
43
44
45
46 //**************************************************************************
47 // STREAM BUFFER
48 //**************************************************************************
49
50 //-------------------------------------------------
51 // stream_buffer - constructor
52 //-------------------------------------------------
53
stream_buffer(u32 sample_rate)54 stream_buffer::stream_buffer(u32 sample_rate) :
55 m_end_second(0),
56 m_end_sample(0),
57 m_sample_rate(sample_rate),
58 m_sample_attos((sample_rate == 0) ? ATTOSECONDS_PER_SECOND : ((ATTOSECONDS_PER_SECOND + sample_rate - 1) / sample_rate)),
59 m_buffer(sample_rate)
60 {
61 }
62
63
64 //-------------------------------------------------
65 // stream_buffer - destructor
66 //-------------------------------------------------
67
~stream_buffer()68 stream_buffer::~stream_buffer()
69 {
70 #if (SOUND_DEBUG)
71 if (m_wav_file != nullptr)
72 {
73 flush_wav();
74 close_wav();
75 }
76 #endif
77 }
78
79
80 //-------------------------------------------------
81 // set_sample_rate - set a new sample rate for
82 // this buffer
83 //-------------------------------------------------
84
set_sample_rate(u32 rate,bool resample)85 void stream_buffer::set_sample_rate(u32 rate, bool resample)
86 {
87 // skip if nothing is actually changing
88 if (rate == m_sample_rate)
89 return;
90
91 // force resampling off if coming to or from an invalid rate, or if we're at time 0 (startup)
92 sound_assert(rate >= SAMPLE_RATE_MINIMUM - 1);
93 if (rate < SAMPLE_RATE_MINIMUM || m_sample_rate < SAMPLE_RATE_MINIMUM || (m_end_second == 0 && m_end_sample == 0))
94 resample = false;
95
96 // note the time and period of the current buffer (end_time is AFTER the final sample)
97 attotime prevperiod = sample_period();
98 attotime prevend = end_time();
99
100 // compute the time and period of the new buffer
101 attotime newperiod = attotime(0, (ATTOSECONDS_PER_SECOND + rate - 1) / rate);
102 attotime newend = attotime(prevend.seconds(), (prevend.attoseconds() / newperiod.attoseconds()) * newperiod.attoseconds());
103
104 // buffer a short runway of previous samples; in order to support smooth
105 // sample rate changes (needed by, e.g., Q*Bert's Votrax), we buffer a few
106 // samples at the previous rate, and then reconstitute them resampled
107 // (via simple point sampling) at the new rate. The litmus test is the
108 // voice when jumping off the edge in Q*Bert; without this extra effort
109 // it is crackly and/or glitchy at times
110 sample_t buffer[64];
111 int buffered_samples = std::min(m_sample_rate, std::min(rate, u32(ARRAY_LENGTH(buffer))));
112
113 // if the new rate is lower, downsample into our holding buffer;
114 // otherwise just copy into our holding buffer for later upsampling
115 bool new_rate_higher = (rate > m_sample_rate);
116 if (resample)
117 {
118 if (!new_rate_higher)
119 backfill_downsample(&buffer[0], buffered_samples, newend, newperiod);
120 else
121 {
122 u32 end = m_end_sample;
123 for (int index = 0; index < buffered_samples; index++)
124 {
125 end = prev_index(end);
126 #if (SOUND_DEBUG)
127 // multiple resamples can occur before clearing out old NaNs so
128 // neuter them for this specific case
129 if (std::isnan(m_buffer[end]))
130 buffer[index] = 0;
131 else
132 #endif
133 buffer[index] = get(end);
134 }
135 }
136 }
137
138 // ensure our buffer is large enough to hold a full second at the new rate
139 if (m_buffer.size() < rate)
140 m_buffer.resize(rate);
141
142 // set the new rate
143 m_sample_rate = rate;
144 m_sample_attos = newperiod.attoseconds();
145
146 // compute the new end sample index based on the buffer time
147 m_end_sample = time_to_buffer_index(prevend, false, true);
148
149 // if the new rate is higher, upsample from our temporary buffer;
150 // otherwise just copy our previously-downsampled data
151 if (resample)
152 {
153 #if (SOUND_DEBUG)
154 // for aggressive debugging, fill the buffer with NANs to catch anyone
155 // reading beyond what we resample below
156 fill(NAN);
157 #endif
158
159 if (new_rate_higher)
160 backfill_upsample(&buffer[0], buffered_samples, prevend, prevperiod);
161 else
162 {
163 u32 end = m_end_sample;
164 for (int index = 0; index < buffered_samples; index++)
165 {
166 end = prev_index(end);
167 put(end, buffer[index]);
168 }
169 }
170 }
171
172 // if not resampling, clear the buffer
173 else
174 fill(0);
175 }
176
177
178 //-------------------------------------------------
179 // open_wav - open a WAV file for logging purposes
180 //-------------------------------------------------
181
182 #if (SOUND_DEBUG)
open_wav(char const * filename)183 void stream_buffer::open_wav(char const *filename)
184 {
185 // always open at 48k so that sound programs can handle it
186 // re-sample as needed
187 m_wav_file = wav_open(filename, 48000, 1);
188 }
189 #endif
190
191
192 //-------------------------------------------------
193 // flush_wav - flush data to the WAV file
194 //-------------------------------------------------
195
196 #if (SOUND_DEBUG)
flush_wav()197 void stream_buffer::flush_wav()
198 {
199 // skip if no file
200 if (m_wav_file == nullptr)
201 return;
202
203 // grab a view of the data from the last-written point
204 read_stream_view view(this, m_last_written, m_end_sample, 1.0f);
205 m_last_written = m_end_sample;
206
207 // iterate over chunks for conversion
208 s16 buffer[1024];
209 for (int samplebase = 0; samplebase < view.samples(); samplebase += ARRAY_LENGTH(buffer))
210 {
211 // clamp to the buffer size
212 int cursamples = view.samples() - samplebase;
213 if (cursamples > ARRAY_LENGTH(buffer))
214 cursamples = ARRAY_LENGTH(buffer);
215
216 // convert and fill
217 for (int sampindex = 0; sampindex < cursamples; sampindex++)
218 buffer[sampindex] = s16(view.get(samplebase + sampindex) * 32768.0);
219
220 // write to the WAV
221 wav_add_data_16(m_wav_file, buffer, cursamples);
222 }
223 }
224 #endif
225
226
227 //-------------------------------------------------
228 // close_wav - close the logging WAV file
229 //-------------------------------------------------
230
231 #if (SOUND_DEBUG)
close_wav()232 void stream_buffer::close_wav()
233 {
234 if (m_wav_file != nullptr)
235 wav_close(m_wav_file);
236 m_wav_file = nullptr;
237 }
238 #endif
239
240
241 //-------------------------------------------------
242 // index_time - return the attotime of a given
243 // index within the buffer
244 //-------------------------------------------------
245
index_time(s32 index) const246 attotime stream_buffer::index_time(s32 index) const
247 {
248 index = clamp_index(index);
249 return attotime(m_end_second - ((index > m_end_sample) ? 1 : 0), index * m_sample_attos);
250 }
251
252
253 //-------------------------------------------------
254 // time_to_buffer_index - given an attotime,
255 // return the buffer index corresponding to it
256 //-------------------------------------------------
257
time_to_buffer_index(attotime time,bool round_up,bool allow_expansion)258 u32 stream_buffer::time_to_buffer_index(attotime time, bool round_up, bool allow_expansion)
259 {
260 // compute the sample index within the second
261 int sample = (time.attoseconds() + (round_up ? (m_sample_attos - 1) : 0)) / m_sample_attos;
262 sound_assert(sample >= 0 && sample <= size());
263
264 // if the time is past the current end, make it the end
265 if (time.seconds() > m_end_second || (time.seconds() == m_end_second && sample > m_end_sample))
266 {
267 sound_assert(allow_expansion);
268
269 m_end_sample = sample;
270 m_end_second = time.m_seconds;
271
272 // due to round_up, we could tweak over the line into the next second
273 if (sample >= size())
274 {
275 m_end_sample -= size();
276 m_end_second++;
277 }
278 }
279
280 // if the time is before the start, fail
281 if (time.seconds() + 1 < m_end_second || (time.seconds() + 1 == m_end_second && sample < m_end_sample))
282 throw emu_fatalerror("Attempt to create an out-of-bounds view");
283
284 return clamp_index(sample);
285 }
286
287
288 //-------------------------------------------------
289 // backfill_downsample - this is called BEFORE
290 // the sample rate change to downsample from the
291 // end of the current buffer into a temporary
292 // holding location
293 //-------------------------------------------------
294
backfill_downsample(sample_t * dest,int samples,attotime newend,attotime newperiod)295 void stream_buffer::backfill_downsample(sample_t *dest, int samples, attotime newend, attotime newperiod)
296 {
297 // compute the time of the first sample to be backfilled; start one period before
298 attotime time = newend - newperiod;
299
300 // loop until we run out of buffered data
301 int dstindex;
302 for (dstindex = 0; dstindex < samples && time.seconds() >= 0; dstindex++)
303 {
304 u32 srcindex = time_to_buffer_index(time, false);
305 #if (SOUND_DEBUG)
306 // multiple resamples can occur before clearing out old NaNs so
307 // neuter them for this specific case
308 if (std::isnan(m_buffer[srcindex]))
309 dest[dstindex] = 0;
310 else
311 #endif
312 dest[dstindex] = get(srcindex);
313 time -= newperiod;
314 }
315 for ( ; dstindex < samples; dstindex++)
316 dest[dstindex] = 0;
317 }
318
319
320 //-------------------------------------------------
321 // backfill_upsample - this is called AFTER the
322 // sample rate change to take a copied buffer
323 // of samples at the old rate and upsample them
324 // to the new (current) rate
325 //-------------------------------------------------
326
backfill_upsample(sample_t const * src,int samples,attotime prevend,attotime prevperiod)327 void stream_buffer::backfill_upsample(sample_t const *src, int samples, attotime prevend, attotime prevperiod)
328 {
329 // compute the time of the first sample to be backfilled; start one period before
330 attotime time = end_time() - sample_period();
331
332 // also adjust the buffered sample end time to point to the sample time of the
333 // final sample captured
334 prevend -= prevperiod;
335
336 // loop until we run out of buffered data
337 u32 end = m_end_sample;
338 int srcindex = 0;
339 while (1)
340 {
341 // if our backfill time is before the current buffered sample time,
342 // back up until we have a sample that covers this time
343 while (time < prevend && srcindex < samples)
344 {
345 prevend -= prevperiod;
346 srcindex++;
347 }
348
349 // stop when we run out of source
350 if (srcindex >= samples)
351 break;
352
353 // write this sample at the pevious position
354 end = prev_index(end);
355 put(end, src[srcindex]);
356
357 // back up to the next sample time
358 time -= sample_period();
359 }
360 }
361
362
363
364 //**************************************************************************
365 // SOUND STREAM OUTPUT
366 //**************************************************************************
367
368 //-------------------------------------------------
369 // sound_stream_output - constructor
370 //-------------------------------------------------
371
sound_stream_output()372 sound_stream_output::sound_stream_output() :
373 m_stream(nullptr),
374 m_index(0),
375 m_gain(1.0)
376 {
377 }
378
379
380 //-------------------------------------------------
381 // init - initialization
382 //-------------------------------------------------
383
init(sound_stream & stream,u32 index,char const * tag)384 void sound_stream_output::init(sound_stream &stream, u32 index, char const *tag)
385 {
386 // set the passed-in data
387 m_stream = &stream;
388 m_index = index;
389
390 // save our state
391 auto &save = stream.device().machine().save();
392 save.save_item(&stream.device(), "stream.output", tag, index, NAME(m_gain));
393
394 #if (LOG_OUTPUT_WAV)
395 std::string filename = stream.device().machine().basename();
396 filename += stream.device().tag();
397 for (int index = 0; index < filename.size(); index++)
398 if (filename[index] == ':')
399 filename[index] = '_';
400 if (dynamic_cast<default_resampler_stream *>(&stream) != nullptr)
401 filename += "_resampler";
402 filename += "_OUT_";
403 char buf[10];
404 sprintf(buf, "%d", index);
405 filename += buf;
406 filename += ".wav";
407 m_buffer.open_wav(filename.c_str());
408 #endif
409 }
410
411
412 //-------------------------------------------------
413 // name - return the friendly name of this output
414 //-------------------------------------------------
415
name() const416 std::string sound_stream_output::name() const
417 {
418 // start with our owning stream's name
419 std::ostringstream str;
420 util::stream_format(str, "%s Ch.%d", m_stream->name(), m_stream->output_base() + m_index);
421 return str.str();
422 }
423
424
425 //-------------------------------------------------
426 // optimize_resampler - optimize resamplers by
427 // either returning the native rate or another
428 // input's resampler if they can be reused
429 //-------------------------------------------------
430
optimize_resampler(sound_stream_output * input_resampler)431 sound_stream_output &sound_stream_output::optimize_resampler(sound_stream_output *input_resampler)
432 {
433 // if no resampler, or if the resampler rate matches our rate, return ourself
434 if (input_resampler == nullptr || buffer_sample_rate() == input_resampler->buffer_sample_rate())
435 return *this;
436
437 // scan our list of resamplers to see if there's another match
438 for (auto &resampler : m_resampler_list)
439 if (resampler->buffer_sample_rate() == input_resampler->buffer_sample_rate())
440 return *resampler;
441
442 // add the input to our list and return the one we were given back
443 m_resampler_list.push_back(input_resampler);
444 return *input_resampler;
445 }
446
447
448
449 //**************************************************************************
450 // SOUND STREAM INPUT
451 //**************************************************************************
452
453 //-------------------------------------------------
454 // sound_stream_input - constructor
455 //-------------------------------------------------
456
sound_stream_input()457 sound_stream_input::sound_stream_input() :
458 m_owner(nullptr),
459 m_native_source(nullptr),
460 m_resampler_source(nullptr),
461 m_index(0),
462 m_gain(1.0),
463 m_user_gain(1.0)
464 {
465 }
466
467
468 //-------------------------------------------------
469 // init - initialization
470 //-------------------------------------------------
471
init(sound_stream & stream,u32 index,char const * tag,sound_stream_output * resampler)472 void sound_stream_input::init(sound_stream &stream, u32 index, char const *tag, sound_stream_output *resampler)
473 {
474 // set the passed-in values
475 m_owner = &stream;
476 m_index = index;
477 m_resampler_source = resampler;
478
479 // save our state
480 auto &save = stream.device().machine().save();
481 save.save_item(&stream.device(), "stream.input", tag, index, NAME(m_gain));
482 save.save_item(&stream.device(), "stream.input", tag, index, NAME(m_user_gain));
483 }
484
485
486 //-------------------------------------------------
487 // name - return the friendly name of this input
488 //-------------------------------------------------
489
name() const490 std::string sound_stream_input::name() const
491 {
492 // start with our owning stream's name
493 std::ostringstream str;
494 util::stream_format(str, "%s", m_owner->name());
495
496 // if we have a source, indicate where the sound comes from by device name and tag
497 if (valid())
498 util::stream_format(str, " <- %s", m_native_source->name());
499 return str.str();
500 }
501
502
503 //-------------------------------------------------
504 // set_source - wire up the output source for
505 // our consumption
506 //-------------------------------------------------
507
set_source(sound_stream_output * source)508 void sound_stream_input::set_source(sound_stream_output *source)
509 {
510 m_native_source = source;
511 if (m_resampler_source != nullptr)
512 m_resampler_source->stream().set_input(0, &source->stream(), source->index());
513 }
514
515
516 //-------------------------------------------------
517 // update - update our source's stream to the
518 // current end time and return a view to its
519 // contents
520 //-------------------------------------------------
521
update(attotime start,attotime end)522 read_stream_view sound_stream_input::update(attotime start, attotime end)
523 {
524 // shouldn't get here unless valid
525 sound_assert(valid());
526
527 // pick an optimized resampler
528 sound_stream_output &source = m_native_source->optimize_resampler(m_resampler_source);
529
530 // if not using our own resampler, keep it up to date in case we need to invoke it later
531 if (m_resampler_source != nullptr && &source != m_resampler_source)
532 m_resampler_source->set_end_time(end);
533
534 // update the source, returning a view of the needed output over the start and end times
535 return source.stream().update_view(start, end, source.index()).apply_gain(m_gain * m_user_gain * source.gain());
536 }
537
538
539 //-------------------------------------------------
540 // apply_sample_rate_changes - tell our sources
541 // to apply any sample rate changes, informing
542 // them of our current rate
543 //-------------------------------------------------
544
apply_sample_rate_changes(u32 updatenum,u32 downstream_rate)545 void sound_stream_input::apply_sample_rate_changes(u32 updatenum, u32 downstream_rate)
546 {
547 // shouldn't get here unless valid
548 sound_assert(valid());
549
550 // if we have a resampler, tell it (and it will tell the native source)
551 if (m_resampler_source != nullptr)
552 m_resampler_source->stream().apply_sample_rate_changes(updatenum, downstream_rate);
553
554 // otherwise, just tell the native source directly
555 else
556 m_native_source->stream().apply_sample_rate_changes(updatenum, downstream_rate);
557 }
558
559
560
561 //**************************************************************************
562 // SOUND STREAM
563 //**************************************************************************
564
565 //-------------------------------------------------
566 // sound_stream - private common constructor
567 //-------------------------------------------------
568
sound_stream(device_t & device,u32 inputs,u32 outputs,u32 output_base,u32 sample_rate,sound_stream_flags flags)569 sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, sound_stream_flags flags) :
570 m_device(device),
571 m_next(nullptr),
572 m_sample_rate((sample_rate < SAMPLE_RATE_MINIMUM) ? (SAMPLE_RATE_MINIMUM - 1) : (sample_rate < SAMPLE_RATE_OUTPUT_ADAPTIVE) ? sample_rate : 48000),
573 m_pending_sample_rate(SAMPLE_RATE_INVALID),
574 m_last_sample_rate_update(0),
575 m_input_adaptive(sample_rate == SAMPLE_RATE_INPUT_ADAPTIVE),
576 m_output_adaptive(sample_rate == SAMPLE_RATE_OUTPUT_ADAPTIVE),
577 m_synchronous((flags & STREAM_SYNCHRONOUS) != 0),
578 m_resampling_disabled((flags & STREAM_DISABLE_INPUT_RESAMPLING) != 0),
579 m_sync_timer(nullptr),
580 m_input(inputs),
581 m_input_view(inputs),
582 m_empty_buffer(100),
583 m_output_base(output_base),
584 m_output(outputs),
585 m_output_view(outputs)
586 {
587 sound_assert(outputs > 0);
588
589 // create a name
590 m_name = m_device.name();
591 m_name += " '";
592 m_name += m_device.tag();
593 m_name += "'";
594
595 // create a unique tag for saving
596 std::string state_tag = string_format("%d", m_device.machine().sound().unique_id());
597 auto &save = m_device.machine().save();
598 save.save_item(&m_device, "stream.sample_rate", state_tag.c_str(), 0, NAME(m_sample_rate));
599 save.register_postload(save_prepost_delegate(FUNC(sound_stream::postload), this));
600
601 // initialize all inputs
602 for (unsigned int inputnum = 0; inputnum < m_input.size(); inputnum++)
603 {
604 // allocate a resampler stream if needed, and get a pointer to its output
605 sound_stream_output *resampler = nullptr;
606 if (!m_resampling_disabled)
607 {
608 m_resampler_list.push_back(std::make_unique<default_resampler_stream>(m_device));
609 resampler = &m_resampler_list.back()->m_output[0];
610 }
611
612 // add the new input
613 m_input[inputnum].init(*this, inputnum, state_tag.c_str(), resampler);
614 }
615
616 // initialize all outputs
617 for (unsigned int outputnum = 0; outputnum < m_output.size(); outputnum++)
618 m_output[outputnum].init(*this, outputnum, state_tag.c_str());
619
620 // create an update timer for synchronous streams
621 if (synchronous())
622 m_sync_timer = m_device.machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sound_stream::sync_update), this));
623
624 // force an update to the sample rates
625 sample_rate_changed();
626 }
627
628
629 //-------------------------------------------------
630 // sound_stream - constructor
631 //-------------------------------------------------
632
sound_stream(device_t & device,u32 inputs,u32 outputs,u32 output_base,u32 sample_rate,stream_update_delegate callback,sound_stream_flags flags)633 sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags) :
634 sound_stream(device, inputs, outputs, output_base, sample_rate, flags)
635 {
636 m_callback_ex = std::move(callback);
637 }
638
639
640 //-------------------------------------------------
641 // ~sound_stream - destructor
642 //-------------------------------------------------
643
~sound_stream()644 sound_stream::~sound_stream()
645 {
646 }
647
648
649 //-------------------------------------------------
650 // set_sample_rate - set the sample rate on a
651 // given stream
652 //-------------------------------------------------
653
set_sample_rate(u32 new_rate)654 void sound_stream::set_sample_rate(u32 new_rate)
655 {
656 // we will update this on the next global update
657 if (new_rate != sample_rate())
658 m_pending_sample_rate = new_rate;
659 }
660
661
662 //-------------------------------------------------
663 // set_input - configure a stream's input
664 //-------------------------------------------------
665
set_input(int index,sound_stream * input_stream,int output_index,float gain)666 void sound_stream::set_input(int index, sound_stream *input_stream, int output_index, float gain)
667 {
668 VPRINTF(("stream_set_input(%p, '%s', %d, %p, %d, %f)\n", (void *)this, m_device.tag(),
669 index, (void *)input_stream, output_index, (double) gain));
670
671 // make sure it's a valid input
672 if (index >= m_input.size())
673 fatalerror("stream_set_input attempted to configure nonexistent input %d (%d max)\n", index, int(m_input.size()));
674
675 // make sure it's a valid output
676 if (input_stream != nullptr && output_index >= input_stream->m_output.size())
677 fatalerror("stream_set_input attempted to use a nonexistent output %d (%d max)\n", output_index, int(m_output.size()));
678
679 // wire it up
680 m_input[index].set_source((input_stream != nullptr) ? &input_stream->m_output[output_index] : nullptr);
681 m_input[index].set_gain(gain);
682
683 // update sample rates now that we know the input
684 sample_rate_changed();
685 }
686
687
688 //-------------------------------------------------
689 // update - force a stream to update to
690 // the current emulated time
691 //-------------------------------------------------
692
update()693 void sound_stream::update()
694 {
695 // ignore any update requests if we're already up to date
696 attotime start = m_output[0].end_time();
697 attotime end = m_device.machine().time();
698 if (start >= end)
699 return;
700
701 // regular update then
702 update_view(start, end);
703 }
704
705
706 //-------------------------------------------------
707 // update_view - force a stream to update to
708 // the current emulated time and return a view
709 // to the generated samples from the given
710 // output number
711 //-------------------------------------------------
712
update_view(attotime start,attotime end,u32 outputnum)713 read_stream_view sound_stream::update_view(attotime start, attotime end, u32 outputnum)
714 {
715 sound_assert(start <= end);
716 sound_assert(outputnum < m_output.size());
717
718 // clean up parameters for when the asserts go away
719 if (outputnum >= m_output.size())
720 outputnum = 0;
721 if (start > end)
722 start = end;
723
724 g_profiler.start(PROFILER_SOUND);
725
726 // reposition our start to coincide with the current buffer end
727 attotime update_start = m_output[outputnum].end_time();
728 if (update_start <= end)
729 {
730 // create views for all the outputs
731 for (unsigned int outindex = 0; outindex < m_output.size(); outindex++)
732 m_output_view[outindex] = m_output[outindex].view(update_start, end);
733
734 // skip if nothing to do
735 u32 samples = m_output_view[0].samples();
736 sound_assert(samples >= 0);
737 if (samples != 0 && m_sample_rate >= SAMPLE_RATE_MINIMUM)
738 {
739 sound_assert(!synchronous() || samples == 1);
740
741 // ensure all input streams are up to date, and create views for them as well
742 for (unsigned int inputnum = 0; inputnum < m_input.size(); inputnum++)
743 {
744 if (m_input[inputnum].valid())
745 m_input_view[inputnum] = m_input[inputnum].update(update_start, end);
746 else
747 m_input_view[inputnum] = empty_view(update_start, end);
748 sound_assert(m_input_view[inputnum].samples() > 0);
749 sound_assert(m_resampling_disabled || m_input_view[inputnum].sample_rate() == m_sample_rate);
750 }
751
752 #if (SOUND_DEBUG)
753 // clear each output view to NANs before we call the callback
754 for (unsigned int outindex = 0; outindex < m_output.size(); outindex++)
755 m_output_view[outindex].fill(NAN);
756 #endif
757
758 // if we have an extended callback, that's all we need
759 m_callback_ex(*this, m_input_view, m_output_view);
760
761 #if (SOUND_DEBUG)
762 // make sure everything was overwritten
763 for (unsigned int outindex = 0; outindex < m_output.size(); outindex++)
764 for (int sampindex = 0; sampindex < m_output_view[outindex].samples(); sampindex++)
765 m_output_view[outindex].get(sampindex);
766
767 for (unsigned int outindex = 0; outindex < m_output.size(); outindex++)
768 m_output[outindex].m_buffer.flush_wav();
769 #endif
770 }
771 }
772 g_profiler.stop();
773
774 // return the requested view
775 return read_stream_view(m_output_view[outputnum], start);
776 }
777
778
779 //-------------------------------------------------
780 // apply_sample_rate_changes - if there is a
781 // pending sample rate change, apply it now
782 //-------------------------------------------------
783
apply_sample_rate_changes(u32 updatenum,u32 downstream_rate)784 void sound_stream::apply_sample_rate_changes(u32 updatenum, u32 downstream_rate)
785 {
786 // grab the new rate and invalidate
787 u32 new_rate = (m_pending_sample_rate != SAMPLE_RATE_INVALID) ? m_pending_sample_rate : m_sample_rate;
788 m_pending_sample_rate = SAMPLE_RATE_INVALID;
789
790 // clamp to the minimum - 1 (anything below minimum means "off" and
791 // will not call the sound callback at all)
792 if (new_rate < SAMPLE_RATE_MINIMUM)
793 new_rate = SAMPLE_RATE_MINIMUM - 1;
794
795 // if we're input adaptive, override with the rate of our input
796 if (input_adaptive() && m_input.size() > 0 && m_input[0].valid())
797 new_rate = m_input[0].source().stream().sample_rate();
798
799 // if we're output adaptive, override with the rate of our output
800 if (output_adaptive())
801 {
802 if (m_last_sample_rate_update == updatenum)
803 sound_assert(new_rate == m_sample_rate);
804 else
805 m_last_sample_rate_update = updatenum;
806 new_rate = downstream_rate;
807 }
808
809 // if something is different, process the change
810 if (new_rate != SAMPLE_RATE_INVALID && new_rate != m_sample_rate)
811 {
812 // update to the new rate and notify everyone
813 #if (SOUND_DEBUG)
814 printf("stream %s changing rates %d -> %d\n", name().c_str(), m_sample_rate, new_rate);
815 #endif
816 m_sample_rate = new_rate;
817 sample_rate_changed();
818 }
819
820 // now call through our inputs and apply the rate change there
821 for (auto &input : m_input)
822 if (input.valid())
823 input.apply_sample_rate_changes(updatenum, m_sample_rate);
824 }
825
826
827 //-------------------------------------------------
828 // print_graph_recursive - helper for debugging;
829 // prints info on this stream and then recursively
830 // prints info on all inputs
831 //-------------------------------------------------
832
833 #if (SOUND_DEBUG)
print_graph_recursive(int indent,int index)834 void sound_stream::print_graph_recursive(int indent, int index)
835 {
836 osd_printf_info("%*s%s Ch.%d @ %d\n", indent, "", name().c_str(), index + m_output_base, sample_rate());
837 for (int index = 0; index < m_input.size(); index++)
838 if (m_input[index].valid())
839 {
840 if (m_input[index].m_resampler_source != nullptr)
841 m_input[index].m_resampler_source->stream().print_graph_recursive(indent + 2, m_input[index].m_resampler_source->index());
842 else
843 m_input[index].m_native_source->stream().print_graph_recursive(indent + 2, m_input[index].m_native_source->index());
844 }
845 }
846 #endif
847
848
849 //-------------------------------------------------
850 // sample_rate_changed - recompute sample
851 // rate data, and all streams that are affected
852 // by this stream
853 //-------------------------------------------------
854
sample_rate_changed()855 void sound_stream::sample_rate_changed()
856 {
857 // if invalid, just punt
858 if (m_sample_rate == SAMPLE_RATE_INVALID)
859 return;
860
861 // update all output buffers
862 for (auto &output : m_output)
863 output.sample_rate_changed(m_sample_rate);
864
865 // if synchronous, prime the timer
866 if (synchronous())
867 reprime_sync_timer();
868 }
869
870
871 //-------------------------------------------------
872 // postload - save/restore callback
873 //-------------------------------------------------
874
postload()875 void sound_stream::postload()
876 {
877 // set the end time of all of our streams to now
878 for (auto &output : m_output)
879 output.set_end_time(m_device.machine().time());
880
881 // recompute the sample rate information
882 sample_rate_changed();
883 }
884
885
886 //-------------------------------------------------
887 // reprime_sync_timer - set up the next sync
888 // timer to go off just a hair after the end of
889 // the current sample period
890 //-------------------------------------------------
891
reprime_sync_timer()892 void sound_stream::reprime_sync_timer()
893 {
894 attotime curtime = m_device.machine().time();
895 attotime target = m_output[0].end_time() + attotime(0, 1);
896 m_sync_timer->adjust(target - curtime);
897 }
898
899
900 //-------------------------------------------------
901 // sync_update - timer callback to handle a
902 // synchronous stream
903 //-------------------------------------------------
904
sync_update(void *,s32)905 void sound_stream::sync_update(void *, s32)
906 {
907 update();
908 reprime_sync_timer();
909 }
910
911
912 //-------------------------------------------------
913 // empty_view - return an empty view covering the
914 // given time period as a substitute for invalid
915 // inputs
916 //-------------------------------------------------
917
empty_view(attotime start,attotime end)918 read_stream_view sound_stream::empty_view(attotime start, attotime end)
919 {
920 // if our dummy buffer doesn't match our sample rate, update and clear it
921 if (m_empty_buffer.sample_rate() != m_sample_rate)
922 m_empty_buffer.set_sample_rate(m_sample_rate, false);
923
924 // allocate a write view so that it can expand, and convert back to a read view
925 // on the return
926 return write_stream_view(m_empty_buffer, start, end);
927 }
928
929
930
931 //**************************************************************************
932 // RESAMPLER STREAM
933 //**************************************************************************
934
935 //-------------------------------------------------
936 // default_resampler_stream - derived sound_stream
937 // class that handles resampling
938 //-------------------------------------------------
939
default_resampler_stream(device_t & device)940 default_resampler_stream::default_resampler_stream(device_t &device) :
941 sound_stream(device, 1, 1, 0, SAMPLE_RATE_OUTPUT_ADAPTIVE, stream_update_delegate(&default_resampler_stream::resampler_sound_update, this), STREAM_DISABLE_INPUT_RESAMPLING),
942 m_max_latency(0)
943 {
944 // create a name
945 m_name = "Default Resampler '";
946 m_name += device.tag();
947 m_name += "'";
948 }
949
950
951 //-------------------------------------------------
952 // resampler_sound_update - stream callback
953 // handler for resampling an input stream to the
954 // target sample rate of the output
955 //-------------------------------------------------
956
resampler_sound_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)957 void default_resampler_stream::resampler_sound_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
958 {
959 sound_assert(inputs.size() == 1);
960 sound_assert(outputs.size() == 1);
961
962 auto &input = inputs[0];
963 auto &output = outputs[0];
964
965 // if the input has an invalid rate, just fill with zeros
966 if (input.sample_rate() <= 1)
967 {
968 output.fill(0);
969 return;
970 }
971
972 // optimize_resampler ensures we should not have equal sample rates
973 sound_assert(input.sample_rate() != output.sample_rate());
974
975 // compute the stepping value and the inverse
976 stream_buffer::sample_t step = stream_buffer::sample_t(input.sample_rate()) / stream_buffer::sample_t(output.sample_rate());
977 stream_buffer::sample_t stepinv = 1.0 / step;
978
979 // determine the latency we need to introduce, in input samples:
980 // 1 input sample for undersampled inputs
981 // 1 + step input samples for oversampled inputs
982 s64 latency_samples = 1 + ((step < 1.0) ? 0 : s32(step));
983 if (latency_samples <= m_max_latency)
984 latency_samples = m_max_latency;
985 else
986 m_max_latency = latency_samples;
987 attotime latency = latency_samples * input.sample_period();
988
989 // clamp the latency to the start (only relevant at the beginning)
990 s32 dstindex = 0;
991 attotime output_start = output.start_time();
992 auto numsamples = output.samples();
993 while (latency > output_start && dstindex < numsamples)
994 {
995 output.put(dstindex++, 0);
996 output_start += output.sample_period();
997 }
998 if (dstindex >= numsamples)
999 return;
1000
1001 // create a rebased input buffer around the adjusted start time
1002 read_stream_view rebased(input, output_start - latency);
1003 sound_assert(rebased.start_time() + latency <= output_start);
1004
1005 // compute the fractional input start position
1006 attotime delta = output_start - (rebased.start_time() + latency);
1007 sound_assert(delta.seconds() == 0);
1008 stream_buffer::sample_t srcpos = stream_buffer::sample_t(double(delta.attoseconds()) / double(rebased.sample_period_attoseconds()));
1009 sound_assert(srcpos <= 1.0f);
1010
1011 // input is undersampled: point sample except where our sample period covers a boundary
1012 s32 srcindex = 0;
1013 if (step < 1.0)
1014 {
1015 stream_buffer::sample_t cursample = rebased.get(srcindex++);
1016 for ( ; dstindex < numsamples; dstindex++)
1017 {
1018 // if still within the current sample, just replicate
1019 srcpos += step;
1020 if (srcpos <= 1.0)
1021 output.put(dstindex, cursample);
1022
1023 // if crossing a sample boundary, blend with the neighbor
1024 else
1025 {
1026 srcpos -= 1.0;
1027 sound_assert(srcpos <= step + 1e-5);
1028 stream_buffer::sample_t prevsample = cursample;
1029 cursample = rebased.get(srcindex++);
1030 output.put(dstindex, stepinv * (prevsample * (step - srcpos) + srcpos * cursample));
1031 }
1032 }
1033 sound_assert(srcindex <= rebased.samples());
1034 }
1035
1036 // input is oversampled: sum the energy
1037 else
1038 {
1039 float cursample = rebased.get(srcindex++);
1040 for ( ; dstindex < numsamples; dstindex++)
1041 {
1042 // compute the partial first sample and advance
1043 stream_buffer::sample_t scale = 1.0 - srcpos;
1044 stream_buffer::sample_t sample = cursample * scale;
1045
1046 // add in complete samples until we only have a fraction left
1047 stream_buffer::sample_t remaining = step - scale;
1048 while (remaining >= 1.0)
1049 {
1050 sample += rebased.get(srcindex++);
1051 remaining -= 1.0;
1052 }
1053
1054 // add in the final partial sample
1055 cursample = rebased.get(srcindex++);
1056 sample += cursample * remaining;
1057 output.put(dstindex, sample * stepinv);
1058
1059 // our position is now the remainder
1060 srcpos = remaining;
1061 sound_assert(srcindex <= rebased.samples());
1062 }
1063 }
1064 }
1065
1066
1067
1068 //**************************************************************************
1069 // SOUND MANAGER
1070 //**************************************************************************
1071
1072 //-------------------------------------------------
1073 // sound_manager - constructor
1074 //-------------------------------------------------
1075
sound_manager(running_machine & machine)1076 sound_manager::sound_manager(running_machine &machine) :
1077 m_machine(machine),
1078 m_update_timer(nullptr),
1079 m_update_number(0),
1080 m_last_update(attotime::zero),
1081 m_finalmix_leftover(0),
1082 m_samples_this_update(0),
1083 m_finalmix(machine.sample_rate()),
1084 m_leftmix(machine.sample_rate()),
1085 m_rightmix(machine.sample_rate()),
1086 m_compressor_scale(1.0),
1087 m_compressor_counter(0),
1088 m_muted(0),
1089 m_nosound_mode(machine.osd().no_sound()),
1090 m_attenuation(0),
1091 m_unique_id(0),
1092 m_wavfile(nullptr),
1093 m_first_reset(true)
1094 {
1095 // get filename for WAV file or AVI file if specified
1096 const char *wavfile = machine.options().wav_write();
1097 const char *avifile = machine.options().avi_write();
1098
1099 // handle -nosound and lower sample rate if not recording WAV or AVI
1100 if (m_nosound_mode && wavfile[0] == 0 && avifile[0] == 0)
1101 machine.m_sample_rate = 11025;
1102
1103 // count the mixers
1104 #if VERBOSE
1105 mixer_interface_iterator iter(machine.root_device());
1106 VPRINTF(("total mixers = %d\n", iter.count()));
1107 #endif
1108
1109 // register callbacks
1110 machine.configuration().config_register("mixer", config_load_delegate(&sound_manager::config_load, this), config_save_delegate(&sound_manager::config_save, this));
1111 machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(&sound_manager::pause, this));
1112 machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&sound_manager::resume, this));
1113 machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&sound_manager::reset, this));
1114 machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&sound_manager::stop_recording, this));
1115
1116 // register global states
1117 machine.save().save_item(NAME(m_last_update));
1118
1119 // set the starting attenuation
1120 set_attenuation(machine.options().volume());
1121
1122 // start the periodic update flushing timer
1123 m_update_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(sound_manager::update), this));
1124 m_update_timer->adjust(STREAMS_UPDATE_ATTOTIME, 0, STREAMS_UPDATE_ATTOTIME);
1125 }
1126
1127
1128 //-------------------------------------------------
1129 // sound_manager - destructor
1130 //-------------------------------------------------
1131
~sound_manager()1132 sound_manager::~sound_manager()
1133 {
1134 }
1135
1136
1137 //-------------------------------------------------
1138 // stream_alloc - allocate a new stream with the
1139 // new-style callback and flags
1140 //-------------------------------------------------
1141
stream_alloc(device_t & device,u32 inputs,u32 outputs,u32 sample_rate,stream_update_delegate callback,sound_stream_flags flags)1142 sound_stream *sound_manager::stream_alloc(device_t &device, u32 inputs, u32 outputs, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags)
1143 {
1144 // determine output base
1145 u32 output_base = 0;
1146 for (auto &stream : m_stream_list)
1147 if (&stream->device() == &device)
1148 output_base += stream->output_count();
1149
1150 m_stream_list.push_back(std::make_unique<sound_stream>(device, inputs, outputs, output_base, sample_rate, callback, flags));
1151 return m_stream_list.back().get();
1152 }
1153
1154
1155 //-------------------------------------------------
1156 // start_recording - begin audio recording
1157 //-------------------------------------------------
1158
start_recording()1159 void sound_manager::start_recording()
1160 {
1161 // open the output WAV file if specified
1162 const char *wavfile = machine().options().wav_write();
1163 if (wavfile[0] != 0 && m_wavfile == nullptr)
1164 m_wavfile = wav_open(wavfile, machine().sample_rate(), 2);
1165 }
1166
1167
1168 //-------------------------------------------------
1169 // stop_recording - end audio recording
1170 //-------------------------------------------------
1171
stop_recording()1172 void sound_manager::stop_recording()
1173 {
1174 // close any open WAV file
1175 if (m_wavfile != nullptr)
1176 wav_close(m_wavfile);
1177 m_wavfile = nullptr;
1178 }
1179
1180
1181 //-------------------------------------------------
1182 // set_attenuation - set the global volume
1183 //-------------------------------------------------
1184
set_attenuation(float attenuation)1185 void sound_manager::set_attenuation(float attenuation)
1186 {
1187 // currently OSD only supports integral attenuation
1188 m_attenuation = int(attenuation);
1189 machine().osd().set_mastervolume(m_muted ? -32 : m_attenuation);
1190 }
1191
1192
1193 //-------------------------------------------------
1194 // indexed_mixer_input - return the mixer
1195 // device and input index of the global mixer
1196 // input
1197 //-------------------------------------------------
1198
indexed_mixer_input(int index,mixer_input & info) const1199 bool sound_manager::indexed_mixer_input(int index, mixer_input &info) const
1200 {
1201 // scan through the mixers until we find the indexed input
1202 for (device_mixer_interface &mixer : mixer_interface_iterator(machine().root_device()))
1203 {
1204 if (index < mixer.inputs())
1205 {
1206 info.mixer = &mixer;
1207 info.stream = mixer.input_to_stream_input(index, info.inputnum);
1208 sound_assert(info.stream != nullptr);
1209 return true;
1210 }
1211 index -= mixer.inputs();
1212 }
1213
1214 // didn't locate
1215 info.mixer = nullptr;
1216 return false;
1217 }
1218
1219
1220 //-------------------------------------------------
1221 // samples - fills the specified buffer with
1222 // 16-bit stereo audio samples generated during
1223 // the current frame
1224 //-------------------------------------------------
1225
samples(s16 * buffer)1226 void sound_manager::samples(s16 *buffer)
1227 {
1228 for (int sample = 0; sample < m_samples_this_update * 2; sample++)
1229 *buffer++ = m_finalmix[sample];
1230 }
1231
1232
1233 //-------------------------------------------------
1234 // mute - mute sound output
1235 //-------------------------------------------------
1236
mute(bool mute,u8 reason)1237 void sound_manager::mute(bool mute, u8 reason)
1238 {
1239 if (mute)
1240 m_muted |= reason;
1241 else
1242 m_muted &= ~reason;
1243 set_attenuation(m_attenuation);
1244 }
1245
1246
1247 //-------------------------------------------------
1248 // recursive_remove_stream_from_orphan_list -
1249 // remove the given stream from the orphan list
1250 // and recursively remove all our inputs
1251 //-------------------------------------------------
1252
recursive_remove_stream_from_orphan_list(sound_stream * which)1253 void sound_manager::recursive_remove_stream_from_orphan_list(sound_stream *which)
1254 {
1255 m_orphan_stream_list.erase(which);
1256 for (int inputnum = 0; inputnum < which->input_count(); inputnum++)
1257 {
1258 auto &input = which->input(inputnum);
1259 if (input.valid())
1260 recursive_remove_stream_from_orphan_list(&input.source().stream());
1261 }
1262 }
1263
1264
1265 //-------------------------------------------------
1266 // apply_sample_rate_changes - recursively
1267 // update sample rates throughout the system
1268 //-------------------------------------------------
1269
apply_sample_rate_changes()1270 void sound_manager::apply_sample_rate_changes()
1271 {
1272 // update sample rates if they have changed
1273 for (speaker_device &speaker : speaker_device_iterator(machine().root_device()))
1274 {
1275 int stream_out;
1276 sound_stream *stream = speaker.output_to_stream_output(0, stream_out);
1277
1278 // due to device removal, some speakers may end up with no outputs; just skip those
1279 if (stream != nullptr)
1280 {
1281 sound_assert(speaker.outputs() == 1);
1282 stream->apply_sample_rate_changes(m_update_number, machine().sample_rate());
1283 }
1284 }
1285 }
1286
1287
1288 //-------------------------------------------------
1289 // reset - reset all sound chips
1290 //-------------------------------------------------
1291
reset()1292 void sound_manager::reset()
1293 {
1294 // reset all the sound chips
1295 for (device_sound_interface &sound : sound_interface_iterator(machine().root_device()))
1296 sound.device().reset();
1297
1298 // apply any sample rate changes now
1299 apply_sample_rate_changes();
1300
1301 // on first reset, identify any orphaned streams
1302 if (m_first_reset)
1303 {
1304 m_first_reset = false;
1305
1306 // put all the streams on the orphan list to start
1307 for (auto &stream : m_stream_list)
1308 m_orphan_stream_list[stream.get()] = 0;
1309
1310 // then walk the graph like we do on update and remove any we touch
1311 for (speaker_device &speaker : speaker_device_iterator(machine().root_device()))
1312 {
1313 int dummy;
1314 sound_stream *output = speaker.output_to_stream_output(0, dummy);
1315 if (output != nullptr)
1316 recursive_remove_stream_from_orphan_list(output);
1317 }
1318
1319 #if (SOUND_DEBUG)
1320 // dump the sound graph when we start up
1321 for (speaker_device &speaker : speaker_device_iterator(machine().root_device()))
1322 {
1323 int index;
1324 sound_stream *output = speaker.output_to_stream_output(0, index);
1325 if (output != nullptr)
1326 output->print_graph_recursive(0, index);
1327 }
1328
1329 // dump the orphan list as well
1330 if (m_orphan_stream_list.size() != 0)
1331 {
1332 osd_printf_info("\nOrphaned streams:\n");
1333 for (auto &stream : m_orphan_stream_list)
1334 osd_printf_info(" %s\n", stream.first->name());
1335 }
1336 #endif
1337 }
1338 }
1339
1340
1341 //-------------------------------------------------
1342 // pause - pause sound output
1343 //-------------------------------------------------
1344
pause()1345 void sound_manager::pause()
1346 {
1347 mute(true, MUTE_REASON_PAUSE);
1348 }
1349
1350
1351 //-------------------------------------------------
1352 // resume - resume sound output
1353 //-------------------------------------------------
1354
resume()1355 void sound_manager::resume()
1356 {
1357 mute(false, MUTE_REASON_PAUSE);
1358 }
1359
1360
1361 //-------------------------------------------------
1362 // config_load - read and apply data from the
1363 // configuration file
1364 //-------------------------------------------------
1365
config_load(config_type cfg_type,util::xml::data_node const * parentnode)1366 void sound_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
1367 {
1368 // we only care about game files
1369 if (cfg_type != config_type::GAME)
1370 return;
1371
1372 // might not have any data
1373 if (parentnode == nullptr)
1374 return;
1375
1376 // iterate over channel nodes
1377 for (util::xml::data_node const *channelnode = parentnode->get_child("channel"); channelnode != nullptr; channelnode = channelnode->get_next_sibling("channel"))
1378 {
1379 mixer_input info;
1380 if (indexed_mixer_input(channelnode->get_attribute_int("index", -1), info))
1381 {
1382 float defvol = channelnode->get_attribute_float("defvol", 1.0f);
1383 float newvol = channelnode->get_attribute_float("newvol", -1000.0f);
1384 if (newvol != -1000.0f)
1385 info.stream->input(info.inputnum).set_user_gain(newvol / defvol);
1386 }
1387 }
1388 }
1389
1390
1391 //-------------------------------------------------
1392 // config_save - save data to the configuration
1393 // file
1394 //-------------------------------------------------
1395
config_save(config_type cfg_type,util::xml::data_node * parentnode)1396 void sound_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
1397 {
1398 // we only care about game files
1399 if (cfg_type != config_type::GAME)
1400 return;
1401
1402 // iterate over mixer channels
1403 if (parentnode != nullptr)
1404 for (int mixernum = 0; ; mixernum++)
1405 {
1406 mixer_input info;
1407 if (!indexed_mixer_input(mixernum, info))
1408 break;
1409 float newvol = info.stream->input(info.inputnum).user_gain();
1410
1411 if (newvol != 1.0f)
1412 {
1413 util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr);
1414 if (channelnode != nullptr)
1415 {
1416 channelnode->set_attribute_int("index", mixernum);
1417 channelnode->set_attribute_float("newvol", newvol);
1418 }
1419 }
1420 }
1421 }
1422
1423
1424 //-------------------------------------------------
1425 // adjust_toward_compressor_scale - adjust the
1426 // current scale factor toward the current goal,
1427 // in small increments
1428 //-------------------------------------------------
1429
adjust_toward_compressor_scale(stream_buffer::sample_t curscale,stream_buffer::sample_t prevsample,stream_buffer::sample_t rawsample)1430 stream_buffer::sample_t sound_manager::adjust_toward_compressor_scale(stream_buffer::sample_t curscale, stream_buffer::sample_t prevsample, stream_buffer::sample_t rawsample)
1431 {
1432 stream_buffer::sample_t proposed_scale = curscale;
1433
1434 // if we want to get larger, increment by 0.01
1435 if (curscale < m_compressor_scale)
1436 {
1437 proposed_scale += 0.01f;
1438 if (proposed_scale > m_compressor_scale)
1439 proposed_scale = m_compressor_scale;
1440 }
1441
1442 // otherwise, decrement by 0.01
1443 else
1444 {
1445 proposed_scale -= 0.01f;
1446 if (proposed_scale < m_compressor_scale)
1447 proposed_scale = m_compressor_scale;
1448 }
1449
1450 // compute the sample at the current scale and at the proposed scale
1451 stream_buffer::sample_t cursample = rawsample * curscale;
1452 stream_buffer::sample_t proposed_sample = rawsample * proposed_scale;
1453
1454 // if they trend in the same direction, it's ok to take the step
1455 if ((cursample < prevsample && proposed_sample < prevsample) || (cursample > prevsample && proposed_sample > prevsample))
1456 curscale = proposed_scale;
1457
1458 // return the current scale
1459 return curscale;
1460 }
1461
1462
1463 //-------------------------------------------------
1464 // update - mix everything down to its final form
1465 // and send it to the OSD layer
1466 //-------------------------------------------------
1467
update(void * ptr,int param)1468 void sound_manager::update(void *ptr, int param)
1469 {
1470 VPRINTF(("sound_update\n"));
1471
1472 g_profiler.start(PROFILER_SOUND);
1473
1474 // determine the duration of this update
1475 attotime update_period = machine().time() - m_last_update;
1476 sound_assert(update_period.seconds() == 0);
1477
1478 // use that to compute the number of samples we need from the speakers
1479 attoseconds_t sample_rate_attos = HZ_TO_ATTOSECONDS(machine().sample_rate());
1480 m_samples_this_update = update_period.attoseconds() / sample_rate_attos;
1481
1482 // recompute the end time to an even sample boundary
1483 attotime endtime = m_last_update + attotime(0, m_samples_this_update * sample_rate_attos);
1484
1485 // clear out the mix bufers
1486 std::fill_n(&m_leftmix[0], m_samples_this_update, 0);
1487 std::fill_n(&m_rightmix[0], m_samples_this_update, 0);
1488
1489 // force all the speaker streams to generate the proper number of samples
1490 for (speaker_device &speaker : speaker_device_iterator(machine().root_device()))
1491 speaker.mix(&m_leftmix[0], &m_rightmix[0], m_last_update, endtime, m_samples_this_update, (m_muted & MUTE_REASON_SYSTEM));
1492
1493 // determine the maximum in this section
1494 stream_buffer::sample_t curmax = 0;
1495 for (int sampindex = 0; sampindex < m_samples_this_update; sampindex++)
1496 {
1497 auto sample = m_leftmix[sampindex];
1498 if (sample < 0)
1499 sample = -sample;
1500 if (sample > curmax)
1501 curmax = sample;
1502
1503 sample = m_rightmix[sampindex];
1504 if (sample < 0)
1505 sample = -sample;
1506 if (sample > curmax)
1507 curmax = sample;
1508 }
1509
1510 // pull in current compressor scale factor before modifying
1511 stream_buffer::sample_t lscale = m_compressor_scale;
1512 stream_buffer::sample_t rscale = m_compressor_scale;
1513
1514 // if we're above what the compressor will handle, adjust the compression
1515 if (curmax * m_compressor_scale > 1.0)
1516 {
1517 m_compressor_scale = 1.0 / curmax;
1518 m_compressor_counter = STREAMS_UPDATE_FREQUENCY / 5;
1519 }
1520
1521 // if we're currently scaled, wait a bit to see if we can trend back toward 1.0
1522 else if (m_compressor_counter != 0)
1523 m_compressor_counter--;
1524
1525 // try to migrate toward 0 unless we're going to introduce clipping
1526 else if (m_compressor_scale < 1.0 && curmax * 1.01 * m_compressor_scale < 1.0)
1527 {
1528 m_compressor_scale *= 1.01f;
1529 if (m_compressor_scale > 1.0)
1530 m_compressor_scale = 1.0;
1531 }
1532
1533 #if (SOUND_DEBUG)
1534 if (lscale != m_compressor_scale)
1535 printf("scale=%.5f\n", m_compressor_scale);
1536 #endif
1537
1538 // track whether there are pending scale changes in left/right
1539 stream_buffer::sample_t lprev = 0, rprev = 0;
1540
1541 // now downmix the final result
1542 u32 finalmix_step = machine().video().speed_factor();
1543 u32 finalmix_offset = 0;
1544 s16 *finalmix = &m_finalmix[0];
1545 int sample;
1546 for (sample = m_finalmix_leftover; sample < m_samples_this_update * 1000; sample += finalmix_step)
1547 {
1548 int sampindex = sample / 1000;
1549
1550 // ensure that changing the compression won't reverse direction to reduce "pops"
1551 stream_buffer::sample_t lsamp = m_leftmix[sampindex];
1552 if (lscale != m_compressor_scale && sample != m_finalmix_leftover)
1553 lscale = adjust_toward_compressor_scale(lscale, lprev, lsamp);
1554
1555 // clamp the left side
1556 lprev = lsamp *= lscale;
1557 if (lsamp > 1.0)
1558 lsamp = 1.0;
1559 else if (lsamp < -1.0)
1560 lsamp = -1.0;
1561 finalmix[finalmix_offset++] = s16(lsamp * 32767.0);
1562
1563 // ensure that changing the compression won't reverse direction to reduce "pops"
1564 stream_buffer::sample_t rsamp = m_rightmix[sampindex];
1565 if (rscale != m_compressor_scale && sample != m_finalmix_leftover)
1566 rscale = adjust_toward_compressor_scale(rscale, rprev, rsamp);
1567
1568 // clamp the left side
1569 rprev = rsamp *= rscale;
1570 if (rsamp > 1.0)
1571 rsamp = 1.0;
1572 else if (rsamp < -1.0)
1573 rsamp = -1.0;
1574 finalmix[finalmix_offset++] = s16(rsamp * 32767.0);
1575 }
1576 m_finalmix_leftover = sample - m_samples_this_update * 1000;
1577
1578 // play the result
1579 if (finalmix_offset > 0)
1580 {
1581 if (!m_nosound_mode)
1582 machine().osd().update_audio_stream(finalmix, finalmix_offset / 2);
1583 machine().osd().add_audio_to_recording(finalmix, finalmix_offset / 2);
1584 machine().video().add_sound_to_recording(finalmix, finalmix_offset / 2);
1585 if (m_wavfile != nullptr)
1586 wav_add_data_16(m_wavfile, finalmix, finalmix_offset);
1587 }
1588
1589 // update any orphaned streams so they don't get too far behind
1590 for (auto &stream : m_orphan_stream_list)
1591 stream.first->update();
1592
1593 // remember the update time
1594 m_last_update = endtime;
1595 m_update_number++;
1596
1597 // apply sample rate changes
1598 apply_sample_rate_changes();
1599
1600 // notify that new samples have been generated
1601 emulator_info::sound_hook();
1602
1603 g_profiler.stop();
1604 }
1605