/examples/drums/drums.py

http://echo-nest-remix.googlecode.com/ · Python · 144 lines · 122 code · 7 blank · 15 comment · 19 complexity · 9e1cb33a39d0362260dd48504821307a MD5 · raw file

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