The key parts of the application are as follows. First of all, the SoundTouchInterop32.cs and SoundTouchInterop64.cs files include the necessary PInvoke signatures to call the x86 and x64 versions of SoundTouch respectively. These are SoundTouch.dll and SoundTouch_x64.dll. Make sure these DLLs are available in the path when running.

I’ve also created a wrapper class called SoundTouch which simplifies access to SoundTouch and calls the correct PInvoke method depending on whether the process is 64 bit or not.

The next part is VarispeedSampleProvider. This implements NAudio’s ISampleProvider interface so it can be easily inserted into a signal chain. It also exposes a PlaybackRate property which can be set to 1.0 for regular speed and 2.0 for 2x playback etc.

The constructor for VarispeedSampleProvider takes a source provider, which is the input stream you want to speed up (in our example an audio file), the readDurationInMilliseconds, which allows control of how much will be read from the source provider in a single read. Obviously when you are speeding up or slowing down, the amount of audio you need to read from the source is different from the amount of time taken to play that audio. Something like 100ms will be fine to use here.

Finally, the SoundTouchProfile allows us to specify what SoundTouch options we want to use. There are a few switches you can experiment with which adjust quality and performance. The most significant is UseTempo. In tempo mode, SoundTouch will pitch compensate when you change speed, so the music will remain at the same pitch, just a different speed. This avoids the “chipmunk effect” when you play back at higher speeds. In the demo app I let you switch between modes while playback is stopped.

All that remains is to create an AudioFileReader, pass it into the VarispeedSampleProvider, and then pass that to the output device (WaveOutEvent in our example) to be played.

The one other thing worth mentioning in the demo project is that I allow you to reposition in the file, and when you do so, it’s a good idea to tell SoundTouch that a reposition has taken place so internal buffers can be flushed. This is done by calling Reposition on the VarispeedSampleProvider.

About Mark Heath

I'm a Microsoft MVP and software developer based in Southampton, England, currently working as a Software Architect for NICE Systems. I create courses for Pluralsight and am the author of several open source libraries. I currently specialize in architecting Azure based systems and audio programming. You can find me on: