metaforce/Runtime/Audio/CStaticAudioPlayer.cpp

102 lines
3.3 KiB
C++

#include "Runtime/Audio/CStaticAudioPlayer.hpp"
#include "Runtime/CDvdFile.hpp"
#include "Runtime/CDvdRequest.hpp"
namespace metaforce {
#define RSF_BUFFER_SIZE 0x20000
//CStaticAudioPlayer::CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, std::string_view 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);
// x10_rsfRem = file.Length();
// x14_rsfLength = x10_rsfRem;
//
// u32 bufCount = (x10_rsfRem + RSF_BUFFER_SIZE - 1) / RSF_BUFFER_SIZE;
// x48_buffers.reserve(bufCount);
// x38_dvdRequests.reserve(bufCount);
//
// for (int remBytes = x10_rsfRem; remBytes > 0; remBytes -= RSF_BUFFER_SIZE) {
// u32 thisSz = RSF_BUFFER_SIZE;
// if (remBytes < RSF_BUFFER_SIZE)
// 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::optional<g72x_state>& loopState) const {
for (u32 remBytes = numSamples / 2; remBytes;) {
u32 curBuf = cur / RSF_BUFFER_SIZE;
u32 thisBytes = (curBuf + 1) * RSF_BUFFER_SIZE - 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 * RSF_BUFFER_SIZE];
for (u32 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;
}
}
} // namespace metaforce