Skip to content

Commit

Permalink
Improved 3D sound
Browse files Browse the repository at this point in the history
  • Loading branch information
deathkiller committed Dec 17, 2023
1 parent 9712a77 commit b9baad1
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Sources/Jazz2/Actors/Solid/PinballBumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace Jazz2::Actors::Solid
SetTransition(_currentAnimation->State | (AnimState)0x200, true);
PlaySfx("Hit"_s, 0.8f);

constexpr float forceMult = /*24.0f*/12.0f;
constexpr float forceMult = 12.0f;
Vector2f force = (player->GetPos() - _pos).Normalize() * forceMult;
if (!_levelHandler->IsReforged()) {
force.Y *= 0.7f;
Expand Down
14 changes: 7 additions & 7 deletions Sources/Shared/Base/TypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "../Common.h"

// If `DEATH_NO_RUNTIME_CAST` is defined, standard dynamic_cast<>() is used in runtime_cast<T>()
// If `DEATH_NO_RUNTIME_CAST` is defined, standard dynamic_cast<T>() is used in runtime_cast<T>()
#if !defined(DEATH_NO_RUNTIME_CAST)

#include <memory>
Expand Down Expand Up @@ -215,22 +215,22 @@ namespace Death { namespace TypeInfo { namespace Implementation {
}

template<class Base, class ...OtherBases, class Self>
static const void* FindInstance(TypeId id, const Self* self) noexcept {
if (const void* ptr = self->Base::__FindInstance(id)) {
static const void* FindInstance(TypeId t, const Self* self) noexcept {
if (const void* ptr = self->Base::__FindInstance(t)) {
return ptr;
}
return FindInstance<OtherBases...>(id, self);
return FindInstance<OtherBases...>(t, self);
}
};
}}}

/** @brief Class annotation to enable optimized @ref runtime_cast() functionality */
#define DEATH_RTTI_OBJECT(...) \
friend struct Death::TypeInfo::Implementation::Helpers; \
virtual const void* __FindInstance(Death::TypeInfo::Implementation::TypeId id) const noexcept { \
if (id == Death::TypeInfo::Implementation::Helpers::GetTypeId(this)) \
virtual const void* __FindInstance(Death::TypeInfo::Implementation::TypeId t) const noexcept { \
if (t == Death::TypeInfo::Implementation::Helpers::GetTypeId(this)) \
return this; \
return Death::TypeInfo::Implementation::Helpers::FindInstance<__VA_ARGS__>(id, this); \
return Death::TypeInfo::Implementation::Helpers::FindInstance<__VA_ARGS__>(t, this); \
}

/** @brief Safely converts pointers to classes up, down, and sideways along the inheritance hierarchy of classes annotated by @ref DEATH_RTTI_OBJECT() */
Expand Down
7 changes: 7 additions & 0 deletions Sources/nCine/Audio/ALAudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,15 @@ namespace nCine
}
}

const Vector3f& ALAudioDevice::getListenerPosition() const
{
return _listenerPos;
}

