mmfcc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +0 -0
- data/Rakefile +1 -0
- data/bin/mmfcc +10 -0
- data/lib/mmfcc.rb +2 -0
- data/lib/mmfcc/clustering.rb +85 -0
- data/lib/mmfcc/command.rb +29 -0
- data/lib/mmfcc/mfcc.rb +148 -0
- data/lib/mmfcc/version.rb +3 -0
- data/mmfcc.gemspec +23 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c2d12ce70bab6304d063e738501344d110ebb087
|
4
|
+
data.tar.gz: df115cd944bedd7ac3d432a01346bd927909c419
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 209d10bd2cf1a88d339fe787d50ef44581e6243c5309fb767adb6d92806f5941abb3609eb28074c603493a814e41384911632ecae5cfc5603bceb8a69ab0e2e0
|
7
|
+
data.tar.gz: cc5b7b328fe53d3e039d5da16d150ddb59bda499a19ee6dcd0f1db18a3e7c7b2f96ade206811ff64d67cbde3e751852cc954df606acb4045b15354dd5ef5673c
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/mmfcc
ADDED
data/lib/mmfcc.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
module Mmfcc
|
3
|
+
require "rubygems"
|
4
|
+
require "ai4r"
|
5
|
+
|
6
|
+
class Clustering
|
7
|
+
|
8
|
+
def initialize(cnum)
|
9
|
+
@cnum = cnum
|
10
|
+
end
|
11
|
+
|
12
|
+
def kmeans(all_mfcc, clusterNum)
|
13
|
+
|
14
|
+
ai4r_data = Ai4r::Data::DataSet.new(:data_items=> all_mfcc)
|
15
|
+
|
16
|
+
cluster = Ai4r::Clusterers::KMeans.new
|
17
|
+
cluster.build(ai4r_data, clusterNum)
|
18
|
+
|
19
|
+
return cluster
|
20
|
+
end
|
21
|
+
|
22
|
+
def loadMFCC(mfccFile, m, all_mfcc)
|
23
|
+
|
24
|
+
mfcc = []
|
25
|
+
mfccs = []
|
26
|
+
|
27
|
+
File.open(mfccFile, "r+b") {|f|
|
28
|
+
while line = f.read(4)
|
29
|
+
if line == "" then
|
30
|
+
break
|
31
|
+
end
|
32
|
+
|
33
|
+
val = line.unpack('f')[0]
|
34
|
+
mfcc.push(val)
|
35
|
+
|
36
|
+
|
37
|
+
if mfcc.length==m then
|
38
|
+
mfccs.push(mfcc)
|
39
|
+
all_mfcc.push(mfcc)
|
40
|
+
mfcc=[]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
return mfccs
|
46
|
+
end
|
47
|
+
|
48
|
+
def run
|
49
|
+
|
50
|
+
mfccDir = './mfcc/'
|
51
|
+
|
52
|
+
clusterNum = @cnum.to_i
|
53
|
+
mfcc_dict = {}
|
54
|
+
all_mfcc = []
|
55
|
+
|
56
|
+
Find.find(mfccDir) {|mfccFile|
|
57
|
+
next unless mfccFile.end_with?(".mfc")
|
58
|
+
mfcc = loadMFCC(mfccFile, 20, all_mfcc)
|
59
|
+
mfcc_dict[mfccFile]=mfcc
|
60
|
+
}
|
61
|
+
|
62
|
+
cluster = kmeans(all_mfcc, clusterNum)
|
63
|
+
|
64
|
+
writeToFile = File.open("./histgram.txt",'w')
|
65
|
+
|
66
|
+
mfcc_dict.each{|key, value|
|
67
|
+
writeToFile.puts key
|
68
|
+
|
69
|
+
histgram = [0]*clusterNum
|
70
|
+
|
71
|
+
value.each{|d|
|
72
|
+
i = cluster.eval(d)
|
73
|
+
histgram[i]+=1
|
74
|
+
}
|
75
|
+
|
76
|
+
str_hist = histgram.join(" ")
|
77
|
+
writeToFile.puts str_hist
|
78
|
+
|
79
|
+
}
|
80
|
+
|
81
|
+
puts "histgram.txt is created."
|
82
|
+
writeToFile.close
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mmfcc
|
2
|
+
require "find"
|
3
|
+
|
4
|
+
class Command
|
5
|
+
def run
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
params = ARGV.getopts('mc',"type:mp3", "m4apath:./m4a/", "mp3path:./mp3/", "cnum:8")
|
9
|
+
|
10
|
+
if params["m"] then
|
11
|
+
puts "calculating mfcc..."
|
12
|
+
|
13
|
+
require 'mmfcc/mfcc'
|
14
|
+
|
15
|
+
mfcc = Mmfcc::Mfcc.new(params["type"], params["m4apath"], params["mp3path"])
|
16
|
+
mfcc.run
|
17
|
+
end
|
18
|
+
|
19
|
+
if params["c"] then
|
20
|
+
puts "start clustering..."
|
21
|
+
|
22
|
+
require 'mmfcc/clustering'
|
23
|
+
|
24
|
+
clustering = Mmfcc::Clustering.new(params["cnum"])
|
25
|
+
clustering.run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/mmfcc/mfcc.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
|
2
|
+
module Mmfcc
|
3
|
+
class Mfcc
|
4
|
+
|
5
|
+
def initialize(type, m4apath, mp3path)
|
6
|
+
@type = type
|
7
|
+
@m4apath = m4apath
|
8
|
+
@mp3path = mp3path
|
9
|
+
end
|
10
|
+
|
11
|
+
def m4aToRaw(m4aFile)
|
12
|
+
system("ffmpeg -i "+m4aFile+" -ab 32k -ar 16000 temp.m4a")
|
13
|
+
# decode mp3 to wav
|
14
|
+
system("ffmpeg -i temp.m4a temp.wav")
|
15
|
+
# convert wav to raw
|
16
|
+
system("sox temp.wav temp.raw")
|
17
|
+
# delete needless
|
18
|
+
system("rm temp.m4a")
|
19
|
+
system("rm temp.wav")
|
20
|
+
end
|
21
|
+
|
22
|
+
def mp3ToRaw(mp3File)
|
23
|
+
system("lame --resample 16 -b 32 -a "+mp3File+" temp.mp3")
|
24
|
+
# decode mp3 to wav
|
25
|
+
system("lame --decode temp.mp3 temp.wav")
|
26
|
+
# convert wav to raw
|
27
|
+
system("sox temp.wav temp.raw")
|
28
|
+
# delete needless
|
29
|
+
system("rm temp.mp3")
|
30
|
+
system("rm temp.wav")
|
31
|
+
end
|
32
|
+
|
33
|
+
def calcNumSample(rawFile)
|
34
|
+
# calculate byte
|
35
|
+
filesize = File.size?("temp.raw")
|
36
|
+
numsample = filesize / 2
|
37
|
+
return numsample
|
38
|
+
end
|
39
|
+
|
40
|
+
def extractCenter(inFile, outFile, period)
|
41
|
+
numsample = calcNumSample(inFile)
|
42
|
+
p numsample
|
43
|
+
|
44
|
+
fs = 16000
|
45
|
+
center = numsample / 2
|
46
|
+
start = center - fs * period
|
47
|
+
ends = center + fs * period
|
48
|
+
|
49
|
+
if start < 0 then
|
50
|
+
start = 0
|
51
|
+
end
|
52
|
+
if ends > numsample - 1 then
|
53
|
+
ends = numsample - 1
|
54
|
+
end
|
55
|
+
|
56
|
+
system("bcut +s -s "+start.to_s+" -e "+ends.to_s+" < temp.raw > "+outFile)
|
57
|
+
end
|
58
|
+
|
59
|
+
def calcMFCC(rawFile, mfccFile)
|
60
|
+
# sampling rate: 16kHz
|
61
|
+
# frame length: 400
|
62
|
+
# shift broad: 160
|
63
|
+
# num of channel: 40
|
64
|
+
# MFCC: 19 dimentions + energy
|
65
|
+
system("x2x +sf < "+rawFile+" | frame -l 400 -p 160 | mfcc -l 400 -f 16 -n 40 -m 19 -E > "+mfccFile)
|
66
|
+
end
|
67
|
+
|
68
|
+
def run
|
69
|
+
|
70
|
+
m4aDir = @m4apath
|
71
|
+
mp3Dir = @mp3path
|
72
|
+
mfccDir = './mfcc/'
|
73
|
+
rawDir = './raw/'
|
74
|
+
|
75
|
+
if not Dir::exist?(mfccDir) then
|
76
|
+
Dir::mkdir(mfccDir)
|
77
|
+
end
|
78
|
+
if not Dir::exist?(rawDir) then
|
79
|
+
Dir::mkdir(rawDir)
|
80
|
+
end
|
81
|
+
|
82
|
+
if @type == "m4a" then
|
83
|
+
|
84
|
+
if not Dir::exist?(m4aDir) then
|
85
|
+
raise "there is no directry for m4a. Please make directry ./m4a/"
|
86
|
+
end
|
87
|
+
|
88
|
+
Find.find(m4aDir) {|m4aFile|
|
89
|
+
next unless FileTest.file?(m4aFile)
|
90
|
+
next unless m4aFile.end_with?(".m4a")
|
91
|
+
|
92
|
+
mfccFile = m4aFile.sub(".m4a",".mfc")
|
93
|
+
mfccFile = mfccFile.sub(m4aDir, mfccDir)
|
94
|
+
|
95
|
+
rawFile = m4aFile.sub(".m4a",".raw")
|
96
|
+
rawFile = rawFile.sub(m4aDir, rawDir)
|
97
|
+
|
98
|
+
begin
|
99
|
+
# decode MP3
|
100
|
+
m4aToRaw(m4aFile)
|
101
|
+
|
102
|
+
# convert 30s mp3 to rawFile
|
103
|
+
extractCenter("temp.raw", rawFile, 15)
|
104
|
+
|
105
|
+
calcMFCC(rawFile, mfccFile)
|
106
|
+
|
107
|
+
system("rm temp.raw")
|
108
|
+
rescue
|
109
|
+
next
|
110
|
+
puts "failed at decode m4a"
|
111
|
+
end
|
112
|
+
}
|
113
|
+
else
|
114
|
+
|
115
|
+
if not Dir::exist?(mp3Dir) then
|
116
|
+
raise "there is no directry for mp3. Please make directry ./mp3/"
|
117
|
+
end
|
118
|
+
|
119
|
+
Find.find(mp3Dir) {|mp3File|
|
120
|
+
next unless FileTest.file?(mp3File)
|
121
|
+
next unless mp3File.end_with?(".mp3")
|
122
|
+
|
123
|
+
mfccFile = mp3File.sub(".mp3",".mfc")
|
124
|
+
mfccFile = mfccFile.sub(mp3Dir, mfccDir)
|
125
|
+
|
126
|
+
rawFile = mp3File.sub(".mp3",".raw")
|
127
|
+
rawFile = rawFile.sub(mp3Dir, rawDir)
|
128
|
+
|
129
|
+
begin
|
130
|
+
# decode MP3
|
131
|
+
mp3ToRaw(mp3File)
|
132
|
+
|
133
|
+
# convert 30s mp3 to rawFile
|
134
|
+
extractCenter("temp.raw", rawFile, 15)
|
135
|
+
|
136
|
+
calcMFCC(rawFile, mfccFile)
|
137
|
+
|
138
|
+
system("rm temp.raw")
|
139
|
+
rescue
|
140
|
+
next
|
141
|
+
puts "failed at decode mp3"
|
142
|
+
end
|
143
|
+
}
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/mmfcc.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "mmfcc/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "mmfcc"
|
7
|
+
s.version = Mmfcc::VERSION
|
8
|
+
s.authors = ["RittaNarita"]
|
9
|
+
s.email = ["narittan@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/RittaNarita/Mmfcc"
|
11
|
+
s.summary = %q{the tool for making mfcc of songs}
|
12
|
+
s.description = %q{you can make the Mel-frequency cepstrum, which is a feature spectrum of a song. }
|
13
|
+
s.license = "GPLv2"
|
14
|
+
s.rubyforge_project = "mmfcc"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "ai4r", '~> 0'
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmfcc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- RittaNarita
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ai4r
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: 'you can make the Mel-frequency cepstrum, which is a feature spectrum
|
28
|
+
of a song. '
|
29
|
+
email:
|
30
|
+
- narittan@gmail.com
|
31
|
+
executables:
|
32
|
+
- mmfcc
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".gitignore"
|
37
|
+
- Gemfile
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- bin/mmfcc
|
41
|
+
- lib/mmfcc.rb
|
42
|
+
- lib/mmfcc/clustering.rb
|
43
|
+
- lib/mmfcc/command.rb
|
44
|
+
- lib/mmfcc/mfcc.rb
|
45
|
+
- lib/mmfcc/version.rb
|
46
|
+
- mmfcc.gemspec
|
47
|
+
homepage: https://github.com/RittaNarita/Mmfcc
|
48
|
+
licenses:
|
49
|
+
- GPLv2
|
50
|
+
metadata: {}
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project: mmfcc
|
67
|
+
rubygems_version: 2.2.0
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: the tool for making mfcc of songs
|
71
|
+
test_files: []
|