Here is a example program that will take an audio sample, stretch it out in time but will preserve the pitch. It’s based loosely on paulstretch.
Written in BlitzMax NG.  The program is written for simplicity not speed.

The important variables are:

ScaleFactor : how much to stretch the audio, a value of 3 would be 3 times the original length.
WindowLen: Larger makes a cleaner sound but is slower to run. Must be a power of 2.
Number of threads to run: This should less that the number of logical cores on your cpu.

Hit escape key to exit the program. Download windows exe, sourcecode and included audio file HERE


'// Time stretch audio roughly based on paulstretch by A.Woodard [aaron at kerneltrick.com]

SuperStrict
Import brl.glmax2d
Import brl.threadpool
Import pub.freeaudio
Import brl.audio
Import brl.audiosample
Import brl.wavloader
Import brl.oggloader

AppTitle = "Timestretch audio in BlitzMax"

Type TTask Extends TRunnable
	Global mutex:TMutex = TMutex.Create()
	Field Readpos:Int, Writepos:Int
	Method New(Rp:Int, Wp:Int)
		ReadPos = Rp
		Writepos = Wp
		Print("task::new")
	End Method
	
	Method run()
		DoChunk(ReadPos, writepos, mutex)
		Delay 2
	End Method
End Type

SeedRnd(MilliSecs())

Const TWOPI:Double = Pi * 2
Const GW:Int = 800
Const GH:Int = 600
Const OrigAudioFile:String = "dhm.wav"

Global Tpool:TThreadPoolExecutor = TThreadPoolExecutor.newFixedThreadPool(4)  '// Num threads should be less than cpu cores
Global Origdata:Float[]
Global ScaleFactor:Float = 4													'// How much to stretch the audio
Global Newdata:Float[(Origdata.length * scalefactor) + 1]
Global WindowLen:Float = 1024 * 4												'// Window size, larger sounds better but is slower
Global Offset:Float = (WindowLen / 2) / (ScaleFactor)
Global ReadPos:Int = 0
Global N:Int = windowlen
Global orig:TAudioSample

Graphics GW, GH,0,10

DoStretch()

While Not KeyHit(KEY_ESCAPE)
	Cls
		DrawData()
		'DrawText(Tpool.threadCount + " " + Tpool.threadsWorking, 10, 10)
		
		If KeyHit(KEY_1) And Tpool.threadsWorking = 0 Then
			PlaySound(LoadSound(orig))
		EndIf
		
		If KeyHit(KEY_2) And Tpool.threadsWorking = 0 Then
			Local newdat:Short[Newdata.length]
			For Local i:Int = 0 Until newdat.Length
				newdat[i] = Newdata[i] * 32767
			Next
			Local newsamp:TAudioSample = New TAudioSample()
			newsamp.format = SF_MONO16LE
			newsamp = newsamp.CreateStatic(Varptr newdat[0], newdat.Length, 44100, SF_MONO16LE)
			PlaySound(LoadSound(newsamp))
		End If
		
		If Tpool.threadsWorking = 0 Then
			DrawText("Press 1 to play original sound, Press 2 to play stretched sound", 10, 10)
		Else
			DrawText("Working, wait....", 10, 10)
		EndIf
		
	Flip
Wend


'-------------------------------------------------------------------------------------------------
Function DoStretch()
	Local cPos:Int
	Local count:Int = 0
	If Not(Not (WindowLen & (WindowLen - 1))) Then Notify("windowlen must be pow/2", 1) ;End
	orig:TAudioSample = LoadAudioSample(OrigAudioFile)	'// Assumes Mono. Using ogg sample beacuse this func hates .wav
	If Not orig Then Notify("Cant load audio", 1) ;End
	orig = orig.Convert(SF_MONO16LE)
	Origdata = New Float[orig.Length]
	Local p:Short Ptr = Short Ptr(orig.samples)
	
	For Local i:Int = 0 Until orig.Length
		Origdata[i] = 0.8 * ((Float(Short(32767 - p[0])) / 32767.0) - 1.0) 
		p:+1
	Next
	
	Newdata = New Float[(Origdata.Length * ScaleFactor) + 1]
	
	While ReadPos + WindowLen < Origdata.Length
		CPos = ((N / 2) * Count)
		
		Tpool.execute(New TTask(ReadPos, CPos))
		
		Count:+1
		ReadPos:+Offset
	Wend
