Emitter: Use std::array where applicable

Makes the data more strongly-typed and prevents implicit array->pointer
decay
This commit is contained in:
Lioncash 2019-09-07 20:19:47 -04:00
parent 0be0ca2911
commit 29e7d8bc1e
9 changed files with 63 additions and 58 deletions

View File

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
#include <list>
@ -39,7 +40,7 @@ public:
void resetSampleRate(double sampleRate) 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 start() override;
void stop() override;

View File

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <cfloat>
#include <cmath>
@ -10,9 +11,9 @@
namespace amuse {
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) {
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));
}
inline float Normalize(Vector3f& out) {
float dist = Length(out);
if (dist == 0.f)
return 0.f;
out[0] /= dist;
out[1] /= dist;
out[2] /= dist;
return dist;
inline Vector3f Normalize(const Vector3f& in) {
const float dist = Length(in);
if (dist == 0.f) {
return {};
}
return {in[0] / dist, in[1] / dist, in[2] / dist};
}
/** Voice wrapper with positional-3D level control */

View File

@ -1,5 +1,7 @@
#pragma once
#include <array>
namespace amuse {
class IBackendSubmix;
@ -34,7 +36,7 @@ public:
virtual void resetChannelLevels() = 0;
/** 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 */
virtual void setPitchRatio(double ratio, bool slew) = 0;

View File

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <cstdint>
#include <cstdlib>
#include <list>
@ -146,7 +147,7 @@ class Voice : public Entity {
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_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 */
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,
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 _setSurroundPan(float span);
void _setChannelCoefs(const float coefs[8]);
void _setChannelCoefs(const std::array<float, 8>& coefs);
void _setPitchWheel(float pitchWheel);
void _notifyCtrlChange(uint8_t ctrl, int8_t val);
@ -261,7 +262,7 @@ public:
void setSurroundPan(float span);
/** 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 */
void startEnvelope(double dur, float vol, const Curve* envCurve);

View File

@ -36,9 +36,9 @@ void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSamp
void BooBackendVoice::resetChannelLevels() { m_booVoice->resetChannelLevels(); }
void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) {
BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix);
m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs, slew);
void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const std::array<float, 8>& coefs, bool slew) {
auto& smx = *static_cast<BooBackendSubmix*>(submix);
m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs.data(), slew);
}
void BooBackendVoice::setPitchRatio(double ratio, bool slew) { m_booVoice->setPitchRatio(ratio, slew); }

View File

@ -5,14 +5,11 @@
#include "amuse/Voice.hpp"
namespace amuse {
static void Delta(Vector3f& out, const Vector3f& a, const Vector3f& b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
static constexpr Vector3f Delta(const Vector3f& a, const Vector3f& b) {
return {a[0] - b[0], a[1] - b[1], a[2] - b[2]};
}
Emitter::~Emitter() {}
Emitter::~Emitter() = default;
Emitter::Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, float maxDist, float minVol,
float falloff, bool doppler)
@ -54,12 +51,11 @@ void Emitter::_update() {
return;
}
float coefs[8] = {};
std::array<float, 8> coefs{};
double avgDopplerRatio = 0.0;
for (auto& listener : m_engine.m_activeListeners) {
Vector3f listenerToEmitter;
Delta(listenerToEmitter, m_pos, listener->m_pos);
const Vector3f listenerToEmitter = Delta(m_pos, listener->m_pos);
const float dist = Length(listenerToEmitter);
const float panDist = Dot(listenerToEmitter, listener->m_right);
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);
if (att > FLT_EPSILON) {
/* Apply pan law */
float thisCoefs[8] = {};
m_vox->_panLaw(thisCoefs, frontPan, backPan, span);
const std::array<float, 8> thisCoefs = m_vox->_panLaw(frontPan, backPan, span);
/* 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);
}
}
/* Calculate doppler */
if (m_doppler) {
/* Positive values indicate emitter and listener closing in */
Vector3f dirDelta;
Delta(dirDelta, m_dir, listener->m_dir);
Vector3f posDelta;
Delta(posDelta, listener->m_pos, m_pos);
Normalize(posDelta);
float deltaSpeed = Dot(dirDelta, posDelta);
if (listener->m_soundSpeed != 0.f)
const Vector3f dirDelta = Delta(m_dir, listener->m_dir);
const Vector3f posDelta = Normalize(Delta(listener->m_pos, m_pos));
const float deltaSpeed = Dot(dirDelta, posDelta);
if (listener->m_soundSpeed != 0.f) {
avgDopplerRatio += 1.0 + deltaSpeed / listener->m_soundSpeed;
else
} else {
avgDopplerRatio += 1.0;
}
}
}
if (m_engine.m_activeListeners.size() != 0) {
m_vox->setChannelCoefs(coefs);
@ -110,7 +104,7 @@ void Emitter::_update() {
}
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_dir[i] = dir[i];
}

View File

@ -1,5 +1,7 @@
#include "amuse/Engine.hpp"
#include <array>
#include "amuse/AudioGroup.hpp"
#include "amuse/AudioGroupData.hpp"
#include "amuse/Common.hpp"
@ -11,7 +13,7 @@
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() {
m_backend.setCallbackInterface(nullptr);

View File

@ -2,10 +2,12 @@
namespace amuse {
static void Cross(Vector3f& out, const Vector3f& a, const Vector3f& b) {
out[0] = a[1] * b[2] - a[2] * b[1];
out[1] = a[2] * b[0] - a[0] * b[2];
out[2] = a[0] * b[1] - a[1] * b[0];
static constexpr Vector3f Cross(const Vector3f& a, const Vector3f& b) {
return {
a[1] * b[2] - a[2] * b[1],
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) {
@ -16,11 +18,9 @@ void Listener::setVectors(const float* pos, const float* dir, const float* headi
m_up[i] = up[i];
}
Normalize(m_heading);
Normalize(m_up);
Cross(m_right, m_heading, m_up);
Normalize(m_right);
m_heading = Normalize(m_heading);
m_up = Normalize(m_up);
m_right = Normalize(Cross(m_heading, m_up));
m_dirty = true;
}

View File

@ -155,10 +155,11 @@ ObjToken<Voice> Voice::_findVoice(int vid, ObjToken<Voice> thisPtr) {
}
std::unique_ptr<int8_t[]>& Voice::_ensureCtrlVals() {
if (m_ctrlValsSelf)
if (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;
}
@ -902,7 +903,9 @@ void Voice::setVolume(float 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 */
switch (m_engine.m_channelSet) {
case AudioChannelSet::Stereo:
@ -1010,6 +1013,8 @@ void Voice::_panLaw(float coefs[8], float frontPan, float backPan, float totalSp
break;
}
return coefs;
}
void Voice::_setPan(float pan) {
@ -1020,8 +1025,7 @@ void Voice::_setPan(float pan) {
m_curPan = std::clamp(pan, -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);
float coefs[8] = {};
_panLaw(coefs, totalPan, totalPan, totalSpan);
const auto coefs = _panLaw(totalPan, totalPan, totalSpan);
_setChannelCoefs(coefs);
}
@ -1048,13 +1052,13 @@ void Voice::setSurroundPan(float 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->getAuxA().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)
return;