Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::SpectralFrameEngineT< SampleType > Class Template Reference

Streaming multichannel STFT/WOLA engine. More...

#include <spectral_frame_engine.hpp>

Public Member Functions

 SpectralFrameEngineT ()=default
void prepare (const SpectralFrameEngineConfig &config)
 RT contract: prepare() allocates FFT/window/ring/frame storage and is not audio-thread safe.
int latency_samples () const
 Fixed delay of the equal-hop process() path.
std::int64_t first_frame_start () const
 Stream position of the first analysis frame after prepare()/reset(): 0 without full-overlap stream start, otherwise in (-fft_size, 0] and a multiple of analysis_hop.
int fft_size () const
int analysis_hop () const
int num_bins () const
int channels () const
std::uint64_t retained_storage_bytes () const noexcept
 Logical retained allocations, using actual container capacities and the selected FFT provider's backing-store charge (excluding allocator metadata).
template<typename Fn>
SpectralSplitResult analyze_guarded (const SampleType *const *in, int count, Fn &&fn)
 Checked split analysis refuses the whole block before ingest on a clock or block-limit error.
SpectralSplitResult synthesize_frame_guarded (const std::complex< SampleType > *const *frames) noexcept
 Equal-hop split synthesis.
void stop_synthesis_guarded () noexcept
 After a fatal frame at the current origin, prior samples are final: this frame cannot contribute before its origin.
SpectralSplitResult read_output_guarded (SampleType *const *out, int count, int &consumed) noexcept
 Pop a finite prefix and return its length.
template<typename Fn>
void process (const SampleType *const *in, SampleType *const *out, int num_samples, Fn &&on_frames)
 Equal-hop streaming: push num_samples per channel, invoke on_frames(std::complex<SampleType>* const* frames, int num_bins) once per completed analysis frame (modify in place), resynthesize at the analysis hop, and write exactly num_samples per channel to out (the first latency_samples() of the stream are zeros).
int samples_until_next_frame () const
 Samples that must still be fed before the next analysis frame completes (>= 1).
template<typename Fn>
void analyze (const SampleType *const *in, int num_samples, Fn &&on_frames)
 Split API — analysis only.
void synthesize_frame (std::complex< SampleType > *const *frames, int synthesis_hop)
 Split API — overlap-add one spectral frame (all channels) at the current synthesis position, then advance it by synthesis_hop.
int available_output () const
 Split API — number of final (fully overlapped) output samples that can be read right now.
void read_output (SampleType *const *out, int num_samples)
 Split API — pop exactly num_samples per channel into out.
void reset ()

Detailed Description

template<typename SampleType = float>
class pulp::signal::SpectralFrameEngineT< SampleType >

Streaming multichannel STFT/WOLA engine.

Not thread-safe; one instance per audio stream.

Constructor & Destructor Documentation

◆ SpectralFrameEngineT()

template<typename SampleType = float>
pulp::signal::SpectralFrameEngineT< SampleType >::SpectralFrameEngineT ( )
default

Member Function Documentation

◆ analysis_hop()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::analysis_hop ( ) const
inline

◆ analyze()

template<typename SampleType = float>
template<typename Fn>
void pulp::signal::SpectralFrameEngineT< SampleType >::analyze ( const SampleType *const * in,
int num_samples,
Fn && on_frames )
inline

Split API — analysis only.

Pushes num_samples per channel from in, invoking on_frames once per completed frame. Runs are split exactly at frame boundaries, so frames land at fft_size + first_frame_start() + k * hop for ANY feed chunking — the analysis hop the callback observes is constant regardless of host block size. With full-overlap stream start the first frames arrive after fewer than fft_size samples and carry the implicit pre-stream silence.

◆ analyze_guarded()

template<typename SampleType = float>
template<typename Fn>
SpectralSplitResult pulp::signal::SpectralFrameEngineT< SampleType >::analyze_guarded ( const SampleType *const * in,
int count,
Fn && fn )
inline

Checked split analysis refuses the whole block before ingest on a clock or block-limit error.

Frame borrows expire when the callback returns.

◆ available_output()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::available_output ( ) const
inline

Split API — number of final (fully overlapped) output samples that can be read right now.

◆ channels()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::channels ( ) const
inline

◆ fft_size()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::fft_size ( ) const
inline

◆ first_frame_start()

template<typename SampleType = float>
std::int64_t pulp::signal::SpectralFrameEngineT< SampleType >::first_frame_start ( ) const
inline

