Skip to content

Instantly share code, notes, and snippets.

@koyachi
Created January 4, 2010 16:06
Show Gist options
  • Save koyachi/268614 to your computer and use it in GitHub Desktop.
Save koyachi/268614 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'rubygems'
#require 'scissor'
#require 'scissor/echonest'
require 'echonest'
require 'yaml'
file = ARGV[0] || 'vera_lynn-over_the_rainbow.mp3'
echonest = Echonest 'YOUR_KEY'
open "#{file}.sections.yaml", "w" do |f|
f.write YAML.dump(echonest.get_sections(file))
end
open "#{file}.segemnts.yaml", "w" do |f|
f.write YAML.dump(echonest.get_segments(file))
end
open "#{file}.beats.yaml", "w" do |f|
f.write YAML.dump(echonest.get_beats(file))
end
require 'rubygems'
require 'scissor'
require 'yaml'
file = ARGV[0] || 'vera_lynn-over_the_rainbow.mp3'
start_sec = ARGV[1].to_f
end_sec = ARGV[2].to_f
duration = end_sec - start_sec
p "#{start_sec} #{duration}"
file = File.expand_path file
dir = File.dirname file
basename = File.basename file
beats = YAML.load_file("#{file}.beats.yaml") .map{|e|e.ivars['value']}
mp3 = Scissor file
extracted_beats = beats.find_all do |beat|
beat > start_sec && beat < (start_sec + duration)
end
puts extracted_beats.join(', ')
prev = extracted_beats.shift
extracted_beats.map do |beat|
fragment = mp3.slice prev, beat - prev
prev = beat
fragment
end.inject(Scissor()) do |r,i|
r + i
end.to_file "#{dir}/#{basename}.extracted.mp3"
__END__
# [memo]
# % ruby extract.rb 56 22
# 56.54187, 57.45314, 58.39871, 59.33056, 60.26698, 61.17596, 62.09638, 63.00536, 63.91434, 64.82103, 65.72315, 66.6207, 67.50452, 68.39063, 69.27217, 70.06129, 70.77629, 71.66926, 72.55537, 73.49408, 74.42962, 75.40833, 76.35507, 77.26986
# 2010-01-05 koyachi
#% ruby extract.rb Arabic\ Music\ from\ Jordan.mp3 215 238
#"215.0 23.0"
#215.4816, 216.02584, 216.56888, 217.11929, 217.65863, 218.20906, 218.76042, 219.3053, 219.85663, 220.4043, 220.95103, 221.50423, 222.05833, 222.60874, 223.15455, 223.70947, 224.25493, 224.79895, 225.34278, 225.88716, 226.4318, 226.97593, 227.51933, 228.06418, 228.60813, 229.15321, 229.70244, 230.24455, 230.79124, 231.34051, 231.88133, 232.42425, 232.96802, 233.51765, 234.05645, 234.6016, 235.14536, 235.68942, 236.22777, 236.77133, 237.32174, 237.8716
# result
# => http://soundcloud.com/koyachi/arabic-music-from-jordan-mp3-randomsort-10240-320
require 'rubygems'
require 'scissor'
# over the rainbow
#$beats = [56.54187, 57.45314, 58.39871, 59.33056, 60.26698, 61.17596, 62.09638, 63.00536, 63.91434, 64.82103, 65.72315, 66.6207, 67.50452, 68.39063, 69.27217, 70.06129, 70.77629, 71.66926, 72.55537, 73.49408, 74.42962, 75.40833, 76.35507, 77.26986]
# Arabic Music from Jordan
$beats = [215.4816, 216.02584, 216.56888, 217.11929, 217.65863, 218.20906, 218.76042, 219.3053, 219.85663, 220.4043, 220.95103, 221.50423, 222.05833, 222.60874, 223.15455, 223.70947, 224.25493, 224.79895, 225.34278, 225.88716, 226.4318, 226.97593, 227.51933, 228.06418, 228.60813, 229.15321, 229.70244, 230.24455, 230.79124, 231.34051, 231.88133, 232.42425, 232.96802, 233.51765, 234.05645, 234.6016, 235.14536, 235.68942, 236.22777, 236.77133, 237.32174, 237.8716]
$beat_index = (0..$beats.length-2).map{|i| i}
$po_size = 1024 * 10
$step = $po_size / 32
srand Time.now.to_i
def init_population(size)
population = (1..size).map do |i|
{
:dna => $beat_index.shuffle,
:survived => 1,
:parent => 0,
:fitness => 0,
}
end
end
def update_fitness(population)
population.each do |po|
po[:fitness] = fitness $beat_index, po[:dna], $beat_index.length-1
end
end
def fitness(a, b, len, offset = 0)
denominator = (len - offset) ** 2
result = (offset..len).map do |i|
(a[i] - b[i]) ** 2
end.inject(0){|r,i| r + i}.to_f
1.0 - Math.sqrt(result) / denominator
end
def process(i)
population = init_population $po_size
update_fitness population
sorted_population = population.sort{|a,b| a[:fitness] <=> b[:fitness]}
sorted_population.each do |po|
p "#{po[:fitness]} #{po[:dna].join(',')}"
end
sorted_population
end
def gen_mp3(population)
# file = 'vera_lynn-over_the_rainbow.mp3'
file = 'Arabic Music from Jordan.mp3'
file = File.expand_path file
dir = File.dirname file
basename = File.basename file
mp3 = Scissor file
prev = $beats.shift
segments = $beats.map do |b|
r = {
:start => b,
:duration => b - prev,
}
prev = b
r
end
fragments = []
population.each_with_index do |po,i|
if i % $step == 0
fragments << po[:dna].map do |seq|
fragment = mp3.slice segments[seq][:start], segments[seq][:duration]
end.inject(Scissor()){|r,e| r+e}
end
end
fragments.inject(Scissor()){|r,e| r+e}.to_file "#{dir}/#{basename}.randomsort_#{$po_size}_#{$step}.mp3"
end
population = process 0
gen_mp3 population
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment