mirror of https://github.com/AxioDL/metaforce.git
Implement CStaticAudioPlayer
This commit is contained in:
parent
43c8cdf4ae
commit
c3bf6ec5cc
|
@ -56,18 +56,21 @@ void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
|
||||||
TLockedToken<CTexture> xrayPalette = objStore.GetObj("TXTR_XRayPalette");
|
TLockedToken<CTexture> xrayPalette = objStore.GetObj("TXTR_XRayPalette");
|
||||||
m_particleView.reset(new ParticleView(*this, m_viewResources, *m_rootView, xrayPalette));
|
m_particleView.reset(new ParticleView(*this, m_viewResources, *m_rootView, xrayPalette));
|
||||||
|
|
||||||
//m_moviePlayer.reset(new CMoviePlayer("Video/SpecialEnding.thp", 1.f, false, true));
|
#if 0
|
||||||
//m_moviePlayer->SetFrame({-1.0f, 1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {1.0f, -1.0f, 0.f}, {1.0f, 1.0f, 0.f});
|
m_moviePlayer.reset(new CMoviePlayer("Video/SpecialEnding.thp", 1.f, false, true));
|
||||||
/*
|
m_moviePlayer->SetFrame({-1.0f, 1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {1.0f, -1.0f, 0.f}, {1.0f, 1.0f, 0.f});
|
||||||
CDvdFile testRSF("Audio/frontend_1.rsf");
|
CDvdFile testRSF("Audio/frontend_1.rsf");
|
||||||
u64 rsfLen = testRSF.Length();
|
u64 rsfLen = testRSF.Length();
|
||||||
m_rsfBuf.reset(new u8[rsfLen]);
|
m_rsfBuf.reset(new u8[rsfLen]);
|
||||||
testRSF.SyncRead(m_rsfBuf.get(), rsfLen);
|
testRSF.SyncRead(m_rsfBuf.get(), rsfLen);
|
||||||
*/
|
CMoviePlayer::SetStaticAudio(m_rsfBuf.get(), rsfLen, 416480, 1973664);
|
||||||
//CMoviePlayer::SetStaticAudio(m_rsfBuf.get(), rsfLen, 416480, 1973664);
|
|
||||||
|
|
||||||
m_videoVoice = m_voiceEngine->allocateNewStereoVoice(32000, &m_voiceCallback);
|
m_videoVoice = m_voiceEngine->allocateNewStereoVoice(32000, &m_voiceCallback);
|
||||||
m_videoVoice->start();
|
m_videoVoice->start();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_newAudioPlayer.emplace(*m_voiceEngine, "Audio/frontend_1.rsf", 416480, 1973664);
|
||||||
|
m_newAudioPlayer->StartMixing();
|
||||||
|
|
||||||
//m_rootView->accessContentViews().clear();
|
//m_rootView->accessContentViews().clear();
|
||||||
m_rootView->accessContentViews().push_back(m_particleView.get());
|
m_rootView->accessContentViews().push_back(m_particleView.get());
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
|
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
|
||||||
#include "Runtime/Graphics/Shaders/CXRayBlurFilter.hpp"
|
#include "Runtime/Graphics/Shaders/CXRayBlurFilter.hpp"
|
||||||
#include "Runtime/Graphics/Shaders/CCameraBlurFilter.hpp"
|
#include "Runtime/Graphics/Shaders/CCameraBlurFilter.hpp"
|
||||||
|
#include "Runtime/Audio/CStaticAudioPlayer.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -91,6 +92,8 @@ class ViewManager : public specter::IViewManager
|
||||||
AudioVoiceCallback(ViewManager& vm) : m_vm(vm) {}
|
AudioVoiceCallback(ViewManager& vm) : m_vm(vm) {}
|
||||||
} m_voiceCallback;
|
} m_voiceCallback;
|
||||||
|
|
||||||
|
std::experimental::optional<CStaticAudioPlayer> m_newAudioPlayer;
|
||||||
|
|
||||||
hecl::SystemString m_recentProjectsPath;
|
hecl::SystemString m_recentProjectsPath;
|
||||||
std::vector<hecl::SystemString> m_recentProjects;
|
std::vector<hecl::SystemString> m_recentProjects;
|
||||||
hecl::SystemString m_recentFilesPath;
|
hecl::SystemString m_recentFilesPath;
|
||||||
|
|
|
@ -4,6 +4,7 @@ set(AUDIO_SOURCES
|
||||||
CAudioGroupSet.hpp CAudioGroupSet.cpp
|
CAudioGroupSet.hpp CAudioGroupSet.cpp
|
||||||
CSfxManager.hpp CSfxManager.cpp
|
CSfxManager.hpp CSfxManager.cpp
|
||||||
CSfxHandle.hpp CSfxHandle.cpp
|
CSfxHandle.hpp CSfxHandle.cpp
|
||||||
|
CStaticAudioPlayer.hpp CStaticAudioPlayer.cpp
|
||||||
g721.c g721.h)
|
g721.c g721.h)
|
||||||
|
|
||||||
runtime_add_list(Audio AUDIO_SOURCES)
|
runtime_add_list(Audio AUDIO_SOURCES)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
#ifndef __URDE_CSTATICAUDIOPLAYER_HPP__
|
||||||
|
#define __URDE_CSTATICAUDIOPLAYER_HPP__
|
||||||
|
|
||||||
|
#include "RetroTypes.hpp"
|
||||||
|
#include "g721.h"
|
||||||
|
#include "boo/audiodev/IAudioVoice.hpp"
|
||||||
|
#include "boo/audiodev/IAudioVoiceEngine.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
class IDvdRequest;
|
||||||
|
|
||||||
|
class CStaticAudioPlayer
|
||||||
|
{
|
||||||
|
std::string x0_path;
|
||||||
|
u32 x10_rsfRem = -1;
|
||||||
|
u32 x14_rsfLength;
|
||||||
|
u32 x18_curSamp = 0;
|
||||||
|
u32 x1c_loopStartSamp;
|
||||||
|
u32 x20_loopEndSamp;
|
||||||
|
u32 x24_ = 0;
|
||||||
|
//std::unique_ptr<u8[]> x28_dmaLeft;
|
||||||
|
//std::unique_ptr<u8[]> x30_dmaRight;
|
||||||
|
std::vector<std::shared_ptr<IDvdRequest>> x38_dvdRequests;
|
||||||
|
std::vector<std::unique_ptr<u8[]>> x48_buffers;
|
||||||
|
g72x_state x58_leftState;
|
||||||
|
g72x_state x8c_rightState;
|
||||||
|
std::experimental::optional<g72x_state> m_leftStateLoop;
|
||||||
|
std::experimental::optional<g72x_state> m_rightStateLoop;
|
||||||
|
u32 xc0_volume = 32768; // Out of 32768
|
||||||
|
|
||||||
|
static int16_t SampClamp(int32_t val)
|
||||||
|
{
|
||||||
|
if (val < -32768) val = -32768;
|
||||||
|
else if (val > 32767) val = 32767;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AudioVoiceCallback : boo::IAudioVoiceCallback
|
||||||
|
{
|
||||||
|
CStaticAudioPlayer& m_parent;
|
||||||
|
void preSupplyAudio(boo::IAudioVoice&, double) {}
|
||||||
|
size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data)
|
||||||
|
{
|
||||||
|
if (m_parent.IsReady())
|
||||||
|
m_parent.Decode(data, frames);
|
||||||
|
else
|
||||||
|
memset(data, 0, 4 * frames);
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
AudioVoiceCallback(CStaticAudioPlayer& p) : m_parent(p) {}
|
||||||
|
} m_voiceCallback;
|
||||||
|
std::unique_ptr<boo::IAudioVoice> m_voice;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, const std::string& path,
|
||||||
|
int loopStart, int loopEnd);
|
||||||
|
bool IsReady();
|
||||||
|
void DecodeMonoAndMix(s16* bufOut, u32 numSamples,
|
||||||
|
u32 cur, u32 loopEndCur, u32 loopStartCur,
|
||||||
|
int vol, g72x_state& state,
|
||||||
|
std::experimental::optional<g72x_state>& loopState) const;
|
||||||
|
void Decode(s16* bufOut, u32 numSamples);
|
||||||
|
|
||||||
|
void StartMixing()
|
||||||
|
{
|
||||||
|
m_voice->start();
|
||||||
|
}
|
||||||
|
void StopMixing()
|
||||||
|
{
|
||||||
|
m_voice->stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __URDE_CSTATICAUDIOPLAYER_HPP__
|
|
@ -8,7 +8,7 @@ hecl::ProjectPath CDvdFile::m_DvdRoot;
|
||||||
|
|
||||||
class CFileDvdRequest : public IDvdRequest
|
class CFileDvdRequest : public IDvdRequest
|
||||||
{
|
{
|
||||||
CDvdFile& m_dvdFile;
|
std::shared_ptr<athena::io::FileReader> m_reader;
|
||||||
void* m_buf;
|
void* m_buf;
|
||||||
u32 m_len;
|
u32 m_len;
|
||||||
ESeekOrigin m_whence;
|
ESeekOrigin m_whence;
|
||||||
|
@ -41,18 +41,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
CFileDvdRequest(CDvdFile& file, void* buf, u32 len, ESeekOrigin whence, int off)
|
CFileDvdRequest(CDvdFile& file, void* buf, u32 len, ESeekOrigin whence, int off)
|
||||||
: m_dvdFile(file), m_buf(buf), m_len(len), m_whence(whence), m_offset(off) {}
|
: m_reader(file.m_reader), m_buf(buf), m_len(len), m_whence(whence), m_offset(off) {}
|
||||||
|
|
||||||
void DoRequest()
|
void DoRequest()
|
||||||
{
|
{
|
||||||
if (m_cancel)
|
if (m_cancel)
|
||||||
return;
|
return;
|
||||||
if (m_whence == ESeekOrigin::Cur && m_offset == 0)
|
if (m_whence == ESeekOrigin::Cur && m_offset == 0)
|
||||||
m_dvdFile.m_reader.readBytesToBuf(m_buf, m_len);
|
m_reader->readBytesToBuf(m_buf, m_len);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_dvdFile.m_reader.seek(m_offset, athena::SeekOrigin(m_whence));
|
m_reader->seek(m_offset, athena::SeekOrigin(m_whence));
|
||||||
m_dvdFile.m_reader.readBytesToBuf(m_buf, m_len);
|
m_reader->readBytesToBuf(m_buf, m_len);
|
||||||
}
|
}
|
||||||
m_complete = true;
|
m_complete = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,17 +39,19 @@ class CDvdFile
|
||||||
static void WorkerProc();
|
static void WorkerProc();
|
||||||
|
|
||||||
std::string x18_path;
|
std::string x18_path;
|
||||||
athena::io::FileReader m_reader;
|
std::shared_ptr<athena::io::FileReader> m_reader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Initialize(const hecl::ProjectPath& path);
|
static void Initialize(const hecl::ProjectPath& path);
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
CDvdFile(const char* path)
|
CDvdFile(const char* path)
|
||||||
: x18_path(path), m_reader(hecl::ProjectPath(m_DvdRoot, path).getAbsolutePath()) {}
|
: x18_path(path),
|
||||||
|
m_reader(std::make_shared<athena::io::FileReader>(
|
||||||
|
hecl::ProjectPath(m_DvdRoot, path).getAbsolutePath())) {}
|
||||||
void UpdateFilePos(int pos)
|
void UpdateFilePos(int pos)
|
||||||
{
|
{
|
||||||
m_reader.seek(pos, athena::SeekOrigin::Begin);
|
m_reader->seek(pos, athena::SeekOrigin::Begin);
|
||||||
}
|
}
|
||||||
static bool FileExists(const char* path)
|
static bool FileExists(const char* path)
|
||||||
{
|
{
|
||||||
|
@ -57,13 +59,13 @@ public:
|
||||||
}
|
}
|
||||||
void CloseFile()
|
void CloseFile()
|
||||||
{
|
{
|
||||||
m_reader.close();
|
m_reader->close();
|
||||||
}
|
}
|
||||||
std::shared_ptr<IDvdRequest> AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off);
|
std::shared_ptr<IDvdRequest> AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off);
|
||||||
void SyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int offset)
|
void SyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int offset)
|
||||||
{
|
{
|
||||||
m_reader.seek(offset, athena::SeekOrigin(whence));
|
m_reader->seek(offset, athena::SeekOrigin(whence));
|
||||||
m_reader.readBytesToBuf(buf, len);
|
m_reader->readBytesToBuf(buf, len);
|
||||||
}
|
}
|
||||||
std::shared_ptr<IDvdRequest> AsyncRead(void* buf, u32 len)
|
std::shared_ptr<IDvdRequest> AsyncRead(void* buf, u32 len)
|
||||||
{
|
{
|
||||||
|
@ -71,9 +73,9 @@ public:
|
||||||
}
|
}
|
||||||
void SyncRead(void* buf, u32 len)
|
void SyncRead(void* buf, u32 len)
|
||||||
{
|
{
|
||||||
m_reader.readBytesToBuf(buf, len);
|
m_reader->readBytesToBuf(buf, len);
|
||||||
}
|
}
|
||||||
u64 Length() {return m_reader.length();}
|
u64 Length() {return m_reader->length();}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,7 @@ void CFrontEndUI::HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArch
|
||||||
|
|
||||||
void CFrontEndUI::Draw() const
|
void CFrontEndUI::Draw() const
|
||||||
{
|
{
|
||||||
printf("DRAW\n");
|
//printf("DRAW\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrontEndUI::UpdateMovies(float dt)
|
void CFrontEndUI::UpdateMovies(float dt)
|
||||||
|
@ -285,7 +285,7 @@ void CFrontEndUI::TransitionToFive()
|
||||||
|
|
||||||
CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue)
|
CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue)
|
||||||
{
|
{
|
||||||
printf("UPDATE\n");
|
//printf("UPDATE\n");
|
||||||
|
|
||||||
if (xdc_saveUI && x50_curScreen >= EScreen::Three)
|
if (xdc_saveUI && x50_curScreen >= EScreen::Three)
|
||||||
{
|
{
|
||||||
|
|
2
amuse
2
amuse
|
@ -1 +1 @@
|
||||||
Subproject commit 9cf96ad6f94ffa6594a78358d39b195909f0b27c
|
Subproject commit 1dfdf4c392a0389b1a37f0e9c2064a42dd47b63f
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
||||||
Subproject commit 38624fb37507c53138b06c4b600cda02e6c7e924
|
Subproject commit 4f4ddb902ac6144051ef23d8a35f7b94db46cf41
|
Loading…
Reference in New Issue