Stream position of the first analysis frame after prepare()/reset(): 0 without full-overlap stream start, otherwise in (-fft_size, 0] and a multiple of analysis_hop.

Frame k analyses input [first_frame_start() + k * hop, ... + fft_size), silence before 0.

◆ latency_samples()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::latency_samples ( ) const
inline

Fixed delay of the equal-hop process() path.

A frame is only final once every overlapping frame has been added, which trails the input by up to fft_size + (analysis_hop - 1) samples depending on block phase; the constant fft_size + analysis_hop bound makes the reported latency exact and block-size independent.

◆ num_bins()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::num_bins ( ) const
inline

◆ prepare()

template<typename SampleType = float>
void pulp::signal::SpectralFrameEngineT< SampleType >::prepare ( const SpectralFrameEngineConfig & config)
inline

RT contract: prepare() allocates FFT/window/ring/frame storage and is not audio-thread safe.

After prepare(), process(), analyze(), synthesize_frame(), available_output(), read_output(), reset(), and accessors are allocation-free for blocks no larger than max_block and synthesis hops no larger than max_synthesis_hop. The callback must also be RT-safe.

◆ process()

template<typename SampleType = float>
template<typename Fn>
void pulp::signal::SpectralFrameEngineT< SampleType >::process ( const SampleType *const * in,
SampleType *const * out,
int num_samples,
Fn && on_frames )
inline

Equal-hop streaming: push num_samples per channel, invoke on_frames(std::complex<SampleType>* const* frames, int num_bins) once per completed analysis frame (modify in place), resynthesize at the analysis hop, and write exactly num_samples per channel to out (the first latency_samples() of the stream are zeros).

◆ read_output()

template<typename SampleType = float>
void pulp::signal::SpectralFrameEngineT< SampleType >::read_output ( SampleType *const * out,
int num_samples )
inline

Split API — pop exactly num_samples per channel into out.

Callers should not request more than available_output(); any excess is filled with silence without advancing the read position (the engine never invents a variable delay on its own).

◆ read_output_guarded()

template<typename SampleType = float>
SpectralSplitResult pulp::signal::SpectralFrameEngineT< SampleType >::read_output_guarded ( SampleType *const * out,
int count,
int & consumed )
inlinenoexcept

Pop a finite prefix and return its length.

On failure the caller keeps that prefix and supplies terminal silence from the first unread sample.

◆ reset()

template<typename SampleType = float>
void pulp::signal::SpectralFrameEngineT< SampleType >::reset ( )
inline

◆ retained_storage_bytes()

template<typename SampleType = float>
std::uint64_t pulp::signal::SpectralFrameEngineT< SampleType >::retained_storage_bytes ( ) const
inlinenoexcept

Logical retained allocations, using actual container capacities and the selected FFT provider's backing-store charge (excluding allocator metadata).

◆ samples_until_next_frame()

template<typename SampleType = float>
int pulp::signal::SpectralFrameEngineT< SampleType >::samples_until_next_frame ( ) const
inline

Samples that must still be fed before the next analysis frame completes (>= 1).

Lets a caller chunk its feed so each analyze call ends exactly when a frame emits — making the in-block offset of the completed frame known precisely (needed to evaluate per-frame control trajectories, e.g. a smoothed pitch ratio, at the correct position instead of the chunk end).

◆ stop_synthesis_guarded()

template<typename SampleType = float>
void pulp::signal::SpectralFrameEngineT< SampleType >::stop_synthesis_guarded ( )
inlinenoexcept

After a fatal frame at the current origin, prior samples are final: this frame cannot contribute before its origin.

Retain that prefix and prohibit further synthesis until reset; no failing frame is committed.

◆ synthesize_frame()

template<typename SampleType = float>
void pulp::signal::SpectralFrameEngineT< SampleType >::synthesize_frame ( std::complex< SampleType > *const * frames,
int synthesis_hop )
inline

Split API — overlap-add one spectral frame (all channels) at the current synthesis position, then advance it by synthesis_hop.

frames must hold channels() pointers to num_bins() bins (DC..Nyquist); the conjugate half is reconstructed internally. The synthesis position starts at first_frame_start(); output that falls before stream position 0 is discarded.

◆ synthesize_frame_guarded()

template<typename SampleType = float>
SpectralSplitResult pulp::signal::SpectralFrameEngineT< SampleType >::synthesize_frame_guarded ( const std::complex< SampleType > *const * frames)
inlinenoexcept

Equal-hop split synthesis.

Validate and stage every channel and divisor before committing any ring cell, preserving earlier history on failure.


The documentation for this class was generated from the following file: