Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
noise_morpher.hpp
Go to the documentation of this file.
1#pragma once
2
25
27
28#include <algorithm>
29#include <cmath>
30#include <cstddef>
31#include <cstdint>
32#include <complex>
33#include <vector>
34
35namespace pulp::signal {
36
41template <typename SampleType = float>
43public:
44 static bool checked_retained_bytes(int num_bins, std::uint64_t target_max_bytes,
45 std::uint64_t& bytes) noexcept {
46 CheckedRetainedByteCharge charge(target_max_bytes);
47 const auto bins = static_cast<std::uint64_t>(num_bins);
48 if (!charge.add<SampleType>(bins) || !charge.add<SampleType>(bins))
49 return false;
50 bytes = charge.total();
51 return true;
52 }
53
54 void prepare(int num_bins, std::uint64_t seed = 0x9e3779b97f4a7c15ull) {
55 num_bins_ = num_bins;
56 seed_ = seed ? seed : 0x9e3779b97f4a7c15ull;
57 rng_ = seed_;
58 env_a_.assign(static_cast<size_t>(num_bins), SampleType{0});
59 env_b_.assign(static_cast<size_t>(num_bins), SampleType{0});
60 have_prev_ = false;
61 }
62
63 int num_bins() const { return num_bins_; }
64
65 void reset() {
66 rng_ = seed_;
67 have_prev_ = false;
68 }
69
73 void push_envelope(const SampleType* noise_mag) {
74 std::copy(noise_mag, noise_mag + num_bins_, env_b_.begin());
75 if (!have_prev_) {
76 std::copy(env_b_.begin(), env_b_.end(), env_a_.begin());
77 have_prev_ = true;
78 }
79 }
80
84 void advance() { std::swap(env_a_, env_b_); }
85
96 void set_synthesis_gain(SampleType g) {
97 synth_gain_ = g > SampleType{0} ? g : SampleType{1};
98 }
99
100 void synthesize(SampleType frac, std::complex<SampleType>* out) {
101 const SampleType f = frac < SampleType{0}
102 ? SampleType{0}
103 : (frac > SampleType{1} ? SampleType{1} : frac);
104 for (int k = 0; k < num_bins_; ++k) {
105 const SampleType mag = (env_a_[static_cast<size_t>(k)] * (SampleType{1} - f)
106 + env_b_[static_cast<size_t>(k)] * f) * synth_gain_;
107 const SampleType phase = next_phase();
108 out[k] = std::polar(mag, phase);
109 }
110 }
111
114 void push_masked_envelope(const SampleType* full_mag, const SampleType* noise_mask) {
115 for (int k = 0; k < num_bins_; ++k)
116 scratch_[static_cast<size_t>(k)] = full_mag[k] * noise_mask[k];
117 push_envelope(scratch_.data());
118 }
119
121 scratch_.assign(static_cast<size_t>(num_bins_), SampleType{0});
122 }
123
124private:
125 SampleType next_phase() {
126 rng_ ^= rng_ >> 12;
127 rng_ ^= rng_ << 25;
128 rng_ ^= rng_ >> 27;
129 const std::uint64_t r = rng_ * 0x2545f4914f6cdd1dull;
130 // Uniform phase in [-pi, pi).
131 const double u = static_cast<double>(r >> 11) * (1.0 / 9007199254740992.0);
132 return static_cast<SampleType>((u * 2.0 - 1.0) * 3.14159265358979323846);
133 }
134
135 int num_bins_ = 0;
136 SampleType synth_gain_ = SampleType{1};
137 std::uint64_t seed_ = 0;
138 std::uint64_t rng_ = 0;
139 bool have_prev_ = false;
140 std::vector<SampleType> env_a_;
141 std::vector<SampleType> env_b_;
142 std::vector<SampleType> scratch_;
143};
144
147
148} // namespace pulp::signal
Definition checked_allocation.hpp:57
bool add(std::uint64_t elements) noexcept
Definition checked_allocation.hpp:63
std::uint64_t total() const noexcept
Definition checked_allocation.hpp:83
RT contract: prepare() and prepare_masked_scratch() allocate storage and must run off the audio threa...
Definition noise_morpher.hpp:42
void set_synthesis_gain(SampleType g)
Emit one synthesis frame at interpolation position frac in [0,1] between the previous and current env...
Definition noise_morpher.hpp:96
void advance()
Commit the current "to" envelope as the next "from" endpoint.
Definition noise_morpher.hpp:84
void synthesize(SampleType frac, std::complex< SampleType > *out)
Definition noise_morpher.hpp:100
static bool checked_retained_bytes(int num_bins, std::uint64_t target_max_bytes, std::uint64_t &bytes) noexcept
Definition noise_morpher.hpp:44
void prepare(int num_bins, std::uint64_t seed=0x9e3779b97f4a7c15ull)
Definition noise_morpher.hpp:54
void push_masked_envelope(const SampleType *full_mag, const SampleType *noise_mask)
Convenience: pull the noise component out of a full magnitude frame using an STN noise mask,...
Definition noise_morpher.hpp:114
int num_bins() const
Definition noise_morpher.hpp:63
void push_envelope(const SampleType *noise_mag)
Set the noise magnitude envelope for the current analysis frame.
Definition noise_morpher.hpp:73
void prepare_masked_scratch()
Definition noise_morpher.hpp:120
void reset()
Definition noise_morpher.hpp:65
Definition additive_bank.hpp:218
@ u
Definition formant_filter_bank.hpp:20
NoiseMorpherT< float > NoiseMorpher
Definition noise_morpher.hpp:145
NoiseMorpherT< double > NoiseMorpher64
Definition noise_morpher.hpp:146