3 #include "core/geo/triangle_vec.h" 4 #include "core/scene_data.h" 6 #include "utilities/aligned/set.h" 22 template <
typename Vertex,
typename Surface>
23 double area(
const generic_scene_data<Vertex, Surface>& scene,
24 size_t surface_index) {
28 return std::accumulate(
29 begin(scene.get_triangles()),
30 end(scene.get_triangles()),
32 [&](
auto running_total,
auto tri) {
33 return running_total +
34 (tri.surface == surface_index
35 ? geo::area(geo::get_triangle_vec3(
36 tri, scene.get_vertices().data()))
42 template <
typename Vertex,
typename Surface>
43 double area(
const generic_scene_data<Vertex, Surface>& scene) {
45 return std::accumulate(
46 begin(scene.get_triangles()),
47 end(scene.get_triangles()),
49 [&](
auto running_total,
auto tri) {
50 return running_total +
51 geo::area(geo::get_triangle_vec3(
52 tri, scene.get_vertices().data()));
58 template <
typename Vertex,
typename Surface>
59 auto absorption_area(
const generic_scene_data<Vertex, Surface>& scene,
60 size_t surface_index) {
61 return scene.get_surfaces()[surface_index].absorption *
62 area(scene, surface_index);
66 template <
typename Vertex,
typename Surface>
67 auto equivalent_absorption_area(
68 const generic_scene_data<Vertex, Surface>& scene) {
69 const auto num_surfaces = scene.get_surfaces().size();
70 decltype(absorption_area(scene, 0)) running_total{};
71 for (
auto i = 0u; i != num_surfaces; ++i) {
72 running_total += absorption_area(scene, i);
79 std::array<std::pair<cl_uint, cl_uint>, 3> get_index_pairs(
const triangle& t);
82 template <
typename It>
83 bool triangles_are_oriented(It begin, It end) {
86 util::aligned::set<std::pair<cl_uint, cl_uint>> table;
89 for (; begin != end; ++begin) {
91 for (
const auto& pair : get_index_pairs(*begin)) {
93 if (!table.insert(pair).second) {
103 float six_times_tetrahedron_volume(
const geo::triangle_vec3& t);
106 template <
typename Vertex,
typename Surface>
107 float estimate_room_volume(
const generic_scene_data<Vertex, Surface>& scene) {
108 return std::abs(std::accumulate(
109 begin(scene.get_triangles()),
110 end(scene.get_triangles()),
112 [&](
auto running_total,
auto tri) {
113 return running_total +
114 six_times_tetrahedron_volume(
115 geo::get_triangle_vec3(
117 scene.get_vertices().data()));
125 float estimate_air_intensity_absorption(
float frequency,
float humidity);
127 template <
size_t... Ix>
128 auto estimate_air_intensity_absorption(
129 const std::array<
float,
sizeof...(Ix)>& band_centres,
131 std::index_sequence<Ix...>) {
132 return std::array<float,
sizeof...(Ix)>{{estimate_air_intensity_absorption(
133 std::get<Ix>(band_centres), humidity)...}};
136 template <
size_t Bands>
137 auto estimate_air_intensity_absorption(
138 const std::array<float, Bands>& band_centres,
float humidity) {
139 return estimate_air_intensity_absorption(
140 band_centres, humidity, std::make_index_sequence<Bands>{});
147 template <
typename Absorption,
typename Coeff>
148 auto sabine_reverb_time(
double room_volume,
149 Absorption absorption_area,
150 Coeff air_coefficient) {
151 if (room_volume <= 0) {
152 throw std::runtime_error{
"Room volume is non-positive"};
154 if (any(absorption_area <= 0)) {
155 throw std::runtime_error{
"Absorption area is non-positive"};
158 const auto numerator = 0.161f * room_volume;
159 const auto denominator =
160 absorption_area + (4 * room_volume * air_coefficient);
161 return numerator / denominator;
166 template <
typename Vertex,
typename Surface,
typename Coeff>
167 auto sabine_reverb_time(
const generic_scene_data<Vertex, Surface>& scene,
168 Coeff air_coefficient) {
169 return sabine_reverb_time(estimate_room_volume(scene),
170 equivalent_absorption_area(scene),
174 template <
typename Absorption,
typename Coeff>
175 auto eyring_reverb_time(
double room_volume,
176 Absorption absorption_area,
178 Coeff air_coefficient) {
179 if (room_volume <= 0) {
180 throw std::runtime_error{
"Room volume is non-positive"};
182 if (any(absorption_area <= 0)) {
183 throw std::runtime_error{
"Absorption area is non-positive"};
186 const auto numerator = 0.161f * room_volume;
187 const auto denominator =
188 -full_area * log(1 - (absorption_area / full_area)) +
189 (4 * room_volume * air_coefficient);
190 return numerator / denominator;
194 template <
typename Vertex,
typename Surface,
typename Coeff>
195 auto eyring_reverb_time(
const generic_scene_data<Vertex, Surface>& scene,
196 Coeff air_coefficient) {
197 return eyring_reverb_time(estimate_room_volume(scene),
198 equivalent_absorption_area(scene),
Definition: capsule_base.h:9