void ALAudioDevice::updateListener(const Vector3f& position, const Vector3f& velocity)
{
_listenerPos = position;

alListener3f(AL_POSITION, position.X * LengthToPhysical, position.Y * -LengthToPhysical, position.Z * -LengthToPhysical);
alListener3f(AL_VELOCITY, velocity.X * VelocityToPhysical, velocity.Y * -VelocityToPhysical, velocity.Z * -VelocityToPhysical);
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/nCine/Audio/ALAudioDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace nCine
void unregisterPlayer(IAudioPlayer* player) override;
void updatePlayers() override;

const Vector3f& getListenerPosition() const override;
void updateListener(const Vector3f& position, const Vector3f& velocity) override;

int nativeFrequency() override;
Expand All @@ -81,6 +82,8 @@ namespace nCine
SmallVector<ALuint, MaxSources> sourcePool_;
/// The array of currently active audio players
SmallVector<IAudioPlayer*, MaxSources> players_;
/// Listener position
Vector3f _listenerPos;
/// native device frequency
int nativeFreq_;

Expand Down
4 changes: 3 additions & 1 deletion Sources/nCine/Audio/AudioBufferPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ namespace nCine

updateFilters();

Vector3f adjustedPos = getAdjustedPosition(device, position_, isSourceRelative_);

alSourcei(sourceId_, AL_SOURCE_RELATIVE, isSourceRelative_ ? AL_TRUE : AL_FALSE);
alSource3f(sourceId_, AL_POSITION, position_.X * IAudioDevice::LengthToPhysical, position_.Y * -IAudioDevice::LengthToPhysical, position_.Z * -IAudioDevice::LengthToPhysical);
alSource3f(sourceId_, AL_POSITION, adjustedPos.X, adjustedPos.Y, adjustedPos.Z);
alSourcef(sourceId_, AL_REFERENCE_DISTANCE, IAudioDevice::ReferenceDistance);
alSourcef(sourceId_, AL_MAX_DISTANCE, IAudioDevice::MaxDistance);

Expand Down
4 changes: 3 additions & 1 deletion Sources/nCine/Audio/AudioStreamPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ namespace nCine

updateFilters();

Vector3f adjustedPos = getAdjustedPosition(device, position_, isSourceRelative_);

alSourcei(sourceId_, AL_SOURCE_RELATIVE, isSourceRelative_ ? AL_TRUE : AL_FALSE);
alSource3f(sourceId_, AL_POSITION, position_.X * IAudioDevice::LengthToPhysical, position_.Y * -IAudioDevice::LengthToPhysical, position_.Z * -IAudioDevice::LengthToPhysical);
alSource3f(sourceId_, AL_POSITION, adjustedPos.X, adjustedPos.Y, adjustedPos.Z);
alSourcef(sourceId_, AL_REFERENCE_DISTANCE, IAudioDevice::ReferenceDistance);
alSourcef(sourceId_, AL_MAX_DISTANCE, IAudioDevice::MaxDistance);

Expand Down
8 changes: 5 additions & 3 deletions Sources/nCine/Audio/IAudioDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ namespace nCine
class IAudioDevice
{
public:
static constexpr unsigned int UnavailableSource = ~0U;
static constexpr unsigned int UnavailableSource = ~0u;

// TODO: Revise these constants
static constexpr float LengthToPhysical = 0.0000000005f;
static constexpr float VelocityToPhysical = 2.0f;
static constexpr float LengthToPhysical = 1.0f / 100.0f;
static constexpr float VelocityToPhysical = FrameTimer::FramesPerSecond / 100.0f;
static constexpr float ReferenceDistance = 200.0f * LengthToPhysical;
static constexpr float MaxDistance = 900.0f * LengthToPhysical;

Expand Down Expand Up @@ -60,6 +60,7 @@ namespace nCine
/// Updates players state (and buffer queue in the case of stream players)
virtual void updatePlayers() = 0;

virtual const Vector3f& getListenerPosition() const = 0;
virtual void updateListener(const Vector3f& position, const Vector3f& velocity) = 0;

virtual int nativeFrequency() = 0;
Expand Down Expand Up @@ -101,6 +102,7 @@ namespace nCine
unsigned int registerPlayer(IAudioPlayer* player) override { return UnavailableSource; }
void unregisterPlayer(IAudioPlayer* player) override { }
void updatePlayers() override {}
const Vector3f& getListenerPosition() const override { return Vector3f::Zero; }
void updateListener(const Vector3f& position, const Vector3f& velocity) override { }
int nativeFrequency() override { return 0; }
};
Expand Down
42 changes: 40 additions & 2 deletions Sources/nCine/Audio/IAudioPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

#include "IAudioPlayer.h"
#include "IAudioDevice.h"
#include "../ServiceLocator.h"
#include "../Primitives/Vector3.h"

namespace nCine
{
IAudioPlayer::IAudioPlayer(ObjectType type)
: Object(type), sourceId_(IAudioDevice::UnavailableSource), state_(PlayerState::Stopped), isLooping_(false),
isSourceRelative_(false), gain_(1.0f), pitch_(1.0f), lowPass_(1.0f), position_(0.0f, 0.0f, 0.0f), filterHandle_(0)
isSourceRelative_(false), gain_(1.0f), pitch_(1.0f), lowPass_(1.0f), position_(0.0f, 0.0f, 0.0f), filterHandle_(0)
{
}

Expand Down Expand Up @@ -79,7 +80,9 @@ namespace nCine
{
position_ = position;
if (state_ == PlayerState::Playing) {
alSource3f(sourceId_, AL_POSITION, position.X * IAudioDevice::LengthToPhysical, position.Y * -IAudioDevice::LengthToPhysical, position.Z * -IAudioDevice::LengthToPhysical);
IAudioDevice& device = theServiceLocator().audioDevice();
Vector3f adjustedPos = getAdjustedPosition(device, position_, isSourceRelative_);
alSource3f(sourceId_, AL_POSITION, adjustedPos.X, adjustedPos.Y, adjustedPos.Z);
}
}

Expand All @@ -104,4 +107,39 @@ namespace nCine
}
#endif
}

