mirror of https://github.com/AxioDL/amuse.git
Emitter: Use std::array where applicable
Makes the data more strongly-typed and prevents implicit array->pointer decay
This commit is contained in:
parent
0be0ca2911
commit
29e7d8bc1e
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -39,7 +40,7 @@ public:
|
||||||
void resetSampleRate(double sampleRate) override;
|
void resetSampleRate(double sampleRate) override;
|
||||||
|
|
||||||
void resetChannelLevels() override;
|
void resetChannelLevels() override;
|
||||||
void setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) override;
|
void setChannelLevels(IBackendSubmix* submix, const std::array<float, 8>& coefs, bool slew) override;
|
||||||
void setPitchRatio(double ratio, bool slew) override;
|
void setPitchRatio(double ratio, bool slew) override;
|
||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -10,9 +11,9 @@
|
||||||
namespace amuse {
|
namespace amuse {
|
||||||
class Listener;
|
class Listener;
|
||||||
|
|
||||||
using Vector3f = float[3];
|
using Vector3f = std::array<float, 3>;
|
||||||
|
|
||||||
inline float Dot(const Vector3f& a, const Vector3f& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
|
constexpr float Dot(const Vector3f& a, const Vector3f& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
|
||||||
|
|
||||||
inline float Length(const Vector3f& a) {
|
inline float Length(const Vector3f& a) {
|
||||||
if (std::fabs(a[0]) <= FLT_EPSILON && std::fabs(a[1]) <= FLT_EPSILON && std::fabs(a[2]) <= FLT_EPSILON)
|
if (std::fabs(a[0]) <= FLT_EPSILON && std::fabs(a[1]) <= FLT_EPSILON && std::fabs(a[2]) <= FLT_EPSILON)
|
||||||
|
@ -20,14 +21,14 @@ inline float Length(const Vector3f& a) {
|
||||||
return std::sqrt(Dot(a, a));
|
return std::sqrt(Dot(a, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float Normalize(Vector3f& out) {
|
inline Vector3f Normalize(const Vector3f& in) {
|
||||||
float dist = Length(out);
|
const float dist = Length(in);
|
||||||
if (dist == 0.f)
|
|
||||||
return 0.f;
|
if (dist == 0.f) {
|
||||||
out[0] /= dist;
|
return {};
|
||||||
out[1] /= dist;
|
}
|
||||||
out[2] /= dist;
|
|
||||||
return dist;
|
return {in[0] / dist, in[1] / dist, in[2] / dist};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Voice wrapper with positional-3D level control */
|
/** Voice wrapper with positional-3D level control */
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace amuse {
|
namespace amuse {
|
||||||
class IBackendSubmix;
|
class IBackendSubmix;
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ public:
|
||||||
virtual void resetChannelLevels() = 0;
|
virtual void resetChannelLevels() = 0;
|
||||||
|
|
||||||
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
||||||
virtual void setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) = 0;
|
virtual void setChannelLevels(IBackendSubmix* submix, const std::array<float, 8>& coefs, bool slew) = 0;
|
||||||
|
|
||||||
/** Called by client to dynamically adjust the pitch of voices with dynamic pitch enabled */
|
/** Called by client to dynamically adjust the pitch of voices with dynamic pitch enabled */
|
||||||
virtual void setPitchRatio(double ratio, bool slew) = 0;
|
virtual void setPitchRatio(double ratio, bool slew) = 0;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -146,7 +147,7 @@ class Voice : public Entity {
|
||||||
float m_tremoloScale = 0.f; /**< minimum volume factor produced via LFO */
|
float m_tremoloScale = 0.f; /**< minimum volume factor produced via LFO */
|
||||||
float m_tremoloModScale = 0.f; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
float m_tremoloModScale = 0.f; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
||||||
|
|
||||||
float m_lfoPeriods[2] = {}; /**< time-periods for LFO1 and LFO2 */
|
std::array<float, 2> m_lfoPeriods{}; /**< time-periods for LFO1 and LFO2 */
|
||||||
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
||||||
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
||||||
|
|
||||||
|
@ -186,10 +187,10 @@ class Voice : public Entity {
|
||||||
ObjToken<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
|
ObjToken<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
|
||||||
uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
||||||
|
|
||||||
void _panLaw(float coefsOut[8], float frontPan, float backPan, float totalSpan) const;
|
std::array<float, 8> _panLaw(float frontPan, float backPan, float totalSpan) const;
|
||||||
void _setPan(float pan);
|
void _setPan(float pan);
|
||||||
void _setSurroundPan(float span);
|
void _setSurroundPan(float span);
|
||||||
void _setChannelCoefs(const float coefs[8]);
|
void _setChannelCoefs(const std::array<float, 8>& coefs);
|
||||||
void _setPitchWheel(float pitchWheel);
|
void _setPitchWheel(float pitchWheel);
|
||||||
void _notifyCtrlChange(uint8_t ctrl, int8_t val);
|
void _notifyCtrlChange(uint8_t ctrl, int8_t val);
|
||||||
|
|
||||||
|
@ -261,7 +262,7 @@ public:
|
||||||
void setSurroundPan(float span);
|
void setSurroundPan(float span);
|
||||||
|
|
||||||
/** Set current voice channel coefficients immediately */
|
/** Set current voice channel coefficients immediately */
|
||||||
void setChannelCoefs(const float coefs[8]);
|
void setChannelCoefs(const std::array<float, 8>& coefs);
|
||||||
|
|
||||||
/** Start volume envelope to specified level */
|
/** Start volume envelope to specified level */
|
||||||
void startEnvelope(double dur, float vol, const Curve* envCurve);
|
void startEnvelope(double dur, float vol, const Curve* envCurve);
|
||||||
|
|
|
@ -36,9 +36,9 @@ void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSamp
|
||||||
|
|
||||||
void BooBackendVoice::resetChannelLevels() { m_booVoice->resetChannelLevels(); }
|
void BooBackendVoice::resetChannelLevels() { m_booVoice->resetChannelLevels(); }
|
||||||
|
|
||||||
void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) {
|
void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const std::array<float, 8>& coefs, bool slew) {
|
||||||
BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix);
|
auto& smx = *static_cast<BooBackendSubmix*>(submix);
|
||||||
m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs, slew);
|
m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs.data(), slew);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BooBackendVoice::setPitchRatio(double ratio, bool slew) { m_booVoice->setPitchRatio(ratio, slew); }
|
void BooBackendVoice::setPitchRatio(double ratio, bool slew) { m_booVoice->setPitchRatio(ratio, slew); }
|
||||||
|
|
|
@ -5,14 +5,11 @@
|
||||||
#include "amuse/Voice.hpp"
|
#include "amuse/Voice.hpp"
|
||||||
|
|
||||||
namespace amuse {
|
namespace amuse {
|
||||||
|
static constexpr Vector3f Delta(const Vector3f& a, const Vector3f& b) {
|
||||||
static void Delta(Vector3f& out, const Vector3f& a, const Vector3f& b) {
|
return {a[0] - b[0], a[1] - b[1], a[2] - b[2]};
|
||||||
out[0] = a[0] - b[0];
|
|
||||||
out[1] = a[1] - b[1];
|
|
||||||
out[2] = a[2] - b[2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter::~Emitter() {}
|
Emitter::~Emitter() = default;
|
||||||
|
|
||||||
Emitter::Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, float maxDist, float minVol,
|
Emitter::Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, float maxDist, float minVol,
|
||||||
float falloff, bool doppler)
|
float falloff, bool doppler)
|
||||||
|
@ -54,12 +51,11 @@ void Emitter::_update() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float coefs[8] = {};
|
std::array<float, 8> coefs{};
|
||||||
double avgDopplerRatio = 0.0;
|
double avgDopplerRatio = 0.0;
|
||||||
|
|
||||||
for (auto& listener : m_engine.m_activeListeners) {
|
for (auto& listener : m_engine.m_activeListeners) {
|
||||||
Vector3f listenerToEmitter;
|
const Vector3f listenerToEmitter = Delta(m_pos, listener->m_pos);
|
||||||
Delta(listenerToEmitter, m_pos, listener->m_pos);
|
|
||||||
const float dist = Length(listenerToEmitter);
|
const float dist = Length(listenerToEmitter);
|
||||||
const float panDist = Dot(listenerToEmitter, listener->m_right);
|
const float panDist = Dot(listenerToEmitter, listener->m_right);
|
||||||
const float frontPan = std::clamp(panDist / listener->m_frontDiff, -1.f, 1.f);
|
const float frontPan = std::clamp(panDist / listener->m_frontDiff, -1.f, 1.f);
|
||||||
|
@ -74,29 +70,27 @@ void Emitter::_update() {
|
||||||
att = m_attCache.getVolume(att, false);
|
att = m_attCache.getVolume(att, false);
|
||||||
if (att > FLT_EPSILON) {
|
if (att > FLT_EPSILON) {
|
||||||
/* Apply pan law */
|
/* Apply pan law */
|
||||||
float thisCoefs[8] = {};
|
const std::array<float, 8> thisCoefs = m_vox->_panLaw(frontPan, backPan, span);
|
||||||
m_vox->_panLaw(thisCoefs, frontPan, backPan, span);
|
|
||||||
|
|
||||||
/* Take maximum coefficient across listeners */
|
/* Take maximum coefficient across listeners */
|
||||||
for (int i = 0; i < 8; ++i)
|
for (size_t i = 0; i < coefs.size(); ++i) {
|
||||||
coefs[i] = std::max(coefs[i], thisCoefs[i] * att * listener->m_volume);
|
coefs[i] = std::max(coefs[i], thisCoefs[i] * att * listener->m_volume);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate doppler */
|
/* Calculate doppler */
|
||||||
if (m_doppler) {
|
if (m_doppler) {
|
||||||
/* Positive values indicate emitter and listener closing in */
|
/* Positive values indicate emitter and listener closing in */
|
||||||
Vector3f dirDelta;
|
const Vector3f dirDelta = Delta(m_dir, listener->m_dir);
|
||||||
Delta(dirDelta, m_dir, listener->m_dir);
|
const Vector3f posDelta = Normalize(Delta(listener->m_pos, m_pos));
|
||||||
Vector3f posDelta;
|
const float deltaSpeed = Dot(dirDelta, posDelta);
|
||||||
Delta(posDelta, listener->m_pos, m_pos);
|
if (listener->m_soundSpeed != 0.f) {
|
||||||
Normalize(posDelta);
|
|
||||||
float deltaSpeed = Dot(dirDelta, posDelta);
|
|
||||||
if (listener->m_soundSpeed != 0.f)
|
|
||||||
avgDopplerRatio += 1.0 + deltaSpeed / listener->m_soundSpeed;
|
avgDopplerRatio += 1.0 + deltaSpeed / listener->m_soundSpeed;
|
||||||
else
|
} else {
|
||||||
avgDopplerRatio += 1.0;
|
avgDopplerRatio += 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_engine.m_activeListeners.size() != 0) {
|
if (m_engine.m_activeListeners.size() != 0) {
|
||||||
m_vox->setChannelCoefs(coefs);
|
m_vox->setChannelCoefs(coefs);
|
||||||
|
@ -110,7 +104,7 @@ void Emitter::_update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emitter::setVectors(const float* pos, const float* dir) {
|
void Emitter::setVectors(const float* pos, const float* dir) {
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < m_pos.size(); ++i) {
|
||||||
m_pos[i] = pos[i];
|
m_pos[i] = pos[i];
|
||||||
m_dir[i] = dir[i];
|
m_dir[i] = dir[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "amuse/Engine.hpp"
|
#include "amuse/Engine.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "amuse/AudioGroup.hpp"
|
#include "amuse/AudioGroup.hpp"
|
||||||
#include "amuse/AudioGroupData.hpp"
|
#include "amuse/AudioGroupData.hpp"
|
||||||
#include "amuse/Common.hpp"
|
#include "amuse/Common.hpp"
|
||||||
|
@ -11,7 +13,7 @@
|
||||||
|
|
||||||
namespace amuse {
|
namespace amuse {
|
||||||
|
|
||||||
static const float FullLevels[8] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
|
constexpr std::array<float, 8> FullLevels{1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
|
||||||
|
|
||||||
Engine::~Engine() {
|
Engine::~Engine() {
|
||||||
m_backend.setCallbackInterface(nullptr);
|
m_backend.setCallbackInterface(nullptr);
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
namespace amuse {
|
namespace amuse {
|
||||||
|
|
||||||
static void Cross(Vector3f& out, const Vector3f& a, const Vector3f& b) {
|
static constexpr Vector3f Cross(const Vector3f& a, const Vector3f& b) {
|
||||||
out[0] = a[1] * b[2] - a[2] * b[1];
|
return {
|
||||||
out[1] = a[2] * b[0] - a[0] * b[2];
|
a[1] * b[2] - a[2] * b[1],
|
||||||
out[2] = a[0] * b[1] - a[1] * b[0];
|
a[2] * b[0] - a[0] * b[2],
|
||||||
|
a[0] * b[1] - a[1] * b[0],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Listener::setVectors(const float* pos, const float* dir, const float* heading, const float* up) {
|
void Listener::setVectors(const float* pos, const float* dir, const float* heading, const float* up) {
|
||||||
|
@ -16,11 +18,9 @@ void Listener::setVectors(const float* pos, const float* dir, const float* headi
|
||||||
m_up[i] = up[i];
|
m_up[i] = up[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Normalize(m_heading);
|
m_heading = Normalize(m_heading);
|
||||||
Normalize(m_up);
|
m_up = Normalize(m_up);
|
||||||
Cross(m_right, m_heading, m_up);
|
m_right = Normalize(Cross(m_heading, m_up));
|
||||||
Normalize(m_right);
|
|
||||||
|
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,10 +155,11 @@ ObjToken<Voice> Voice::_findVoice(int vid, ObjToken<Voice> thisPtr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<int8_t[]>& Voice::_ensureCtrlVals() {
|
std::unique_ptr<int8_t[]>& Voice::_ensureCtrlVals() {
|
||||||
if (m_ctrlValsSelf)
|
if (m_ctrlValsSelf) {
|
||||||
return m_ctrlValsSelf;
|
return m_ctrlValsSelf;
|
||||||
m_ctrlValsSelf.reset(new int8_t[128]);
|
}
|
||||||
memset(m_ctrlValsSelf.get(), 0, 128);
|
|
||||||
|
m_ctrlValsSelf = std::make_unique<int8_t[]>(128);
|
||||||
return m_ctrlValsSelf;
|
return m_ctrlValsSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,7 +903,9 @@ void Voice::setVolume(float vol) {
|
||||||
vox->setVolume(vol);
|
vox->setVolume(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_panLaw(float coefs[8], float frontPan, float backPan, float totalSpan) const {
|
std::array<float, 8> Voice::_panLaw(float frontPan, float backPan, float totalSpan) const {
|
||||||
|
std::array<float, 8> coefs{};
|
||||||
|
|
||||||
/* -3dB panning law for various channel configs */
|
/* -3dB panning law for various channel configs */
|
||||||
switch (m_engine.m_channelSet) {
|
switch (m_engine.m_channelSet) {
|
||||||
case AudioChannelSet::Stereo:
|
case AudioChannelSet::Stereo:
|
||||||
|
@ -1010,6 +1013,8 @@ void Voice::_panLaw(float coefs[8], float frontPan, float backPan, float totalSp
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return coefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_setPan(float pan) {
|
void Voice::_setPan(float pan) {
|
||||||
|
@ -1020,8 +1025,7 @@ void Voice::_setPan(float pan) {
|
||||||
m_curPan = std::clamp(pan, -1.f, 1.f);
|
m_curPan = std::clamp(pan, -1.f, 1.f);
|
||||||
const float totalPan = std::clamp(m_curPan, -1.f, 1.f);
|
const float totalPan = std::clamp(m_curPan, -1.f, 1.f);
|
||||||
const float totalSpan = std::clamp(m_curSpan, -1.f, 1.f);
|
const float totalSpan = std::clamp(m_curSpan, -1.f, 1.f);
|
||||||
float coefs[8] = {};
|
const auto coefs = _panLaw(totalPan, totalPan, totalSpan);
|
||||||
_panLaw(coefs, totalPan, totalPan, totalSpan);
|
|
||||||
_setChannelCoefs(coefs);
|
_setChannelCoefs(coefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,13 +1052,13 @@ void Voice::setSurroundPan(float span) {
|
||||||
vox->setSurroundPan(span);
|
vox->setSurroundPan(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_setChannelCoefs(const float coefs[8]) {
|
void Voice::_setChannelCoefs(const std::array<float, 8>& coefs) {
|
||||||
m_backendVoice->setChannelLevels(m_studio->getMaster().m_backendSubmix.get(), coefs, true);
|
m_backendVoice->setChannelLevels(m_studio->getMaster().m_backendSubmix.get(), coefs, true);
|
||||||
m_backendVoice->setChannelLevels(m_studio->getAuxA().m_backendSubmix.get(), coefs, true);
|
m_backendVoice->setChannelLevels(m_studio->getAuxA().m_backendSubmix.get(), coefs, true);
|
||||||
m_backendVoice->setChannelLevels(m_studio->getAuxB().m_backendSubmix.get(), coefs, true);
|
m_backendVoice->setChannelLevels(m_studio->getAuxB().m_backendSubmix.get(), coefs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::setChannelCoefs(const float coefs[8]) {
|
void Voice::setChannelCoefs(const std::array<float, 8>& coefs) {
|
||||||
if (m_destroyed)
|
if (m_destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue