VAE - Virtual Audio Engine 1
Small Data Driven Audio Engine
vae_spcap.hpp
Go to the documentation of this file.
1#ifndef _VAE_SPCAP
2#define _VAE_SPCAP
3
4#include "../vae_types.hpp"
5#include "../vae_util.hpp"
6
7namespace vae { namespace core {
8 /**
9 * @brief Struct containing SPCAP and preconfigured speaker setups
10 */
11 struct SPCAP {
12 /**
13 * @brief Class handling SPCAP for arbitrary speaker setups
14 * @tparam N Amount of speakers. Does not include LFE.
15 */
16 template <Size N>
18 struct Speaker {
19 Vec3 dir; ///< Position of the speaker on a unit sphere
21 };
23 public:
24 /**
25 * @brief Construct a new SPCAPConfig object
26 * Implemented according to
27 * https://www.researchgate.net/publication/235080603_A_Novel_Multichannel_Panning_Method_for_Standard_and_Arbitrary_Loudspeaker_Configurations
28 * @param positions Speaker positions, will be normalized.
29 */
30 SPCAPConfig(const std::initializer_list<Vec3>& positions) {
31 Size i = 0;
32 for (const auto& speaker : positions) {
33 mSpeakers[i] = { glm::normalize(speaker), Sample(0) };
34 i++;
35 }
36 for (i = 0; i < N; i++) {
37 for (Size j = 0; j < N; j++) {
38 // Calculate the effective number of speakers according to (2)
39 // Can be done in advance and ideally at compiletime
40 // since the positions of the speakers will not change
42 Sample(0.5) * (Sample(1.0) + glm::dot(mSpeakers[i].dir, mSpeakers[j].dir));
43 }
44 }
45 }
46
47 static constexpr Size speakers = N;
48
49
50 /**
51 * @brief Calculate per channel volumes for a given direction
52 *
53 * @param direction The relative and normalized direction
54 * @param result Result array of channel volumes
55 * @param attenuation Distance attenuation multiplied on the result
56 * @param spread Value from 0-1 controlling "wideness" of the sound
57 */
58 inline void pan(const Vec3& direction, Sample result[N], Sample attenuation, Sample spread) const {
59 VAE_PROFILER_SCOPE_NAMED("SPCAP Pan")
60 // TODO make spread change based on distance and use something like radius instead
61 Sample sumGains = 0.0;
62 // const Sample tightness = (Sample(1) - spread) * Sample(10) + Sample(0.05);
63 const Sample tightness = 1.0;
64 std::fill_n(result, N, Sample(0));
65 for (Size i = 0; i < N; i++) {
66 Sample gain = glm::dot(mSpeakers[i].dir, direction) + Sample(1.0); // (1)
67 gain = powf(gain, tightness); // (9)
68 gain *= Sample(0.5); // (1)
69 gain /= mSpeakers[i].effective; // (3)
70 gain = gain * gain; // (4)
71 result[i] = gain;
72 sumGains += gain; // (4)
73 }
74
75 for (Size i = 0; i < N; i++) {
76 result[i] = sqrtf(result[i] / sumGains) * attenuation; // (8)
77 }
78 }
79 };
80
81 // Initialized below because c++ 14
87 }; // SPCAP
88
89 /**
90 * TODO there's probably a smart way to make this all constexpr
91 */
92
94 { 0, 0, -1 } // Center
95 };
96 const SPCAP::SPCAPConfig<2> SPCAP::HeadphoneSPCAP = {
97 { -1, 0, 0 }, { +1, 0, 0 } // LR Side
98 };
99 const SPCAP::SPCAPConfig<2> SPCAP::StereroSPCAP = {
100 { -1, 0, -1 }, { +1, 0, -1 } // LR Front
101 };
102 const SPCAP::SPCAPConfig<4> SPCAP::QuadSPCAP = {
103 { -1, 0, -1 }, { +1, 0, -1 }, // LR Front
104 { -1, 0, +1 }, { +1, 0, +1 } // LR Back
105 };
106 const SPCAP::SPCAPConfig<5> SPCAP::SuroundSPCAP = {
107 { -1, 0, -1 }, { +1, 0, -1 }, // LR Front
108 { -1, 0, +1 }, { +1, 0, +1 }, // LR Back
109 { 0, 0, -1 } // Center
110 };
111} } // core::vae
112
113#endif // _VAE_SPCAP
Class handling SPCAP for arbitrary speaker setups.
Definition: vae_spcap.hpp:17
void pan(const Vec3 &direction, Sample result[N], Sample attenuation, Sample spread) const
Calculate per channel volumes for a given direction.
Definition: vae_spcap.hpp:58
SPCAPConfig(const std::initializer_list< Vec3 > &positions)
Construct a new SPCAPConfig object Implemented according to https://www.researchgate....
Definition: vae_spcap.hpp:30
static constexpr Size speakers
Definition: vae_spcap.hpp:47
glm::vec3 Vec3
Definition: vae_types.hpp:47
Contains Typedefinitions and basic structures use by the public API and internally.
Definition: vae.hpp:31
unsigned int Size
How the elements are addressed in the heapbuffer.
Definition: vae.hpp:33
float Sample
Default sample types used where ever possible, changing this means the engine needs to be recompiled,...
Definition: vae.hpp:32
Vec3 dir
Position of the speaker on a unit sphere.
Definition: vae_spcap.hpp:19
Struct containing SPCAP and preconfigured speaker setups.
Definition: vae_spcap.hpp:11
static const SPCAPConfig< 2 > StereroSPCAP
Definition: vae_spcap.hpp:84
static const SPCAPConfig< 1 > MonoSPCAP
TODO there's probably a smart way to make this all constexpr.
Definition: vae_spcap.hpp:82
static const SPCAPConfig< 4 > QuadSPCAP
Definition: vae_spcap.hpp:85
static const SPCAPConfig< 5 > SuroundSPCAP
Definition: vae_spcap.hpp:86
static const SPCAPConfig< 2 > HeadphoneSPCAP
Definition: vae_spcap.hpp:83
#define VAE_PROFILER_SCOPE_NAMED(name)
Profiles a scope and names it.