Vector3f IAudioPlayer::getAdjustedPosition(IAudioDevice& device, const Vector3f& pos, bool isSourceRelative)
{
Vector3f listenerPos;
Vector3f adjustedPos = Vector3f(pos.X * IAudioDevice::LengthToPhysical, pos.Y * -IAudioDevice::LengthToPhysical, pos.Z * -IAudioDevice::LengthToPhysical);

if (!isSourceRelative) {
listenerPos = device.getListenerPosition();
listenerPos.X *= IAudioDevice::LengthToPhysical;
listenerPos.Y *= -IAudioDevice::LengthToPhysical;
listenerPos.Z *= -IAudioDevice::LengthToPhysical;

adjustedPos -= listenerPos;
}

// Flatten depth position a little, so far away sounds that can still be seen appear louder
adjustedPos.Z *= 0.5f;

// Normalize audio position for smooth panning when near. Do it in physical units, so this remains constant regardless of unit changes.
constexpr float SmoothPanRadius = 5.0f;
float listenerSpaceDist = adjustedPos.Length();
if (listenerSpaceDist < SmoothPanRadius) {
float panningActive = listenerSpaceDist / SmoothPanRadius;
adjustedPos = Vector3f::Lerp(
Vector3(0.0f, 0.0f, 1.0f + (SmoothPanRadius - 1.0f) * panningActive),
adjustedPos,
panningActive);
}

if (!isSourceRelative) {
adjustedPos += listenerPos;
}

return adjustedPos;
}
}
3 changes: 3 additions & 0 deletions Sources/nCine/Audio/IAudioPlayer.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "IAudioDevice.h"
#include "../Base/Object.h"
#include "../Primitives/Vector3.h"

Expand Down Expand Up @@ -143,6 +144,8 @@ namespace nCine

virtual void updateFilters();

static Vector3f getAdjustedPosition(IAudioDevice& device, const Vector3f& pos, bool isSourceRelative);

friend class ALAudioDevice;
};
}
16 changes: 11 additions & 5 deletions Sources/nCine/Primitives/Vector2.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ namespace nCine
Vector2 Normalized() const;
Vector2& Normalize();

template <class S>
friend S Dot(const Vector2<S>& v1, const Vector2<S>& v2);
static T Dot(const Vector2& v1, const Vector2& v2);
static Vector2 Lerp(const Vector2& a, const Vector2& b, float t);

/// A vector with all zero elements
static const Vector2 Zero;
Expand Down Expand Up @@ -306,10 +306,16 @@ namespace nCine
return *this;
}

template <class S>
inline S Dot(const Vector2<S>& v1, const Vector2<S>& v2)
template <class T>
inline T Vector2<T>::Dot(const Vector2<T>& v1, const Vector2<T>& v2)
{
return static_cast<T>(v1.X * v2.X + v1.Y * v2.Y);
}

