f7f297c3df
Adds full array/waveform support through the synthetic DSP engine: a dsp.Sample value model (scalar or []float64), array ops (index, slice, sum, mean, min, max, length, fft) with an in-tree radix-2 FFT, and static type propagation (OpOutputType) that the editor mirrors to colour wires by data type and flag invalid wirings. Stateful filters and lua stay scalar-only. Adds a waveform plot mode (x-vs-index trace). Also: errored-node hover reasons, S/N add-signal/add-node HUD shortcuts in the synthetic editor, and view-mode widgets that blend with the canvas background (chrome kept in edit mode). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package dsp
|
|
|
|
import "math"
|
|
|
|
// nextPow2 returns the smallest power of two >= n (and at least 1).
|
|
func nextPow2(n int) int {
|
|
p := 1
|
|
for p < n {
|
|
p <<= 1
|
|
}
|
|
return p
|
|
}
|
|
|
|
// fftRadix2 computes the in-place iterative radix-2 Cooley-Tukey FFT of the
|
|
// complex signal held in re/im. len(re) == len(im) must be a power of two. The
|
|
// transform overwrites re/im with the frequency-domain result. This is a small
|
|
// self-contained implementation (no external dependency) used by the synthetic
|
|
// fft op.
|
|
func fftRadix2(re, im []float64) {
|
|
n := len(re)
|
|
if n <= 1 {
|
|
return
|
|
}
|
|
|
|
// Bit-reversal permutation.
|
|
for i, j := 1, 0; i < n; i++ {
|
|
bit := n >> 1
|
|
for ; j&bit != 0; bit >>= 1 {
|
|
j ^= bit
|
|
}
|
|
j ^= bit
|
|
if i < j {
|
|
re[i], re[j] = re[j], re[i]
|
|
im[i], im[j] = im[j], im[i]
|
|
}
|
|
}
|
|
|
|
// Danielson-Lanczos butterflies.
|
|
for length := 2; length <= n; length <<= 1 {
|
|
ang := -2 * math.Pi / float64(length)
|
|
wReal, wImag := math.Cos(ang), math.Sin(ang)
|
|
for i := 0; i < n; i += length {
|
|
curReal, curImag := 1.0, 0.0
|
|
half := length >> 1
|
|
for k := 0; k < half; k++ {
|
|
a := i + k
|
|
b := i + k + half
|
|
tReal := curReal*re[b] - curImag*im[b]
|
|
tImag := curReal*im[b] + curImag*re[b]
|
|
re[b] = re[a] - tReal
|
|
im[b] = im[a] - tImag
|
|
re[a] += tReal
|
|
im[a] += tImag
|
|
curReal, curImag = curReal*wReal-curImag*wImag, curReal*wImag+curImag*wReal
|
|
}
|
|
}
|
|
}
|
|
}
|