Setting pitch of audio buffer?

Hey

I’m trying to write a program that plays audio buffers but I’m stuck on how to change the pitch or playback speed of a buffer.

Does anyone know how this could be achieved?

Basically what I want is to be able to call mBufferPlayerNode->start(); but have it play at a pitch I set.

Thanks

You can set the sample rate in the device used in your output node. Will that help?

I am not sure what “playing a buffer at a pitch” means. Could you explain?

Hey
I just want to change to playback speed so it plays at a different pitch. So if the playback speed is faster the pitch is higher etc. Would the sample rate change this?

I haven’t tried it myself, but I think it should. However, I don’t know whether the OS handling resampling to arbitrary sample rates on its own. Maybe you could do a test and share the results?

Hey theflyingtom it sounds like you want the ability to time-stretch / pitch shift audio interactively, in which case I wouldnt recommend changing the OS sample rate to do this. I dont think Cinder audio has a built in time stretching / downsampling algorithm built in so you might have to dig a bit deeper to do this.

The OS output sample rate (usually 44,100Hz, you can see these in the OS audio settings) should probably stay the same for the app at runtime which means the buffers should be processed at the sample rate / “speed”. This means you need to stretch / squash the audio data at the time you are filling the audio buffer ( assume your’e reading from an audio file). I haven’t written one of these algorithms myself but here is some reading matter that might help.


http://www.surina.net/soundtouch/
http://breakfastquay.com/rubberband/
and I think https://github.com/micknoise/Maximilian has granular pitch stretching

In which case, an easier approach would be to load the audio in Ableton or SuperCollider and control it from Cinder?

thanks @felixfaire This is what I’m after. I will do some digging and let you know how I go. Thanks for the resources.

@balachandran_c This would be easier but the end platform is a raspberry pi so I don’t think this is possible.

Hmm after doing some digging I’m not sure if this is what I’m after.
I’m trying to write a program that will play a sample at a certain pitch depending on which key is pressed on the keyboard.
For eg. press the key ‘g’ and the sample plays at its original speed and pitch.
press the key ‘h’ and it plays at a slightly higher pitch and speed.
‘f’ would be lower pitch and slower etc.

It seems that the audio buffer will need to be resampled to play it at a higher/lower pitch. Is this going to be extremely expensive to do?
Would I run the bufferPlayerNode into a bufferRecorderNode that is set to a different sample rate?
If so would this make realtime very difficult to achieve?

I feel like I may be over complicating this problem but also maybe it’s not as easy as I imagine it is.

I think what you’re asking for is the feature on this issue, ‘varispeed playback’. I was hoping to get to it during this release cycle but didn’t manage to. It isn’t too difficult but there are some intricacies in doing it right; ideally the speed would be controllable with an audio::Param() that can be ramped smoothly.

As that feature isn’t implemented yet, you could use libpd (Cinder-PureDataNode), there are many publically available patches that will do pitch-controlled buffer playback. Would also love it if someone else decided to take this one on, I can discuss implementation strategies if so.

I think maybe I can make this work using mBufferPlayerNode->seek() to control the speed

It seems like you can run super collider on RPi. http://celesteh.blogspot.in/2014/04/building-supercollider-36-on-raspberry.html

If you don’t need time-variable speed adjustment, another thing you could do is make a bunch of copies of your sample and place them in different audio::BufferRefs, and then use an audio::dsp::Converter to change their samplerate. Then when you want to play a specific pitched version, you swap it into the audio::BufferPlayerNode with its setBuffer() method. Kinda brute force IMO, really its obvious to me now that we need a speed control directly on BufferPlayerNode.