Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
waveguide_junction.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <algorithm>
7#include <array>
8#include <cmath>
9#include <cstddef>
10#include <limits>
11#include <type_traits>
12
13namespace pulp::signal {
14
20template <typename SampleType = float, std::size_t MaxPorts = 4> class WaveguideJunctionT {
21 static_assert(std::is_floating_point_v<SampleType>);
22 static_assert(MaxPorts >= 2);
23 static_assert(MaxPorts <= 4);
24
25 public:
26 static constexpr double minimum_impedance = 1.0e-6;
27
28 WaveguideJunctionT() { impedances_.fill(1.0); }
29
30 void set_port_count(std::size_t count) noexcept {
31 if (count >= 2 && count <= MaxPorts)
32 port_count_ = count;
33 }
34
35 [[nodiscard]] std::size_t port_count() const noexcept { return port_count_; }
36
37 void set_impedance(std::size_t port_index, SampleType impedance) noexcept {
38 if (port_index >= MaxPorts)
39 return;
40 const auto value = static_cast<double>(impedance);
41 if (!std::isfinite(value))
42 return;
43 impedances_[port_index] = std::max(value, minimum_impedance);
44 }
45
46 [[nodiscard]] SampleType impedance(std::size_t port_index) const noexcept {
47 return port_index < MaxPorts ? static_cast<SampleType>(impedances_[port_index])
48 : SampleType{};
49 }
50
56 [[nodiscard]] bool scatter(const SampleType* incoming, SampleType* outgoing,
57 std::size_t count) noexcept {
58 if (incoming == nullptr || outgoing == nullptr || count != port_count_)
59 return false;
60
61 std::array<long double, MaxPorts> input{};
62 long double weighted_pressure = 0.0L;
63 long double reciprocal_sum = 0.0L;
64 for (std::size_t i = 0; i < count; ++i) {
65 const auto value = static_cast<long double>(incoming[i]);
66 if (!std::isfinite(value)) {
67 publish_previous(outgoing, count);
68 return false;
69 }
70 input[i] = value;
71 const auto reciprocal = 1.0L / static_cast<long double>(impedances_[i]);
72 weighted_pressure += value * reciprocal;
73 reciprocal_sum += reciprocal;
74 }
75 if (!(reciprocal_sum > 0.0L) || !std::isfinite(weighted_pressure) ||
76 !std::isfinite(reciprocal_sum)) {
77 publish_previous(outgoing, count);
78 return false;
79 }
80
81 const auto junction_pressure = 2.0L * weighted_pressure / reciprocal_sum;
82 std::array<SampleType, MaxPorts> replacement{};
83 for (std::size_t i = 0; i < count; ++i) {
84 const auto value = junction_pressure - input[i];
85 if (!finite_sample(value)) {
86 publish_previous(outgoing, count);
87 return false;
88 }
89 replacement[i] = static_cast<SampleType>(value);
90 }
91 for (std::size_t i = 0; i < count; ++i) {
92 outgoing[i] = replacement[i];
93 last_output_[i] = replacement[i];
94 }
95 return true;
96 }
97
98 void reset() noexcept { last_output_.fill(SampleType{}); }
99
100 private:
101 [[nodiscard]] static bool finite_sample(long double value) noexcept {
102 const auto limit = static_cast<long double>(std::numeric_limits<SampleType>::max());
103 return std::isfinite(value) && value <= limit && value >= -limit;
104 }
105
106 void publish_previous(SampleType* outgoing, std::size_t count) const noexcept {
107 for (std::size_t i = 0; i < count; ++i)
108 outgoing[i] = last_output_[i];
109 }
110
111 std::array<double, MaxPorts> impedances_{};
112 std::array<SampleType, MaxPorts> last_output_{};
113 std::size_t port_count_ = 2;
114};
115
118
119} // namespace pulp::signal
A bounded N-port pressure-wave scattering junction.
Definition waveguide_junction.hpp:20
float impedance(std::size_t port_index) const noexcept
Definition waveguide_junction.hpp:46
static constexpr double minimum_impedance
Definition waveguide_junction.hpp:26
void reset() noexcept
Definition waveguide_junction.hpp:98
std::size_t port_count() const noexcept
Definition waveguide_junction.hpp:35
void set_impedance(std::size_t port_index, SampleType impedance) noexcept
Definition waveguide_junction.hpp:37
bool scatter(const SampleType *incoming, SampleType *outgoing, std::size_t count) noexcept
Scatters one incoming pressure wave per active port.
Definition waveguide_junction.hpp:56
void set_port_count(std::size_t count) noexcept
Definition waveguide_junction.hpp:30
WaveguideJunctionT()
Definition waveguide_junction.hpp:28
Definition additive_bank.hpp:218
WaveguideJunctionT< double > WaveguideJunction64
Definition waveguide_junction.hpp:117
@ i
Definition formant_filter_bank.hpp:20
WaveguideJunctionT< float > WaveguideJunction
Definition waveguide_junction.hpp:116