paulstretch_python

PaulStretch python version
Log | Files | Refs | README

paulstretch_mono.py (3160B)


      1 #
      2 # Paul's Extreme Sound Stretch (Paulstretch) - Python version
      3 #
      4 # by Nasca Octavian PAUL, Targu Mures, Romania
      5 # http://www.paulnasca.com/
      6 #
      7 # http://hypermammut.sourceforge.net/paulstretch/
      8 #
      9 # this file is released under Public Domain
     10 #
     11 
     12 
     13 import sys
     14 from numpy import *
     15 import scipy.io.wavfile
     16 import wave
     17 
     18 def load_wav(filename):
     19     try:
     20         wavedata=scipy.io.wavfile.read(filename)
     21         samplerate=int(wavedata[0])
     22         smp=wavedata[1]*(1.0/32768.0)
     23         if len(smp.shape)>1: #convert to mono
     24             smp=(smp[:,0]+smp[:,1])*0.5
     25         return (samplerate,smp)
     26     except:
     27         print ("Error loading wav: "+filename)
     28         return None
     29 
     30 
     31 
     32 ########################################
     33 
     34 def paulstretch(samplerate,smp,stretch,windowsize_seconds,outfilename):
     35     outfile=wave.open(outfilename,"wb")
     36     outfile.setsampwidth(2)
     37     outfile.setframerate(samplerate)
     38     outfile.setnchannels(1)
     39 
     40     #make sure that windowsize is even and larger than 16
     41     windowsize=int(windowsize_seconds*samplerate)
     42     if windowsize<16:
     43         windowsize=16
     44     windowsize=int(windowsize/2)*2
     45     half_windowsize=int(windowsize/2)
     46 
     47     #correct the end of the smp
     48     end_size=int(samplerate*0.05)
     49     if end_size<16:
     50         end_size=16
     51     smp[len(smp)-end_size:len(smp)]*=linspace(1,0,end_size)
     52 
     53     
     54     #compute the displacement inside the input file
     55     start_pos=0.0
     56     displace_pos=(windowsize*0.5)/stretch
     57 
     58     #create Hann window
     59     window=0.5-cos(arange(windowsize,dtype='float')*2.0*pi/(windowsize-1))*0.5
     60 
     61     old_windowed_buf=zeros(windowsize)
     62     hinv_sqrt2=(1+sqrt(0.5))*0.5
     63     hinv_buf=hinv_sqrt2-(1.0-hinv_sqrt2)*cos(arange(half_windowsize,dtype='float')*2.0*pi/half_windowsize)
     64 
     65     while True:
     66 
     67         #get the windowed buffer
     68         istart_pos=int(floor(start_pos))
     69         buf=smp[istart_pos:istart_pos+windowsize]
     70         if len(buf)<windowsize:
     71             buf=append(buf,zeros(windowsize-len(buf)))
     72         buf=buf*window
     73     
     74         #get the amplitudes of the frequency components and discard the phases
     75         freqs=abs(fft.rfft(buf))
     76 
     77         #randomize the phases by multiplication with a random complex number with modulus=1
     78         ph=random.uniform(0,2*pi,len(freqs))*1j
     79         freqs=freqs*exp(ph)
     80 
     81         #do the inverse FFT 
     82         buf=fft.irfft(freqs)
     83 
     84         #window again the output buffer
     85         buf*=window
     86 
     87 
     88         #overlap-add the output
     89         output=buf[0:half_windowsize]+old_windowed_buf[half_windowsize:windowsize]
     90         old_windowed_buf=buf
     91 
     92         #remove the resulted amplitude modulation
     93         output*=hinv_buf
     94         
     95         #clamp the values to -1..1 
     96         output[output>1.0]=1.0
     97         output[output<-1.0]=-1.0
     98 
     99         #write the output to wav file
    100         outfile.writeframes(int16(output*32767.0).tostring())
    101 
    102         start_pos+=displace_pos
    103         if start_pos>=len(smp):
    104             print ("100 %")
    105             break
    106         sys.stdout.write ("%d %% \r" % int(100.0*start_pos/len(smp)))
    107         sys.stdout.flush()
    108 
    109     outfile.close()
    110 ########################################
    111 
    112 (samplerate,smp)=load_wav("input.wav")
    113 
    114 paulstretch(samplerate,smp,8.0,0.25,"out.wav")
    115 
    116 
    117