Skip to content

Commit a53af4e

Browse files
committed
spcap test and some comments;
optionally build pimpl in cmake
1 parent fe9b9ec commit a53af4e

File tree

6 files changed

+64
-23
lines changed

6 files changed

+64
-23
lines changed

CMakeLists.txt

+7-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ project(
1010
LANGUAGES CXX
1111
)
1212

13-
option(BUILD_SHARED_LIBS "Build shared lib" OFF) # broken in subproject but works with pimpl
13+
option(BUILD_SHARED_LIBS "Build shared lib" OFF)
14+
option(VAE_BUILD_PIMPL "Build PIMPL API" OFF)
1415
option(VAE_PROFILER "Use profiler" OFF)
1516
option(VAE_BACKEND_PORTAUDIO "Compile with port audio" OFF)
1617
option(VAE_BACKEND_RTAUDIO "Compile with RtAudio" ON)
@@ -25,7 +26,9 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
2526

2627
################# add main lib #################
2728

28-
file(GLOB PUBLIC_API "src/api/*.cpp")
29+
if (VAE_BUILD_PIMPL)
30+
file(GLOB PIMPL_API "src/api/*.cpp")
31+
endif()
2932
file(GLOB SRC_CORE "src/core/*.hpp")
3033
file(GLOB SRC_WRAPPED "src/wrapped/*.cpp")
3134
file(GLOB SRC_DEVICE "src/core/device/*.hpp")
@@ -37,7 +40,7 @@ if (BUILD_SHARED_LIBS)
3740
${SRC_CORE}
3841
${SRC_WRAPPED}
3942
${SRC_DEVICE}
40-
${PUBLIC_API}
43+
${PIMPL_API}
4144
)
4245
target_compile_definitions(
4346
vae
@@ -51,11 +54,10 @@ else()
5154
${SRC_CORE}
5255
${SRC_WRAPPED}
5356
${SRC_DEVICE}
54-
${PUBLIC_API}
57+
${PIMPL_API}
5558
)
5659
endif()
5760

58-
source_group("api" FILES ${PUBLIC_API})
5961
source_group("core" FILES ${SRC_CORE})
6062

6163
#Add an alias so that library can be used inside the build tree, e.g. when testing

example/pimpl/compiletime.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#include "../../include/vae/vae_pimpl.hpp"
22
#include <chrono>
33
#include <thread>
4+
45
int main() {
56
auto e = vae::EnginePimpl::create();
67
e->start();
78
std::this_thread::sleep_for(std::chrono::duration<double, std::milli>(4000));
8-
e->stop();
9+
e->stop(); // stopping is optional
910
e->destroy();
1011
return 0;
1112
}

src/core/algo/vae_spcap.hpp

+33-14
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,38 @@
66

