diff --git a/configure.py b/configure.py index bb21a4f5..2d6be8dc 100755 --- a/configure.py +++ b/configure.py @@ -1067,7 +1067,7 @@ def MatchingFor(*versions): Object(Matching, "Inagaki/RockSoundMgr.cpp"), Object(Matching, "Inagaki/GameSoundTable.cpp"), Object(NonMatching, "Inagaki/ShoreSoundMgr.cpp"), - Object(NonMatching, "Inagaki/CircleSoundMgr.cpp"), + Object(Matching, "Inagaki/CircleSoundMgr.cpp"), Object(Matching, "Inagaki/CoasterSoundMgr.cpp"), Object(Matching, "Inagaki/MapSoundObjectMgr.cpp"), Object(Matching, "Inagaki/GameAudioFxConfig.cpp"), diff --git a/include/Inagaki/GameAudioCamera.h b/include/Inagaki/GameAudioCamera.h index a8f6f9a7..e4a3f3a8 100644 --- a/include/Inagaki/GameAudioCamera.h +++ b/include/Inagaki/GameAudioCamera.h @@ -64,11 +64,16 @@ class CameraMgr { u32 getSceneMax() const { return mSceneMax; } + CameraInfo* getCameraInfo(u32 index) const { + #line 79 + JUT_ASSERT_MSG(index < _4, "GameAudioCamera : カメラナンバーが不正です。\n"); + return mCamInfo + index; + } //private: - CustomAudience<4> *mAudience; - u32 _4; - u32 mSceneMax; - CameraInfo *mCamInfo; + CustomAudience<4> *mAudience; // 00 + u32 _4; // 04 + u32 mSceneMax; // 08 + CameraInfo *mCamInfo; // 0c }; // Size: 0x10 } diff --git a/include/Inagaki/GameAudioMain.h b/include/Inagaki/GameAudioMain.h index 00284341..4fc6d352 100644 --- a/include/Inagaki/GameAudioMain.h +++ b/include/Inagaki/GameAudioMain.h @@ -115,7 +115,7 @@ class Main CustomMgr *mMgr; // 00 CustomAudience<4> *mAudience; // 04 - u8 _08[0xC - 0x8]; // + u8 _08[0xC - 0x8]; // 08 CustomSoundTable *mTable; // 0C u8 _10[4]; // JAUSectionHeap *mSectionHeap; // 14 diff --git a/include/Inagaki/GameSoundMgr.h b/include/Inagaki/GameSoundMgr.h index 430d10f3..42d4bf26 100644 --- a/include/Inagaki/GameSoundMgr.h +++ b/include/Inagaki/GameSoundMgr.h @@ -28,10 +28,10 @@ class SoundMgr : public JAUDopplerSoundObject, public JKRDisposer virtual ~SoundMgr(); virtual void init(); virtual void setSe(u32 id); - virtual void loop(); void setEcho(JAISoundHandle *handlePtr, f32 mix); JAISoundHandle *startSoundCustom(u32 soundID, u32 p2); + virtual void loop(); static void setKillSwAll(bool killSw); @@ -357,12 +357,34 @@ class ShoreSoundMgr : public SoundMgr { class CircleSoundMgr : public SoundMgr { public: - CircleSoundMgr(Vec *, f32, f32, f32, JKRHeap *); // 0x8012dc34 + CircleSoundMgr(Vec *pos, f32 radius, f32 minY, f32 maxY, JKRHeap *heap); // 0x8012dc34 + ~CircleSoundMgr(); // 0x8012dd68 + void loop(); // 0x8012ddc8 + void frameWork(); // 0x8012e02c - void calcPlayPos(u32); // 0x8012e064 - void setSe(u32); // 0x8012e3f4 + + // Compute playing position for the given index + // Return true if a new position has been computed, false otherwise + bool calcPlayPos(u32 index); // 0x8012e064 + + void setSe(u32 soundEffectID); // 0x8012e3f4 + +private: + JGeometry::TVec3f& getPlayPos(s32 index) { // fabricated + return mPlayPos[index]; + } + + u8 _5c; // 5c + bool mHasHeightRange; // 5d + bool mNoClamp; // 5e + u8 _5f; //5f + bool* mPlayPosComputed; // 60 + f32 mMinY; // 64 + f32 mMaxY; // 68 + f32 mRadius; // 6c + JGeometry::TVec3f *mPlayPos; // 70 }; } diff --git a/src/Inagaki/CircleSoundMgr.cpp b/src/Inagaki/CircleSoundMgr.cpp index 53143470..39ff66dc 100644 --- a/src/Inagaki/CircleSoundMgr.cpp +++ b/src/Inagaki/CircleSoundMgr.cpp @@ -1,22 +1,197 @@ +#include "Inagaki/GameAudioHostIO.h" +#include "Inagaki/GameAudioMain.h" #include "Inagaki/GameSoundMgr.h" +#include "Inagaki/GameAudioCamera.h" +#include "JSystem/JAudio/Interface/JAIAudience.h" +#include "JSystem/JAudio/Interface/JAISound.h" #include "JSystem/JAudio/JASFakeMatch2.h" +#include "JSystem/JAudio/System/JASGadget.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JUtility/JUTAssert.h" + +#include "dolphin/mtx.h" + +#include "std/math.h" namespace GameAudio { -CircleSoundMgr::CircleSoundMgr(Vec *pos, f32, f32, f32, JKRHeap *heap) : SoundMgr(pos, heap, 4) { - +CircleSoundMgr::CircleSoundMgr(Vec *pos, f32 radius, f32 minY, f32 maxY, JKRHeap *heap) + : SoundMgr(pos, heap, 4) { + mRadius = radius; + mMinY = minY; + mMaxY = maxY; + + if(mMinY == mMaxY) + { + mHasHeightRange = false; + } + else { + mHasHeightRange = true; + } + + mNoClamp = false; + // Unused + _5c = false; + + mPlayPos = new JGeometry::TVec3f[4]; + mPlayPosComputed = new bool[4]; + + for(u8 i = 0; i < 4; i++) + { + mPlayPos[i].set(0.f, 0.f, 0.f); + mPlayPosComputed[i] = false; + } } CircleSoundMgr::~CircleSoundMgr() {} -void CircleSoundMgr::loop() {} +void CircleSoundMgr::loop() { + #line 63 + JUT_ASSERT_MSG(mSoundPos != NULL, "CircleSoundMgr::loop disable中です!!!!!\n"); + + if(mKillSw) { + return; + } + + const u32 sceneMax = GameAudio::Main::getAudio()->getCamera()->getSceneMax(); + + // Forced to cast sceneMax into its own u32 type here... + for(s32 index = 0; index < (u32)sceneMax; index++){ + if ((*this)[index] == NULL) { + continue; + } + + mPlayPosComputed[index] = calcPlayPos(index); + + const JGeometry::TVec3f& playPos = getPlayPos(index); + JAIAudible *audible = (*this)[index]->getAudible(); + if(audible) { + audible->setPos(playPos); + } + } +} + +void CircleSoundMgr::frameWork() { + if(mKillSw) { + return; + } + loop(); +} + +bool CircleSoundMgr::calcPlayPos(u32 index) { + mPlayPosComputed[index] = false; + + CameraInfo* info = GameAudio::Main::getAudio()->getCamera()->getCameraInfo(index); + + JGeometry::TVec3 cameraPosition (info->_0); + + f32 distanceZ = mSoundPos->z - cameraPosition.z; + f32 distanceX = mSoundPos->x - cameraPosition.x; + f32 distanceSquare = (distanceX * distanceX) + (distanceZ * distanceZ); -void CircleSoundMgr::frameWork() {} + f32 radiusSquare = mRadius * mRadius; -void CircleSoundMgr::calcPlayPos(u32) {} + if(radiusSquare > distanceSquare) + { + mPlayPos[index] = cameraPosition; + } + else { + if (mNoClamp == false) { + f32 distance = std::sqrtf(distanceSquare); -void CircleSoundMgr::setSe(u32) {} + f32 scale = mRadius / distance; + + JGeometry::TVec3 toCamera = (cameraPosition - *mSoundPos); + mPlayPos[index] = (toCamera * scale) + *mSoundPos; + } + else { + return false; + } + } + + if(mHasHeightRange == 0) // 2c8 + { + mPlayPos[index].y = cameraPosition.y; + } + else if (cameraPosition.y < mMinY) { + if (mNoClamp == false) { + mPlayPos[index].y = mMinY; + } + else { + return false; + } + } + else if (cameraPosition.y > mMaxY) { + if (mNoClamp == false) { + mPlayPos[index].y = mMaxY; + } + else { + return false; + } + } + else { + mPlayPos[index].y = cameraPosition.y; + } + + mPlayPosComputed[index] = true; + return true; +} + +void CircleSoundMgr::setSe(u32 soundEffectID) { + if(mKillSw) { + return; + } + + JAISoundStarter* soundStarter = JASGlobalInstance::getInstance(); + const u32 sceneMax = GameAudio::Main::getAudio()->getCamera()->getSceneMax(); + + for(s32 index = 0; index < (u32)sceneMax; index++) { + if(!calcPlayPos(index)) { + continue; + } + + JAISoundHandle& handle = (*this)[index]; + + soundStarter->startSound(soundEffectID, &handle, NULL); + + if(handle.sound_ == NULL) { + continue; + } + + if(handle->getAudible() == NULL) { + const u32 otherScreensMask = (1 << index) ^ 0xf; + + handle->newAudible( + JGeometry::TVec3f (mPlayPos[index]), + &mPlayPos[index], + otherScreensMask, + NULL); + } + + const s32 partnerCameraIndex = index ^ 2; + if(partnerCameraIndex >= sceneMax) { + continue; + } + + const JGeometry::TVec3f partnerCameraPosition + = (GameAudio::Main::getAudio()->getCamera()->getCameraInfo(partnerCameraIndex)->_0); + + const JGeometry::TVec3f& cameraPosition + = (GameAudio::Main::getAudio()->getCamera()->getCameraInfo(index)->_0); + + const f32 distance = PSVECDistance(&partnerCameraPosition, &cameraPosition); + + if(distance < GameAudio::GA_MULTI_CAMERA_VOL_DOWN_DISTANCE) + { + const f32 volume = 1.f - ( + (GameAudio::GA_MULTI_CAMERA_VOL_DOWN_RATE * (GA_MULTI_CAMERA_VOL_DOWN_DISTANCE - distance)) + / GA_MULTI_CAMERA_VOL_DOWN_DISTANCE); + + handle->params_.mMove.moveVolume(volume, 0); + } + } +} }