template <class T>
inline Vector2<T> Vector2<T>::Lerp(const Vector2<T>& a, const Vector2<T>& b, float t)
{
return static_cast<S>(v1.X * v2.X + v1.Y * v2.Y);
return Vector2<T>(t * (b.X - a.X) + a.X, t * (b.Y - a.Y) + a.Y);
}

template <class T>
Expand Down
27 changes: 15 additions & 12 deletions Sources/nCine/Primitives/Vector3.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ namespace nCine

Vector2<T> ToVector2() const;

template <class S>
friend S Dot(const Vector3<S>& v1, const Vector3<S>& v2);
template <class S>
friend Vector3<S> Cross(const Vector3<S>& v1, const Vector3<S>& v2);
static T Dot(const Vector3& v1, const Vector3& v2);
static Vector3 Cross(const Vector3& v1, const Vector3& v2);
static Vector3 Lerp(const Vector3& a, const Vector3& b, float t);

/// A vector with all zero elements
static const Vector3 Zero;
Expand Down Expand Up @@ -348,22 +347,26 @@ namespace nCine
return Vector2<T>(X, Y);
}

template <class S>
inline S dot(const Vector3<S>& v1, const Vector3<S>& v2)
template <class T>
inline T Vector3<T>::Dot(const Vector3<T>& v1, const Vector3<T>& v2)
{
return static_cast<S>(v1.X * v2.X +
v1.Y * v2.Y +
v1.Z * v2.Z);
return static_cast<T>(v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z);
}

template <class S>
inline Vector3<S> Cross(const Vector3<S>& v1, const Vector3<S>& v2)
template <class T>
inline Vector3<T> Vector3<T>::Cross(const Vector3<T>& v1, const Vector3<T>& v2)
{
return Vector3<S>(v1.Y * v2.Z - v1.Z * v2.Y,
return Vector3<T>(v1.Y * v2.Z - v1.Z * v2.Y,
v1.Z * v2.X - v1.X * v2.Z,
v1.X * v2.Y - v1.Y * v2.X);
}

template <class T>
inline Vector3<T> Vector3<T>::Lerp(const Vector3<T>& a, const Vector3<T>& b, float t)
{
return Vector3<T>(t * (b.X - a.X) + a.X, t * (b.Y - a.Y) + a.Y, t * (b.Z - a.Z) + a.Z);
}

template <class T>
const Vector3<T> Vector3<T>::Zero(0, 0, 0);
template <class T>
Expand Down
19 changes: 11 additions & 8 deletions Sources/nCine/Primitives/Vector4.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ namespace nCine
Vector2<T> ToVector2() const;
Vector3<T> ToVector3() const;

template <class S>
friend S Dot(const Vector4<S>& v1, const Vector4<S>& v2);
static T Dot(const Vector4& v1, const Vector4& v2);
static Vector4 Lerp(const Vector4& a, const Vector4& b, float t);

/// A vector with all zero elements
static const Vector4 Zero;
Expand Down Expand Up @@ -377,13 +377,16 @@ namespace nCine
return Vector3<T>(X, Y, Z);
}

template <class S>
inline S Dot(const Vector4<S>& v1, const Vector4<S>& v2)
template <class T>
inline T Vector4<T>::Dot(const Vector4<T>& v1, const Vector4<T>& v2)
{
return static_cast<T>(v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z + v1.W * v2.W);
}

template <class T>
inline Vector4<T> Vector4<T>::Lerp(const Vector4<T>& a, const Vector4<T>& b, float t)
{
return static_cast<S>(v1.X * v2.X +
v1.Y * v2.Y +
v1.Z * v2.Z +
v1.W * v2.W);
return Vector4<T>(t * (b.X - a.X) + a.X, t * (b.Y - a.Y) + a.Y, t * (b.Z - a.Z) + a.Z, t * (b.W - a.W) + a.W);
}

template <class T>
Expand Down

0 comments on commit b9baad1

Please sign in to comment.