DSP streaming bug fixes

This commit is contained in:
Jack Andersen 2017-01-18 10:57:48 -10:00
parent 0acc4b4612
commit 3cc93ffd75
7 changed files with 184 additions and 124 deletions

View File

@ -698,9 +698,9 @@ bool FRME::Extract(const SpecBase &dataSpec,
"frme_obj.rotation_quaternion = mtxd[1] * angle\n" "frme_obj.rotation_quaternion = mtxd[1] * angle\n"
"frme_obj.scale = mtxd[2]\n" "frme_obj.scale = mtxd[2]\n"
"bpy.context.scene.objects.link(frme_obj)\n", "bpy.context.scene.objects.link(frme_obj)\n",
w.basis[0].vec[0], w.basis[0].vec[1], w.basis[0].vec[2],w.origin.vec[0], w.basis[0].vec[0], w.basis[0].vec[1], w.basis[0].vec[2], w.origin.vec[0],
w.basis[1].vec[0], w.basis[1].vec[1], w.basis[1].vec[2],w.origin.vec[1], w.basis[1].vec[0], w.basis[1].vec[1], w.basis[1].vec[2], w.origin.vec[1],
w.basis[2].vec[0], w.basis[2].vec[1], w.basis[2].vec[2],w.origin.vec[2]); w.basis[2].vec[0], w.basis[2].vec[1], w.basis[2].vec[2], w.origin.vec[2]);
} }
os.centerView(); os.centerView();

View File

@ -73,9 +73,6 @@ void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
//m_newAudioPlayer.emplace(*m_voiceEngine, "Audio/frontend_1.rsf", 416480, 1973664); //m_newAudioPlayer.emplace(*m_voiceEngine, "Audio/frontend_1.rsf", 416480, 1973664);
//m_newAudioPlayer->StartMixing(); //m_newAudioPlayer->StartMixing();
// Test DSP streaming
CStreamAudioManager::Start(false, "Audio/rui_samusL.dsp|Audio/rui_samusR.dsp", 0x7f, true, 1.f, 1.f);
//m_rootView->accessContentViews().clear(); //m_rootView->accessContentViews().clear();
m_rootView->accessContentViews().push_back(m_particleView.get()); m_rootView->accessContentViews().push_back(m_particleView.get());
m_rootView->updateSize(); m_rootView->updateSize();

View File

