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