MUSIC Spectrum — Control Systems/Spectral Measurements
Control_Systems/Spectral_Measurements/MUSIC_Spectrum · 1 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.
MUSIC Spectrum
Control Systems / Spectral Measurements
The MUSIC pseudospectrum of a signal frame – MATLAB's
pmusic. The frame's correlation matrix R of order m is
decomposed as R = V·diag(λ)·V′, eigenvalues in
descending order; the p largest span the signal subspace and the other
m−p eigenvectors vk the noise subspace orthogonal to it.
A sinusoid in the frame lies in the signal subspace, so its frequency is where
the noise subspace has almost nothing:
S(f) = 1 ÷ Σk>p |Vk(f)|², Vk(f) = Σn vk[n]·e−j2πfn, f = k/nfft cycles per sample.
R is built by the covariance method: with L = N−m+1, row i of the
data matrix X holds samples i+m−1 down to i, and R = X′X/L, exactly
corrmtx(x, m−1, 'cov') multiplied by its own transpose. Peaks
mark the sinusoids' frequencies; their heights are not powers.
Ports
- x – the signal frame, an [N,1] column with the oldest sample first. N is read off the wire and must be at least 2m−1 – as many rows in the data matrix as it has columns – and at most 128. A Tapped Delay with Delay Order Oldest turns a stream into such a frame.
- S – the pseudospectrum, [floor(nfft/2)+1, 1] one-sided (bins 0 to nfft/2, DC first) or [nfft, 1] two-sided; bin k is at frequency k/nfft of the sampling rate.
Parameters
- Signal Subspace Dimension – p, the number of complex exponentials in the frame: two per real sinusoid. A whole number from 1 to m−1. Defaults to 4, two real sinusoids.
- Correlation Matrix Order – m, the size of the m×m correlation matrix and the length of each eigenvector, a whole number from 2 to 16. pmusic uses 2p, and so does the default, 8.
- Dimension Rule – how the signal subspace dimension is decided:
- Fixed – it is p.
- Threshold – pmusic's two-element form [p thr]: it is the number of eigenvalues greater than Threshold times the smallest one, but never more than p, and p when none is.
- Threshold – thr, the multiple of the smallest eigenvalue the Threshold rule compares against; a number of 0 or more. Defaults to 10. Ignored by the Fixed rule.
- FFT Length – nfft, the number of frequency points around the whole circle, a whole number from 2 to 1024. Defaults to 256, pmusic's. An nfft below m samples each eigenvector's transform at nfft points all the same, which is what pmusic's own transform does.
- Spectrum Range – One-sided (the default, pmusic's for a real signal): bins 0 to floor(nfft/2), with nothing doubled, because a pseudospectrum is not a density. Two-sided: all nfft bins.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text, all from one program, so every target does the same arithmetic in the same order as the simulation: the correlation matrix, a cyclic Jacobi eigenvalue solve, the sort, and one transform per eigenvector. All six settings and the frame length are structural; re-export after changing any of them.
The three HDL targets run that program in real arithmetic
and quantize only at the ports: simulation-only, not offered as
synthesizable. An eigenvalue solve takes square roots and divides by the data,
which a Q16.16 datapath does not carry.
Simulink bridge
None (Support::None). pmusic is a Signal
Processing Toolbox function and that toolbox ships no Simulink library;
a search of every DSP System Toolbox and Simulink library on R2026a found no
MUSIC, subspace or pseudospectrum block, so there is no path a diagram could
name. The bridge reports this block rather than dropping it silently, and it has
no parity testbench; code export verification covers all ten
languages.
Notes
- Algebraic: the output depends on this step's frame alone.
- Verified against R2026a: the same program agrees with
pmusicto 2.2e−11 relative on every bin over 1400 frames of tones in noise, the threshold form and both ranges included. With m = 2p the block ispmusic(x, p, nfft); for any other m it ispmusic(corrmtx(x, m−1, 'cov'), p, nfft). Add'twosided'for the two-sided range and write p as [p thr] for the threshold rule. - When the signal subspace is the smaller one (p ≤ m−p) the block does what pmusic does: it sums the p signal eigenvectors and answers 1 ÷ |m − Σ|, the same number by orthonormality.
- ⚠ There is no
rootmusicmode, and the reason is measured.rootmusicroots the noise-subspace polynomial and reports the p frequencies whose roots sit closest to the unit circle, with their powers. Over 500 perturbations of a 24-sample frame the FREQUENCIES were steady (1.5e−14 under a 1e−15 perturbation, 1e−6 rad under one Q16.16 quantum) but the POWERS were not: a 1e−15 perturbation moved them by 1.4e−10 relative and one Q16.16 quantum moved them by 9.8 %, ten times the band the three HDL targets are held to. A mode whose answer no rig can certify is not shipped; the peaks of this pseudospectrum locate the same frequencies. - An eigenvector's sign is arbitrary, and this block's solver and MATLAB's SVD choose differently; the pseudospectrum reads each one only through |Vk(f)|², which no sign changes.
- A frame whose signal and noise eigenvalues are nearly equal – no sinusoid, or more sinusoids than p/2 – has no well-defined split and the answer then depends on rounding. Drive it with tones.
- The three HDL targets' output port is Q16.16, whose largest value is 32767; a frame with almost no noise gives a peak far beyond it, which those three targets cannot carry while the other seven do.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Spectral_Measurements/MUSIC_Spectrum |
| family | Control_Systems/Spectral_Measurements |
| solver environment class | ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_MUSIC_Spectrum |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/MUSIC_Spectrum/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_MUSIC_Spectrum.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/MUSIC_Spectrum/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_MUSIC_Spectrum.h |
| default size on canvas | 150 × 76 px |
| ports at insert | 1 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | x |
| 2 | out | ICoreDouble | S |
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 variable | Default | Simulink parameter |
|---|---|---|
Signal Subspace Dimension | 4 | not crossed |
Correlation Matrix Order | 8 | not crossed |
Dimension Rule | Fixed%~%Threshold~~Fixed | not crossed |
Threshold | 10 | not crossed |
FFT Length | 256 | not crossed |
Spectrum Range | One-sided%~%Two-sided~~One-sided | not crossed |
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.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
| deliberately not crossed | Signal Subspace Dimension, Correlation Matrix Order, Dimension Rule, Threshold, FFT Length, Spectrum Range |
Caveat (shown to the user): pmusic is a Signal Processing Toolbox function, not a Simulink library block -- that toolbox ships no Simulink library -- and a search of 97 DSP System Toolbox and Simulink libraries (8600 blocks, R2026a) found no MUSIC, subspace or pseudospectrum block, 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:
B0every 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).
MUSIC Spectrum -- MATLAB's pmusic, the subspace pseudospectrum of a frame R = corrmtx(x, m-1, 'cov')' * corrmtx(x, m-1, 'cov') order m, L = N - m + 1 rows R = V diag(lambda) V', lambda descending cyclic Jacobi S(f) = 1 / SUM_{k > p} |V_k(f)|^2, f = 0, 1/nfft, ... the noise subspace
Read out of R2026a's pmusic.m, private/music.m, private/musicOptions.m and corrmtx.m, then measured. What that pinned, each a wrong answer if guessed:
- pmusic builds the correlation matrix of order 2p from a vector by corrmtx's COVARIANCE
method -- N - m + 1 rows, each the m newest-first samples, scaled by 1/sqrt(N - m + 1) -- and takes the SVD of that data matrix; the squared singular values are the eigenvalues. This block takes the eigenvalues of X'X by Jacobi instead: the same subspaces.
- pmusic sums the SIGNAL eigenvectors when they are the fewer (p <= m - p) and answers
1 / |m - SUM|, the noise sum by orthonormality; this block does the same.
- The [p thr] form keeps p_eff = min(p, #{lambda > thr * lambda_min}), or p when no
eigenvalue clears the bar.
- freqz(v, 1, nfft, 'whole') with nfft below the vector length WRAPS the vector (the DTFT
sampled at nfft points: 1.1e-15 from the wrapped DFT, 2.1 from the truncated one), which is what a direct transform at 2 pi k / nfft does too.
- One-sided is bins 0 .. floor(nfft/2) with NOTHING doubled: a pseudospectrum is not a density.
Measured: a prototype of exactly this program against pmusic on 7 configurations x 200 frames of two tones plus noise (N 16..32, m 4..12, nfft 5..64, one- and two-sided, the threshold form, p above and below m/2): worst relative disagreement 2.2e-11 on any bin -- the peaks, where 1/D amplifies the rounding of forming X'X rather than taking the SVD of X.
Support::None: a sweep of 97 Simulink libraries (8600 blocks) found no MUSIC, subspace or pseudospectrum block, and pmusic is a Signal Processing Toolbox function, which ships none.
Sample results#
No stimulus produced a sampled output in this rig — The frame has 1 samples; it must have at least 2m - 1 = 15 (as many data-matrix rows as the order m = 8) and at most 128.. 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 ee1ac01a4e538ed0c5e24de27bed3622cf0687b7 · produced by docsSample --out <folder> --blocks MUSIC_Spectrum Eigenvector_Spectrum Lomb_Scargle_Periodogram --steps 60
Sample data: docs/generated/samples/Control_Systems__Spectral_Measurements__MUSIC_Spectrum.json