Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Nasca Octavian PAUL committed Feb 19, 2011
0 parents commit ec0dac9
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README
@@ -0,0 +1,5 @@
This is Paulstretch , Python version
by Nasca Octavian PAUL, Targu Mures, Romania

Requirements: Numpy, Scipy

149 changes: 149 additions & 0 deletions paulstretch_stereo.py
@@ -0,0 +1,149 @@
#!/usr/bin/env python
#
# Paul's Extreme Sound Stretch (Paulstretch) - Python version
#
# by Nasca Octavian PAUL, Targu Mures, Romania
#
# http://hypermammut.sourceforge.net/paulstretch/
#
#


import sys
from numpy import *
import scipy.io.wavfile
import wave
from optparse import OptionParser

def load_wav(filename):
try:
wavedata=scipy.io.wavfile.read(filename)
samplerate=int(wavedata[0])
smp=wavedata[1]*(1.0/32768.0)
smp=smp.transpose()
if len(smp.shape)==1: #convert to stereo
smp=tile(smp,(2,1))
return (samplerate,smp)
except:
print "Error loading wav: "+filename
return None



def optimize_windowsize(n):
orig_n=n
while True:
n=orig_n
while (n%2)==0:
n/=2
while (n%3)==0:
n/=3
while (n%5)==0:
n/=5

if n<2:
break
orig_n+=1
return orig_n

def paulstretch(samplerate,smp,stretch,windowsize_seconds,outfilename):
nchannels=smp.shape[0]

outfile=wave.open(outfilename,"wb")
outfile.setsampwidth(2)
outfile.setframerate(samplerate)
outfile.setnchannels(nchannels)

#make sure that windowsize is even and larger than 16
windowsize=int(windowsize_seconds*samplerate)
if windowsize<16:
windowsize=16
windowsize=optimize_windowsize(windowsize)
windowsize=int(windowsize/2)*2
half_windowsize=int(windowsize/2)

#correct the end of the smp
nsamples=smp.shape[1]
end_size=int(samplerate*0.05)
if end_size<16:
end_size=16

smp[:,nsamples-end_size:nsamples]*=linspace(1,0,end_size)


#compute the displacement inside the input file
start_pos=0.0
displace_pos=(windowsize*0.5)/stretch

#create Hann window
window=0.5-cos(arange(windowsize,dtype='float')*2.0*pi/(windowsize-1))*0.5

old_windowed_buf=zeros((2,windowsize))
hinv_sqrt2=(1+sqrt(0.5))*0.5
hinv_buf=(hinv_sqrt2-(1.0-hinv_sqrt2)*cos(arange(half_windowsize,dtype='float')*2.0*pi/half_windowsize))/hinv_sqrt2

while True:
#get the windowed buffer
istart_pos=int(floor(start_pos))
buf=smp[:,istart_pos:istart_pos+windowsize]
if buf.shape[1]<windowsize:
buf=append(buf,zeros((2,windowsize-buf.shape[1])),1)
buf=buf*window

#get the amplitudes of the frequency components and discard the phases
freqs=abs(fft.rfft(buf))

#randomize the phases by multiplication with a random complex number with modulus=1
ph=random.uniform(0,2*pi,(nchannels,freqs.shape[1]))*1j
freqs=freqs*exp(ph)

#do the inverse FFT
buf=fft.irfft(freqs)

#window again the output buffer
buf*=window

#overlap-add the output
output=buf[:,0:half_windowsize]+old_windowed_buf[:,half_windowsize:windowsize]
old_windowed_buf=buf

#remove the resulted amplitude modulation
output*=hinv_buf

#clamp the values to -1..1
output[output>1.0]=1.0
output[output<-1.0]=-1.0

#write the output to wav file
outfile.writeframes(int16(output.ravel(1)*32767.0).tostring())

start_pos+=displace_pos
if start_pos>=nsamples:
print "100 %"
break
print "%d %% \r" % int(100.0*start_pos/nsamples),
sys.stdout.flush()

outfile.close()

########################################
print "Paul's Extreme Sound Stretch (Paulstretch) - Python version 20110219"
print "by Nasca Octavian PAUL, Targu Mures, Romania\n"
parser = OptionParser(usage="usage: %prog [options] input_wav output_wav")
parser.add_option("-s", "--stretch", dest="stretch",help="stretch amount (1.0 = no stretch)",type="float",default=8.0)
parser.add_option("-w", "--window_size", dest="window_size",help="window size (seconds)",type="float",default=0.25)
(options, args) = parser.parse_args()


if (len(args)<2) or (options.stretch<=0.0) or (options.window_size<=0.001):
print "Error in command line parameters. Run this program with --help for help."
sys.exit(1)

print "stretch amount =",options.stretch
print "window size =",options.window_size,"seconds"
(samplerate,smp)=load_wav(args[0])

paulstretch(samplerate,smp,options.stretch,options.window_size,args[1])



0 comments on commit ec0dac9

Please sign in to comment.