Package echonest :: Package remix :: Module modify
[hide private]
[frames] | no frames]

Source Code for Module echonest.remix.modify

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  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
21 - def doInBlocks(self, f, in_data, arg):
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
41 - def processAudio(self, f, data, arg):
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
57 - def shiftRate(self, audio_data, ratio=1):
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
66 - def shiftTempo(self, audio_data, ratio):
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
75 - def shiftRateChange(self, audio_data, percent):
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
84 - def shiftTempoChange(self, audio_data, percent):
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
93 - def shiftPitchSemiTones(self, audio_data, semitones=0):
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 # I think this is right, but maybe it has to be between -12 and 12? 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
103 - def shiftPitchOctaves(self, audio_data, octaves=0):
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 # what are the limits? Nothing in soundtouch documentation... 111 return self.doInBlocks(self.setPitchOctaves, audio_data.data, octaves)
112
113 - def shiftPitch(self, audio_data, ratio=1):
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