Phase vocoder in RNBO — is a hop size smaller than the FFT size possible?
I'm porting a Max for Live device to RNBO for a Raspberry Pi build. The original uses gizmo~ inside pfft~ for pitch shifting, and since RNBO has neither object I've been implementing a phase vocoder in codebox~ following Laroche & Dolson's peak-shifting method.
The algorithm itself works. On a bin-centred sine tone it shifts accurately at every ratio I need (0.5, 1.5, 2, 3, 4), measuring within about a cent with a single clean peak and no sidebands. On real instruments and on granular buffer playback it's unusable, a constant fluttering, at a musical rate rather than at the frame rate or any multiple of it.
I believe the cause is analysis time resolution, and I'd like to know whether there's a way around it that I've missed.
As far as I can tell, fft~ streams one bin per sample, so a 2048-point FFT necessarily takes 2048 samples to emit a frame and the hop is locked to the FFT size. I'm getting overlap by running four fft~/ifft~ chains in parallel with phase offsets of 0/512/1024/1536, which does give a properly overlapped output sum. But each individual chain still analyses on a 46 ms window, so nothing faster than that is resolved, and gizmo~ inside pfft~ at overlap 4 has a hop of N/4.
Things I've already tried:
fft~ 2048 512 0— no change, consistent with framesize being clamped to the FFT sizedropping to 512-point FFTs with four chains at 64-sample offsets, for an 11.6 ms window, improves nothing audibly and costs frequency resolution
one chain versus four sounds the same, so it isn't the chains disagreeing with each other
measuring the peak set frame to frame on real instrument: only about 22% of detected peaks persist at the same bin between frames, and the count swings between roughly 50 and 150 per frame, so the spectral partitioning is being redrawn 21 times a second. Adding a prominence test cut the peak count to around 6 and raised persistence to 42%, but didn't change what I hear.
My questions:
Is there any way to get a genuine hop smaller than the FFT size in RNBO, an
fft~argument or attribute I've missed, or another approach entirely?fftstream/ifftstreamincodebox~looked like the right tool but fails withNo option of name: win_bufnameon RNBO 1.4.5, which I understand was supposed to be fixed in 1.4.4. Is that expected, and is there a working example of them anywhere?Has anyone got a phase vocoder working well in RNBO? I couldn't find one published.
Is a
gizmo~equivalent, orpfft~-style overlapped framing, on the roadmap?
Happy to share the codebox~ source and measurements if useful. Running RNBO 1.4.5 in Max 9, targeting a Pi with a Pisound Micro.