diff options
Diffstat (limited to 'src/devices/sound/cdda.cpp')
-rw-r--r-- | src/devices/sound/cdda.cpp | 190 |
1 files changed, 131 insertions, 59 deletions
diff --git a/src/devices/sound/cdda.cpp b/src/devices/sound/cdda.cpp index 1b2d766493e..281a625c0bf 100644 --- a/src/devices/sound/cdda.cpp +++ b/src/devices/sound/cdda.cpp @@ -8,18 +8,16 @@ #include "emu.h" #include "cdda.h" -#define MAX_SECTORS ( 4 ) - +static constexpr int MAX_SECTORS = 4; +static constexpr int MAX_SCAN_SECTORS = 2; //------------------------------------------------- // sound_stream_update - handle a stream update //------------------------------------------------- -void cdda_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +void cdda_device::sound_stream_update(sound_stream &stream) { - get_audio_data(&outputs[0][0], &outputs[1][0], samples); - m_audio_volume[0] = int16_t(outputs[0][0]); - m_audio_volume[1] = int16_t(outputs[1][0]); + get_audio_data(stream); } //------------------------------------------------- @@ -29,9 +27,9 @@ void cdda_device::sound_stream_update(sound_stream &stream, stream_sample_t **in void cdda_device::device_start() { /* allocate an audio cache */ - m_audio_cache = std::make_unique<uint8_t[]>(CD_MAX_SECTOR_DATA * MAX_SECTORS ); + m_audio_cache = std::make_unique<uint8_t[]>(cdrom_file::MAX_SECTOR_DATA * MAX_SECTORS ); - m_stream = machine().sound().stream_alloc(*this, 0, 2, clock()); + m_stream = stream_alloc(0, 2, clock()); m_audio_playing = 0; m_audio_pause = 0; @@ -40,32 +38,26 @@ void cdda_device::device_start() m_audio_length = 0; m_audio_samples = 0; m_audio_bptr = 0; - m_disc = nullptr; - - save_item( NAME(m_audio_playing) ); - save_item( NAME(m_audio_pause) ); - save_item( NAME(m_audio_ended_normally) ); - save_item( NAME(m_audio_lba) ); - save_item( NAME(m_audio_length) ); - save_pointer( NAME(m_audio_cache), CD_MAX_SECTOR_DATA * MAX_SECTORS ); - save_item( NAME(m_audio_samples) ); - save_item( NAME(m_audio_bptr) ); -} - - -/*------------------------------------------------- - cdda_set_cdrom - set the CD-ROM file for the - given CDDA stream --------------------------------------------------*/ - -void cdda_device::set_cdrom(void *file) -{ - m_disc = (cdrom_file *)file; + m_sequence_counter = 0; + m_audio_scan = 0; + m_audio_scan_direction = 0; + + save_item(NAME(m_audio_playing)); + save_item(NAME(m_audio_pause)); + save_item(NAME(m_audio_ended_normally)); + save_item(NAME(m_audio_lba)); + save_item(NAME(m_audio_length)); + save_pointer(NAME(m_audio_cache), cdrom_file::MAX_SECTOR_DATA * MAX_SECTORS); + save_item(NAME(m_audio_samples)); + save_item(NAME(m_audio_bptr)); + save_item(NAME(m_sequence_counter)); + save_item(NAME(m_audio_scan)); + save_item(NAME(m_audio_scan_direction)); } /*------------------------------------------------- - cdda_start_audio - begin playback of a Red + start_audio - begin playback of a Red Book audio track -------------------------------------------------*/ @@ -82,7 +74,7 @@ void cdda_device::start_audio(uint32_t startlba, uint32_t numblocks) /*------------------------------------------------- - cdda_stop_audio - stop playback of a Red Book + stop_audio - stop playback of a Red Book audio track -------------------------------------------------*/ @@ -95,7 +87,7 @@ void cdda_device::stop_audio() /*------------------------------------------------- - cdda_pause_audio - pause/unpause playback of + pause_audio - pause/unpause playback of a Red Book audio track -------------------------------------------------*/ @@ -105,21 +97,69 @@ void cdda_device::pause_audio(int pause) m_audio_pause = pause; } +/*------------------------------------------------- + scan_forward - begins an audible fast scan + in the forward direction +-------------------------------------------------*/ +void cdda_device::scan_forward() +{ + m_audio_scan = true; + m_audio_scan_direction = true; +} /*------------------------------------------------- - cdda_get_audio_lba - returns the current LBA + scan_reverse - begins an audible fast scan + in the backwards direction +-------------------------------------------------*/ +void cdda_device::scan_reverse() +{ + m_audio_scan = true; + m_audio_scan_direction = false; +} + +/*------------------------------------------------- + cancel_scan - stops scan mode and resumes + normal operation +-------------------------------------------------*/ +void cdda_device::cancel_scan() +{ + m_audio_scan = false; +} + +/*------------------------------------------------- + set_audio_lba - sets the current audio LBA + play position without changing any modes. +-------------------------------------------------*/ + +void cdda_device::set_audio_lba(uint32_t lba) +{ + m_stream->update(); + m_audio_lba = lba; +} + +/*------------------------------------------------- + get_audio_lba - returns the current LBA (physical sector) during Red Book playback -------------------------------------------------*/ uint32_t cdda_device::get_audio_lba() { m_stream->update(); - return m_audio_lba; + return m_audio_lba - ((m_audio_samples + (cdrom_file::MAX_SECTOR_DATA / 4) - 1) / (cdrom_file::MAX_SECTOR_DATA / 4)); } +/*------------------------------------------------- + set_audio_length - sets the current audio LBA + play position without changing any modes. +-------------------------------------------------*/ + +void cdda_device::set_audio_length(uint32_t sectors) +{ + m_audio_length = sectors; +} /*------------------------------------------------- - cdda_audio_active - returns Red Book audio + audio_active - returns Red Book audio playback status -------------------------------------------------*/ @@ -131,7 +171,7 @@ int cdda_device::audio_active() /*------------------------------------------------- - cdda_audio_paused - returns if Red Book + audio_paused - returns if Red Book playback is paused -------------------------------------------------*/ @@ -142,7 +182,7 @@ int cdda_device::audio_paused() /*------------------------------------------------- - cdda_audio_ended - returns if a Red Book + audio_ended - returns if a Red Book track reached it's natural end -------------------------------------------------*/ @@ -159,42 +199,46 @@ int cdda_device::audio_ended() converts it to 2 16-bit 44.1 kHz streams -------------------------------------------------*/ -void cdda_device::get_audio_data(stream_sample_t *bufL, stream_sample_t *bufR, uint32_t samples_wanted) +void cdda_device::get_audio_data(sound_stream &stream) { - int i; int16_t *audio_cache = (int16_t *) m_audio_cache.get(); - while (samples_wanted > 0) + for (int sampindex = 0; sampindex < stream.samples(); ) { /* if no file, audio not playing, audio paused, or out of disc data, just zero fill */ - if (!m_disc || !m_audio_playing || m_audio_pause || (!m_audio_length && !m_audio_samples)) + if (m_disc->sequence_counter() != m_sequence_counter || !m_disc->exists() || !m_audio_playing || m_audio_pause || (!m_audio_length && !m_audio_samples)) { - if( m_disc && m_audio_playing && !m_audio_pause && !m_audio_length ) + if( m_audio_playing && !m_audio_pause && !m_audio_length ) { m_audio_playing = false; m_audio_ended_normally = true; + m_audio_end_cb(ASSERT_LINE); } - memset(bufL, 0, sizeof(stream_sample_t)*samples_wanted); - memset(bufR, 0, sizeof(stream_sample_t)*samples_wanted); + m_sequence_counter = m_disc->sequence_counter(); + m_audio_data[0] = m_audio_data[1] = 0; return; } - int samples = samples_wanted; + int samples = stream.samples() - sampindex; if (samples > m_audio_samples) { samples = m_audio_samples; } - for (i = 0; i < samples; i++) + for (int i = 0; i < samples; i++) { /* CD-DA data on the disc is big-endian */ - *bufL++ = (int16_t) big_endianize_int16( audio_cache[ m_audio_bptr ] ); m_audio_bptr++; - *bufR++ = (int16_t) big_endianize_int16( audio_cache[ m_audio_bptr ] ); m_audio_bptr++; + m_audio_data[0] = s16(big_endianize_int16( audio_cache[ m_audio_bptr ] )); + stream.put_int(0, sampindex + i, m_audio_data[0], 32768); + m_audio_bptr++; + m_audio_data[1] = s16(big_endianize_int16( audio_cache[ m_audio_bptr ] )); + stream.put_int(1, sampindex + i, m_audio_data[1], 32768); + m_audio_bptr++; } - samples_wanted -= samples; + sampindex += samples; m_audio_samples -= samples; if (m_audio_samples == 0) @@ -205,14 +249,38 @@ void cdda_device::get_audio_data(stream_sample_t *bufL, stream_sample_t *bufR, u sectors = MAX_SECTORS; } - for (i = 0; i < sectors; i++) + for (int i = 0; i < sectors; i++) { - cdrom_read_data(m_disc, m_audio_lba, &m_audio_cache[CD_MAX_SECTOR_DATA*i], CD_TRACK_AUDIO); - - m_audio_lba++; + const auto adr_control = m_disc->get_adr_control(m_disc->get_track(m_audio_lba)); + + // Don't attempt to play data tracks + if (BIT(adr_control, 2)) + { + std::fill_n(&m_audio_cache[cdrom_file::MAX_SECTOR_DATA * i], cdrom_file::MAX_SECTOR_DATA, 0); + } + else + { + m_disc->read_data(m_audio_lba, &m_audio_cache[cdrom_file::MAX_SECTOR_DATA * i], cdrom_file::CD_TRACK_AUDIO); + } + + if (!m_audio_scan) + { + m_audio_lba++; + } + else + { + if (m_audio_scan_direction) + { + m_audio_lba += 2; + } + else + { + m_audio_lba -= 2; + } + } } - m_audio_samples = (CD_MAX_SECTOR_DATA*sectors)/4; + m_audio_samples = (cdrom_file::MAX_SECTOR_DATA*sectors)/4; m_audio_length -= sectors; /* reset feedout ptr */ @@ -222,13 +290,16 @@ void cdda_device::get_audio_data(stream_sample_t *bufL, stream_sample_t *bufR, u } /*------------------------------------------------- - cdda_get_channel_volume - sets CD-DA volume level - for either speaker, used for volume control display + get_channel_sample - reads currently decoded + data sample on the stream. + Used by PC Engine CD class family for volume + metering on audio CD player. -------------------------------------------------*/ -int16_t cdda_device::get_channel_volume(int channel) +int16_t cdda_device::get_channel_sample(int channel) { - return m_audio_volume[channel]; + m_stream->update(); + return m_audio_data[channel]; } DEFINE_DEVICE_TYPE(CDDA, cdda_device, "cdda", "CD/DA") @@ -236,7 +307,8 @@ DEFINE_DEVICE_TYPE(CDDA, cdda_device, "cdda", "CD/DA") cdda_device::cdda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, CDDA, tag, owner, clock) , device_sound_interface(mconfig, *this) - , m_disc(nullptr) + , m_disc(*this, finder_base::DUMMY_TAG) , m_stream(nullptr) + , m_audio_end_cb(*this) { } |