When the number of frequencies/bins grows, it is computationally much cheaper to use the well known FFT algorithm instead, at the price of needing to handle input data by blocks instead of "streaming".
I'm also not sure how this is causal? It has a weighted-time window (biasing the more recent sound), which is farily novel, but I wouldn't call that causal.
This is not to say I don't think this is cool, it certainly looks better than existing techniques like synchrosqueezing for pushing the limit of the heisenberg uncertainty principle (technically given ideal conditions synchrosqueezing can outperform the principle, but only a specific subset of signals).
I wrote this cross-disciplinary paper about resonance a few years ago. You may find it useful or at least interesting.
https://www.frontiersin.org/journals/neurorobotics/articles/...
Actually I wonder if this technique can be adapted to use gammatone filters specifically, rather than simple bandpass filters.
That is, `y(t') = integral e^kt x(t' - t) dt`, with k complex and negative real part.
If you discretize that using simple integration and t' = i dt, t = j dt you get
y_i = dt sum_j e^(k j dt) x_{i - j}
y_{i+1} = dt sum_j e^(k j dt) x_{i+1 - j}
= (dt e^(k dt) sum_j' e^(k j' dt) x_{i - j'}) + x_i
= dt e^(k dt) y_i + x_i
If we then scale this by some value, such that A y_i = z_i we can write this as z_{i+1} = dt e^(k dt) z_i + A x_i
Here the `dt e^(k dt)` plays a similar role to (1-alpha) and A is similar to P alpha - the difference being that P changes over time, while A is constant.We can write `z_i = e^{w dt i} r_i` where w is the imaginary part of k
e^{w dt (i+1)} r_{i+1} = dt e^(k dt) e^{w dt i} r_i + A x_i
r_{i+1} = dt e^((k - w) dt) r_i + e^{-w dt (i+1) } A x_i
= (1-alpha) r_i + p_i x_i
Where p_i = e^{-w dt (i+1) } A = e^{-w dt ) p_{i-1}
Which is exactly the result from the resonate web-page.The neat thing about recognising this as a convolution integral, is that we can use shaping other than exponential decay - we can implement a box filter using only two states, or a triangular filter (this is a bit trickier and takes more states). While they're tricky to derive, they tend to run really quickly.
For me the main motivation developing Resonate was for interactive systems: very simple, no buffering, no window... Also, no need to compute all the FFT bins so in that sense more efficient!
- The Oscillators app demonstrates real-time linear, log and Mel scale spectrograms, as well as derived audio features such as chromagrams and MFCCs https://alexandrefrancois.org/Oscillators/
- The Resonate Youtube playlist features video captures of real-time demonstrations. https://www.youtube.com/playlist?list=PLVcB_ABiKC_cbemxXUUJX...
- The open source Oscillators Swift package contains reference implementations in Swift and C++.https://github.com/alexandrefrancois/Oscillators
- The open source python module noFFT provides python and C++ implementations of Resonate functions and Jupyter notebooks illustrating their use in offline settings. https://github.com/alexandrefrancois/noFFT
james_a_craig•3d ago
It's given in the source as 3.14159274101257324219 when the right value to the same number of digits is 3.14159265358979323846. Very weird. I noticed when I went to look at the C++ to see how this algorithm was actually implemented.
https://github.com/alexandrefrancois/noFFT/blob/main/src/Res... line 31.
pvg•3d ago
james_a_craig•3d ago
pvg•3d ago
2YwaZHXV•3d ago
though I agree that it is odd to see, and not sure I see a reason why they wouldn't use 3.14159265358979323846
james_a_craig•3d ago
arjf•3d ago
pvg•3d ago