Class: Noyes::MelFilter
Overview
Mel filter takes an m x n matrix. The inner array becomes equal to the number of mel filter banks (nfilt). The dimensionality of the outer array remains unchanged.
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Math
#dot_product, log2, max, min
#+, #|
Constructor Details
#initialize(srate, nfft, nfilt, lowerf, upperf) ⇒ MelFilter
Returns a new instance of MelFilter.
9
10
11
12
13
14
15
16
17
18
|
# File 'lib/ruby_impl/mel_filter.rb', line 9
def initialize srate, nfft, nfilt, lowerf, upperf
bank_params = MelFilter.make_bank_parameters srate, nfft, nfilt, lowerf, upperf
@indices = []
@weights = []
bank_params.map do |params|
ind, weights = MelFilter.make_filter *params
@indices << ind
@weights << weights
end
end
|
Class Method Details
.determine_bin(in_freq, step_freq) ⇒ Object
42
43
44
|
# File 'lib/ruby_impl/mel_filter.rb', line 42
def self.determine_bin in_freq, step_freq
step_freq * (in_freq/step_freq).round
end
|
.make_bank_parameters(srate, nfft, nfilt, lowerf, upperf) ⇒ Object
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# File 'lib/ruby_impl/mel_filter.rb', line 45
def self.make_bank_parameters srate, nfft, nfilt, lowerf, upperf
raise 'Number of FFT points is <= 0.' if nfft == 0
raise 'Number of filters is <= 0.' if nfilt == 0
srate = srate.to_f; lowerf = lowerf.to_f; upperf = upperf.to_f
left_edge = Array.new nfilt
right_edge = Array.new nfilt
center_freq = Array.new nfilt
melmax = self.to_mel upperf
melmin = self.to_mel lowerf
delta_freq_mel = (melmax - melmin) / (nfilt + 1.0)
delta_freq = srate/nfft
left_edge[0] = self.determine_bin lowerf, delta_freq
next_edge_mel = melmin
nfilt.times do |i|
next_edge_mel += delta_freq_mel
next_edge = self.to_linear next_edge_mel
center_freq[i] = self.determine_bin next_edge, delta_freq
right_edge[i-1] = center_freq[i] if i > 0
left_edge[i+1] = center_freq[i] if i < nfilt - 1
end
next_edge_mel += delta_freq_mel
next_edge = self.to_linear next_edge_mel
right_edge[nfilt-1] = self.determine_bin next_edge, delta_freq
fparams = Array.new nfilt
nfilt.times do |i|
initial_freq_bin = self.determine_bin left_edge[i], delta_freq
initial_freq_bin += delta_freq if initial_freq_bin < left_edge[i]
fparams[i] = [left_edge[i], center_freq[i], right_edge[i],
initial_freq_bin, delta_freq]
end
fparams
end
|
.make_filter(left, center, right, init_freq, delta) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# File 'lib/ruby_impl/mel_filter.rb', line 78
def self.make_filter left, center, right, init_freq, delta
raise 'delta freq has zero value' if delta == 0
if (right - left).round == 0 || (center - left).round == 0 ||
(right - center).round == 0
raise 'filter boundaries too close'
end
n_elements = ((right - left)/ delta + 1).round
raise 'number of mel elements is zero' if n_elements == 0
weights = Array.new n_elements
height = 1
left_slope = height / (center - left)
right_slope = height / (center - right)
index_fw = 0
init_freq.step right, delta do |current|
if current < center
weights[index_fw] = left_slope * (current - left)
else
weights[index_fw] = height + right_slope * (current - center)
end
index_fw += 1
end
[(init_freq/delta).round, weights]
end
|
.to_linear(m) ⇒ Object
38
39
40
41
|
# File 'lib/ruby_impl/mel_filter.rb', line 38
def self.to_linear m
return m.map {|melfreq| self.to_linear melfreq} if m.respond_to? :map
700.0 * (10.0**(m/2595.0) - 1.0)
end
|
.to_mel(f) ⇒ Object
34
35
36
37
|
# File 'lib/ruby_impl/mel_filter.rb', line 34
def self.to_mel f
return f.map {|linfreq| self.to_mel linfreq} if f.respond_to? :map
2595.0 * Math.log10(1.0 + f/700.0)
end
|
Instance Method Details
#<<(power_spectra) ⇒ Object
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/ruby_impl/mel_filter.rb', line 19
def << power_spectra
power_spectra.map do |spectrum|
mel_bank = Array.new @indices.size
@indices.size.times do |i|
initial_index, weights = @indices[i], @weights[i]
output = 0.0
weights.size.times do |j|
index = initial_index + j
output += spectrum[index] * weights[j] if index < spectrum.length
end
mel_bank[i] = output
end
mel_bank
end
end
|
#apply_weights(init_index, weights, spectrum) ⇒ Object
105
106
107
108
109
110
111
|
# File 'lib/ruby_impl/mel_filter.rb', line 105
def apply_weights init_index, weights, spectrum
output = 0.0
weights.size.times do |i|
output += spectrum[i + init_index] * weights[i]
end
output
end
|