mr_eko 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -0
- data/README.md +2 -0
- data/Rakefile +171 -0
- data/TODO +1 -0
- data/bin/mreko +90 -0
- data/db/migrate/001_add_playlists.rb +16 -0
- data/db/migrate/002_add_songs.rb +36 -0
- data/db/migrate/003_add_useful_song_fields.rb +20 -0
- data/db/migrate/04_add_code_to_songs.rb +13 -0
- data/ext/enmfp/LICENSE +54 -0
- data/ext/enmfp/README +96 -0
- data/ext/enmfp/RELEASE_NOTES +34 -0
- data/ext/enmfp/codegen.Darwin +0 -0
- data/ext/enmfp/codegen.Linux-i686 +0 -0
- data/ext/enmfp/codegen.Linux-x86_64 +0 -0
- data/ext/enmfp/codegen.windows.exe +0 -0
- data/lib/mr_eko/core.rb +16 -0
- data/lib/mr_eko/playlist.rb +100 -0
- data/lib/mr_eko/presets.rb +29 -0
- data/lib/mr_eko/song.rb +122 -0
- data/lib/mr_eko.rb +101 -0
- data/mr_eko.gemspec +97 -0
- data/test/mr_eko_test.rb +25 -0
- data/test/playlist_test.rb +135 -0
- data/test/test.rb +22 -0
- metadata +227 -0
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'date'
|
4
|
+
require "bundler"
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
#############################################################################
|
7
|
+
#
|
8
|
+
# Helper functions
|
9
|
+
#
|
10
|
+
#############################################################################
|
11
|
+
|
12
|
+
def name
|
13
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
18
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
19
|
+
end
|
20
|
+
|
21
|
+
def date
|
22
|
+
Date.today.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def rubyforge_project
|
26
|
+
name
|
27
|
+
end
|
28
|
+
|
29
|
+
def gemspec_file
|
30
|
+
"#{name}.gemspec"
|
31
|
+
end
|
32
|
+
|
33
|
+
def gem_file
|
34
|
+
"#{name}-#{version}.gem"
|
35
|
+
end
|
36
|
+
|
37
|
+
def replace_header(head, header_name)
|
38
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
39
|
+
end
|
40
|
+
|
41
|
+
#############################################################################
|
42
|
+
#
|
43
|
+
# Standard tasks
|
44
|
+
#
|
45
|
+
#############################################################################
|
46
|
+
|
47
|
+
task :default => :test
|
48
|
+
|
49
|
+
require 'rake/testtask'
|
50
|
+
Rake::TestTask.new(:test) do |test|
|
51
|
+
test.libs << 'lib' << 'test'
|
52
|
+
test.verbose = true
|
53
|
+
test.pattern = 'test/**/*_test.rb'
|
54
|
+
test.ruby_opts << "-rubygems -rtest"
|
55
|
+
test.warning = false
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Generate RCov test coverage and open in your browser"
|
60
|
+
task :coverage do
|
61
|
+
require 'rcov'
|
62
|
+
sh "rm -fr coverage"
|
63
|
+
sh "rcov test/test_*.rb"
|
64
|
+
sh "open coverage/index.html"
|
65
|
+
end
|
66
|
+
|
67
|
+
require 'rake/rdoctask'
|
68
|
+
Rake::RDocTask.new do |rdoc|
|
69
|
+
rdoc.rdoc_dir = 'rdoc'
|
70
|
+
rdoc.title = "#{name} #{version}"
|
71
|
+
rdoc.rdoc_files.include('README*')
|
72
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
73
|
+
end
|
74
|
+
|
75
|
+
#############################################################################
|
76
|
+
#
|
77
|
+
# Custom tasks (add your own tasks here)
|
78
|
+
#
|
79
|
+
#############################################################################
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
#############################################################################
|
84
|
+
#
|
85
|
+
# Packaging tasks
|
86
|
+
#
|
87
|
+
#############################################################################
|
88
|
+
|
89
|
+
desc "Create tag v#{version} and push to Github"
|
90
|
+
task :release => :build do
|
91
|
+
unless `git branch` =~ /^\* master$/
|
92
|
+
puts "You must be on the master branch to release!"
|
93
|
+
exit!
|
94
|
+
end
|
95
|
+
# sh "git commit --allow-empty -a"
|
96
|
+
sh "git tag v#{version}"
|
97
|
+
sh "git push origin master"
|
98
|
+
sh "git push origin v#{version}"
|
99
|
+
end
|
100
|
+
|
101
|
+
desc "Build #{gem_file} into the pkg directory"
|
102
|
+
task :build => :gemspec do
|
103
|
+
sh "mkdir -p pkg"
|
104
|
+
sh "gem build #{gemspec_file}"
|
105
|
+
sh "mv #{gem_file} pkg"
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "Generate #{gemspec_file}"
|
109
|
+
task :gemspec => :validate do
|
110
|
+
# read spec file and split out manifest section
|
111
|
+
spec = File.read(gemspec_file)
|
112
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
113
|
+
|
114
|
+
# replace name version and date
|
115
|
+
replace_header(head, :name)
|
116
|
+
replace_header(head, :version)
|
117
|
+
replace_header(head, :date)
|
118
|
+
#comment this out if your rubyforge_project has a different name
|
119
|
+
replace_header(head, :rubyforge_project)
|
120
|
+
|
121
|
+
# determine file list from git ls-files
|
122
|
+
files = `git ls-files`.
|
123
|
+
split("\n").
|
124
|
+
sort.
|
125
|
+
reject { |file| file =~ /^\./ }.
|
126
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
127
|
+
map { |file| " #{file}" }.
|
128
|
+
join("\n")
|
129
|
+
|
130
|
+
# piece file back together and write
|
131
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
132
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
133
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
134
|
+
puts "Updated #{gemspec_file}"
|
135
|
+
end
|
136
|
+
|
137
|
+
desc "Validate #{gemspec_file}"
|
138
|
+
task :validate do
|
139
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
140
|
+
unless libfiles.empty?
|
141
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
142
|
+
exit!
|
143
|
+
end
|
144
|
+
unless Dir['VERSION*'].empty?
|
145
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
146
|
+
exit!
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
desc "Load all the codes"
|
152
|
+
task :environment do
|
153
|
+
require 'lib/mr_eko'
|
154
|
+
end
|
155
|
+
|
156
|
+
desc 'Launch an IRB console'
|
157
|
+
task :console do
|
158
|
+
libs = "-rlib/mr_eko -rirb/completion"
|
159
|
+
exec "irb #{libs}"
|
160
|
+
end
|
161
|
+
|
162
|
+
namespace :db do
|
163
|
+
|
164
|
+
desc "Migrate up to the latest schema"
|
165
|
+
task :migrate => :environment do
|
166
|
+
require 'sequel/extensions/migration'
|
167
|
+
# Sequel::Migrator.apply(MrEko.connection, File.join(File.dirname(__FILE__), "db", "migrate"), 0) # DOWN
|
168
|
+
Sequel::Migrator.apply(MrEko.connection, File.join(File.dirname(__FILE__), "db", "migrate"))
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Figure out how to get FFMPEG included in gem (possible w/ licensing?)
|
data/bin/mreko
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$0 = 'Mr Eko'
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), '../lib')
|
5
|
+
require 'mr_eko'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
require 'sequel/extensions/migration'
|
9
|
+
Sequel::Migrator.apply(MrEko.connection, File.join(File.dirname(__FILE__), "..", "db", "migrate"))
|
10
|
+
|
11
|
+
def parse_options
|
12
|
+
|
13
|
+
options = { :format => :text }
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: #{$0} [options]"
|
17
|
+
|
18
|
+
opts.separator ""
|
19
|
+
opts.separator "Specific options:"
|
20
|
+
opts.on("-p", "--preset NAME", String, "Select a preset. Options are (#{MrEko::Presets::FACTORY.keys.join(', ')})") do |preset|
|
21
|
+
options[:preset] = preset
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-m", "--min-tempo BPM", Integer, "Specify minimum tempo") do |bpm|
|
25
|
+
options[:min_tempo] = bpm
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-M", "--max-tempo BPM", Integer, "Specify maximum tempo") do |bpm|
|
29
|
+
options[:max_tempo] = bpm
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-t", "--time-sig SIG", Integer, "Specify time signature") do |ts|
|
33
|
+
options[:time_signature] = ts
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-l", "--max-length SEC", Integer, "Specify maximum song length (in seconds)") do |sec|
|
37
|
+
options[:max_duration] = sec
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-d", "--mode MODE", String, "Specify mode (minor or major)") do |mode|
|
41
|
+
unless MrEko::MODES.include?(mode)
|
42
|
+
raise ArgumentError.new("Mode must be #{MrEko::MODES.join(' or ')}")
|
43
|
+
end
|
44
|
+
options[:mode] = mode
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("-f", "--format FORMAT", MrEko::Playlist::FORMATS,
|
48
|
+
"Select output type (#{MrEko::Playlist::FORMATS.join(', ')})") do |format|
|
49
|
+
unless MrEko::Playlist::FORMATS.include?(format)
|
50
|
+
raise ArgumentError.new("Format must be one of #{MrEko::Playlist::FORMATS.join(', ')}")
|
51
|
+
end
|
52
|
+
options[:format] = format
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
opts.separator ""
|
57
|
+
opts.separator "Common options:"
|
58
|
+
|
59
|
+
# No argument, shows at tail. This will print an options summary.
|
60
|
+
# Try it and see!
|
61
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
62
|
+
puts opts
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
|
66
|
+
# Another typical switch to print the version.
|
67
|
+
# opts.on_tail("--version", "Show version") do
|
68
|
+
# puts OptionParser::Version.join('.')
|
69
|
+
# exit
|
70
|
+
# end
|
71
|
+
end.parse!
|
72
|
+
|
73
|
+
options
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
case ARGV[0]
|
78
|
+
when 'scan'
|
79
|
+
ARGV.shift
|
80
|
+
ARGV.each do |file|
|
81
|
+
MrEko::Song.create_from_file!(file)
|
82
|
+
end
|
83
|
+
when 'playlist'
|
84
|
+
options = parse_options
|
85
|
+
format = options.delete(:format)
|
86
|
+
playlist = MrEko::Playlist.create_from_options(options)
|
87
|
+
puts playlist.output(format)
|
88
|
+
else
|
89
|
+
puts "nothing for #{ARGV[0]}"
|
90
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class AddPlaylists < Sequel::Migration
|
2
|
+
def up
|
3
|
+
create_table(:playlists) do
|
4
|
+
primary_key :id
|
5
|
+
String :name
|
6
|
+
DateTime :created_on
|
7
|
+
DateTime :updated_on
|
8
|
+
|
9
|
+
index :name, :unique => true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def down
|
14
|
+
drop_table :playlists
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class AddSongs < Sequel::Migration
|
2
|
+
def up
|
3
|
+
create_table(:songs) do
|
4
|
+
primary_key :id
|
5
|
+
String :md5, :length => 32
|
6
|
+
String :filename
|
7
|
+
String :artist, :length => 100
|
8
|
+
String :album
|
9
|
+
String :title
|
10
|
+
Float :duration
|
11
|
+
Float :loudness
|
12
|
+
Float :fade_out
|
13
|
+
Float :fade_in
|
14
|
+
Float :tempo
|
15
|
+
Integer :time_signature, :length => 1
|
16
|
+
Integer :key, :length => 2
|
17
|
+
Integer :mode, :length => 1
|
18
|
+
DateTime :created_on
|
19
|
+
DateTime :updated_on
|
20
|
+
|
21
|
+
index :md5, :unique => true
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :playlists_songs do
|
25
|
+
Integer :playlist_id
|
26
|
+
Integer :song_id
|
27
|
+
|
28
|
+
index [:playlist_id, :song_id], :unique => true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def down
|
33
|
+
drop_table :songs
|
34
|
+
drop_table :playlists_songs
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AddUsefulSongFields < Sequel::Migration
|
2
|
+
def up
|
3
|
+
alter_table(:songs) do
|
4
|
+
add_column :echonest_id, String
|
5
|
+
add_column :danceability, Float
|
6
|
+
add_column :energy, Float
|
7
|
+
add_column :bitrate, Integer, :size => 4
|
8
|
+
add_index :echonest_id
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def down
|
13
|
+
alter_table(:songs) do
|
14
|
+
drop_column :echonest_id
|
15
|
+
drop_column :danceability
|
16
|
+
drop_column :energy
|
17
|
+
drop_column :bitrate
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/ext/enmfp/LICENSE
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Code Generator Library License and Distribution Agreement
|
2
|
+
PLEASE READ THIS AGREEMENT (“AGREEMENT”) BEFORE DOWNLOADING THIS LIBRARY. BY DOWNLOADING THE LIBRARY YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS AGREEMENT, DO NOT DOWNLOAD OR USE THIS LIBRARY.
|
3
|
+
|
4
|
+
IF YOU ARE ACCEPTING THESE TERMS ON BEHALF OF ANOTHER PERSON OR A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU HAVE FULL AUTHORITY TO ACT FOR AND TO BIND THAT PERSON, COMPANY, OR LEGAL ENTITY TO THESE TERMS.
|
5
|
+
|
6
|
+
This is a binding legal agreement between you (“you” or "Developer") and The Echo Nest Corporation ("Echo Nest"). This Agreement relates to the Code Generator Library in object code form (“Library”) that you download from the Echo Nest web site or that Echo Nest otherwise provides, including releases, versions and updates and all associated on-line or electronic documentation. The Library consist of various software programs in object code form (each a “Library Program”).
|
7
|
+
|
8
|
+
PURPOSE OF THIS AGREEMENT.
|
9
|
+
|
10
|
+
The Library Programs are designed to generate and transmit music identification codes (“Music Codes”) and/or to use Music Codes to retrieve related data (“Metadata”) from the Internet in accordance with specification developed by Echo Nest (the “EN Community Music Code Specification”), which are available at the.echonest.com.
|
11
|
+
|
12
|
+
There are servers on the Internet that conform to the EN Community Music Code Specification and are operated by Echo Nest or other parties that have been certified by Echo Nest (collectively “Certified Community Servers”). These Certified Community Servers are designed to aggregate and share Music Codes to build a publicly available Music Code index. (Information regarding Certified Community Server software and licenses is available at the.echonest.com.)
|
13
|
+
|
14
|
+
The purpose of this license is to assist Developer to create and distribute applications that include Library Programs and that interact with one or more Certified Community Servers under the EN Community Music Code Specification.
|
15
|
+
|
16
|
+
REGISTRATION. Developer must provide registration information to download the Library and enter into this Agreement. Developer represents that it has provided true, accurate, current and complete information as prompted by the sign-up process (the "Registration Data") and that Developer will promptly update the Registration Data to keep it accurate, current and complete.
|
17
|
+
|
18
|
+
LICENSE GRANT. Subject to the terms of this Agreement, Echo Nest grants Developer a royalty-free, non-exclusive, non-transferable license to the Library as follows:
|
19
|
+
|
20
|
+
Developer may use the Library internally for the purpose of developing one or more compiled applications that embed and use some or all of the Library Programs and that conforms to the EN Community Music Code Specification (each an “Application”). For such purposes, Developer may make a reasonable number of internal copies of the Library and the various Library Programs.
|
21
|
+
|
22
|
+
Developer may replicate and distribute the included Library Programs worldwide as an embedded component of your Application. Developer may also internally use the included Library Programs as an embedded component of your Application.
|
23
|
+
|
24
|
+
LIMITATIONS TO CERTIFIED COMMUNITY SERVERS.
|
25
|
+
|
26
|
+
As a limitation and condition of the license grant in this Agreement, Developer agrees to develop and/or distribute only those Applications that are programmed to interact via the Internet or other network with one or more Certified Community Servers. Developer agrees that the Applications will not be programmed or enabled to transmit Music Codes to any other servers or destinations on the Internet.
|
27
|
+
|
28
|
+
SUBLICENSES. If Developer creates or distributes Applications, Developer agrees to do so only under binding legal agreements with licensees though all levels of distribution as follows:
|
29
|
+
|
30
|
+
Each such agreement must be at least as protective of Echo Nest in its terms and conditions as this Agreement and must disclaim any warranty by or liability of Echo Nest or its suppliers.
|
31
|
+
|
32
|
+
Each such agreement must Include the following form of legend: “Portions from Echo Nest Community Music Code Library. ©2010 The Echo Nest. The Echo Nest is a trademark of The Echo Nest Corporation.” If the Application includes a proprietary notice display for Developer or any third party, then the Application will also include, in the same display, the above-mentioned Echo Nest legend.
|
33
|
+
|
34
|
+
UPDATES. Echo Nest may, but is not obligated to issue versions of the Library, including, but not limited to maintenance releases, updates, or upgrades. Versions of the Library, if any, will be available at the.echonest.com. All such versions will be deemed to be under this Agreement. Echo Nest is not obligated to provide support or maintenance for the Library or any Application.
|
35
|
+
|
36
|
+
WARRANTY AND LIABILITY DISCLAIMERS.
|
37
|
+
|
38
|
+
ECHO NEST AND ITS LICENSORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. Echo Nest makes no warranties or representations of any kind with respect to the results of your use of the Library.
|
39
|
+
|
40
|
+
Echo Nest and its suppliers will not be liable for any special, incidental, or indirect damages, or for any economic or consequential damages, including without limitation lost profits or lost savings, even if Echo Nest or its suppliers have been advised of the possibility of such damages. Echo Nest’s entire liability to Developer is limited to $25.00, which Developer agrees is a reasonable limitation.
|
41
|
+
|
42
|
+
THE DISCLAIMERS AND LIMITATIONS IN THIS SECTION COVER THE LIBRARY, ALL MUSIC CODES, AND ANY ONLINE SERVICES OR DATA OBTAINED BY USE OF THE LIBRARY, ALL OF WHICH IS PROVIDED “AS IS.”
|
43
|
+
|
44
|
+
INDEMNIFICATION BY DEVELOPER. Developer agrees to defend, indemnify and hold Echo Nest, its affiliates and their respective employees, officers and agents (the "Echo Nest Indemnified Parties") harmless from any and all claims, damages, losses, liabilities, costs and expenses (including reasonable attorney's fees) (a) arising out of or in connection with any third party claim relating to an Application, (b) arising from Developer’s breach of this Agreement, or (c) alleging, with regard to any Application, any violation of intellectual property or other proprietary rights.
|
45
|
+
|
46
|
+
TERM. This Agreement is effective from the date Developer downloads, first uses, or installs the Library and shall be terminated upon the earliest to occur of the following: a) Developer breaches any term or condition of this Agreement; (b) Developer destroys the Library and accompanying documentation, together with any copy thereof; or (c) Echo Nest terminates this Agreement in writing (which may be by email). In case of termination, Developer shall immediately destroy all copies of the Library and certify to Echo Nest in writing that it has done so. Licenses of the Library Programs granted to end users will survive termination. The following provisions survive termination: Sections 7, 8, 9 and 12.
|
47
|
+
|
48
|
+
GENERAL RESTRICTIONS. Developer agrees not to distribute or disclose the Library or any Library Programs except as embedded in an Application. (Developer is encouraged to advise other developers to obtain the Library through the.echonest.com.) Developer may not reverse engineer, disassemble, or decompile the Library or any Library Program. Developer agrees not to use, copy, sublicense, distribute, convey or transfer the Library or any Library Program except as expressly permitted under this Agreement. Developer is solely responsible to its customers and licensees for any update or support obligation or other obligation or liability which may arise from the distribution of any Application.
|
49
|
+
|
50
|
+
OTHER LAWS. This Agreement gives Developer specific legal rights. Developer may have others that vary by jurisdiction. In some jurisdictions exclusion or limitation of consequential or incidental damages and/or other exclusions or limitations of liability may not apply. This Agreement does not affect any statutory consumer rights that cannot be waived or limited by contract.
|
51
|
+
|
52
|
+
LICENSE TO U.S. GOVERNMENT. If Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in Software and accompanying documentation will be only as set forth in this Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD acquisitions). Supplier is The Echo Nest, 48 Grove Street, Suite 206, Somerville, MA 02144.
|
53
|
+
|
54
|
+
MISCELLANEOUS. All notices or other communications required to be given hereunder shall be in writing and delivered via certified mail, Express Mail or Federal Express, return receipt requested, postage prepaid, at the recipient party’s last known address. Echo Nest may provide notice by email at the address provided in registration or by posting notice on its web site. This Agreement shall be governed by the laws of the Commonwealth of Massachusetts without regard to conflicts of law provisions and applicable US federal law. The UN Convention for the International Sale of Commercial Goods is excluded. Non-enforcement of any provision hereof shall not operate as a waiver. Any purported assignment or transfer of this Agreement by Developer is void, unless approved in advance by Echo Nest in writing, except that Developer may transfer the Library and this Agreement to a successor in interest of its entire business who assumes the obligations of this Agreement. Echo Nest may transfer this Agreement. If any provision of this Agreement is held to be invalid or unenforceable, then that provision notwithstanding, this Agreement shall remain in full force and effect and such provision shall be deemed omitted. Developer agrees to comply with all applicable export restrictions and laws. Developer grants Echo Nest a permanent right to use, copy, and exploit any feedback or advice that Developer provides. This Agreement is the complete statement of the agreement between Echo Nest and Developer and supersedes all proposals, prior agreements (oral or written) and all other communications between Echo Nest and Developer relating to its subject matter.
|
data/ext/enmfp/README
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
The Echo Nest Musical Fingerprint (ENMFP) Code Generator
|
2
|
+
Release 3.1-5
|
3
|
+
July XX 2010
|
4
|
+
|
5
|
+
|
6
|
+
###### The Echo Nest Musical Fingerprint (ENMFP)
|
7
|
+
|
8
|
+
Read more:
|
9
|
+
|
10
|
+
http://notes.variogr.am/post/544559482/the-echo-nest-musical-fingerprint-enmfp
|
11
|
+
http://developer.echonest.com/docs/v4/song.html#identify
|
12
|
+
|
13
|
+
The ENMFP is a musical fingerprint that uses portions of the Echo Nest Analyze "machine listening" toolkit to extract musical features that allow copies of songs to be identified. This allows you to resolve an unknown song against a database of songs. The Echo Nest currently maintains the only song database compatible with ENMFP codes, however, the design of the service is such that anyone can run and maintain a mirror of the code database to avoid "lock in" to a specific vendor.
|
14
|
+
|
15
|
+
The ENMFP is robust to time and pitch modification, is resilient to drastic reductions in fidelity and can even detect uses of audio in remixes, samples and sometimes even cover songs.
|
16
|
+
|
17
|
+
You only need to query for 20 seconds of audio (or less sometimes) to get a result.
|
18
|
+
|
19
|
+
The server component of the ENMFP is open source and will be released shortly.
|
20
|
+
|
21
|
+
The code generator component of the ENMFP is under the Echo Nest Community Music Code License, which allows free use for all applications provided that the codes are queried for and sent to an authorized server. The authorized servers mirror with each other to share all data.
|
22
|
+
|
23
|
+
There are two ways to use the code generator: link the provided shared libraries with your application and pass it pointers to PCM data from songs, or use a precompiled binary that accepts a filename as an argument and outputs JSON suitable for querying the ENFMP servers.
|
24
|
+
|
25
|
+
|
26
|
+
###### Dynamic library -- libcodegen
|
27
|
+
|
28
|
+
The package contains binary libraries for Linux (i686 and x86_64), Mac (10.6 only) and Windows. You can compile these libraries into your app to generate codes suitable for querying the ENMFP API based on PCM data. See test.cxx for a very simple test program that links with libcodegen. Put libcodegen somewhere that LD_LIBRARY_PATH knows about and compile the test program:
|
29
|
+
|
30
|
+
(this is an example for Linux i686, for other platforms change the library name accordingly)
|
31
|
+
|
32
|
+
g++ -o codegen.test test.cxx -lcodegen.Linux-i686
|
33
|
+
|
34
|
+
Run it with the example .raw file of 20 seconds of "Billie Jean":
|
35
|
+
|
36
|
+
./codegen.test billie.raw 10
|
37
|
+
|
38
|
+
Which will output code JSON suitable for querying the ENMFP API:
|
39
|
+
|
40
|
+
[
|
41
|
+
{"metadata":{"filename":"billie.raw", "samples_decoded":441208, "version":3.14}, "code_count":154, "code":"JxVlIuNwzAMQ1fxCDL133+xo1rnGqNAEcWy/ERa2aKeZmW...
|
42
|
+
]
|
43
|
+
|
44
|
+
You can POST or this JSON directly to song/identify, for example:
|
45
|
+
|
46
|
+
# curl -F "query=@post_string" http://developer.echonest.com/api/v4/song/identify?api_key=YOUR_KEY
|
47
|
+
{"fp_lookup_time_ms": 21, "results": [{"songID": "SOAFVGQ1280ED4E371", "match_type": "fp", "title": "Billie Jean", "artist": "Michael Jackson",
|
48
|
+
"artistID": "ARXPPEY1187FB51DF4", "score": 63, "release": "Thriller"}]}
|
49
|
+
|
50
|
+
(you can also use GET, see the API description)
|
51
|
+
|
52
|
+
Notes about libcodegen:
|
53
|
+
|
54
|
+
Code generation takes a buffer of floating point PCM data sampled at 22050 Hz and mono.
|
55
|
+
|
56
|
+
Codegen * pCodegen = new Codegen(_pSamples, _NumberSamples, offset);
|
57
|
+
|
58
|
+
the "offset" parameter creates a hint to the server on where the sample is taken from in the original file. If you know this (for example, if you are automatically scanning a large library of audio, choosing specific 20 seconds chunks of audio) the server will use this information but it is not required.
|
59
|
+
|
60
|
+
After compute, you want to call pCodegen->getCodeString() to get the code string. (The code string is just a base64 encoding of a zlib compression of the original code string, which is a series of ASCII numbers.)
|
61
|
+
|
62
|
+
|
63
|
+
###### Example code generator
|
64
|
+
|
65
|
+
This package also contains an example code generator binary for all 3 platforms (Mac 10.6/10.5, Windows, Linux 64-bit & 32-bit.) This code generator has more features -- it will output ID3 tag information and uses ffmpeg to decode any type of file. If you don't need to compile libcodegen into your app you can rely on this. Note that you need to have ffmpeg installed and accessible on your path for this to work.
|
66
|
+
|
67
|
+
./codegen.Linux-x86_64 billie_jean.mp3 10 10
|
68
|
+
|
69
|
+
Will take 10 seconds of audio from 10 seconds into the file and output JSON suitable for querying:
|
70
|
+
|
71
|
+
{"metadata":{"artist":"Michael jackson", "release":"800 chansons des annes 80", "title":"Billie jean", "genre":"", "bitrate":192,
|
72
|
+
"sample_rate":44100, "seconds":294, "filename":"billie_jean.mp3", "samples_decoded":220598, "given_duration":10, "start_offset":10,
|
73
|
+
"version":3.14}, "code_count":76, "codes":"JxVlIuNwzAMQ1fxCDL133+xo1rnGqNAEcWy/ERa2aKeZmW...
|
74
|
+
|
75
|
+
You can POST this JSON directly to alpha_identify_song, for example:
|
76
|
+
|
77
|
+
# curl -F "query=@post_string" http://beta.developer.echonest.com/api/v4/song/identify?api_key=YOUR_KEY
|
78
|
+
{"fp_lookup_time_ms": 21, "results": [{"songID": "SOAFVGQ1280ED4E371", "match_type": "fp", "title": "Billie Jean", "artist": "Michael Jackson",
|
79
|
+
"artistID": "ARXPPEY1187FB51DF4", "score": 63, "release": "Thriller"}]
|
80
|
+
|
81
|
+
(you can also use GET, see the API description)
|
82
|
+
|
83
|
+
###### FAQ
|
84
|
+
|
85
|
+
Q: I get "Couldn't decode any samples with: ffmpeg" when running the example code generator.
|
86
|
+
|
87
|
+
A1: When running the example code generator (codegen.$(PLATFORM)) make sure ffmpeg is accessible to your path. Try running ffmpeg filename.mp3 on the file you are testing the code generator with. If it doesn't work, codegen won't work.
|
88
|
+
|
89
|
+
A2: Are you trying to decode billie.raw with the example code generator? billie.raw is only for test.cxx; it is just packed PCM, not a playable file. It is meant to illustrate how to use libcodegen.
|
90
|
+
|
91
|
+
|
92
|
+
###### Questions, comments
|
93
|
+
|
94
|
+
Send to enmfp@googlecode.com
|
95
|
+
|
96
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Release Notes for ENMFP codegen
|
2
|
+
|
3
|
+
3.10 April 21 2010
|
4
|
+
First version
|
5
|
+
|
6
|
+
3.11 April 28 2010
|
7
|
+
Fencepost bugfix on codestring builder
|
8
|
+
|
9
|
+
3.12 May 18 2010
|
10
|
+
Codestring now base64 zlib string
|
11
|
+
|
12
|
+
3.13 June 24 2010
|
13
|
+
Codestring now base64 urlsafe zlib string
|
14
|
+
|
15
|
+
3.14 July 7 2010
|
16
|
+
Bugfix on JSON emitter (was not escaping properly)
|
17
|
+
codegen.Darwin works properly on Mac OS X 10.5 (note: libcodegen is not supported on 10.5 yet, only 10.6/lin/win)
|
18
|
+
Codegen reports compute time and decode time in the JSON (no longer to stderr)
|
19
|
+
Codegen memory leaks fixed (Jason Sundram)
|
20
|
+
Codestring 18% shorter, old ways from 3.10 on still work on the query end (Jason Sundram)
|
21
|
+
|
22
|
+
3.15 July XX 2010
|
23
|
+
Common.h included in dist
|
24
|
+
Threaded mode, activate with -s (mac and linux only, windows will iterate)
|
25
|
+
JSON output now by default a list of code queries with tag
|
26
|
+
Fixes for iOS 4.0 compatibility
|
27
|
+
Lowrank option (testing, off by default)
|
28
|
+
Fixed memory leak in FFT routine
|
29
|
+
Use Accelerate on iOS 4
|
30
|
+
"Too few events detected" no longer throws exception but returns empty codestring
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/mr_eko/core.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module MrEko
|
2
|
+
|
3
|
+
module Core
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, GlobalHelpers)
|
6
|
+
base.extend GlobalHelpers
|
7
|
+
end
|
8
|
+
|
9
|
+
module GlobalHelpers
|
10
|
+
def log(string, level=:debug)
|
11
|
+
MrEko.logger.send(level, string)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|