mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 03:47:43 +00:00
Implement CStaticAudioPlayer
This commit is contained in:
109
Runtime/Audio/CStaticAudioPlayer.cpp
Normal file
109
Runtime/Audio/CStaticAudioPlayer.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "CStaticAudioPlayer.hpp"
|
||||
#include "CDvdFile.hpp"
|
||||
#include "CDvdRequest.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CStaticAudioPlayer::CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, const std::string& path,
|
||||
int loopStart, int loopEnd)
|
||||
: x0_path(path), x1c_loopStartSamp(loopStart & 0xfffffffe), x20_loopEndSamp(loopEnd & 0xfffffffe),
|
||||
m_voiceCallback(*this), m_voice(engine.allocateNewStereoVoice(32000, &m_voiceCallback))
|
||||
{
|
||||
// These are mixed directly into boo voice engine instead
|
||||
//x28_dmaLeft.reset(new u8[640]);
|
||||
//x30_dmaRight.reset(new u8[640]);
|
||||
|
||||
CDvdFile file(path.c_str());
|
||||
x10_rsfRem = file.Length();
|
||||
x14_rsfLength = x10_rsfRem;
|
||||
|
||||
u32 bufCount = (x10_rsfRem + 0x20000 - 1) / 0x20000;
|
||||
x48_buffers.reserve(bufCount);
|
||||
x38_dvdRequests.reserve(bufCount);
|
||||
|
||||
for (int remBytes = x10_rsfRem; remBytes > 0; remBytes -= 0x20000)
|
||||
{
|
||||
u32 thisSz = 0x20000;
|
||||
if (remBytes < 0x20000)
|
||||
thisSz = ROUND_UP_32(remBytes);
|
||||
|
||||
x48_buffers.emplace_back(new u8[thisSz]);
|
||||
x38_dvdRequests.push_back(file.AsyncRead(x48_buffers.back().get(), thisSz));
|
||||
}
|
||||
|
||||
g72x_init_state(&x58_leftState);
|
||||
g72x_init_state(&x8c_rightState);
|
||||
}
|
||||
|
||||
bool CStaticAudioPlayer::IsReady()
|
||||
{
|
||||
if (x38_dvdRequests.size())
|
||||
return x38_dvdRequests.back()->IsComplete();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStaticAudioPlayer::DecodeMonoAndMix(s16* bufOut, u32 numSamples,
|
||||
u32 cur, u32 loopEndCur, u32 loopStartCur,
|
||||
int vol, g72x_state& state,
|
||||
std::experimental::optional<g72x_state>& loopState) const
|
||||
{
|
||||
for (u32 remBytes = numSamples / 2; remBytes;)
|
||||
{
|
||||
u32 curBuf = cur / 0x20000;
|
||||
u32 thisBytes = (curBuf + 1) * 0x20000 - cur;
|
||||
thisBytes = std::min(thisBytes, remBytes);
|
||||
u32 remTillLoop = loopEndCur - cur;
|
||||
remTillLoop = std::min(remTillLoop, thisBytes);
|
||||
|
||||
const std::unique_ptr<u8[]>& buf = x48_buffers[curBuf];
|
||||
const u8* byte = &buf[cur - curBuf * 0x20000];
|
||||
|
||||
for (int i=0; i<remTillLoop; ++i, ++byte)
|
||||
{
|
||||
if (!loopState && cur + i == loopStartCur)
|
||||
loopState.emplace(state);
|
||||
|
||||
*bufOut = SampClamp((g721_decoder(*byte & 0xf, &state) * vol) >> 15);
|
||||
bufOut += 2;
|
||||
|
||||
*bufOut = SampClamp((g721_decoder(*byte >> 4 & 0xf, &state) * vol) >> 15);
|
||||
bufOut += 2;
|
||||
}
|
||||
|
||||
cur += remTillLoop;
|
||||
remBytes -= remTillLoop;
|
||||
if (cur == loopEndCur)
|
||||
{
|
||||
cur = loopStartCur;
|
||||
if (loopState)
|
||||
state = *loopState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CStaticAudioPlayer::Decode(s16* bufOut, u32 numSamples)
|
||||
{
|
||||
DecodeMonoAndMix(bufOut, numSamples, x18_curSamp / 2,
|
||||
x20_loopEndSamp / 2, x1c_loopStartSamp / 2,
|
||||
xc0_volume, x58_leftState, m_leftStateLoop);
|
||||
|
||||
u32 halfway = x14_rsfLength / 2;
|
||||
DecodeMonoAndMix(bufOut + 1, numSamples, x18_curSamp / 2 + halfway,
|
||||
x20_loopEndSamp / 2 + halfway, x1c_loopStartSamp / 2 + halfway,
|
||||
xc0_volume, x8c_rightState, m_rightStateLoop);
|
||||
|
||||
for (u32 remSamples = numSamples; remSamples;)
|
||||
{
|
||||
u32 remTillLoop = x20_loopEndSamp - x18_curSamp;
|
||||
remTillLoop = std::min(remTillLoop, remSamples);
|
||||
|
||||
x18_curSamp += remTillLoop;
|
||||
remSamples -= remTillLoop;
|
||||
|
||||
if (x18_curSamp == x20_loopEndSamp)
|
||||
x18_curSamp = x1c_loopStartSamp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user