diff --git a/README b/README new file mode 100644 index 0000000..96e16ab --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +This is Paulstretch , Python version +by Nasca Octavian PAUL, Targu Mures, Romania + +Requirements: Numpy, Scipy + diff --git a/paulstretch_stereo.py b/paulstretch_stereo.py new file mode 100755 index 0000000..4b2c53d --- /dev/null +++ b/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]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]) + + +