End Function


'-------------------------------------------------------------------------------------------------
Function DoChunk(Readpos:Int, Writepos:Int, mut:TMutex)
	Print "HERE  " + ReadPos + " " + Writepos
	Local cp:Float[N]
	Local sp:Float[N]
	Local SpecBuff:Float[]
	Local obuff:Float[]
	Local isr:Float = 0.853
	
	SpecBuff = Origdata[Readpos..(Readpos + N)]
	
	For Local i:Int = 0 Until N
		SpecBuff[i]:*Sine(Pi * i / (N))
	Next
	Speccy(SpecBuff, -1, cp, sp)
	cp[0] = 0
	sp[0] = 0
	For Local i:Int = 0 Until N / 2
		cp[i] = Sqr(cp[i] * cp[i] + sp[i] * sp[i])
		Local p:Float = Rnd(-Pi, Pi)
		sp[i] = cp[i] * Sine(p)
		cp[i] = cp[i] * Cosine(p)
	Next
	
	Speccy(SpecBuff, 1, cp, sp)
	
	For Local i:Int = 0 Until N
		SpecBuff[i]:*Sine(Pi * i / N)
	Next
	
	mut.Lock()	
		For Local i:Int = 0 Until N '/ 2
			Newdata[i + Writepos]:+(SpecBuff[i])		
			Newdata[i + Writepos]:*(isr - (1.0 - isr) * Sine(Pi * i / N))
		Next
		
		For Local i:Int = 0 Until N
			Newdata[i + Writepos] = ClampOne(Newdata[i + Writepos])
		Next
	mut.Unlock
	
	Function Speccy(buff:Float[], s:Int = -1, cp:Float[], sp:Float[])	'// Insanely slow !!!
		If s = 1 Then
			MemClear(Varptr buff[0], SizeOf(1:Float) * N)	
			For Local k:Int = 0 Until N
				For Local b:Int = 0 Until N / 2
					Local a:Float = 2.0 * b * Pi * k / N
					buff[k]:+(cp[b] * Cosine(a)) + ((-sp[b]) * Sine(a))
				Next
				buff[k] = 2 * buff[k] / N
			Next
		Else
			MemClear(Varptr cp[0], SizeOf(1:Float) * N)
			MemClear(Varptr sp[0], SizeOf(1:Float) * N)
			For Local k:Int = 0 Until N		
				For Local b:Int = 0 Until N / 2
					Local a# = 2.0 * b * Pi * k / N
					sp[b]:+Buff[k] * s * Sine(a)
					cp[b]:+buff[k] * Cosine(a)		
				Next
			Next
		End If
	EndFunction
End Function
'-------------------------------------------------------------------------------------------------
Function DrawData()
	Local x:Float
	Local xs:Float = GW / Float(Newdata.length)
	For Local i:Int = 0 Until Origdata.Length
		DrawRect(x, 200 + Origdata[i] * 100, 2, 1)
		x:+xs
	Next
	x = 0
	For Local i:Int = 0 Until Newdata.Length
		DrawRect(x, 400 + Newdata[i] * 100, 2, 1)
		x:+xs
	Next
	SetColor 255, 0, 255
	DrawText("Original", 50, 200 - 5)
	DrawText("Streched", 50, 400 - 5)
	SetColor 255, 255, 255
	'DrawRect(0, 200, 1000, 1)
	Delay 10
End Function

'-------------------------------------------------------------------------------------------------
Function Sine:Double(x:Double) inline
    Local k:Int;Local y:Double;Local z:Double
    z = x
    z:*0.3183098861837907
    z:+6755399441055744.0
    k = Int Ptr(Varptr(z))[0]
    z = k
    z:*3.1415926535897932
    x:-z;y = x;y:*x
    z = 0.0073524681968701
    z:*y
    z:-0.1652891139701474
    z:*y
    z:+0.9996919862959676
    x:*z;k:&1;k:+k;z = k;z:*x;x:-z
    Return x
End Function

'-------------------------------------------------------------------------------------------------
Function Cosine:Double(x:Double) Inline
	Return Sine((3.1415926535897932 / 2.0) - x)
End Function
'-------------------------------------------------------------------------------------------------
Function ClampOne:Double(x:Double) Inline
	Return 0.5 * (Abs(x + 1) - Abs(x - 1))
End Function
'-------------------------------------------------------------------------------------------------