77
namespace vae { namespace core {
88
/**
9-
* @brief Struct providing SPCAP configurations hard coded
9+
* @brief Struct containing SPCAP and preconfigured speaker setups
1010
*/
1111
struct SPCAP {
12+
/**
13+
* @brief Class handling SPCAP for arbitrary speaker setups
14+
* @tparam N Amount of speakers. Does not include LFE.
15+
*/
1216
template <int N>
1317
class SPCAPConfig {
1418
struct Speaker {
15-
Vec3 dir;
16-
Sample effective;
19+
Vec3 dir; // Position of the speaker on a unit sphere
20+
Sample effective; //
1721
};
1822
Speaker mSpeakers[N];
1923
public:
20-
SPCAPConfig(const std::initializer_list<Vec3>& directions) {
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) {
2131
int i = 0;
22-
for (const auto& speaker : directions) {
32+
for (const auto& speaker : positions) {
2333
mSpeakers[i] = { glm::normalize(speaker), Sample(0) };
2434
i++;
2535
}
2636
for (i = 0; i < N; i++) {
2737
for (int j = 0; j < N; j++) {
38+
// Calculate the effective number of speakers according to (2)
39+
// Can be done in adavnce and ideally at compiletime
40+
// since the positions of the speakers will not change
2841
mSpeakers[i].effective +=
2942
Sample(0.5) * (Sample(1.0) + glm::dot(mSpeakers[i].dir, mSpeakers[j].dir));
3043
}
@@ -41,32 +54,38 @@ namespace vae { namespace core {
4154
* @param attenuation Distance attenuation multiplied on the result
4255
* @param spread Value from 0-1 controlling "wideness" of the sound
4356
*/
44-
void pan(const Vec3& direction, Sample* result, Sample attenuation, Sample spread) const {
57+
void pan(const Vec3& direction, Sample result[N], Sample attenuation, Sample spread) const {
4558
VAE_PROFILER_SCOPE
4659
// TODO make spread change based on distance and use something like radius instead
47-
Sample sumSquaredGains = 0.0;
48-
const Sample tightness = (Sample(1) - spread) * Sample(10) + Sample(0.05);
60+
Sample sumGains = 0.0;
61+
// const Sample tightness = (Sample(1) - spread) * Sample(10) + Sample(0.05);
62+
const Sample tightness = 1.0;
4963
std::fill_n(result, N, Sample(0));
5064
for (int i = 0; i < N; i++) {
51-
Sample gain = Sample(0.5) * powf(Sample(1.0) + glm::dot(mSpeakers[i].dir, direction), tightness);
52-
gain /= mSpeakers[i].effective;
53-
gain = gain * gain;
65+
Sample gain = glm::dot(mSpeakers[i].dir, direction) + Sample(1.0); // (1)
66+
gain = powf(gain, tightness); // (9)
67+
gain *= Sample(0.5); // (1)
68+
gain /= mSpeakers[i].effective; // (3)
69+
gain = gain * gain; // (4)
5470
result[i] = gain;
55-
sumSquaredGains += gain;
71+
sumGains += gain; // (4)
5672
}
5773

5874
for (int i = 0; i < N; i++) {
59-
result[i] = sqrtf(result[i] / sumSquaredGains) * attenuation;
75+
result[i] = sqrtf(result[i] / sumGains) * attenuation; // (8)
6076
}
6177
}
6278
};
63-
// Initialized below because c++
79+
// Initialized below because c++ 14
6480
static const SPCAPConfig<2> HeadphoneSPCAP;
6581
static const SPCAPConfig<2> StereroSPCAP;
6682
static const SPCAPConfig<4> QuadSPCAP;
6783
static const SPCAPConfig<5> SuroundSPCAP;
6884
}; // SPCAP
6985

86+
/**
87+
* TODO there's probably a smart way to make this all constexpr
88+
*/
7089
const SPCAP::SPCAPConfig<2> SPCAP::HeadphoneSPCAP = {
7190
{ -1, 0, 0}, { +1, 0, 0} // LR Side
7291
};

src/core/device/vae_portaudio.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#include "../../../external/portaudio/include/portaudio.h"
99
#include "../../../external/portaudio/src/common/pa_debugprint.h"
10-
#include "util/TMath.hpp"
1110

1211
namespace vae { namespace core {
1312
/**

src/core/vae_util.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33

44
#include "../wrapped/vae_profiler.hpp"
55
#include "../../external/tklb/src/util/TAssert.h"
6+
#include "../../external/tklb/src/util/TMath.hpp"
67
#include "./vae_logger.hpp"
78
#include "../../include/vae/vae.hpp"
89

910
#define VAE_ASSERT(condition) TKLB_ASSERT(condition)
1011
namespace vae { namespace core {
11-
void splitGlobalEventHandle(
12+
inline void splitGlobalEventHandle(
1213
const GlobalEventHandle& handle,
1314
BankHandle& bank, EventHandle& event
1415
) {
15-
1616
bank = handle >> (sizeof(EventHandle) * 8);
1717
event = (handle & InvalidEventHandle);
1818
}

tests/tvae_spcap.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <stdio.h>
2+
#include <cmath>
3+
#include "../src/core/algo/vae_spcap.hpp"
4+
5+
6+
/**
7+
* @brief Test 5.1 panning setup and print volumes for each degree
8+
*/
9+
int main() {
10+
printf("deg,s1,s2,s3,s4,s5\n");
11+
for (int i = 0; i < 360; i++) {
12+
float t = i / float(180) * 3.14159265358979323846;
13+
vae::core::Sample p[5];
14+
vae::core::SPCAP::SuroundSPCAP.pan({
15+
sin(t), cos(t), 0
16+
}, p, 1, 0.5);
17+
printf("%i,%f,%f,%f,%f,%f\n", i, p[0], p[1], p[2], p[3], p[4]);
18+
}
19+
return 0;
20+
}

0 commit comments

Comments
 (0)