mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
DVDInterface: Read DTK data in DVDThread
This commit is contained in:
@ -233,6 +233,7 @@ static u32 s_current_start;
|
|||||||
static u32 s_current_length;
|
static u32 s_current_length;
|
||||||
static u32 s_next_start;
|
static u32 s_next_start;
|
||||||
static u32 s_next_length;
|
static u32 s_next_length;
|
||||||
|
static u32 s_pending_samples;
|
||||||
|
|
||||||
static u32 s_error_code = 0;
|
static u32 s_error_code = 0;
|
||||||
static bool s_disc_inside = false;
|
static bool s_disc_inside = false;
|
||||||
@ -288,6 +289,8 @@ void DoState(PointerWrap& p)
|
|||||||
p.Do(s_current_start);
|
p.Do(s_current_start);
|
||||||
p.Do(s_current_length);
|
p.Do(s_current_length);
|
||||||
|
|
||||||
|
p.Do(s_pending_samples);
|
||||||
|
|
||||||
p.Do(s_last_read_offset);
|
p.Do(s_last_read_offset);
|
||||||
p.Do(s_last_read_time);
|
p.Do(s_last_read_time);
|
||||||
|
|
||||||
@ -311,19 +314,34 @@ void DoState(PointerWrap& p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 ProcessDTKSamples(short* tempPCM, u32 num_samples)
|
static size_t ProcessDTKSamples(std::vector<s16>* temp_pcm, const std::vector<u8>& audio_data)
|
||||||
{
|
{
|
||||||
// TODO: Read audio data using the DVD thread instead of blocking on it?
|
size_t samples_processed = 0;
|
||||||
DVDThread::WaitUntilIdle();
|
size_t bytes_processed = 0;
|
||||||
|
while (samples_processed < temp_pcm->size() / 2 && bytes_processed < audio_data.size())
|
||||||
|
{
|
||||||
|
StreamADPCM::DecodeBlock(&(*temp_pcm)[samples_processed * 2], &audio_data[bytes_processed]);
|
||||||
|
samples_processed += StreamADPCM::SAMPLES_PER_BLOCK;
|
||||||
|
bytes_processed += StreamADPCM::ONE_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < samples_processed * 2; ++i)
|
||||||
|
{
|
||||||
|
// TODO: Fix the mixer so it can accept non-byte-swapped samples.
|
||||||
|
(*temp_pcm)[i] = Common::swap16((*temp_pcm)[i]);
|
||||||
|
}
|
||||||
|
return samples_processed;
|
||||||
|
}
|
||||||
|
|
||||||
u32 samples_processed = 0;
|
static u32 AdvanceDTK(u32 maximum_samples, u32* samples_to_process)
|
||||||
do
|
{
|
||||||
|
u32 bytes_to_process = 0;
|
||||||
|
*samples_to_process = 0;
|
||||||
|
while (*samples_to_process < maximum_samples)
|
||||||
{
|
{
|
||||||
if (s_audio_position >= s_current_start + s_current_length)
|
if (s_audio_position >= s_current_start + s_current_length)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(DVDINTERFACE, "ProcessDTKSamples: "
|
DEBUG_LOG(DVDINTERFACE, "AdvanceDTK: NextStart=%08x, NextLength=%08x, "
|
||||||
"NextStart=%08x,NextLength=%08x,CurrentStart=%08x,CurrentLength=%08x,"
|
"CurrentStart=%08x, CurrentLength=%08x, AudioPos=%08x",
|
||||||
"AudioPos=%08x",
|
|
||||||
s_next_start, s_next_length, s_current_start, s_current_length, s_audio_position);
|
s_next_start, s_next_length, s_current_start, s_current_length, s_audio_position);
|
||||||
|
|
||||||
s_audio_position = s_next_start;
|
s_audio_position = s_next_start;
|
||||||
@ -340,41 +358,49 @@ static u32 ProcessDTKSamples(short* tempPCM, u32 num_samples)
|
|||||||
StreamADPCM::InitFilter();
|
StreamADPCM::InitFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 tempADPCM[StreamADPCM::ONE_BLOCK_SIZE];
|
s_audio_position += StreamADPCM::ONE_BLOCK_SIZE;
|
||||||
// TODO: What if we can't read from s_audio_position?
|
bytes_to_process += StreamADPCM::ONE_BLOCK_SIZE;
|
||||||
s_inserted_volume->Read(s_audio_position, sizeof(tempADPCM), tempADPCM, false);
|
*samples_to_process += StreamADPCM::SAMPLES_PER_BLOCK;
|
||||||
s_audio_position += sizeof(tempADPCM);
|
|
||||||
StreamADPCM::DecodeBlock(tempPCM + samples_processed * 2, tempADPCM);
|
|
||||||
samples_processed += StreamADPCM::SAMPLES_PER_BLOCK;
|
|
||||||
} while (samples_processed < num_samples);
|
|
||||||
for (unsigned i = 0; i < samples_processed * 2; ++i)
|
|
||||||
{
|
|
||||||
// TODO: Fix the mixer so it can accept non-byte-swapped samples.
|
|
||||||
tempPCM[i] = Common::swap16(tempPCM[i]);
|
|
||||||
}
|
}
|
||||||
return samples_processed;
|
|
||||||
|
return bytes_to_process;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DTKStreamingCallback(const std::vector<u8>& audio_data, s64 cycles_late)
|
static void DTKStreamingCallback(const std::vector<u8>& audio_data, s64 cycles_late)
|
||||||
{
|
{
|
||||||
// Send audio to the mixer.
|
// Send audio to the mixer.
|
||||||
static const int NUM_SAMPLES = 48000 / 2000 * 7; // 3.5ms of 48kHz samples
|
std::vector<s16> temp_pcm(s_pending_samples * 2, 0);
|
||||||
short tempPCM[NUM_SAMPLES * 2];
|
ProcessDTKSamples(&temp_pcm, audio_data);
|
||||||
unsigned samples_processed;
|
g_sound_stream->GetMixer()->PushStreamingSamples(temp_pcm.data(), s_pending_samples);
|
||||||
|
|
||||||
|
// Determine which audio data to read next.
|
||||||
|
static const int MAXIMUM_SAMPLES = 48000 / 2000 * 7; // 3.5ms of 48kHz samples
|
||||||
|
u64 read_offset;
|
||||||
|
u32 read_length;
|
||||||
if (s_stream && AudioInterface::IsPlaying())
|
if (s_stream && AudioInterface::IsPlaying())
|
||||||
{
|
{
|
||||||
samples_processed = ProcessDTKSamples(tempPCM, NUM_SAMPLES);
|
read_offset = s_audio_position;
|
||||||
|
read_length = AdvanceDTK(MAXIMUM_SAMPLES, &s_pending_samples);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(tempPCM, 0, sizeof(tempPCM));
|
read_length = 0;
|
||||||
samples_processed = NUM_SAMPLES;
|
s_pending_samples = MAXIMUM_SAMPLES;
|
||||||
}
|
}
|
||||||
g_sound_stream->GetMixer()->PushStreamingSamples(tempPCM, samples_processed);
|
|
||||||
|
|
||||||
int ticks_to_dtk = int(SystemTimers::GetTicksPerSecond() * u64(samples_processed) / 48000);
|
// Read the next chunk of audio data asynchronously.
|
||||||
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::INT_TCINT);
|
s64 ticks_to_dtk = SystemTimers::GetTicksPerSecond() * s64(s_pending_samples) / 48000;
|
||||||
CoreTiming::ScheduleEvent(ticks_to_dtk - cycles_late, s_finish_executing_command, userdata);
|
ticks_to_dtk -= cycles_late;
|
||||||
|
if (read_length > 0)
|
||||||
|
{
|
||||||
|
DVDThread::StartRead(read_offset, read_length, false, ReplyType::DTK, ticks_to_dtk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There's nothing to read, so using DVDThread is unnecessary.
|
||||||
|
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::INT_TCINT);
|
||||||
|
CoreTiming::ScheduleEvent(ticks_to_dtk, s_finish_executing_command, userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
@ -398,6 +424,7 @@ void Init()
|
|||||||
s_next_length = 0;
|
s_next_length = 0;
|
||||||
s_current_start = 0;
|
s_current_start = 0;
|
||||||
s_current_length = 0;
|
s_current_length = 0;
|
||||||
|
s_pending_samples = 0;
|
||||||
|
|
||||||
s_error_code = 0;
|
s_error_code = 0;
|
||||||
s_disc_inside = false;
|
s_disc_inside = false;
|
||||||
|
Reference in New Issue
Block a user