Add synthetic array (waveform) DSP support + UX improvements
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>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user