Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
noise_tilt.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <algorithm>
9#include <array>
10#include <cmath>
11#include <cstddef>
12#include <cstdint>
13#include <type_traits>
14
15namespace pulp::signal {
16
36template <typename SampleType = float> class NoiseTiltT {
37 static_assert(std::is_floating_point_v<SampleType>);
38
39 public:
40 static constexpr double kMinSampleRate = 8000.0;
41 static constexpr double kMaxSampleRate = 384000.0;
42 static constexpr double kMinTiltDbPerOctave = -6.0;
43 static constexpr double kMaxTiltDbPerOctave = 6.0;
44 static constexpr double kReferenceHz = 1000.0;
45 static constexpr double kBandLowHz = 31.25;
46 static constexpr double kBandHighHz = 16000.0;
47 static constexpr std::size_t kShelfCount = 9;
48 static constexpr std::uint32_t kDefaultSeed = NoiseSourceT<SampleType>::default_seed;
49
50 bool prepare(double sample_rate) {
51 if (!(std::isfinite(sample_rate) && sample_rate >= kMinSampleRate &&
53 return false;
54 sample_rate_ = sample_rate;
55 white_.prepare(sample_rate_);
56 design_filters();
57 reset();
58 return true;
59 }
60
61 bool set_tilt_db_per_octave(double tilt) {
62 if (!(std::isfinite(tilt) && tilt >= kMinTiltDbPerOctave && tilt <= kMaxTiltDbPerOctave))
63 return false;
64 tilt_db_per_octave_ = tilt;
65 design_filters();
66 reset_filters();
67 return true;
68 }
69
70 bool set_level(SampleType level) noexcept {
71 if (!(std::isfinite(static_cast<double>(level)) && level >= SampleType{} &&
72 level <= SampleType{1}))
73 return false;
74 level_ = level;
75 return true;
76 }
77
78 void set_seed(std::uint32_t seed) noexcept {
79 white_.set_seed(seed);
80 reset_filters();
81 fault_count_ = 0;
82 }
83
84 void reset() noexcept {
85 white_.reset();
86 reset_filters();
87 fault_count_ = 0;
88 }
89
90 SampleType process() noexcept {
91 SampleType output = white_.white();
92 if (tilt_db_per_octave_ != 0.0) {
93 for (auto& shelf : shelves_)
94 output = shelf.process(output);
95 output *= static_cast<SampleType>(reference_gain_);
96 }
97 output *= level_;
98 output = snap_to_zero(output);
99 if (std::isfinite(static_cast<double>(output)))
100 return output;
101 ++fault_count_;
102 reset_filters();
103 return SampleType{};
104 }
105
106 void process(SampleType* output, std::size_t frames) noexcept {
107 if (output == nullptr)
108 return;
109 for (std::size_t frame = 0; frame < frames; ++frame)
110 output[frame] = process();
111 }
112
113 double sample_rate() const noexcept {
114 return sample_rate_;
115 }
116 double tilt_db_per_octave() const noexcept {
117 return tilt_db_per_octave_;
118 }
119 SampleType level() const noexcept {
120 return level_;
121 }
122 std::uint32_t seed() const noexcept {
123 return white_.seed();
124 }
125 std::uint64_t fault_count() const noexcept {
126 return fault_count_;
127 }
128
129 static constexpr int latency_samples() noexcept {
130 return 0;
131 }
132 static constexpr int tail_samples() noexcept {
133 return 0;
134 }
135
136 private:
137 void design_filters() {
138 const double high_hz = std::min(kBandHighHz, 0.4 * sample_rate_);
139 const double octaves = std::log2(high_hz / kBandLowHz);
140 const double stage_gain_db =
141 tilt_db_per_octave_ * octaves / static_cast<double>(kShelfCount);
142 const double ratio = high_hz / kBandLowHz;
143 for (std::size_t index = 0; index < shelves_.size(); ++index) {
144 const double position =
145 (static_cast<double>(index) + 0.5) / static_cast<double>(kShelfCount);
146 const double center_hz = kBandLowHz * std::pow(ratio, position);
147 shelves_[index].set_coefficients(
148 BiquadT<SampleType>::Type::high_shelf, static_cast<SampleType>(center_hz),
149 static_cast<SampleType>(0.7071067811865476), static_cast<SampleType>(sample_rate_),
150 static_cast<SampleType>(stage_gain_db));
151 }
152
153 double reference_db = 0.0;
154 for (const auto& shelf : shelves_)
155 reference_db += magnitude_db(shelf, kReferenceHz, sample_rate_);
156 reference_gain_ = std::pow(10.0, -reference_db / 20.0);
157 }
158
159 void reset_filters() noexcept {
160 for (auto& shelf : shelves_)
161 shelf.reset();
162 }
163
164 NoiseSourceT<SampleType> white_{};
165 std::array<BiquadT<SampleType>, kShelfCount> shelves_{};
166 double sample_rate_ = 44100.0;
167 double tilt_db_per_octave_ = 0.0;
168 double reference_gain_ = 1.0;
169 SampleType level_ = SampleType{1};
170 std::uint64_t fault_count_ = 0;
171};
172
175
176} // namespace pulp::signal
@ high_shelf
Definition biquad.hpp:58
static constexpr std::uint32_t default_seed
Default seed.
Definition noise_source.hpp:55
Continuous spectral-tilt noise source built from NoiseSourceT's canonical seeded white stream and a f...
Definition noise_tilt.hpp:36
static constexpr double kReferenceHz
Definition noise_tilt.hpp:44
void set_seed(std::uint32_t seed) noexcept
Definition noise_tilt.hpp:78
std::uint64_t fault_count() const noexcept
Definition noise_tilt.hpp:125
static constexpr std::size_t kShelfCount
Definition noise_tilt.hpp:47
static constexpr double kMaxSampleRate
Definition noise_tilt.hpp:41
std::uint32_t seed() const noexcept
Definition noise_tilt.hpp:122
static constexpr double kMinSampleRate
Definition noise_tilt.hpp:40
double sample_rate() const noexcept
Definition noise_tilt.hpp:113
bool prepare(double sample_rate)
Definition noise_tilt.hpp:50
float level() const noexcept
Definition noise_tilt.hpp:119
static constexpr double kBandLowHz
Definition noise_tilt.hpp:45
static constexpr double kMinTiltDbPerOctave
Definition noise_tilt.hpp:42
double tilt_db_per_octave() const noexcept
Definition noise_tilt.hpp:116
static constexpr double kMaxTiltDbPerOctave
Definition noise_tilt.hpp:43
static constexpr int tail_samples() noexcept
Definition noise_tilt.hpp:132
static constexpr int latency_samples() noexcept
Definition noise_tilt.hpp:129
bool set_tilt_db_per_octave(double tilt)
Definition noise_tilt.hpp:61
SampleType process() noexcept
Definition noise_tilt.hpp:90
void reset() noexcept
Definition noise_tilt.hpp:84
static constexpr std::uint32_t kDefaultSeed
Definition noise_tilt.hpp:48
static constexpr double kBandHighHz
Definition noise_tilt.hpp:46
void process(SampleType *output, std::size_t frames) noexcept
Definition noise_tilt.hpp:106
bool set_level(SampleType level) noexcept
Definition noise_tilt.hpp:70
Evaluate what a biquad (or a cascade of them) does to the spectrum.
Definition additive_bank.hpp:218
float magnitude_db(const BiquadT< SampleType > &filter, double freq_hz, double sample_rate)
Ask a live filter what it looks like: the magnitude, in dB, that this BiquadT is applying at freq_hz ...
Definition frequency_response.hpp:130
NoiseTiltT< float > NoiseTilt
Definition noise_tilt.hpp:173
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
@ ratio
base_frequency_hz * ratio.
Definition fm_operator_engine.hpp:20
NoiseTiltT< double > NoiseTilt64
Definition noise_tilt.hpp:174