spectrum-analyzer 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/Gemfile +1 -0
- data/VERSION +1 -1
- data/lib/spectrum-analyzer.rb +9 -15
- data/lib/spectrum-analyzer/config.rb +5 -11
- data/lib/spectrum-analyzer/functions.rb +13 -0
- data/lib/spectrum-analyzer/functions/analyze.rb +7 -0
- data/lib/spectrum-analyzer/functions/generator.rb +129 -0
- data/lib/spectrum-analyzer/{clients → functions}/window_functions.rb +0 -0
- data/lib/spectrum-analyzer/objects/analysis.rb +13 -0
- data/lib/spectrum-analyzer/objects/domain.rb +14 -0
- data/lib/spectrum-analyzer/objects/file.rb +16 -0
- data/lib/spectrum-analyzer/objects/spectrum.rb +11 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/spectrum-analyzer_spec.rb +63 -2
- data/spectrum-analyzer.gemspec +13 -8
- metadata +23 -7
- data/lib/spectrum-analyzer/clients/analyze.rb +0 -5
- data/lib/spectrum-analyzer/clients/generator.rb +0 -139
- data/lib/spectrum-analyzer/criteria/domain.rb +0 -12
- data/lib/spectrum-analyzer/criteria/file.rb +0 -13
- data/lib/spectrum-analyzer/criteria/spectrum.rb +0 -9
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWU3ZTAwYzIwMTM5ZjljNmM4YWRiNDhkOWE4YWQ5ZTQ2MTc3ZGZmYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzY0ODcyZGU3MmE2NTc5MzE3NjBhYjE3MDk0NjY5MjRlOWE1Mjg2Mw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmE0MzBlNjYwNmMzMzUzMjgwZGQwODc5NzFiNTIzMGNmZWVjM2NiNGY2ODJj
|
10
|
+
ZmEwODdmMDgzZmJlYWMxOTllOGZlZDlhMWEwMGFhMTU3N2JjMmVhNzI2MWI4
|
11
|
+
MTc1NzZlODkyZDFkMDI1Yjg5MmNlNzQ4YzI1OWU5NWRmNDgxN2Y=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTQ2MzJhNWZjYWM3NDJhNjA2NWYyNDI0Mjg2YmMwY2RkY2E4NjYyYmM5MjM3
|
14
|
+
MzMzOGQ2YjQzYzU0YTZhMThhMTlmYTlhNjc3YzNkNTg3MDhkYzAzZWM5Nzc2
|
15
|
+
ZDM2MTE3ZmJlZDQ0YTRmMTY3MzIwN2NhNjg4YzM2MDExZWVmOWY=
|
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/spectrum-analyzer.rb
CHANGED
@@ -1,33 +1,27 @@
|
|
1
1
|
require 'ruby-audio'
|
2
2
|
require 'fftw3'
|
3
3
|
|
4
|
-
require_relative '../lib/spectrum-analyzer/config'
|
4
|
+
#require_relative '../lib/spectrum-analyzer/config'
|
5
5
|
|
6
|
-
Dir[File.dirname(__FILE__) + '/spectrum-analyzer
|
7
|
-
Dir[File.dirname(__FILE__) + '/spectrum-analyzer/
|
6
|
+
Dir[File.dirname(__FILE__) + '/spectrum-analyzer/*.rb'].each {| file| load file }
|
7
|
+
Dir[File.dirname(__FILE__) + '/spectrum-analyzer/functions/*.rb'].each {| file| load file }
|
8
|
+
Dir[File.dirname(__FILE__) + '/spectrum-analyzer/objects/*.rb'].each {| file| load file }
|
8
9
|
|
9
10
|
module SpectrumAnalyzer
|
11
|
+
attr_accessor :analysis
|
10
12
|
|
11
|
-
def self.configuration
|
12
|
-
@configuration ||= SpectrumAnalyzer::Config.new()
|
13
|
+
def self.configuration(args = {})
|
14
|
+
@configuration ||= SpectrumAnalyzer::Config.new(args)
|
13
15
|
end
|
14
16
|
|
15
17
|
def self.analyze
|
16
18
|
configuration
|
17
|
-
SpectrumAnalyzer::
|
19
|
+
SpectrumAnalyzer::Functions.analyze
|
18
20
|
end
|
19
21
|
|
20
22
|
def self.quick_analyze
|
21
23
|
configuration
|
22
|
-
SpectrumAnalyzer::
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.file
|
26
|
-
@file ||= SpectrumAnalyzer::File.new()
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.spectrum
|
30
|
-
@spectrum ||= SpectrumAnalyzer::Spectrum.new()
|
24
|
+
SpectrumAnalyzer::Functions.quick_analyze
|
31
25
|
end
|
32
26
|
|
33
27
|
end
|
@@ -2,18 +2,12 @@ module SpectrumAnalyzer
|
|
2
2
|
class Config
|
3
3
|
attr_accessor :file_name, :window_function, :window_size, :analysis_ranges
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@window_size =
|
7
|
-
@window_function = :hanning
|
8
|
-
@analysis_ranges
|
9
|
-
|
10
|
-
{ :b_index => 70, :t_index => 74, :min => 2.0, :max => 4.2 }, #Mid peak
|
11
|
-
{ :b_index => 82, :t_index => 109, :min => 0.8, :max => 2}] #Low area
|
12
|
-
@file_name = "spec/analyze.wav"
|
5
|
+
def initialize(args = {})
|
6
|
+
@window_size = args[:window_size] || 1024
|
7
|
+
@window_function = args[:window_function] || :hanning
|
8
|
+
@analysis_ranges = args[:analysis_ranges] || []
|
9
|
+
@file_name = args[:file_name] || ""
|
13
10
|
end
|
14
11
|
|
15
12
|
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
13
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module SpectrumAnalyzer
|
2
|
+
module Functions
|
3
|
+
class Generator
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@config = SpectrumAnalyzer.configuration
|
7
|
+
@analysis = SpectrumAnalyzer::Objects::Analysis.new(@config.file_name)
|
8
|
+
@window_functions = SpectrumAnalyzer::WindowFunctions.new(@config.window_size)
|
9
|
+
end
|
10
|
+
|
11
|
+
def quick_analyze
|
12
|
+
begin
|
13
|
+
buffer = RubyAudio::Buffer.float(@config.window_size)
|
14
|
+
RubyAudio::Sound.open(@config.file_name) do |snd|
|
15
|
+
while snd.read(buffer) != 0
|
16
|
+
domain = generate_domain(buffer)
|
17
|
+
return true if domain_contains_frequencies?(domain)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
rescue => err
|
22
|
+
error(err)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def analyze
|
27
|
+
generate_spectrum()
|
28
|
+
analyze_spectrum()
|
29
|
+
return @analysis
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def domain_contains_frequencies?(domain)
|
35
|
+
j=0
|
36
|
+
match = Array.new()
|
37
|
+
@config.analysis_ranges.each do |range|
|
38
|
+
sum_total = 0
|
39
|
+
for i in range[:b_index]..range[:t_index]
|
40
|
+
sum_total += domain.values[i] if !domain.values[i].nil?
|
41
|
+
end
|
42
|
+
average = sum_total / (range[:t_index] - range[:b_index])
|
43
|
+
match[j] = average > range[:min] and average < range[:max]
|
44
|
+
j+=1
|
45
|
+
end
|
46
|
+
return !match.include?(false)
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def generate_spectrum
|
52
|
+
begin
|
53
|
+
buffer = RubyAudio::Buffer.float(@config.window_size)
|
54
|
+
RubyAudio::Sound.open(@config.file_name) do |snd|
|
55
|
+
while snd.read(buffer) != 0
|
56
|
+
domain = generate_domain(buffer)
|
57
|
+
@analysis.spectrum.domains.push(domain)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
rescue => err
|
62
|
+
error(err)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def sum_domains
|
67
|
+
@analysis.spectrum.entire_spectrum = Array.new(@analysis.spectrum.domains[0].values.length, 0)
|
68
|
+
@analysis.spectrum.domains.each do |domain|
|
69
|
+
@analysis.spectrum.entire_spectrum.map!.with_index{ |x,i| x + domain.values[i]}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_domain(buffer)
|
74
|
+
windowed_array = apply_window(buffer.to_a, windows[@config.window_function])
|
75
|
+
na = NArray.to_na(windowed_array)
|
76
|
+
fft_array = FFTW3.fft(na).to_a[0, @config.window_size/2]
|
77
|
+
domain = SpectrumAnalyzer::Objects::Domain.new()
|
78
|
+
fft_array.each { |x| domain.raw_values.push(x); domain.values.push(x.magnitude)}
|
79
|
+
domain
|
80
|
+
end
|
81
|
+
|
82
|
+
def analyze_spectrum
|
83
|
+
sum_domains
|
84
|
+
find_occurrences
|
85
|
+
end
|
86
|
+
|
87
|
+
def find_occurrences
|
88
|
+
ranges = @config.analysis_ranges
|
89
|
+
occurrence_count = 0
|
90
|
+
@analysis.spectrum.domains.each do |domain|
|
91
|
+
ranges.each do |range|
|
92
|
+
if find_occurrence(range, domain)
|
93
|
+
occurrence_count += 1
|
94
|
+
domain.contains_frequency_range = true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@analysis.spectrum.num_occurrences = occurrence_count
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_occurrence (range, domain)
|
102
|
+
sum_total = 0
|
103
|
+
for i in range[:b_index]..range[:t_index]
|
104
|
+
sum_total += domain.values[i] if !domain.nil?
|
105
|
+
end
|
106
|
+
average = sum_total / (range[:t_index] - range[:b_index])
|
107
|
+
average > range[:min] and average < range[:max]
|
108
|
+
end
|
109
|
+
|
110
|
+
def windows
|
111
|
+
@window_functions.windows()
|
112
|
+
end
|
113
|
+
|
114
|
+
def apply_window(buffer, window_type)
|
115
|
+
windowed_array = Array.new()
|
116
|
+
i=0
|
117
|
+
buffer.each { |x| windowed_array[i] = x * window_type[i]; i+=1}
|
118
|
+
end
|
119
|
+
|
120
|
+
def error(err)
|
121
|
+
raise StandardError, err
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SpectrumAnalyzer
|
2
|
+
module Objects
|
3
|
+
class Analysis
|
4
|
+
attr_accessor :file, :spectrum
|
5
|
+
|
6
|
+
def initialize(file_name)
|
7
|
+
@spectrum = SpectrumAnalyzer::Objects::Spectrum.new()
|
8
|
+
@file = SpectrumAnalyzer::Objects::File.new(file_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,68 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "SpectrumAnalyzer" do
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@window_size = 512
|
7
|
+
@file_name = 'spec/analyze.wav'
|
8
|
+
SpectrumAnalyzer.configuration(
|
9
|
+
{
|
10
|
+
:window_size => 512,
|
11
|
+
:window_function => :hanning,
|
12
|
+
:analysis_ranges => [
|
13
|
+
{ :b_index => 27, :t_index => 47, :min => 1, :max => 2}, #Low area
|
14
|
+
{ :b_index => 58, :t_index => 64, :min => 2.5, :max => 6.5}, #High peak
|
15
|
+
{ :b_index => 70, :t_index => 74, :min => 2.0, :max => 4.2 }, #Mid peak
|
16
|
+
{ :b_index => 82, :t_index => 109, :min => 0.8, :max => 2} #Low area
|
17
|
+
],
|
18
|
+
:file_name => "spec/analyze.wav"
|
19
|
+
}
|
20
|
+
)
|
21
|
+
|
22
|
+
end
|
23
|
+
it 'returns true if matches are found in the analysis' do\
|
24
|
+
SpectrumAnalyzer.quick_analyze.should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates an analysis object with information about the analysis performed' do
|
28
|
+
analysis = SpectrumAnalyzer.analyze
|
29
|
+
|
30
|
+
analysis.spectrum.should be_a SpectrumAnalyzer::Objects::Spectrum
|
31
|
+
analysis.file.should be_a SpectrumAnalyzer::Objects::File
|
32
|
+
|
33
|
+
analysis.spectrum.num_occurrences.should == 22
|
34
|
+
|
35
|
+
analysis.spectrum.domains[0].should be_a SpectrumAnalyzer::Objects::Domain
|
36
|
+
|
37
|
+
analysis.spectrum.domains[0].values.length.should == @window_size / 2
|
38
|
+
analysis.spectrum.domains[0].raw_values.length.should == @window_size / 2
|
39
|
+
analysis.spectrum.domains[0].values[0].class.should be Float
|
40
|
+
analysis.spectrum.domains[0].raw_values[0].class.should be Complex
|
41
|
+
|
42
|
+
analysis.file.name.should == @file_name
|
43
|
+
analysis.file.sample_rate.should == 8000
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'bombs out without a file :(' do
|
48
|
+
SpectrumAnalyzer.configuration.file_name = ""
|
49
|
+
|
50
|
+
expect{SpectrumAnalyzer.analyze}.to raise_error(StandardError)
|
6
51
|
end
|
52
|
+
#
|
53
|
+
#it 'bombs out without a window :( - Analyze' do
|
54
|
+
# SpectrumAnalyzer.configuration.window_function = []
|
55
|
+
# SpectrumAnalyzer.configuration.file_name = @file_name
|
56
|
+
#
|
57
|
+
# expect(SpectrumAnalyzer.analyze).to raise_error
|
58
|
+
#
|
59
|
+
#end
|
60
|
+
#
|
61
|
+
#it 'bombs out without a window :( - Quick Analyze' do
|
62
|
+
# SpectrumAnalyzer.configuration.window_function = []
|
63
|
+
# SpectrumAnalyzer.configuration.file_name = @file_name
|
64
|
+
#
|
65
|
+
# expect(SpectrumAnalyzer.quick_analyze).to raise_error
|
66
|
+
#
|
67
|
+
#end
|
7
68
|
end
|
data/spectrum-analyzer.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: spectrum-analyzer 0.
|
5
|
+
# stub: spectrum-analyzer 0.2.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "spectrum-analyzer"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.2.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["Justin Roberts"]
|
@@ -27,13 +27,15 @@ Gem::Specification.new do |s|
|
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
29
|
"lib/spectrum-analyzer.rb",
|
30
|
-
"lib/spectrum-analyzer/clients/analyze.rb",
|
31
|
-
"lib/spectrum-analyzer/clients/generator.rb",
|
32
|
-
"lib/spectrum-analyzer/clients/window_functions.rb",
|
33
30
|
"lib/spectrum-analyzer/config.rb",
|
34
|
-
"lib/spectrum-analyzer/
|
35
|
-
"lib/spectrum-analyzer/
|
36
|
-
"lib/spectrum-analyzer/
|
31
|
+
"lib/spectrum-analyzer/functions.rb",
|
32
|
+
"lib/spectrum-analyzer/functions/analyze.rb",
|
33
|
+
"lib/spectrum-analyzer/functions/generator.rb",
|
34
|
+
"lib/spectrum-analyzer/functions/window_functions.rb",
|
35
|
+
"lib/spectrum-analyzer/objects/analysis.rb",
|
36
|
+
"lib/spectrum-analyzer/objects/domain.rb",
|
37
|
+
"lib/spectrum-analyzer/objects/file.rb",
|
38
|
+
"lib/spectrum-analyzer/objects/spectrum.rb",
|
37
39
|
"spec/analyze.wav",
|
38
40
|
"spec/spec_helper.rb",
|
39
41
|
"spec/spectrum-analyzer_spec.rb",
|
@@ -56,6 +58,7 @@ Gem::Specification.new do |s|
|
|
56
58
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
57
59
|
s.add_development_dependency(%q<ruby-audio>, [">= 0"])
|
58
60
|
s.add_development_dependency(%q<fftw3>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
59
62
|
else
|
60
63
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
61
64
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
@@ -64,6 +67,7 @@ Gem::Specification.new do |s|
|
|
64
67
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
65
68
|
s.add_dependency(%q<ruby-audio>, [">= 0"])
|
66
69
|
s.add_dependency(%q<fftw3>, [">= 0"])
|
70
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
67
71
|
end
|
68
72
|
else
|
69
73
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
@@ -73,6 +77,7 @@ Gem::Specification.new do |s|
|
|
73
77
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
74
78
|
s.add_dependency(%q<ruby-audio>, [">= 0"])
|
75
79
|
s.add_dependency(%q<fftw3>, [">= 0"])
|
80
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
76
81
|
end
|
77
82
|
end
|
78
83
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spectrum-analyzer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Roberts
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ! '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description: Analyze a wav file for specific frequency signatures
|
112
126
|
email: justin.roberts@careerbuilder.com
|
113
127
|
executables: []
|
@@ -125,13 +139,15 @@ files:
|
|
125
139
|
- Rakefile
|
126
140
|
- VERSION
|
127
141
|
- lib/spectrum-analyzer.rb
|
128
|
-
- lib/spectrum-analyzer/clients/analyze.rb
|
129
|
-
- lib/spectrum-analyzer/clients/generator.rb
|
130
|
-
- lib/spectrum-analyzer/clients/window_functions.rb
|
131
142
|
- lib/spectrum-analyzer/config.rb
|
132
|
-
- lib/spectrum-analyzer/
|
133
|
-
- lib/spectrum-analyzer/
|
134
|
-
- lib/spectrum-analyzer/
|
143
|
+
- lib/spectrum-analyzer/functions.rb
|
144
|
+
- lib/spectrum-analyzer/functions/analyze.rb
|
145
|
+
- lib/spectrum-analyzer/functions/generator.rb
|
146
|
+
- lib/spectrum-analyzer/functions/window_functions.rb
|
147
|
+
- lib/spectrum-analyzer/objects/analysis.rb
|
148
|
+
- lib/spectrum-analyzer/objects/domain.rb
|
149
|
+
- lib/spectrum-analyzer/objects/file.rb
|
150
|
+
- lib/spectrum-analyzer/objects/spectrum.rb
|
135
151
|
- spec/analyze.wav
|
136
152
|
- spec/spec_helper.rb
|
137
153
|
- spec/spectrum-analyzer_spec.rb
|
@@ -1,139 +0,0 @@
|
|
1
|
-
module SpectrumAnalyzer
|
2
|
-
class Generator
|
3
|
-
def initialize
|
4
|
-
@config = SpectrumAnalyzer.configuration
|
5
|
-
@file = build_file_info
|
6
|
-
@spectrum = SpectrumAnalyzer.spectrum
|
7
|
-
@window_functions = SpectrumAnalyzer::WindowFunctions.new(@config.window_size)
|
8
|
-
end
|
9
|
-
|
10
|
-
def set_file(file)
|
11
|
-
@file = file
|
12
|
-
end
|
13
|
-
|
14
|
-
def quick_analyze
|
15
|
-
begin
|
16
|
-
buffer = RubyAudio::Buffer.float(@config.window_size)
|
17
|
-
RubyAudio::Sound.open(@config.file_name) do |snd|
|
18
|
-
while snd.read(buffer) != 0
|
19
|
-
domain = generate_domain(buffer)
|
20
|
-
return true if domain_contains_frequencies?(domain)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
rescue => error
|
25
|
-
p "Error: " + error.to_s
|
26
|
-
exit
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def build_spectrum
|
31
|
-
generate_spectrum()
|
32
|
-
analyze_spectrum()
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def domain_contains_frequencies?(domain)
|
38
|
-
j=0
|
39
|
-
match = Array.new()
|
40
|
-
@config.analysis_ranges.each do |range|
|
41
|
-
sum_total = 0
|
42
|
-
for i in range[:b_index]..range[:t_index]
|
43
|
-
sum_total += domain.values[i] if !domain.values[i].nil?
|
44
|
-
end
|
45
|
-
average = sum_total / (range[:t_index] - range[:b_index])
|
46
|
-
match[j] = average > range[:min] and average < range[:max]
|
47
|
-
j+=1
|
48
|
-
end
|
49
|
-
return !match.include?(false)
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
def generate_spectrum
|
55
|
-
begin
|
56
|
-
buffer = RubyAudio::Buffer.float(@config.window_size)
|
57
|
-
RubyAudio::Sound.open(@config.file_name) do |snd|
|
58
|
-
while snd.read(buffer) != 0
|
59
|
-
domain = generate_domain(buffer)
|
60
|
-
@spectrum.domains.push(domain)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
rescue => err
|
65
|
-
p "error reading audio file: " + err.to_s
|
66
|
-
exit
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def sum_domains
|
71
|
-
@spectrum.entire_spectrum = Array.new(@spectrum.domains[0].values.length, 0)
|
72
|
-
@spectrum.domains.each do |domain|
|
73
|
-
@spectrum.entire_spectrum.map!.with_index{ |x,i| x + domain.values[i]}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def generate_domain(buffer)
|
78
|
-
windowed_array = apply_window(buffer.to_a, windows[@config.window_function])
|
79
|
-
na = NArray.to_na(windowed_array)
|
80
|
-
fft_array = FFTW3.fft(na).to_a[0, @config.window_size/2]
|
81
|
-
domain = SpectrumAnalyzer::Domain.new()
|
82
|
-
fft_array.each { |x| domain.raw_values.push(x); domain.values.push(x.magnitude)}
|
83
|
-
domain
|
84
|
-
end
|
85
|
-
|
86
|
-
def analyze_spectrum
|
87
|
-
sum_domains
|
88
|
-
find_occurrences
|
89
|
-
end
|
90
|
-
|
91
|
-
def find_occurrences
|
92
|
-
ranges = @config.analysis_ranges
|
93
|
-
occurrence_count = 0
|
94
|
-
@spectrum.domains.each do |domain|
|
95
|
-
ranges.each do |range|
|
96
|
-
if find_occurrence(range, domain)
|
97
|
-
occurrence_count += 1
|
98
|
-
domain.contains_frequency_range = true
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
@spectrum.num_occurrences = occurrence_count
|
103
|
-
end
|
104
|
-
|
105
|
-
def find_occurrence (range, domain)
|
106
|
-
sum_total = 0
|
107
|
-
for i in range[:b_index]..range[:t_index]
|
108
|
-
sum_total += domain.values[i] if !domain.nil?
|
109
|
-
end
|
110
|
-
average = sum_total / (range[:t_index] - range[:b_index])
|
111
|
-
average > range[:min] and average < range[:max]
|
112
|
-
end
|
113
|
-
|
114
|
-
def build_file_info
|
115
|
-
file = SpectrumAnalyzer::File.new(@config.file_name)
|
116
|
-
file.sample_rate = RubyAudio::Sound.open(file.name).info.samplerate
|
117
|
-
file
|
118
|
-
end
|
119
|
-
|
120
|
-
def windows
|
121
|
-
@window_functions.windows()
|
122
|
-
end
|
123
|
-
|
124
|
-
|
125
|
-
def apply_window(buffer, window_type)
|
126
|
-
windowed_array = Array.new()
|
127
|
-
i=0
|
128
|
-
buffer.each { |x| windowed_array[i] = x * window_type[i]; i+=1}
|
129
|
-
end
|
130
|
-
|
131
|
-
def analysis_array
|
132
|
-
@config.analysis_array
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
|