-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfloorreflectionprocessing.cpp
More file actions
134 lines (114 loc) · 4.33 KB
/
Copy pathfloorreflectionprocessing.cpp
File metadata and controls
134 lines (114 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* KFilter6
* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright (C) 2002-2026 Martin Erdtmann
*/
#include "floorreflectionprocessing.h"
#include "floorsurfacemodel.h"
#include <cmath>
namespace
{
constexpr double MillimetresPerMetre = 1000.0;
bool finiteNonNegative(double value)
{
return std::isfinite(value) && value >= 0.0;
}
bool transferEquivalent(const FloorReflectionSettings& left,
const FloorReflectionSettings& right,
double leftBaffleHeightMm,
double leftDriverYmm,
double rightBaffleHeightMm,
double rightDriverYmm)
{
if (left.enabled != right.enabled) {
return false;
}
// Disabled Floor Reflection is neutral regardless of retained placement
// metadata. Editing those values while disabled must not invalidate H_floor.
if (!left.enabled) {
return true;
}
return left.cabinetBottomAboveFloorMm == right.cabinetBottomAboveFloorMm &&
left.listenerHeightAboveFloorMm == right.listenerHeightAboveFloorMm &&
left.horizontalDistanceMm == right.horizontalDistanceMm &&
left.surfacePreset == right.surfacePreset &&
leftBaffleHeightMm == rightBaffleHeightMm &&
leftDriverYmm == rightDriverYmm;
}
FloorReflectionResponse invalidProductResponse()
{
FloorReflectionResponse response;
response.status = FloorReflectionResponseStatus::InvalidParameters;
return response;
}
}
FloorReflectionResponse calculateFloorReflectionProductResponse(
const FloorReflectionSettings& settings,
const BaffleSettings& baffleSettings)
{
if (!settings.enabled) {
return {};
}
if ((settings.surfacePreset != FloorSurfacePreset::HardRigid &&
settings.surfacePreset != FloorSurfacePreset::MikiReference10mm100k) ||
!finiteNonNegative(settings.cabinetBottomAboveFloorMm) ||
!finiteNonNegative(settings.listenerHeightAboveFloorMm) ||
!finiteNonNegative(settings.horizontalDistanceMm) ||
!std::isfinite(baffleSettings.heightMm) ||
!std::isfinite(baffleSettings.driverYmm) ||
baffleSettings.heightMm <= 0.0 ||
baffleSettings.driverYmm < 0.0 ||
baffleSettings.driverYmm > baffleSettings.heightMm) {
return invalidProductResponse();
}
const double sourceHeightMm = settings.cabinetBottomAboveFloorMm +
baffleSettings.heightMm -
baffleSettings.driverYmm;
if (!finiteNonNegative(sourceHeightMm)) {
return invalidProductResponse();
}
const FloorReflectionGeometry geometry{
sourceHeightMm / MillimetresPerMetre,
settings.listenerHeightAboveFloorMm / MillimetresPerMetre,
settings.horizontalDistanceMm / MillimetresPerMetre};
if (settings.surfacePreset == FloorSurfacePreset::HardRigid) {
return calculateIdealRigidFloorReflectionResponse(geometry);
}
return calculateFloorReflectionResponseWithSurfaceModel(
geometry,
mikiPorousRigidBackingDefinition(
KFilterMikiReferenceFloorThicknessM,
KFilterMikiReferenceFloorFlowResistivityPaSPerM2));
}
std::complex<double> applyFloorReflectionResponseSample(
const FloorReflectionResponse& response,
std::size_t sampleIndex,
const std::complex<double>& signal)
{
if (response.status != FloorReflectionResponseStatus::Valid ||
sampleIndex >= KFilterFrequencyCount) {
return signal;
}
return signal * response.values[sampleIndex];
}
const FloorReflectionResponse& FloorReflectionResponseCache::responseFor(
const FloorReflectionSettings& settings,
const BaffleSettings& baffleSettings)
{
if (!m_valid ||
!transferEquivalent(m_cachedSettings, settings,
m_cachedBaffleHeightMm, m_cachedDriverYmm,
baffleSettings.heightMm, baffleSettings.driverYmm)) {
m_response = calculateFloorReflectionProductResponse(settings, baffleSettings);
m_cachedSettings = settings;
m_cachedBaffleHeightMm = baffleSettings.heightMm;
m_cachedDriverYmm = baffleSettings.driverYmm;
m_valid = true;
++m_generation;
}
return m_response;
}
std::uint64_t FloorReflectionResponseCache::generation() const
{
return m_generation;
}