Audio artifacts when playing audio material slowly in sfplay~ (and groove~)

Daniel Craig's icon

Hello.
I have found that when playing audio material down in pitch in sfplay~ (by playing the material at a slower speed, without using time stretching) some very noticeable audio artifacts are being created.
These appear to originate from roughly around where the Nyquist rate is of the original audio material and it tends to sound a little bit like a bit crusher.
For example, assuming we are working at 44KHz, if I play something two octaves down, (at 0.25 speed), there is a clear group of three overtones created between 10K and 12K.
This problem is not quite as pronounced with the groove~ object, but it is still quite noticeable.
I have tried upsampling with poly~ but this doesn't seem to work.
I am using Max 8.
So far the only solution I can think of is using another program to pitch down material I wish to repitch in sfplay~. Of course, this will require the creation of lots of really long audio files. Perhaps somebody has a more elegant solution?
I will be appreciative of any help.
Thank you :)

volker böhm's icon

These are most likely interpolation/resampling artefacts. Using the wave~ object you can choose from various interpolation modes (and groove~ just uses one of those) and study the results - but sadly max doesn't offer high quality interpolation. In max6 the groove~ object had a 'resample' option, but they killed in in later versions, probably because it has always been buggy.
So, I'm afraid you won't get there with plain max objects. Out of this reason, a few years ago, I had written an external object incorporating Dominic Manzoni's free resampling library, which worked quite ok. You might be able to still find this online somewhere (it was called resample~). When max6 with the groove~ resample option came out, I (prematurely) ditch my object.
Then, two years ago, I made a new object for a client, which uses Erik de Castro Lopo's 'Secret Rabbit Code' (SRC) - a high quality sample rate converter library, which changed at the time to a BSD license.
I realize now, that I have never finished the necessary steps to publicly release it.
So, if there is interest in any of these, I can have a look and hopefully dig something out.
By the way, these objects work with buffered audio (so, no sfplay~). (and macos version only, so far).
vb

Chris Rolfe's icon

Yes, as Volker says, it's frequency aliasing. Btw, play~ defaults to 'basic' quality for pitchshifting. You probably want 'best'.

Chris Rolfe's icon

@Volker

It'd be great if you released an MSP object for SRC. Please do.

What's available for realtime on Max is pretty good (there's a cubic, hermite, etc.) but there's no windowed sinc interp. The ZTX pitch-shifter adds formant preservation and transient detection but is proprietary. Hard to say what algorithms pitchshift~ and retune~ are using at the core: the choices are 'basic', 'good', 'better', or 'best' which isn't particularly enlightening.

On the resampling side, I've been revisiting fractional resampling lately. Any thoughts there? Something w/ a polyphase anti-aliasing filter might be pretty fast.

Daniel Craig's icon

Thank you very much to both of you for your very informative responses.

@ Volker
Yes, these past projects of yours interest me very much.
In particular something that behaves like groove~ (with loop sync output to allow one to build smooth crossfades in loops) but with higher quality interpolation would be amazing.
I can't find resample~, although I guess if it's quite old it would be for 32 Bit anyway (I kind of need to run 64).

volker böhm's icon

just to let you know: I found the code for the resample~ object und basically updating for 64bit was no big deal.
but there are still a few issues that need to be resolved...
will come back to this a little later.

Daniel Craig's icon

@ Volker
Thank you.
That's great to hear.
I eagerly await a chance to try it out :)

volker böhm's icon

Hey, so [resample~] works quite ok now, but there are still some gritty details not functioning properly.
And when I compared the results to libsamplerate (by Erik de Castro Lopo) I decided to skip working on resample~ in favour of a shiny, new [vb.src~] !
It uses libsamplerate inside, which should therefore be the best and cleanest option for variable speed playback.
known issues:
- it's not happy with very small buffer sizes, so don't try to build a wavetable osc with it.
- it's ridiculously expensive for very high playback speeds
- it's designed after [groove~] but doesn't have loop points (yet)
get it here: https://vboehm.net/downloads

it's new and pretty much untested, so please report back your findings >)

Daniel Craig's icon

@ Volker
Thank you very much for making this, it is very useful for me.
For most sounds I have tested, it sounds a lot better than groove~ at slow play speeds. It is also not too expensive on CPU (Currently my master patch has 256 instances of vb.src~ and it handles it quite fine).
Initially I had problems in that it often caused Max to freeze and then crash. In particular setting the object to reference another buffer seemed to create the problem. However, I've found that if I don't have multiple vb.src~ objects with the same name, the problem stops (perhaps I was a little silly for not working this out earlier).
Thank you again. A kind person and a scholar you are indeed!

volker böhm's icon

thanks, daniel, glad to hear that it is useful to you and thanks for the report. will investigate if I find the time.
vb

TobyAM's icon

Would love to try this on Windows for my instrument! Sounds juicy

Roman Thilenius's icon


even a proper samplingrate conversion will not get rid of the fact that at /8 speed, the spectrum of the sound ends at nyquist /8.