diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 72f824acb..60d3b3af7 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -30,7 +30,8 @@ void ViewManager::BuildTestPART(urde::IObjectStore& objStore) m_lineRenderer.reset(new urde::CLineRenderer(urde::CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true)); */ m_particleView.reset(new ParticleView(*this, m_viewResources, *m_rootView)); - m_moviePlayer.reset(new CMoviePlayer("Video/00_first_start.thp", -1.f, true, false)); + m_moviePlayer.reset(new CMoviePlayer("Video/SpecialEnding.thp", -1.f, true, true)); + m_videoVoice->start(); //m_rootView->accessContentViews().clear(); m_rootView->accessContentViews().push_back(m_particleView.get()); @@ -147,7 +148,7 @@ void ViewManager::DismissSplash() ViewManager::ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr) : m_fileStoreManager(fileMgr), m_cvarManager(cvarMgr), m_projManager(*this), - m_fontCache(fileMgr), m_translator(urde::SystemLocaleOrEnglish()), + m_fontCache(fileMgr), m_translator(urde::SystemLocaleOrEnglish()), m_voiceCallback(*this), m_recentProjectsPath(hecl::SysFormat(_S("%s/recent_projects.txt"), fileMgr.getStoreRoot().c_str())), m_recentFilesPath(hecl::SysFormat(_S("%s/recent_files.txt"), fileMgr.getStoreRoot().c_str())) { @@ -238,6 +239,11 @@ void ViewManager::init(boo::IApplication* app) m_mainWindow->setWaitCursor(false); + m_voiceAllocator = boo::NewAudioVoiceAllocator(); + boo::AudioChannelSet audioSet = m_voiceAllocator->getAvailableSet(); + m_stereoMatrix.setAudioChannelSet(audioSet); + m_stereoMatrix.setDefaultMatrixCoefficients(); + m_videoVoice = m_voiceAllocator->allocateNewVoice(audioSet, 32000, &m_voiceCallback); CGraphics::InitializeBoo(gf, m_mainWindow->getCommandQueue(), root->renderTex()); CElementGen::Initialize(); CMoviePlayer::Initialize(); @@ -286,6 +292,7 @@ bool ViewManager::proc() m_rootView->draw(gfxQ); CGraphics::EndScene(); gfxQ->execute(); + m_voiceAllocator->pumpVoices(); m_mainWindow->waitForRetrace(); return true; @@ -293,6 +300,7 @@ bool ViewManager::proc() void ViewManager::stop() { + m_videoVoice.reset(); CElementGen::Shutdown(); CMoviePlayer::Shutdown(); CLineRenderer::Shutdown(); diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index d840d9285..732c5de5d 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -1,7 +1,9 @@ #ifndef URDE_VIEW_MANAGER_HPP #define URDE_VIEW_MANAGER_HPP -#include +#include "hecl/CVarManager.hpp" +#include "boo/audiodev/IAudioVoiceAllocator.hpp" +#include "boo/audiodev/AudioMatrix.hpp" #include "ProjectManager.hpp" #include "Space.hpp" @@ -49,6 +51,23 @@ class ViewManager : public specter::IViewManager std::unique_ptr m_partGen; std::unique_ptr m_lineRenderer; std::unique_ptr m_moviePlayer; + std::unique_ptr m_voiceAllocator; + std::unique_ptr m_videoVoice; + boo::AudioMatrixStereo m_stereoMatrix; + struct AudioVoiceCallback : boo::IAudioVoiceCallback + { + ViewManager& m_vm; + std::vector m_stereoBuf; + void needsNextBuffer(boo::IAudioVoice& voice, size_t frames) + { + m_stereoBuf.clear(); + m_stereoBuf.resize(frames * 2); + if (m_vm.m_moviePlayer) + m_vm.m_moviePlayer->MixAudio(m_stereoBuf.data(), nullptr, frames); + m_vm.m_stereoMatrix.bufferStereoSampleData(voice, m_stereoBuf.data(), frames); + } + AudioVoiceCallback(ViewManager& vm) : m_vm(vm) {} + } m_voiceCallback; hecl::SystemString m_recentProjectsPath; std::vector m_recentProjects; diff --git a/Runtime/Audio/dsp.c b/Runtime/Audio/dsp.c index 1c77dca23..9c83955d7 100644 --- a/Runtime/Audio/dsp.c +++ b/Runtime/Audio/dsp.c @@ -2,13 +2,6 @@ static const int NibbleToInt[16] = {0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1}; -static inline short SampClamp(int val) -{ - if (val < -32768) val = -32768; - if (val > 32767) val = 32767; - return val; -} - void DSPDecompressFrame(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, unsigned lastSample) @@ -29,7 +22,7 @@ void DSPDecompressFrame(int16_t* out, const uint8_t* in, factor1 * *prev1 + factor2 * *prev2; sampleData >>= 11; - sampleData = SampClamp(sampleData); + sampleData = DSPSampClamp(sampleData); out[s] = sampleData; *prev2 = *prev1; *prev1 = sampleData; @@ -56,7 +49,7 @@ void DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in, factor1 * *prev1 + factor2 * *prev2; sampleData >>= 11; - sampleData = SampClamp(sampleData); + sampleData = DSPSampClamp(sampleData); out[s*2] = sampleData; *prev2 = *prev1; *prev1 = sampleData; @@ -83,7 +76,7 @@ void DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in, factor1 * *prev1 + factor2 * *prev2; sampleData >>= 11; - sampleData = SampClamp(sampleData); + sampleData = DSPSampClamp(sampleData); out[s*2] = sampleData; out[s*2+1] = sampleData; *prev2 = *prev1; diff --git a/Runtime/Audio/dsp.h b/Runtime/Audio/dsp.h index 6d315a0ff..bd6b95b6d 100644 --- a/Runtime/Audio/dsp.h +++ b/Runtime/Audio/dsp.h @@ -7,6 +7,13 @@ extern "C" { #include +static inline short DSPSampClamp(int val) +{ + if (val < -32768) val = -32768; + if (val > 32767) val = 32767; + return val; +} + void DSPDecompressFrame(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, unsigned lastSample); diff --git a/Runtime/Graphics/CMoviePlayer.cpp b/Runtime/Graphics/CMoviePlayer.cpp index 4f3f14ebf..c04540d4e 100644 --- a/Runtime/Graphics/CMoviePlayer.cpp +++ b/Runtime/Graphics/CMoviePlayer.cpp @@ -462,10 +462,70 @@ void CMoviePlayer::SetStaticAudioVolume(int vol) void CMoviePlayer::SetStaticAudio(const void* data, u32 length, u32 loopStart, u32 loopEnd) { } -void CMoviePlayer::MixAudio(short* out, const short* in, u32 length) + +void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) { + if (xd4_audioSlot == -1) + { + if (in) + memcpy(out, in, samples * 4); + else + memset(out, 0, samples * 4); + return; + } + + while (samples) + { + CTHPTextureSet* tex = &x80_textures[xd4_audioSlot]; + u32 thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); + if (!thisSamples) + { + ++xd4_audioSlot; + if (xd4_audioSlot >= x80_textures.size()) + xd4_audioSlot = 0; + tex = &x80_textures[xd4_audioSlot]; + thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); + } + if (thisSamples) + { + if (in) + { + for (u32 i=0 ; iaudioBuf.get()[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000)); + out[1] = DSPSampClamp(in[1] + + s16(s32(tex->audioBuf.get()[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000)); + out += 2; + in += 2; + } + } + else + { + for (u32 i=0 ; iaudioBuf.get()[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000)); + out[1] = DSPSampClamp( + s16(s32(tex->audioBuf.get()[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000)); + out += 2; + } + } + tex->playedSamples += thisSamples; + samples -= thisSamples; + } + else + { + if (in) + memcpy(out, in, samples * 4); + else + memset(out, 0, samples * 4); + return; + } + } } -void CMoviePlayer::MixStaticAudio(short* out, const short* in, u32 length) + +void CMoviePlayer::MixStaticAudio(short* out, const short* in, u32 samples) { } void CMoviePlayer::StaticMyAudioCallback() @@ -489,7 +549,7 @@ void CMoviePlayer::Rewind() xc8_curFrame = 0; xcc_decodedTexSlot = 0; xd0_drawTexSlot = -1; - xd4_ = -1; + xd4_audioSlot = -1; xd8_decodedTexCount = 0; xdc_frameRem = 0.f; xe8_curSeconds = 0.f; @@ -510,7 +570,8 @@ void CMoviePlayer::DrawFrame() if (xd0_drawTexSlot == -1) return; CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; - CGraphics::g_BooMainCommandQueue->setShaderDataBinding(tex.binding[m_deinterlace ? xf4_26_fieldFlip : 0]); + CGraphics::g_BooMainCommandQueue->setShaderDataBinding + (tex.binding[m_deinterlace ? (xfc_fieldIndex != 0) : 0]); CGraphics::g_BooMainCommandQueue->draw(0, 4); if (!xfc_fieldIndex && CGraphics::g_LastFrameUsedAbove) xf4_26_fieldFlip = true; @@ -593,8 +654,8 @@ void CMoviePlayer::Update(float dt) ++xd0_drawTexSlot; if (xd0_drawTexSlot >= x80_textures.size()) xd0_drawTexSlot = 0; - if (xd4_ == -1) - xd4_ = 0; + if (xd4_audioSlot == -1) + xd4_audioSlot = 0; --xd8_decodedTexCount; ++xc8_curFrame; if (xc8_curFrame == x28_thpHead.numFrames && xf4_24_loop) @@ -668,7 +729,8 @@ void CMoviePlayer::DecodeFromRead(const void* data) break; } case THPComponents::Type::Audio: - THPAudioDecode(tex.audioBuf.get(), (u8*)inptr, x74_audioInfo.numChannels == 2); + tex.audioSamples = THPAudioDecode(tex.audioBuf.get(), (u8*)inptr, x74_audioInfo.numChannels == 2); + tex.playedSamples = 0; inptr += frameHeader.audioSize; break; default: break; diff --git a/Runtime/Graphics/CMoviePlayer.hpp b/Runtime/Graphics/CMoviePlayer.hpp index 59d4d61d5..a61414bf2 100644 --- a/Runtime/Graphics/CMoviePlayer.hpp +++ b/Runtime/Graphics/CMoviePlayer.hpp @@ -86,6 +86,8 @@ private: boo::ITextureD* Y[2] = {}; boo::ITextureD* U = nullptr; boo::ITextureD* V = nullptr; + u32 playedSamples = 0; + u32 audioSamples = 0; std::unique_ptr audioBuf; boo::IShaderDataBinding* binding[2] = {}; }; @@ -103,7 +105,7 @@ private: u32 xc8_curFrame = 0; u32 xcc_decodedTexSlot = 0; u32 xd0_drawTexSlot = -1; - u32 xd4_ = -1; + u32 xd4_audioSlot = -1; s32 xd8_decodedTexCount = 0; float xdc_frameRem = 0.f; EPlayMode xe0_playMode = EPlayMode::Playing; @@ -142,8 +144,8 @@ public: static void DisableStaticAudio(); static void SetStaticAudioVolume(int vol); static void SetStaticAudio(const void* data, u32 length, u32 loopStart, u32 loopEnd); - void MixAudio(short* out, const short* in, u32 length); - static void MixStaticAudio(short* out, const short* in, u32 length); + void MixAudio(s16* out, const s16* in, u32 samples); + static void MixStaticAudio(short* out, const short* in, u32 samples); static void StaticMyAudioCallback(); void Rewind(); diff --git a/hecl b/hecl index f1f3bb641..0e0e454ad 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit f1f3bb641d52a584011bfe2113a797833421ba92 +Subproject commit 0e0e454adec26503b896e3cb2f02195b3516c4a0