Merge pull request #37 from lioncash/emitter

Emitter: Use std::array where applicable
This commit is contained in:
Phillip Stephens 2019-09-08 00:10:40 -07:00 committed by GitHub
commit d88b14c38a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 63 additions and 58 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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); }

View File

@ -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];
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;