Implement doppler effect
This commit is contained in:
parent
f612ba79fa
commit
8c14455096
|
@ -12,19 +12,24 @@ ALSndPlayer gSoundPlayer;
|
|||
|
||||
#define SOUND_FLAGS_3D (1 << 0)
|
||||
#define SOUND_FLAGS_LOOPING (1 << 1)
|
||||
#define SOUND_HAS_STARTED (1 << 2)
|
||||
|
||||
#define SPEED_OF_SOUND 343.2f
|
||||
|
||||
struct ActiveSound {
|
||||
ALSndId soundId;
|
||||
u16 flags;
|
||||
u16 newSoundTicks;
|
||||
float estimatedTimeLeft;
|
||||
struct Vector3 pos3D;
|
||||
struct Vector3 velocity3D;
|
||||
float volume;
|
||||
float basePitch;
|
||||
};
|
||||
|
||||
struct SoundListener {
|
||||
struct Vector3 worldPos;
|
||||
struct Vector3 rightVector;
|
||||
struct Vector3 velocity;
|
||||
};
|
||||
|
||||
struct ActiveSound gActiveSounds[MAX_ACTIVE_SOUNDS];
|
||||
|
@ -33,7 +38,7 @@ int gActiveSoundCount = 0;
|
|||
struct SoundListener gSoundListeners[MAX_SOUND_LISTENERS];
|
||||
int gActiveListenerCount = 0;
|
||||
|
||||
void soundPlayerDetermine3DSound(struct Vector3* at, float* volumeIn, float* volumeOut, int* panOut) {
|
||||
void soundPlayerDetermine3DSound(struct Vector3* at, struct Vector3* velocity, float* volumeIn, float* volumeOut, int* panOut, float* pitchBend) {
|
||||
if (!gActiveListenerCount) {
|
||||
*volumeOut = *volumeIn;
|
||||
*panOut = 64;
|
||||
|
@ -69,7 +74,16 @@ void soundPlayerDetermine3DSound(struct Vector3* at, float* volumeIn, float* vol
|
|||
struct Vector3 offset;
|
||||
vector3Sub(at, &nearestListener->worldPos, &offset);
|
||||
|
||||
float pan = -vector3Dot(&offset, &nearestListener->rightVector) / sqrtf(distance);
|
||||
struct Vector3 relativeVelocity;
|
||||
vector3Sub(velocity, &nearestListener->velocity, &relativeVelocity);
|
||||
|
||||
float invDist = 1.0f / sqrtf(distance);
|
||||
|
||||
float directionalVelocity = -vector3Dot(&offset, &relativeVelocity) * invDist;
|
||||
|
||||
*pitchBend = (SPEED_OF_SOUND + directionalVelocity) * (1.0f / SPEED_OF_SOUND);
|
||||
|
||||
float pan = -vector3Dot(&offset, &nearestListener->rightVector) * invDist;
|
||||
|
||||
pan = pan * 64.0f + 64.0f;
|
||||
|
||||
|
@ -132,7 +146,7 @@ float soundPlayerEstimateLength(ALSound* sound, float speed) {
|
|||
return sampleCount * (1.0f / OUTPUT_RATE) / speed;
|
||||
}
|
||||
|
||||
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at) {
|
||||
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at, struct Vector3* velocity) {
|
||||
if (gActiveSoundCount == MAX_ACTIVE_SOUNDS || soundClipId < 0 || soundClipId >= gSoundClipArray->soundCount) {
|
||||
return SOUND_ID_NONE;
|
||||
}
|
||||
|
@ -148,10 +162,10 @@ ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vecto
|
|||
struct ActiveSound* sound = &gActiveSounds[gActiveSoundCount];
|
||||
|
||||
sound->soundId = result;
|
||||
sound->newSoundTicks = 10;
|
||||
sound->flags = 0;
|
||||
sound->estimatedTimeLeft = soundPlayerEstimateLength(alSound, pitch);
|
||||
sound->volume = volume;
|
||||
sound->basePitch = pitch;
|
||||
|
||||
float startingVolume = volume;
|
||||
int panning = 64;
|
||||
|
@ -159,7 +173,10 @@ ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vecto
|
|||
if (at) {
|
||||
sound->flags |= SOUND_FLAGS_3D;
|
||||
sound->pos3D = *at;
|
||||
soundPlayerDetermine3DSound(at, &startingVolume, &startingVolume, &panning);
|
||||
sound->velocity3D = *velocity;
|
||||
float pitchBend;
|
||||
soundPlayerDetermine3DSound(at, velocity, &startingVolume, &startingVolume, &panning, &pitchBend);
|
||||
pitch = pitch * pitchBend;
|
||||
}
|
||||
|
||||
if (soundPlayerIsLooped(alSound)) {
|
||||
|
@ -184,25 +201,29 @@ void soundPlayerUpdate() {
|
|||
while (index < gActiveSoundCount) {
|
||||
struct ActiveSound* sound = &gActiveSounds[index];
|
||||
|
||||
if (sound->newSoundTicks) {
|
||||
--sound->newSoundTicks;
|
||||
}
|
||||
|
||||
sound->estimatedTimeLeft -= FIXED_DELTA_TIME;
|
||||
|
||||
alSndpSetSound(&gSoundPlayer, sound->soundId);
|
||||
|
||||
if (alSndpGetState(&gSoundPlayer) == AL_STOPPED && !sound->newSoundTicks) {
|
||||
int soundState = alSndpGetState(&gSoundPlayer);
|
||||
|
||||
if (soundState == AL_STOPPED && (sound->flags & SOUND_HAS_STARTED) != 0) {
|
||||
alSndpDeallocate(&gSoundPlayer, sound->soundId);
|
||||
sound->soundId = SOUND_ID_NONE;
|
||||
} else {
|
||||
if (soundState == AL_PLAYING || sound->estimatedTimeLeft < 0.0) {
|
||||
sound->flags |= SOUND_HAS_STARTED;
|
||||
}
|
||||
|
||||
if (sound->flags & SOUND_FLAGS_3D) {
|
||||
float volume;
|
||||
float pitch;
|
||||
int panning;
|
||||
|
||||
soundPlayerDetermine3DSound(&sound->pos3D, &sound->volume, &volume, &panning);
|
||||
soundPlayerDetermine3DSound(&sound->pos3D, &sound->velocity3D, &sound->volume, &volume, &panning, &pitch);
|
||||
alSndpSetVol(&gSoundPlayer, (short)(32767 * volume));
|
||||
alSndpSetPan(&gSoundPlayer, panning);
|
||||
alSndpSetPitch(&gSoundPlayer, sound->basePitch * pitch);
|
||||
}
|
||||
|
||||
++writeIndex;
|
||||
|
@ -254,12 +275,13 @@ void soundPlayerStopAll() {
|
|||
}
|
||||
}
|
||||
|
||||
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at) {
|
||||
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at, struct Vector3* velocity) {
|
||||
struct ActiveSound* activeSound = soundPlayerFindActiveSound(soundId);
|
||||
|
||||
if (activeSound) {
|
||||
activeSound->flags |= SOUND_FLAGS_3D;
|
||||
activeSound->pos3D = *at;
|
||||
activeSound->velocity3D = *velocity;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,7 +292,7 @@ int soundPlayerIsPlaying(ALSndId soundId) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (activeSound->newSoundTicks) {
|
||||
if (!(activeSound->flags & SOUND_HAS_STARTED)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -278,8 +300,9 @@ int soundPlayerIsPlaying(ALSndId soundId) {
|
|||
return activeSound->estimatedTimeLeft > 0.0f && alSndpGetState(&gSoundPlayer) != AL_STOPPED;
|
||||
}
|
||||
|
||||
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, int listenerIndex) {
|
||||
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, struct Vector3* velocity, int listenerIndex) {
|
||||
gSoundListeners[listenerIndex].worldPos = *position;
|
||||
gSoundListeners[listenerIndex].velocity = *velocity;
|
||||
quatMultVector(rotation, &gRight, &gSoundListeners[listenerIndex].rightVector);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ extern char _soundsTblSegmentRomEnd[];
|
|||
|
||||
void soundPlayerInit();
|
||||
void soundPlayerUpdate();
|
||||
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at);
|
||||
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at, struct Vector3* velocity);
|
||||
void soundPlayerStop(ALSndId soundId);
|
||||
void soundPlayerStopAll();
|
||||
|
||||
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at);
|
||||
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at, struct Vector3* velocity);
|
||||
|
||||
int soundPlayerIsPlaying(ALSndId soundId);
|
||||
|
||||
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, int listenerIndex);
|
||||
void soundListenerUpdate(struct Vector3* position, struct Quaternion* rotation, struct Vector3* velocity, int listenerIndex);
|
||||
void soundListenerSetCount(int count);
|
||||
|
||||
#endif
|
|
@ -95,7 +95,7 @@ void decorObjectInit(struct DecorObject* object, struct DecorObjectDefinition* d
|
|||
dynamicSceneSetRoomFlags(object->dynamicId, ROOM_FLAG_FROM_INDEX(room));
|
||||
|
||||
if (definition->soundClipId != -1) {
|
||||
object->playingSound = soundPlayerPlay(definition->soundClipId, 1.0f, 1.0f, &object->rigidBody.transform.position);
|
||||
object->playingSound = soundPlayerPlay(definition->soundClipId, 1.0f, 1.0f, &object->rigidBody.transform.position, &object->rigidBody.velocity);
|
||||
} else {
|
||||
object->playingSound = SOUND_ID_NONE;
|
||||
}
|
||||
|
@ -113,7 +113,11 @@ void decorObjectDelete(struct DecorObject* decorObject) {
|
|||
|
||||
int decorObjectUpdate(struct DecorObject* decorObject) {
|
||||
if (decorObject->playingSound != SOUND_ID_NONE) {
|
||||
soundPlayerUpdatePosition(decorObject->playingSound, &decorObject->rigidBody.transform.position);
|
||||
soundPlayerUpdatePosition(
|
||||
decorObject->playingSound,
|
||||
&decorObject->rigidBody.transform.position,
|
||||
&decorObject->rigidBody.velocity
|
||||
);
|
||||
}
|
||||
|
||||
if (decorObject->rigidBody.flags & RigidBodyFizzled) {
|
||||
|
|
|
@ -95,6 +95,7 @@ ALSndId cutsceneRunnerPlaySound(struct CutsceneStep* step) {
|
|||
step->playSound.soundId,
|
||||
step->playSound.volume * (1.0f / 255.0f),
|
||||
step->playSound.pitch * (1.0f / 64.0f),
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
@ -331,7 +332,7 @@ void cutscenesUpdateSounds() {
|
|||
if (gCutsceneSoundQueues[i]) {
|
||||
struct QueuedSound* curr = gCutsceneSoundQueues[i];
|
||||
|
||||
gCutsceneCurrentSound[i] = soundPlayerPlay(curr->soundId, curr->volume, gCutsceneChannelPitch[i], NULL);
|
||||
gCutsceneCurrentSound[i] = soundPlayerPlay(curr->soundId, curr->volume, gCutsceneChannelPitch[i], NULL, NULL);
|
||||
gCutsceneSoundQueues[i] = curr->next;
|
||||
|
||||
curr->next = gCutsceneNextFreeSound;
|
||||
|
|
|
@ -533,8 +533,8 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
|
|||
quatIdent(&player->body.transform.rotation);
|
||||
|
||||
if (didPassThroughPortal) {
|
||||
soundPlayerPlay(soundsPortalEnter[didPassThroughPortal - 1], 0.75f, 1.0f, NULL);
|
||||
soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f, NULL);
|
||||
soundPlayerPlay(soundsPortalEnter[didPassThroughPortal - 1], 0.75f, 1.0f, NULL, NULL);
|
||||
soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f, NULL, NULL);
|
||||
}
|
||||
|
||||
OSContPad* controllerInput = controllersGetControllerData(0);
|
||||
|
|
|
@ -169,7 +169,7 @@ int elevatorUpdate(struct Elevator* elevator, struct Player* player) {
|
|||
}
|
||||
|
||||
if ((elevator->openAmount == 0.0f && shouldBeOpen) || (elevator->openAmount && !shouldBeOpen)) {
|
||||
soundPlayerPlay(soundsElevatorDoor, 1.0f, 0.5f, &elevator->rigidBody.transform.position);
|
||||
soundPlayerPlay(soundsElevatorDoor, 1.0f, 0.5f, &elevator->rigidBody.transform.position, &gZeroVec);
|
||||
}
|
||||
|
||||
elevator->openAmount = mathfMoveTowards(elevator->openAmount, shouldBeOpen ? 1.0f : 0.0f, OPEN_SPEED * FIXED_DELTA_TIME);
|
||||
|
|
|
@ -272,12 +272,12 @@ void sceneCheckPortals(struct Scene* scene) {
|
|||
|
||||
if (controllerGetButtonDown(0, Z_TRIG) && (scene->player.flags & PlayerHasSecondPortalGun)) {
|
||||
sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1);
|
||||
soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL);
|
||||
soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL, NULL);
|
||||
}
|
||||
|
||||
if (controllerGetButtonDown(0, R_TRIG | L_TRIG) && (scene->player.flags & PlayerHasFirstPortalGun)) {
|
||||
sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1);
|
||||
soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL);
|
||||
soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL, NULL);
|
||||
}
|
||||
|
||||
if (scene->player.body.flags & RigidBodyFizzled) {
|
||||
|
@ -298,7 +298,13 @@ void sceneCheckPortals(struct Scene* scene) {
|
|||
portalCheckForHoles(scene->portals);
|
||||
}
|
||||
|
||||
void sceneUpdatePortalListener(struct Scene* scene, int portalIndex, int listenerIndex) {
|
||||
#define MAX_LISTEN_THROUGH_PORTAL_DISTANCE 3.0f
|
||||
|
||||
int sceneUpdatePortalListener(struct Scene* scene, int portalIndex, int listenerIndex) {
|
||||
if (vector3DistSqrd(&scene->player.lookTransform.position, &scene->portals[portalIndex].transform.position) > MAX_LISTEN_THROUGH_PORTAL_DISTANCE * MAX_LISTEN_THROUGH_PORTAL_DISTANCE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Transform otherInverse;
|
||||
transformInvert(&scene->portals[1 - portalIndex].transform, &otherInverse);
|
||||
struct Transform portalCombined;
|
||||
|
@ -307,19 +313,30 @@ void sceneUpdatePortalListener(struct Scene* scene, int portalIndex, int listene
|
|||
struct Transform relativeTransform;
|
||||
transformConcat(&portalCombined, &scene->player.lookTransform, &relativeTransform);
|
||||
|
||||
soundListenerUpdate(&relativeTransform.position, &relativeTransform.rotation, listenerIndex);
|
||||
struct Vector3 velocity;
|
||||
quatMultVector(&relativeTransform.rotation, &scene->player.body.velocity, &velocity);
|
||||
|
||||
soundListenerUpdate(&relativeTransform.position, &relativeTransform.rotation, &velocity, listenerIndex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sceneUpdateListeners(struct Scene* scene) {
|
||||
soundListenerUpdate(&scene->player.lookTransform.position, &scene->player.lookTransform.rotation, 0);
|
||||
soundListenerUpdate(&scene->player.lookTransform.position, &scene->player.lookTransform.rotation, &scene->player.body.velocity, 0);
|
||||
|
||||
int listenerCount = 1;
|
||||
|
||||
if (collisionSceneIsPortalOpen()) {
|
||||
soundListenerSetCount(3);
|
||||
sceneUpdatePortalListener(scene, 0, 1);
|
||||
sceneUpdatePortalListener(scene, 1, 2);
|
||||
} else {
|
||||
soundListenerSetCount(1);
|
||||
if (sceneUpdatePortalListener(scene, 0, listenerCount)) {
|
||||
++listenerCount;
|
||||
}
|
||||
|
||||
if (sceneUpdatePortalListener(scene, 1, listenerCount)) {
|
||||
++listenerCount;
|
||||
}
|
||||
}
|
||||
|
||||
soundListenerSetCount(listenerCount);
|
||||
}
|
||||
|
||||
struct Transform gRelativeElevatorTransform = {
|
||||
|
@ -551,7 +568,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
|
|||
struct Portal* portal = &scene->portals[portalIndex];
|
||||
|
||||
if (portalAttachToSurface(portal, existingSurface, surfaceIndex, &finalAt)) {
|
||||
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &at->position);
|
||||
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &at->position, &gZeroVec);
|
||||
|
||||
// the portal position may have been adjusted
|
||||
if (transformIndex != NO_TRANSFORM_INDEX) {
|
||||
|
@ -660,7 +677,7 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
|
|||
|
||||
void sceneClosePortal(struct Scene* scene, int portalIndex) {
|
||||
if (gCollisionScene.portalTransforms[portalIndex]) {
|
||||
soundPlayerPlay(soundsPortalFizzle, 1.0f, 1.0f, &gCollisionScene.portalTransforms[portalIndex]->position);
|
||||
soundPlayerPlay(soundsPortalFizzle, 1.0f, 1.0f, &gCollisionScene.portalTransforms[portalIndex]->position, &gZeroVec);
|
||||
gCollisionScene.portalTransforms[portalIndex] = NULL;
|
||||
scene->portals[portalIndex].flags |= PortalFlagsNeedsNewHole;
|
||||
scene->portals[portalIndex].portalSurfaceIndex = -1;
|
||||
|
|
Loading…
Reference in a new issue