1   
  2   
  3  """ 
  4  modify.py 
  5   
  6  Created by Ben Lacker on 2009-06-12. 
  7  Stereo modifications by Peter Sobot on 2011-08-24 
  8  """ 
  9  from echonest.remix.audio import * 
 10  import numpy 
 11  import soundtouch 
 12   
 13 -class Modify(soundtouch.SoundTouch): 
  14 -    def __init__(self, sampleRate=44100, numChannels=1, blockSize = 10000): 
  15          self.setSampleRate(sampleRate) 
 16          self.setChannels(numChannels) 
 17          self.sampleRate = sampleRate 
 18          self.numChannels = numChannels 
 19          self.blockSize = blockSize 
  20   
 22          if self.numChannels == 2: 
 23              c = numpy.empty( ( in_data.size, ), dtype=in_data.dtype ) 
 24              c[0::2] = in_data[:, 0] 
 25              c[1::2] = in_data[:, 1] 
 26              in_data = c 
 27          elif in_data.ndim > 1: 
 28              in_data = in_data[:, 0] 
 29          collect = [] 
 30          if len(in_data) > self.blockSize: 
 31              for x in range(len(in_data)/self.blockSize): 
 32                  start = x * self.blockSize 
 33                  data = in_data[start:start + self.blockSize -1] 
 34                  collect.append(self.processAudio(f, data, arg)) 
 35              data = in_data[-1*(len(in_data) % self.blockSize):] 
 36              collect.append(self.processAudio(f, data, arg)) 
 37          else: 
 38              collect.append(self.processAudio(f, in_data, arg)) 
 39          return assemble(collect, numChannels=self.numChannels, sampleRate=self.sampleRate) 
  40   
 42          f(arg) 
 43          self.putSamples(data) 
 44          out_data = numpy.array(numpy.zeros((len(data)*2,), dtype=numpy.float32)) 
 45          out_samples = self.receiveSamples(out_data) 
 46          shape = (out_samples, ) 
 47          if self.numChannels == 2: 
 48              nd = numpy.array( numpy.zeros( ( out_samples, self.numChannels ), dtype=numpy.float32 ) ) 
 49              nd[:, 0] = out_data[0::2][:out_samples] 
 50              nd[:, 1] = out_data[1::2][:out_samples] 
 51              out_data = nd 
 52              shape = (out_samples, 2) 
 53          new_ad = AudioData(ndarray=out_data[:out_samples*self.numChannels], shape=shape,  
 54                      sampleRate=self.sampleRate, numChannels=self.numChannels) 
 55          return new_ad 
  56   
 58          if not isinstance(audio_data, AudioData): 
 59              raise TypeError('First argument must be an AudioData object.') 
 60          if not (isinstance(ratio, int) or isinstance(ratio, float)): 
 61              raise ValueError('Ratio must be an int or float.') 
 62          if (ratio < 0) or (ratio > 10): 
 63              raise ValueError('Ratio must be between 0 and 10.') 
 64          return self.doInBlocks(self.setRate, audio_data.data, ratio) 
  65   
 67          if not isinstance(audio_data, AudioData): 
 68              raise TypeError('First argument must be an AudioData object.') 
 69          if not (isinstance(ratio, int) or isinstance(ratio, float)): 
 70              raise ValueError('Ratio must be an int or float.') 
 71          if (ratio < 0) or (ratio > 10): 
 72              raise ValueError('Ratio must be between 0 and 10.') 
 73          return self.doInBlocks(self.setTempo, audio_data.data, ratio) 
  74   
 76          if not isinstance(audio_data, AudioData): 
 77              raise TypeError('First argument must be an AudioData object.') 
 78          if not (isinstance(percent, int) or isinstance(percent, float)): 
 79              raise ValueError('Percent must be an int or float.') 
 80          if (percent < -50) or (percent > 100): 
 81              raise ValueError('Percent must be between -50 and 100.') 
 82          return self.doInBlocks(self.setRateChange, audio_data.data, percent) 
  83   
 85          if not isinstance(audio_data, AudioData): 
 86              raise TypeError('First argument must be an AudioData object.') 
 87          if not (isinstance(percent, int) or isinstance(percent, float)): 
 88              raise ValueError('Percent must be an int or float.') 
 89          if (percent < -50) or (percent > 100): 
 90              raise ValueError('Percent must be between -50 and 100.') 
 91          return self.doInBlocks(self.setTempoChange, audio_data.data, percent) 
  92   
 94          if not isinstance(audio_data, AudioData): 
 95              raise TypeError('First argument must be an AudioData object.') 
 96          if not isinstance(semitones, int): 
 97              raise TypeError('Second argument must be an integer.') 
 98           
 99          if abs(semitones) > 60: 
100              raise ValueError('Semitones argument must be an int between -60 and 60.') 
101          return self.doInBlocks(self.setPitchSemiTones, audio_data.data, semitones) 
 102   
104          if not isinstance(audio_data, AudioData): 
105              raise TypeError('First argument must be an AudioData object.') 
106          if not (isinstance(octaves, int) or isinstance(octaves, float)): 
107              raise ValueError('Octaves must be an int or float.') 
108          if abs(octaves) > 5: 
109              raise ValueError('Octaves argument must be between -5 and 5.') 
110           
111          return self.doInBlocks(self.setPitchOctaves, audio_data.data, octaves) 
 112       
114          if not isinstance(audio_data, AudioData): 
115              raise TypeError('First argument must be an AudioData object.') 
116          if not (isinstance(ratio, int) or isinstance(ratio, float)): 
117              raise ValueError('Ratio must be an int or float.') 
118          if (ratio < 0) or (ratio > 10): 
119              raise ValueError('Ratio must be between 0 and 10.') 
120          return self.doInBlocks(self.setPitch, audio_data.data, ratio) 
  121