summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/cdda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/cdda.cpp')
-rw-r--r--src/devices/sound/cdda.cpp190
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)
{
}