DVDInterface: Read DTK data in DVDThread

This commit is contained in:
JosJuice
2016-08-14 16:41:21 +02:00
parent 28bfd52d3a
commit a450e33fb3

View File

@ -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;