Generated reference › Inverse STFT — Control Systems/Time Frequency
kind: generated#block#control-systems-time-frequency

Inverse STFT — Control Systems/Time Frequency

Control_Systems/Time_Frequency/Inverse_STFT · 2 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Inverse STFT

Control Systems / Time Frequency

The inverse short-time Fourier transform of a stream of spectra – MATLAB's istft, one output sample per step. Every hop samples the block reads a one-sided spectrum Sj, inverts it, weights it by the synthesis window and overlap-adds it, dividing each sample by the window power that covered it:

x[t] = Σj w[t−j·hop]a·ifft(Sj)[t−j·hop] ÷ Σj w[t−j·hop]a+1

with a = 1 for weighted overlap-add (istft's default) and a = 0 for overlap-add. The window and overlap are checked for constant overlap-add, as iscola checks them, when a run starts.

Ports

  • Re – the real part of the spectrum, one-sided: [L/2+1, 1], DC first and Nyquist last – the layout of stft(…, 'FrequencyRange', 'onesided') and of this family's Spectrogram.
  • Im – the imaginary part of the same spectrum, the same size. The imaginary parts of DC and Nyquist are ignored, as istft ignores them for a conjugate-symmetric spectrum.
  • y – the reconstructed signal, scalar, one sample per step, L − 1 samples late (see Frames and timing).

Parameters

  • Window Length – L, the frame and transform length: an even whole number from 4 to 32. Even because the one-sided spectrum has a Nyquist bin; bounded above because the inverse transform is unrolled at export and its cost grows as L².
  • Hop Size – the samples from one frame to the next, 1 to L. MATLAB's OverlapLength is L − hop.
  • Window – the synthesis window, which must be the window the spectra were analysed with:
    • Periodic Hann – hann(L, 'periodic'), istft's default.
    • Periodic Hamming – hamming(L, 'periodic').
    • Hann and Hamming – the symmetric windows hann(L) and hamming(L), the ones Spectrogram uses.
    • Rectangular – all ones.
  • Method – WOLA (weighted overlap-add, a = 1, istft's default) or OLA (overlap-add, a = 0).
  • COLA Check – what happens when the window and overlap are not constant overlap-add, judged exactly as iscola(window, L−hop, method) judges it:
    • Warn – the run goes ahead and a warning names the median overlap sum and the largest deviation from it. The inversion is still exact wherever the window covers a sample: the per-sample division makes it so.
    • Refuse – the run is stopped with the same numbers.
    • Off – no check.
    A window whose overlapped powers reach zero at some sample (a Hann window with no overlap) is reported under Warn and Refuse too: such samples cannot be recovered and come out as MATLAB leaves them.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Frames and timing

Frame j is read at sample L − 1 + j·hop, counting from 0 – the sample on which Spectrogram publishes its frame j – and the spectrum is ignored on every other sample. The output at sample k is x[k − (L − 1)]: a latency of L − 1 samples, the least at which every frame covering a sample has arrived. It is zero until the first frame. The first L − 1 output samples are normalized by the fewer frames that cover them, exactly as istft treats the start of its record; a stream has no end, so istft's tail does not arise.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The inverse transform, the synthesis window and the 1/L are folded into one coefficient per bin and frame sample, and the per-sample normalizations into a table of L − 1 + hop numbers, all at export time, so a generated core is multiply-accumulates, one table look-up and one division per sample. Every setting is structural: re-export after changing one.

The three HDL targets are genuine Q16.16 and synthesizable: the inversion is linear, and the division is a multiplication by the reciprocal of the normalization, rounded to Q16.16.

Simulink bridge

None (Support::None). istft is a Signal Processing Toolbox function and that toolbox ships no Simulink library, so there is no path a diagram could name. The bridge reports this block rather than dropping it silently, and it therefore has no parity testbench; code export verification still covers it across all ten languages.

Notes

  • Stateful, and discrete by nature: an overlap-add buffer of L − 1 samples and three counters.
  • Verified against R2026a: a streaming model of this block reproduces istft of stft of a 30-sample record to 1.2×10−15 on every sample before the record's tail, for all five windows and both methods (the source banner carries the numbers).
  • Not reproduced: an FFT length longer than the window (the transform length is L), a centered or two-sided spectrum, a custom window vector, and a complex output ('ConjugateSymmetric' is always on).
  • A spectrum held between frames is fine: only the frame samples are read, so a Spectrogram-style source that holds its output feeds this block directly.
  • Linear, but no state space. The frame schedule makes it periodically time-varying, so model reduction correctly declines to merge it.

Code facts#

FactValue
registered typeControl_Systems/Time_Frequency/Inverse_STFT
familyControl_Systems/Time_Frequency
solver environment classICoreBlock_0_Control_Systems_1_Time_Frequency_2_Inverse_STFT
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Time_Frequency/Inverse_STFT/ICoreBlock_0_Control_Systems_1_Time_Frequency_2_Inverse_STFT.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Time_Frequency/Inverse_STFT/ICoreBlock_0_Control_Systems_1_Time_Frequency_2_Inverse_STFT.h
default size on canvas140 × 80 px
ports at insert2 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleRe
2inICoreDoubleIm
3outICoreDoubley

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Window Length8—
Hop Size2—
WindowPeriodic Hann%~%Periodic Hamming%~%Hann%~%Hamming%~%Recta…—
MethodWOLA%~%OLA~~WOLA—
COLA CheckWarn%~%Refuse%~%Off~~Warn—

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path—
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): istft is a Signal Processing Toolbox function, not a Simulink library block -- that toolbox ships no Simulink library at all -- so there is no path a diagram could name; the block is reported rather than dropped when a model crosses

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 every stimulus in the sample errored — cross-checks skipped

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Inverse STFT -- MATLAB's istft, one output sample per step, with iscola's check Every hop samples the block reads a one-sided spectrum S_j (L/2+1 bins, real and imaginary halves on two ports), inverts it as a conjugate-symmetric L-point spectrum, weights the frame by the synthesis window and overlap-adds it; each output sample is then divided by the sum of the window powers that covered it:

x[t] = SUM_j w[t - j*hop]^a * ifft(S_j)[t - j*hop] / SUM_j w[t - j*hop]^(a+1)

a = 1 is weighted overlap-add (istft's default 'wola'), a = 0 plain overlap-add ('ola'). Frame j is read at sample L-1 + j*hop -- the sample Spectrogram publishes its frame j on -- and the output at sample k is x[k - (L-1)]: a latency of L-1 samples, the least at which every frame covering a sample has arrived.

MEASURED AGAINST R2026a before a line was written (istft.m, formatISTFTInput.m, iscola.m read first), and every one of these is reproduced:

  • istft's normalization is PER SAMPLE, not a constant: normVal accumulates w^(a+1) over the

frames that cover each sample, so the first L-1 samples see fewer frames, and a window that is not constant-overlap-add is still inverted exactly. A value below nseg*eps is replaced by 1 -- the zero end tap of a Hann window at the first sample.

  • With 'FrequencyRange','onesided' and 'ConjugateSymmetric' true, the imaginary parts of DC

and Nyquist are IGNORED (setting them to zero changes the output by 0), and the result equals the real part of the non-symmetric inverse (difference 0).

  • A streaming model of exactly this block, fed stft(x) of a 30-sample record at L = 10, hop 3,

matches istft on every sample before the record's tail -- all five windows, both methods -- to 1.2e-15, and on eight random complex spectra to 4.4e-16. stft's frame j is fft(w .* x(j*hop+1 : j*hop+L)) over bins 0..L/2, the layout this block reads.

  • iscola is transcribed: the w^(a+1) of each hop-long stretch of the window summed, the

median taken, and "COLA" when the largest deviation is below (number of stretches)*eps. At L = 10, hop 3: periodic Hamming WOLA is NOT (median 1.3255136408103434, deviation 0.0089409224310301738), symmetric Hann is (1.125, deviation 0); periodic Hann at L = 8, hop 2 WOLA is (1.5). The block reports that median to the last digit and that deviation to 2e-16 -- the two sum the same numbers in a different order.

Support::None: istft is a Signal Processing Toolbox FUNCTION and that toolbox ships no Simulink library, so there is no counterpart to bridge to or run a parity testbench against.

Sample results#

No stimulus produced a sampled output in this rig — Invalid signal size at Inverse STFT block: ICore Blocks/Home/Inverse STFT. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.

Category unsampled · sample time 0.1 · 60 steps · commit 875fdbf564cf31a145283edf6a75dc1d64d1090a · produced by docsSample --out <folder> --blocks Wigner_Ville_Distribution Cross_Wigner_Ville_Distribution Inverse_STFT Fourier_Synchrosqueezed_Transform Time_Frequency_Ridges Frequency_Domain_Filter_Identification Fill_Gaps EOM_6DOF_ECEF_Quaternion EOM_6DOF_Custom_Variable_Mass_ECEF_Quaternion EOM_6DOF_Simple_Variable_Mass_ECEF_Quaternion ECI_To_ECEF_Rotation_Matrix ECI_Position_To_LLA LLA_To_ECI_Position ECI_Position_To_AER --steps 60

Sample data: docs/generated/samples/Control_Systems__Time_Frequency__Inverse_STFT.json