PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/examples/drums/drums.py

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