Time-stretching individual partials
Hi all,
So I want to do a partial analysis on a sample, crop it to keep only the dominant partials (ie above a certain amplitude) and then shorten those partials proportionally. When I try it out on SPEAR/Audiosculpt it makes a voice sound like bubbles, without sounding too artifact-y. I want to use it, or a process like it, in a piece where voice degrades.
I'm pretty certain this is an fft thing, but honestly whenever I try pfft~ stuff, my brain just keeps hurting, and I still can't get over that they use words like windows and bins. I've searched around on these forums and have found a lot of fft/gen stuff for time stretching generally, but I'm more interested in screwing around with partials themselves rather than a sample as a whole. I'm not necessarily looking at something to recreate SPEAR in Max, but I'd like to be able to learn how it works.
Any help & pointers very appreciated :)
It's hard to do much with pfft~ without knowing a little bit about why it works, but there are some great tutorials available -- here's a few:
https://docs.cycling74.com/max7/tutorials/14_analysischapter04
https://www.youtube.com/watch?v=69A1kGNFYIc
https://www.youtube.com/watch?v=9gQAHf0Sf9I
Filtering out the lower amplitude frequency bins is pretty simple: if the amplitude is less than your threshold, set them to zero. Shortening is a bit trickier. I guess you would first need to detect when a new transient begins (when the amplitude rises above a threshold, perhaps?), and then increase playback speed until the transient falls below a certain threshold again. Which means this isn't a real-time effect, but based on playback from stored sonogram data.
Hey Graham, cheers for the reply. Cool, thanks for the noise reduction bits. I feel like I do kind of get it in principle but when it comes to the actual numbers and cartpols and stuff I get confused.
I don't think I want the playback speed to be higher because then you're going to get the same rhythm at a higher tempo. like this:
Sped Up: https://instaud.io/1y6B
Whereas what I want to be able to control sounds like this:
Shorten: https://instaud.io/1y6x (I like the space it has between the partials which you don't get if you increase playback speed)
Longer: https://instaud.io/1y6z (also cool)
(thru SPEAR)
- unless you mean a variable playback speed for individual transients depending on their original length, in which case you're definitely a wizard, is that possible?
Yeah, what I mean is to speed up the specific transients only.
Here's an example of recording amplitude & phase data to a buffer~, and then playing it back, via pfft~ and gen~. This could form the basic infrastructure for what you want to do.
I'd first try to get the transient detection going. For that you'll need to store state *per bin*. Simplest thing would be to have an onset threshold, and say a transient begins when the bin's amplitude rises above this threshold, and ends when it drops below again. You could easily test this by scaling all output amplitudes to zero if the transient is not detected.
A better detector might use different rising/falling thresholds and slopes. I'd recommend looking at the gen~ vectral example as the simplest demo of per-bin processing (hint: it uses a [data vectorsize] object to store per bin information).
Once that works, then you could use the presence of a transient to increase the playback speed *for that bin only*.