39 std::complex<float>*
const*
channels =
nullptr;
65 bool add_stage(std::unique_ptr<SpectralFrameStage> stage) {
66 if (prepared_ || !stage || stages_.size() == kMaxStages)
68 stages_.push_back(std::move(stage));
74 d.name =
"Spectral Frame";
75 d.manufacturer =
"Pulp";
76 d.bundle_id =
"com.pulp.graph.spectral-frame";
79 d.input_buses = {{
"Main In", config_.channels,
false}};
80 d.output_buses = {{
"Main Out", config_.channels,
false}};
89 config_.channels <= 0 || config_.channels > kMaxChannels ||
93 throw std::invalid_argument(
"spectral frame geometry disagrees with graph");
98 throw std::invalid_argument(
"invalid spectral frame geometry");
100 engine_.prepare(config_);
102 sequence_.store(0, std::memory_order_relaxed);
113 const auto count =
static_cast<int>(output.
num_samples());
114 if (!prepared_ || count < 0 || count > config_.max_block ||
116 input.
num_channels() !=
static_cast<std::size_t
>(config_.channels) ||
117 output.
num_channels() !=
static_cast<std::size_t
>(config_.channels)) {
124 std::array<const float*, kMaxChannels> in{};
125 std::array<float*, kMaxChannels> out{};
126 for (
int ch = 0; ch < config_.channels; ++ch) {
127 in[ch] = input.
channel_ptr(
static_cast<std::size_t
>(ch));
128 out[ch] = output.
channel_ptr(
static_cast<std::size_t
>(ch));
131 in.data(), out.data(), count,
132 [
this](std::complex<float>*
const* bins,
int bin_count)
noexcept {
133 const auto sequence = sequence_.load(std::memory_order_relaxed);
134 if (sequence > static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max() /
135 config_.analysis_hop)) {
136 set_error_(SpectralFrameError::SequenceOverflow);
137 for (int ch = 0; ch < config_.channels; ++ch)
138 std::fill_n(bins[ch], bin_count, std::complex<float>{});
141 const auto origin = engine_.first_frame_start() +
142 static_cast<std::int64_t
>(
sequence) * config_.analysis_hop;
147 config_.analysis_hop,
152 sequence_.store(
sequence + 1, std::memory_order_relaxed);
153 if (!finite_(
view)) {
158 for (
const auto& stage : stages_) {
159 if (!stage->process(
view)) {
164 if (!finite_(
view)) {
174 return prepared_ ? engine_.latency_samples() : 0;
177 return error_.load(std::memory_order_relaxed);
180 return sequence_.load(std::memory_order_relaxed);
185 sequence_.store(0, std::memory_order_relaxed);
190 static constexpr std::size_t kMaxStages = 8;
191 static constexpr int kMaxChannels = 16;
194 if (frame.channels ==
nullptr || frame.channel_count <= 0 ||
195 frame.channel_count > kMaxChannels || frame.bin_count != frame.fft_size / 2 + 1)
197 for (
int ch = 0; ch < frame.channel_count; ++ch) {
198 if (frame.channels[ch] ==
nullptr)
200 for (
int bin = 0; bin < frame.bin_count; ++bin) {
201 const auto value = frame.channels[ch][bin];
202 if (!std::isfinite(value.real()) || !std::isfinite(value.imag()))
205 if (frame.channels[ch][0].imag() != 0 ||
206 frame.channels[ch][frame.bin_count - 1].imag() != 0)
213 for (
int ch = 0; ch < frame.channel_count; ++ch)
214 std::fill_n(frame.channels[ch], frame.bin_count, std::complex<float>{});
218 error_.compare_exchange_strong(expected,
error, std::memory_order_relaxed);
221 signal::SpectralFrameEngineConfig config_;
222 signal::SpectralFrameEngineT<float> engine_;
223 std::vector<std::unique_ptr<SpectralFrameStage>> stages_;
224 double sample_rate_ = 0;
225 std::atomic<std::uint64_t> sequence_{0};
227 bool prepared_ =
false;
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
std::size_t num_samples() const
Definition buffer.hpp:84
std::size_t num_channels() const
Definition buffer.hpp:83
void clear()
Zero-fill all channels.
Definition buffer.hpp:90
SampleType * channel_ptr(std::size_t index)
Raw pointer to one channel's sample data.
Definition buffer.hpp:68
Collection of timestamped MIDI events within a single audio buffer period.
Definition buffer.hpp:31
Type
Definition windowing.hpp:43
@ hann
Definition windowing.hpp:45
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
Definition host_transport_projector.hpp:8
std::optional< SpectralFrameEngineGeometry > checked_spectral_frame_engine_geometry(const SpectralFrameEngineConfig &config, std::uint64_t target_max_bytes=kTargetAddressMaximumBytes) noexcept
Derive every integer and typed backing-store capacity used by prepare().
Definition spectral_frame_engine.hpp:151
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
Streaming STFT analysis + weighted overlap-add (WOLA) synthesis for DSP-grade spectral processing — d...
Definition prepare_resources.hpp:102
double sample_rate
Definition prepare_resources.hpp:103
int input_channels
Definition prepare_resources.hpp:105
int max_buffer_size
Definition prepare_resources.hpp:104
int output_channels
Definition prepare_resources.hpp:106
Process context — passed every audio callback with transport state.
Definition process_context.hpp:89
bool reset_requested
True for the first block after a transport jump, seek, or explicit DSP reset boundary.
Definition process_context.hpp:111
Configuration for a SpectralFrameEngine.
Definition spectral_frame_engine.hpp:56