JPL Spatial
Sound spatialization and propagation library
Loading...
Searching...
No Matches
FrequencyBands.h
Go to the documentation of this file.
1//
2// ██╗██████╗ ██╗ ██╗██████╗ ███████╗
3// ██║██╔══██╗ ██║ ██║██╔══██╗██╔════╝ ** JPL Spatial **
4// ██║██████╔╝ ██║ ██║██████╔╝███████╗
5// ██ ██║██╔═══╝ ██║ ██║██╔══██╗╚════██║ https://github.com/Jaytheway/JPLSpatial
6// ╚█████╔╝██║ ███████╗██║██████╔╝███████║
7// ╚════╝ ╚═╝ ╚══════╝╚═╝╚═════╝ ╚══════╝
8//
9// Copyright 2026 Jaroslav Pevno, JPL Spatial is offered under the terms of the ISC license:
10//
11// Permission to use, copy, modify, and/or distribute this software for any purpose with or
12// without fee is hereby granted, provided that the above copyright notice and this permission
13// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
16// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#pragma once
21
22#include "JPLSpatial/Core.h"
26
27#include <algorithm>
28#include <array>
29#include <span>
30#include <ranges>
31
32namespace JPL
33{
36
37 //======================================================================
38 // Currently we simulate propagation in 4 frequency bands:
39 // 20-176 Hz, 176-775 Hz, 775-3408 Hz, and 3408-22050 Hz
40 // ..or as center frequencies: 59 Hz, 369 Hz, 1625 Hz, 8669 Hz
42
43 //======================================================================
46 {
47 float F1 = 176.0f, F2 = 775.0f, F3 = 3408.0f;
48
49 [[nodiscard]] constexpr bool operator==(const SplitFrequencies&) const noexcept = default;
50 };
51
53 inline constexpr SplitFrequencies cDefaultFrequencySplits{ .F1 = 176.0f, .F2 = 775.0f, .F3 = 3408.0f };
54
55 //======================================================================
56 [[nodiscard]] JPL_INLINE FreqBandCenters ComputeBandCenters(const SplitFrequencies& splitFrequenciesHz, float nyquist = 22050.0f)
57 {
58 const simd lowerEdge(20.0f, splitFrequenciesHz.F1, splitFrequenciesHz.F2, splitFrequenciesHz.F3);
59 const simd upperEdge(splitFrequenciesHz.F1, splitFrequenciesHz.F2, splitFrequenciesHz.F3, nyquist);
60 return Math::Sqrt(lowerEdge * upperEdge);
61 }
62
63 template<std::floating_point T, std::size_t N> requires(N != std::dynamic_extent)
64 [[nodiscard]] JPL_INLINE std::array<T, N + 1> ComputeBandCenters(std::span<const T, N> splitFrequenciesHz, T nyquist = T(22050.0))
65 {
66 std::array<T, N + 1> centers{ T(20.0) }; // init first element as lower bound frequency
67 std::ranges::copy(splitFrequenciesHz, &centers[1]);
68
69 for (uint32 i = 0; i < centers.size() - 1; ++i)
70 centers[i] *= splitFrequenciesHz[i];
71 centers.back() *= nyquist;
72
73 for (T& c : centers)
74 c = Math::Sqrt(c);
75
76 return centers;
77 }
78
79 [[nodiscard]] JPL_INLINE FreqBandCenters ComputeBandLowerThirdCenters(const SplitFrequencies& splitFrequenciesHz, float nyquist = 22050.0f)
80 {
81 const simd lowerEdge(20.0f, splitFrequenciesHz.F1, splitFrequenciesHz.F2, splitFrequenciesHz.F3);
82 const simd upperEdge(splitFrequenciesHz.F1, splitFrequenciesHz.F2, splitFrequenciesHz.F3, 22050.0f);
83
84 const simd bandRatio = upperEdge / lowerEdge;
85 const simd firstThirdCenter = lowerEdge * pow(bandRatio, simd(1.0f / 6.0f)); // cbrt -> sqrt
86
87 return firstThirdCenter;
88 }
89
90 [[nodiscard]] JPL_INLINE SplitFrequencies SplitFrequenciesFromBandCenters(const FreqBandCenters& bandCenters, float nyquist = 22050.0f)
91 {
92 float centers2[4]{};
93 (bandCenters * bandCenters).store(centers2);
94
95 const float f3 = centers2[3] / nyquist;
96 const float f2 = centers2[2] / f3;
97 const float f1 = centers2[1] / f2;
98
99 return SplitFrequencies{ .F1 = f1, .F2 = f2, .F3 = f3 };
100 }
101
102
103 [[nodiscard]] JPL_INLINE FreqBandCenters ComputeBandLowerThirdCenters(const FreqBandCenters& bandCenters, float nyquist = 22050.0f)
104 {
105 return ComputeBandLowerThirdCenters(SplitFrequenciesFromBandCenters(bandCenters, nyquist), nyquist);
106 }
107
111
112} // namespace JPL
JPL_INLINE constexpr T Sqrt(T x) noexcept
Definition Math.h:269
Definition AcousticMaterial.h:36
std::uint32_t uint32
Definition Core.h:311
const FreqBandCenters cBandCenters
Definition FrequencyBands.h:110
constexpr SplitFrequencies cDefaultFrequencySplits
At the moment JPL Spatial uses these frequency sptits for sound propagation.
Definition FrequencyBands.h:53
JPL_INLINE SplitFrequencies SplitFrequenciesFromBandCenters(const FreqBandCenters &bandCenters, float nyquist=22050.0f)
Definition FrequencyBands.h:90
JPL_INLINE FreqBandCenters ComputeBandLowerThirdCenters(const SplitFrequencies &splitFrequenciesHz, float nyquist=22050.0f)
Definition FrequencyBands.h:79
JPL_INLINE simd round(const simd &vec) noexcept
Element-wise round to nearest integer value.
Definition SIMD.h:1930
simd pow(const simd &x, const simd &y) noexcept
Definition SIMDMath.h:372
JPL_INLINE FreqBandCenters ComputeBandCenters(const SplitFrequencies &splitFrequenciesHz, float nyquist=22050.0f)
Definition FrequencyBands.h:56
Split frequencies points for crossover.
Definition FrequencyBands.h:46
float F1
Definition FrequencyBands.h:47
float F2
Definition FrequencyBands.h:47
float F3
Definition FrequencyBands.h:47
constexpr bool operator==(const SplitFrequencies &) const noexcept=default
Minimal 4-wide 32-bit float vector implementation for SIMD.
Definition SIMD.h:60