-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdrums.py
More file actions
148 lines (134 loc) · 5.33 KB
/
drums.py
File metadata and controls
148 lines (134 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
# encoding: utf=8
"""
drums.py
Add drums to a song.
At the moment, only works with songs in 4, and endings are rough.
By Ben Lacker, 2009-02-24.
"""
import numpy
import sys
import time
import echonest.audio as audio
usage="""
Usage:
python drums.py <inputfilename> <breakfilename> <outputfilename> <beatsinbreak> <barsinbreak> [<drumintensity>]
Example:
python drums.py HereComesTheSun.mp3 breaks/AmenBrother.wav HereComeTheDrums.mp3 64 4 0.6
Drum instenity defaults to 0.5
"""
BREAK_FILENAME = 'FunkyDrummer.wav'
def mono_to_stereo(audio_data):
data = audio_data.data.flatten().tolist()
new_data = numpy.array((data,data))
audio_data.data = new_data.swapaxes(0,1)
audio_data.numChannels = 2
return audio_data
def split_break(breakfile,n):
drum_data = []
start = 0
for i in range(n):
start = int((len(breakfile) * (i))/n)
end = int((len(breakfile) * (i+1))/n)
ndarray = breakfile.data[start:end]
new_data = audio.AudioData(ndarray=ndarray,
sampleRate=breakfile.sampleRate,
numChannels=breakfile.numChannels)
drum_data.append(new_data)
return drum_data
def add_fade_out(segment_data):
print "Adding fade out"
when_max_volume = segment_data.data.argmax()
samps_to_end = segment_data.endindex - when_max_volume
linear_max_volume = pow(10.0,segment_data.data.max()/20.0)
ss = 0
cur_vol = float(linear_max_volume)
if(samps_to_end > 0):
how_much_volume_to_decrease_per_samp = linear_max_volume/float(samps_to_end)
print how_much_volume_to_decrease_per_samp
for samps in xrange(samps_to_end):
cur_vol = cur_vol - how_much_volume_to_decrease_per_samp
try:
segment_data.data[ss] *= cur_vol
except IndexError:
pass
ss = ss + 1
return segment_data
def main(input_filename, output_filename, break_filename, break_parts,
measures, mix):
audiofile = audio.LocalAudioFile(input_filename)
sample_rate = audiofile.sampleRate
print "audiofile sample rate: "+str(sample_rate)
breakfile = audio.LocalAudioFile(break_filename)
if breakfile.numChannels == 1:
breakfile = mono_to_stereo(breakfile)
num_channels = audiofile.numChannels
drum_data = split_break(breakfile,break_parts)
hits_per_beat = int(break_parts/(4 * measures))
bars = audiofile.analysis.bars
out_shape = (len(audiofile),num_channels)
out = audio.AudioData(shape=out_shape, sampleRate=sample_rate,
numChannels=num_channels)
if not bars:
print "Didn't find any bars in this analysis!"
print "No output."
sys.exit(-1)
for bar in bars[:-1]:
beats = bar.children()
for i in range(len(beats)):
try:
break_index = ((bar.local_context()[0] %\
measures) * 4) + (i % 4)
except ValueError:
break_index = i % 4
tats = range((break_index) * hits_per_beat,
(break_index + 1) * hits_per_beat)
drum_samps = sum([len(drum_data[x]) for x in tats])
beat_samps = len(audiofile[beats[i]])
beat_shape = (beat_samps,num_channels)
tat_shape = (float(beat_samps/hits_per_beat),num_channels)
beat_data= audio.AudioData(shape=beat_shape,
sampleRate=sample_rate,
numChannels=num_channels)
for j in tats:
tat_data= audio.AudioData(shape=tat_shape,
sampleRate=sample_rate,
numChannels=num_channels)
if drum_samps > beat_samps/hits_per_beat:
# truncate drum hits to fit beat length
tat_data.data = drum_data[j].data[:len(tat_data)]
elif drum_samps < beat_samps/hits_per_beat:
# space out drum hits to fit beat length
#temp_data = add_fade_out(drum_data[j])
tat_data.append(drum_data[j])
tat_data.endindex = len(tat_data)
beat_data.append(tat_data)
del(tat_data)
# account for rounding errors
beat_data.endindex = len(beat_data)
mixed_beat = audio.mix(beat_data, audiofile[beats[i]], mix=mix)
del(beat_data)
out.append(mixed_beat)
finale = bars[-1].start + bars[-1].duration
last = audio.AudioQuantum(audiofile.analysis.bars[-1].start,
audiofile.analysis.duration -
audiofile.analysis.bars[-1].start)
last_data = audio.getpieces(audiofile,[last])
out.append(last_data)
out.encode(output_filename)
if __name__=='__main__':
try:
input_filename = sys.argv[1]
break_filename = sys.argv[2]
output_filename = sys.argv[3]
break_parts = int(sys.argv[4])
measures = int(sys.argv[5])
if len(sys.argv) == 7:
mix = float(sys.argv[6])
else:
mix = 0.5
except:
print usage
sys.exit(-1)
main(input_filename, output_filename, break_filename, break_parts,
measures, mix)