@ -50,19 +50,19 @@ struct SDSPStreamInfo
SDSPStreamInfo(const CDSPStreamManager& stream); SDSPStreamInfo(const CDSPStreamManager& stream);
}; };
struct SDSPStream struct SDSPStream : boo::IAudioVoiceCallback
{ {
bool x0_active; bool x0_active;
bool x1_oneshot; bool x1_oneshot;
u32 x4_ownerId; u32 x4_ownerId;
SDSPStream* x8_stereoLeft; SDSPStream* x8_stereoLeft;
SDSPStream* xc_stereoRight; SDSPStream* xc_companionRight;
SDSPStreamInfo x10_info; SDSPStreamInfo x10_info;
u8 x4c_vol; u8 x4c_vol;
u8 x4d_pan; u8 x4d_pan;
//DVDFileInfo x50_dvdHandle1; //DVDFileInfo x50_dvdHandle1;
//DVDFileInfo x8c_dvdHandle2; //DVDFileInfo x8c_dvdHandle2;
u32 xc8_streamId = -1; // MusyX stream handle //u32 xc8_streamId = -1; // MusyX stream handle
u32 xcc_fileCur = 0; u32 xcc_fileCur = 0;
std::unique_ptr<u8[]> xd4_ringBuffer; std::unique_ptr<u8[]> xd4_ringBuffer;
u32 xd8_ringBytes = 0x11DC0; // 73152 4sec in ADPCM bytes u32 xd8_ringBytes = 0x11DC0; // 73152 4sec in ADPCM bytes
@ -75,33 +75,59 @@ struct SDSPStream
std::shared_ptr<IDvdRequest> m_readReqs[2]; std::shared_ptr<IDvdRequest> m_readReqs[2];
void ReadBuffer(int buf) void ReadBuffer(int buf)
{ {
u32 halfSize = xd8_ringBytes / 2; u32 halfSize = xd8_ringBytes / 2;
u8* data = xd4_ringBuffer.get() + (buf ? halfSize : 0); u8* data = xd4_ringBuffer.get() + (buf ? halfSize : 0);
if (!x10_info.x10_loopFlag && xcc_fileCur == x10_info.xc_adpcmBytes) if (x10_info.x10_loopFlag)
{ {
memset(data, 0, halfSize); u32 remFileBytes = x10_info.x18_loopEndByte - xcc_fileCur;
return;
}
u32 remFileBytes = if (remFileBytes < halfSize)
(x10_info.x10_loopFlag ? x10_info.x18_loopEndByte : x10_info.xc_adpcmBytes) - xcc_fileCur; {
if (remFileBytes < halfSize) printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf);
{ m_file->AsyncSeekRead(data, remFileBytes,
m_readReqs[buf] = m_file->AsyncSeekRead(data, remFileBytes, ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
memset(data + remFileBytes, 0, halfSize - remFileBytes);
if (x10_info.x10_loopFlag)
xcc_fileCur = x10_info.x14_loopStartByte; xcc_fileCur = x10_info.x14_loopStartByte;
u32 remBytes = halfSize - remFileBytes;
printf("Loop Buffering %d from %d into %d\n", remBytes, xcc_fileCur + x10_info.x8_headerSize, buf);
m_readReqs[buf] = m_file->AsyncSeekRead(data + remFileBytes, remBytes,
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
xcc_fileCur += remBytes;
}
else else
xcc_fileCur = x10_info.xc_adpcmBytes; {
printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf);
m_readReqs[buf] = m_file->AsyncSeekRead(data, halfSize,
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
xcc_fileCur += halfSize;
}
} }
else else
{ {
m_readReqs[buf] = m_file->AsyncSeekRead(data, halfSize, if (xcc_fileCur == x10_info.xc_adpcmBytes)
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); {
xcc_fileCur += halfSize; memset(data, 0, halfSize);
return;
}
u32 remFileBytes = x10_info.xc_adpcmBytes - xcc_fileCur;
if (remFileBytes < halfSize)
{
printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf);
m_readReqs[buf] = m_file->AsyncSeekRead(data, remFileBytes,
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
memset(data + remFileBytes, 0, halfSize - remFileBytes);
xcc_fileCur = x10_info.xc_adpcmBytes;
}
else
{
printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf);
m_readReqs[buf] = m_file->AsyncSeekRead(data, halfSize,
ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize);
xcc_fileCur += halfSize;
}
} }
} }
@ -145,97 +171,95 @@ struct SDSPStream
return false; return false;
} }
struct VoiceCallback : boo::IAudioVoiceCallback u32 m_curSample = 0;
u32 m_totalSamples = 0;
s16 m_prev1 = 0;
s16 m_prev2 = 0;
void preSupplyAudio(boo::IAudioVoice&, double) {}
void decompressChunk(u32 readToSample, int16_t*& data)
{ {
SDSPStream& m_parent; auto sampDiv = std::div(m_curSample, 14);
u32 m_curSample = 0; if (sampDiv.rem)
u32 m_totalSamples = 0;
s16 m_prev1 = 0;
s16 m_prev2 = 0;
VoiceCallback(SDSPStream& parent) : m_parent(parent) {}
void preSupplyAudio(boo::IAudioVoice&, double) {}
void decompressChunk(u32 readToSample, int16_t*& data)
{ {
auto sampDiv = std::div(m_curSample, 14); unsigned samps = DSPDecompressFrameRanged(data, xd4_ringBuffer.get() + sampDiv.quot * 8,
if (sampDiv.rem) x10_info.x1c_coef, &m_prev1, &m_prev2, sampDiv.rem,
{ readToSample - m_curSample);
unsigned samps = DSPDecompressFrameRanged(data, m_parent.xd4_ringBuffer.get() + sampDiv.quot * 8, m_curSample += samps;
m_parent.x10_info.x1c_coef, &m_prev1, &m_prev2, sampDiv.rem, data += samps;
readToSample - m_curSample); ++sampDiv.quot;
m_curSample += samps;
data += samps;
++sampDiv.quot;
}
while (m_curSample < readToSample)
{
unsigned samps = DSPDecompressFrame(data, m_parent.xd4_ringBuffer.get() + sampDiv.quot * 8,
m_parent.x10_info.x1c_coef, &m_prev1, &m_prev2,
readToSample - m_curSample);
m_curSample += samps;
data += samps;
++sampDiv.quot;
}
} }
size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) while (m_curSample < readToSample)
{ {
if (m_parent.xe8_silent) unsigned samps = DSPDecompressFrame(data, xd4_ringBuffer.get() + sampDiv.quot * 8,
x10_info.x1c_coef, &m_prev1, &m_prev2,
readToSample - m_curSample);
m_curSample += samps;
data += samps;
++sampDiv.quot;
}
}
size_t supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data)
{
if (xe8_silent)
{
StopStream();
memset(data, 0, frames * 2);
return frames;
}
if (xec_readState != 2 || (xe0_curBuffer == 0 && m_curSample >= xdc_ringSamples / 2))
{
printf("Should fill 0\n");
if (!BufferStream())
{ {
m_parent.StopStream();
memset(data, 0, frames * 2); memset(data, 0, frames * 2);
return frames; return frames;
} }
if (!m_parent.xec_readState || m_curSample >= m_parent.xdc_ringSamples / 2)
{
if (!m_parent.BufferStream())
{
memset(data, 0, frames * 2);
return frames;
}
}
if (!m_parent.x10_info.x10_loopFlag)
{
m_totalSamples += frames;
u32 fileSamples = m_parent.x10_info.xc_adpcmBytes * 14 / 8;
if (m_totalSamples >= fileSamples)
{
u32 overSamples = m_totalSamples - fileSamples;
u32 samplesIn = frames - overSamples;
memset(data + samplesIn, 0, overSamples * 2);
m_parent.StopStream();
}
}
u32 readToSample = m_curSample + frames;
u32 leftoverSamples = 0;
if (readToSample > m_parent.xdc_ringSamples)
{
leftoverSamples = readToSample - m_parent.xdc_ringSamples;
readToSample = m_parent.xdc_ringSamples;
}
decompressChunk(readToSample, data);
if (leftoverSamples)
{
m_parent.BufferStream();
m_curSample = 0;
decompressChunk(leftoverSamples, data);
}
return frames;
} }
} m_booCallback = {*this};
u32 readToSample = m_curSample + frames;
if (!x10_info.x10_loopFlag)
{
m_totalSamples += frames;
u32 fileSamples = x10_info.xc_adpcmBytes * 14 / 8;
if (m_totalSamples >= fileSamples)
{
u32 leftover = m_totalSamples - fileSamples;
readToSample -= leftover;
memset(data + frames - leftover, 0, leftover * 2);
StopStream();
}
}
u32 leftoverSamples = 0;
if (readToSample > xdc_ringSamples)
{
leftoverSamples = readToSample - xdc_ringSamples;
readToSample = xdc_ringSamples;
}
decompressChunk(readToSample, data);
if (leftoverSamples)
{
printf("Should fill 1\n");
BufferStream();
m_curSample = 0;
decompressChunk(leftoverSamples, data);
}
return frames;
}
std::unique_ptr<boo::IAudioVoice> m_booVoice; std::unique_ptr<boo::IAudioVoice> m_booVoice;
void DoAllocateStream() void DoAllocateStream()
{ {
xd4_ringBuffer.reset(new u8[0x11DC0]); xd4_ringBuffer.reset(new u8[0x11DC0]);
m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewMonoVoice(32000.0, &m_booCallback); m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewMonoVoice(32000.0, this);
} }
static void Initialize() static void Initialize()
@ -247,7 +271,6 @@ struct SDSPStream
stream.xd4_ringBuffer.reset(); stream.xd4_ringBuffer.reset();
stream.xd8_ringBytes = 0x11DC0; stream.xd8_ringBytes = 0x11DC0;
stream.xdc_ringSamples = 0x1f410; stream.xdc_ringSamples = 0x1f410;
stream.xc8_streamId = -1;
if (i < 2) if (i < 2)
{ {
stream.x1_oneshot = false; stream.x1_oneshot = false;
@ -272,7 +295,7 @@ struct SDSPStream
if (stream.x4_ownerId == -1) if (stream.x4_ownerId == -1)
stream.x4_ownerId = ++s_HandleCounter2; stream.x4_ownerId = ++s_HandleCounter2;
stream.x8_stereoLeft = nullptr; stream.x8_stereoLeft = nullptr;
stream.xc_stereoRight = nullptr; stream.xc_companionRight = nullptr;
streamOut = &stream; streamOut = &stream;
return stream.x4_ownerId; return stream.x4_ownerId;
} }
@ -312,7 +335,7 @@ struct SDSPStream
stream.UpdateStreamVolume(vol); stream.UpdateStreamVolume(vol);
if (SDSPStream* left = stream.x8_stereoLeft) if (SDSPStream* left = stream.x8_stereoLeft)
left->UpdateStreamVolume(vol); left->UpdateStreamVolume(vol);
if (SDSPStream* right = stream.xc_stereoRight) if (SDSPStream* right = stream.xc_companionRight)
right->UpdateStreamVolume(vol); right->UpdateStreamVolume(vol);
} }
@ -335,7 +358,7 @@ struct SDSPStream
stream.SilenceStream(); stream.SilenceStream();
if (SDSPStream* left = stream.x8_stereoLeft) if (SDSPStream* left = stream.x8_stereoLeft)
left->SilenceStream(); left->SilenceStream();
if (SDSPStream* right = stream.xc_stereoRight) if (SDSPStream* right = stream.xc_companionRight)
right->SilenceStream(); right->SilenceStream();
} }
@ -390,6 +413,9 @@ struct SDSPStream
if (PickFreeStream(rstream, oneshot) == -1) if (PickFreeStream(rstream, oneshot) == -1)
return -1; return -1;
rstream->x8_stereoLeft = lstream;
lstream->xc_companionRight = rstream;
lstream->AllocateStream(linfo, vol, 0); lstream->AllocateStream(linfo, vol, 0);
rstream->AllocateStream(rinfo, vol, 0x7f); rstream->AllocateStream(rinfo, vol, 0x7f);
return lid; return lid;
@ -401,6 +427,8 @@ struct SDSPStream
m_file.emplace(x10_info.x0_fileName); m_file.emplace(x10_info.x0_fileName);
if (!xd4_ringBuffer) if (!xd4_ringBuffer)
DoAllocateStream(); DoAllocateStream();
m_readReqs[0].reset();
m_readReqs[1].reset();
x4c_vol = vol; x4c_vol = vol;
x4d_pan = pan; x4d_pan = pan;
xe8_silent = false; xe8_silent = false;
@ -408,9 +436,15 @@ struct SDSPStream
xe0_curBuffer = -1; xe0_curBuffer = -1;
xd8_ringBytes = 0x11DC0; xd8_ringBytes = 0x11DC0;
xdc_ringSamples = 0x1f410; xdc_ringSamples = 0x1f410;
xcc_fileCur = 0;
m_curSample = 0;
m_totalSamples = 0;
m_prev1 = 0;
m_prev2 = 0;
memset(xd4_ringBuffer.get(), 0, 0x11DC0); memset(xd4_ringBuffer.get(), 0, 0x11DC0);
m_booVoice->resetSampleRate(info.x4_sampleRate); m_booVoice->resetSampleRate(info.x4_sampleRate);
m_booVoice->start(); m_booVoice->start();
UpdateStreamVolume(vol);
} }
static SDSPStream g_Streams[4]; static SDSPStream g_Streams[4];
@ -579,7 +613,7 @@ public:
return false; return false;
if (stream.x7c_streamId == -1) if (stream.x7c_streamId == -1)
return true; return false;
return SDSPStream::IsStreamAvailable(stream.x7c_streamId); return SDSPStream::IsStreamAvailable(stream.x7c_streamId);
} }
@ -613,10 +647,8 @@ public:
} }
} }
void HeaderReadComplete(u32 readLen) void HeaderReadComplete()
{ {
m_dvdReq.reset();
u32 selfIdx = -1; u32 selfIdx = -1;
for (int i=0 ; i<4 ; ++i) for (int i=0 ; i<4 ; ++i)
{ {
@ -627,7 +659,7 @@ public:
} }
} }
if (x70_24_unclaimed || readLen != sizeof(dspadpcm_header) || selfIdx == -1) if (x70_24_unclaimed || selfIdx == -1)
{ {
*this = CDSPStreamManager(); *this = CDSPStreamManager();
return; return;
@ -672,7 +704,20 @@ public:
} }
} }
static bool StartHeaderRead(CDSPStreamManager& stream) static void PollHeaderReadCompletions()
{
for (int i=0 ; i<4 ; ++i)
{
CDSPStreamManager& stream = g_Streams[i];
if (stream.m_dvdReq && stream.m_dvdReq->IsComplete())
{
stream.m_dvdReq.reset();
stream.HeaderReadComplete();
}
}
}
static bool StartMonoHeaderRead(CDSPStreamManager& stream)
{ {
if (stream.x70_26_headerReadState != 0 || stream.x70_24_unclaimed) if (stream.x70_26_headerReadState != 0 || stream.x70_24_unclaimed)
return false; return false;
@ -682,9 +727,29 @@ public:
return false; return false;
stream.x70_26_headerReadState = 1; stream.x70_26_headerReadState = 1;
stream.m_dvdReq = file.AsyncRead(&stream.x0_header, sizeof(dspadpcm_header), stream.m_dvdReq = file.AsyncRead(&stream.x0_header, sizeof(dspadpcm_header));
std::bind(&CDSPStreamManager::HeaderReadComplete, &stream, return true;
std::placeholders::_1)); }
static bool StartStereoHeaderRead(CDSPStreamManager& lstream, CDSPStreamManager& rstream)
{
if (lstream.x70_26_headerReadState != 0 || lstream.x70_24_unclaimed ||
rstream.x70_26_headerReadState != 0 || rstream.x70_24_unclaimed)
return false;
CDvdFile lfile(lstream.x60_fileName.c_str());
if (!lfile)
return false;
CDvdFile rfile(rstream.x60_fileName.c_str());
if (!rfile)
return false;
lstream.x70_26_headerReadState = 1;
rstream.x70_26_headerReadState = 1;
lstream.m_dvdReq = lfile.AsyncRead(&lstream.x0_header, sizeof(dspadpcm_header));
rstream.m_dvdReq = rfile.AsyncRead(&rstream.x0_header, sizeof(dspadpcm_header));
return true; return true;
} }
@ -713,7 +778,7 @@ public:
CDSPStreamManager& stream = g_Streams[idx]; CDSPStreamManager& stream = g_Streams[idx];
stream = tmpStream; stream = tmpStream;
if (!StartHeaderRead(stream)) if (!StartMonoHeaderRead(stream))
{ {
stream.x70_25_headerReadCancelled = true; stream.x70_25_headerReadCancelled = true;
stream.WaitForReadCompletion(); stream.WaitForReadCompletion();
@ -749,9 +814,7 @@ public:
leftStream = tmpLeftStream; leftStream = tmpLeftStream;
rightStream = tmpRightStream; rightStream = tmpRightStream;
bool leftRet = StartHeaderRead(leftStream); if (!StartStereoHeaderRead(leftStream, rightStream))
bool rightRet = StartHeaderRead(rightStream);
if (!leftRet || !rightRet)
{ {
leftStream.x70_25_headerReadCancelled = true; leftStream.x70_25_headerReadCancelled = true;
rightStream.x70_25_headerReadCancelled = true; rightStream.x70_25_headerReadCancelled = true;
@ -1012,8 +1075,7 @@ void CStreamAudioManager::UpdateDSP(bool oneshot, float dt)
if ((p.x10_playState != EPlayerState::FadeIn && if ((p.x10_playState != EPlayerState::FadeIn &&
p.x10_playState != EPlayerState::FadeOut && p.x10_playState != EPlayerState::FadeOut &&
p.x10_playState != EPlayerState::FadeOutNoStop) || p.x10_playState != EPlayerState::FadeOutNoStop))
!CDSPStreamManager::IsStreamAvailable(p.x20_internalHandle))
{ {
if (p.x10_playState == EPlayerState::Playing) if (p.x10_playState == EPlayerState::Playing)
CDSPStreamManager::UpdateVolume(p.x20_internalHandle, CDSPStreamManager::UpdateVolume(p.x20_internalHandle,
@ -1070,6 +1132,7 @@ void CStreamAudioManager::UpdateDSPStreamers(float dt)
void CStreamAudioManager::Update(float dt) void CStreamAudioManager::Update(float dt)
{ {
CDSPStreamManager::PollHeaderReadCompletions();
UpdateDSPStreamers(dt); UpdateDSPStreamers(dt);
} }

View File

@ -32,7 +32,6 @@ public:
bool IsComplete() {return m_complete;} bool IsComplete() {return m_complete;}
void PostCancelRequest() void PostCancelRequest()
{ {
std::unique_lock<std::mutex> lk(CDvdFile::m_WorkerMutex);
m_cancel = true; m_cancel = true;
} }

View File

@ -162,6 +162,7 @@ bool CMain::Proc()
{ {
CGBASupport::GlobalPoll(); CGBASupport::GlobalPoll();
xe8_b24_finished = m_archSupport->Update(); xe8_b24_finished = m_archSupport->Update();
CStreamAudioManager::Start(false, "Audio/min_x_wind_lp_01L.dsp|Audio/min_x_wind_lp_01R.dsp", 0x7f, true, 0.f, 0.f);
CStreamAudioManager::Update(1.f / 60.f); CStreamAudioManager::Update(1.f / 60.f);
return xe8_b24_finished; return xe8_b24_finished;
} }

2
hecl

@ -1 +1 @@
Subproject commit 47d0b4fca984e771d4ffea0096c01f50aea6002d Subproject commit 6c8a6067c841b490c5d4b4bf6bb6da1f9c648ca6

2
nod

@ -1 +1 @@
Subproject commit f998bb34ecc4269a78a088bd1696a34c1889af16 Subproject commit 3f0412ae6960308ac33c52165cc8ed145557755b