plant-sirens 0.3.0 → 0.4.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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'sirens'
3
+ include Sirens
4
+
5
+ # Open the sound.
6
+ s = Sound.new
7
+ s.frameLength = 0.04
8
+ s.hopLength = 0.02
9
+ s.open('sounds/whistle4.wav')
10
+
11
+ # Create the feature objects.
12
+ l = Loudness.new
13
+ ts = TemporalSparsity.new
14
+ ss = SpectralSparsity.new
15
+ sc = SpectralCentroid.new
16
+ ti = TransientIndex.new
17
+ h = Harmonicity.new
18
+
19
+ # Set feature history size for all features.
20
+ [l, ts, ss, sc, ti, h].each do |f|
21
+ f.maxHistorySize = s.frames - 1
22
+ end
23
+
24
+ # Set spectrum size and sample rate for relevant spectral features.
25
+ [sc, ti, h].each do |f|
26
+ f.spectrumSize = s.spectrumSize
27
+ f.sampleRate = s.sampleRate
28
+ end
29
+
30
+ # Set other feature-specific parameters.
31
+ ts.windowSize = 50
32
+ ti.filters = 30
33
+ ti.mels = 15
34
+ h.absThreshold = 1
35
+ h.threshold = 0.1
36
+ h.searchRegionLength = 5
37
+ h.maxPeaks = 3
38
+ h.lpfCoefficient = 0.7
39
+
40
+ # Create a feature set to hold all the features.
41
+ features = FeatureSet.new
42
+
43
+ [l, ts].each do |f|
44
+ features.addSampleFeature f
45
+ end
46
+
47
+ [ss, sc, ti, h].each do |f|
48
+ features.addSpectralFeature f
49
+ end
50
+
51
+ s.features = features
52
+
53
+ # Extract feature histories.
54
+ s.extractFeatures
55
+ s.close
56
+
57
+ # Print the feature histories.
58
+ [l, ts, ss, sc, ti, h].each do |f|
59
+ f.history.each {|value| print value, ','}
60
+ print "\n"
61
+ end
@@ -0,0 +1,89 @@
1
+ require 'rubygems'
2
+ require 'sirens'
3
+ require 'matrix'
4
+
5
+ #---------#
6
+ # Helpers #
7
+ #---------#
8
+
9
+ # Why Matrix isn't built with this is beyond me.
10
+ class Matrix
11
+ def []=(i,j,x)
12
+ @rows[i][j] = x
13
+ end
14
+ end
15
+
16
+ # Normalize a log-likelihood similarity matrix to be a scaled distance matrix.
17
+ def normalize_affinity(matrix)
18
+ ones = Matrix.row_vector(Array.new(matrix.row_size) {1})
19
+ diag = Matrix.column_vector(Array.new(matrix.row_size) {|i| matrix[i, i]})
20
+
21
+ (diag * ones) + (ones.transpose * diag.transpose) - matrix - matrix.transpose
22
+ end
23
+
24
+ #--------#
25
+ # Script #
26
+ #--------#
27
+
28
+ files = ['sounds/whistle1.wav', 'sounds/whistle2.wav', 'sounds/whistle3.wav', 'sounds/whistle4.wav']
29
+ comparators = []
30
+
31
+ # Create the sound object, which will be reused to open and extract features from each sound.
32
+ s = Sirens::Sound.new
33
+ s.frameLength = 0.04
34
+ s.hopLength = 0.02
35
+
36
+ # For each sound, open it, extract its features, and create a comparator for it.
37
+ files.each do |filename|
38
+ # Open the sound.
39
+ s.open(filename)
40
+
41
+ # Create the feature objects.
42
+ l = Sirens::Loudness.new
43
+ ts = Sirens::TemporalSparsity.new
44
+ ss = Sirens::SpectralSparsity.new
45
+ sc = Sirens::SpectralCentroid.new
46
+ ti = Sirens::TransientIndex.new
47
+ h = Sirens::Harmonicity.new
48
+
49
+ # Set feature history size for all features.
50
+ [l, ts, ss, sc, ti, h].each do |f|
51
+ f.maxHistorySize = s.frames - 1
52
+ end
53
+
54
+ # Set spectrum size and sample rate for relevant spectral features.
55
+ [sc, ti, h].each do |f|
56
+ f.spectrumSize = s.spectrumSize
57
+ f.sampleRate = s.sampleRate
58
+ end
59
+
60
+ # Create a feature set to hold all the features.
61
+ features = Sirens::FeatureSet.new
62
+
63
+ [l, ts].each do |f|
64
+ features.addSampleFeature f
65
+ end
66
+
67
+ [ss, sc, ti, h].each do |f|
68
+ features.addSpectralFeature f
69
+ end
70
+
71
+ s.features = features
72
+
73
+ # Extract feature histories.
74
+ s.extractFeatures
75
+ s.close
76
+
77
+ # Make the retrieval model.
78
+ comparators.push Sirens::SoundComparator.new
79
+ comparators.last.features = features
80
+ end
81
+
82
+ # Compute log-likelihood similarity matrix.
83
+ log_likelihood = Matrix.rows(Array.new(comparators.size) {|i| Array.new(comparators.size) {|j| comparators[i].compare(comparators[j])}})
84
+
85
+ # Compute log-scale normalized distance matrix.
86
+ affinity = normalize_affinity log_likelihood
87
+
88
+ # Print results.
89
+ puts log_likelihood, affinity
@@ -6,7 +6,7 @@ include Sirens
6
6
  s = Sound.new
7
7
  s.frameLength = 0.04
8
8
  s.hopLength = 0.02
9
- s.open('sound.wav')
9
+ s.open('sounds/whistle4.wav')
10
10
 
11
11
  # Initialize features.
12
12
  l = Loudness.new
@@ -44,7 +44,7 @@ sc.segmentationParameters.pLagMinus = 0.075
44
44
  ss = SpectralSparsity.new
45
45
  ss.maxHistorySize = s.frames
46
46
  ss.max = 0.6509
47
- ss.min = 1.0 / 1024.0
47
+ ss.min = 0
48
48
  ss.segmentationParameters.alpha = 0.05
49
49
  ss.segmentationParameters.r = 0.0196
50
50
  ss.segmentationParameters.cStayOff = 0.001833506
@@ -56,33 +56,37 @@ ss.segmentationParameters.cStayOn = 0.009296018
56
56
  ss.segmentationParameters.pLagPlus = 0.75
57
57
  ss.segmentationParameters.pLagMinus = 0.75
58
58
 
59
+ # Create a feature set to hold the features.
59
60
  features = FeatureSet.new
60
- features.sampleFeatures = [l]
61
- features.spectralFeatures =[sc, ss]
61
+ features.addSampleFeature l
62
+ features.addSpectralFeature sc
63
+ features.addSpectralFeature ss
64
+ s.features = features
62
65
 
63
66
  # Extract features.
64
67
  before = Time.now
65
68
 
66
- s.features = features
67
69
  s.extractFeatures
68
70
  s.close
69
71
 
70
72
  elapsed = Time.now - before
71
73
  puts "Feature extraction took #{elapsed} seconds."
72
74
 
73
- # Segment sound.
75
+ # Initialize a segmenter.
74
76
  segmenter = Segmenter.new
77
+ segmenter.features = features
75
78
  segmenter.pNew = 0.00000000001
76
79
  segmenter.pOff = 0.00000000001
77
- segmenter.beams = 20
78
80
 
81
+ # Segment sound.
79
82
  before = Time.now
80
83
 
81
- segments = segmenter.segment(features)
84
+ segmenter.segment
82
85
 
83
86
  elapsed = Time.now - before
84
87
  puts "Segmentation took #{elapsed} seconds."
85
88
 
86
- segments.each do |start, duration|
87
- puts "%d-%d" % [start, start + duration]
89
+ # Print segments.
90
+ segmenter.segments.each do |start, stop|
91
+ puts "%d-%d" % [start, stop]
88
92
  end
Binary file
Binary file
Binary file
@@ -1,3 +1,30 @@
1
+ /*
2
+ * Copyright (c) 2009 Brandon Mechtley
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining
5
+ * a copy of this software and associated documentation files (the
6
+ * "Software"), to deal in the Software without restriction, including
7
+ * without limitation the rights to use, copy, modify, merge, publish,
8
+ * distribute, sublicense, and/or sell copies of the Software, and to
9
+ * permit persons to whom the Software is furnished to do so, subject to
10
+ * the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be
13
+ * included in all copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ // Make sure to include Sirens before Rice so that there aren't conflicts between uBLAS and Rice.
25
+ #include "sirens/Sirens.h"
26
+ using namespace Sirens;
27
+
1
28
  #include "rice/Class.hpp"
2
29
  #include "rice/Array.hpp"
3
30
  #include "rice/String.hpp"
@@ -5,17 +32,14 @@
5
32
  #include "rice/Constructor.hpp"
6
33
  using namespace Rice;
7
34
 
8
- #include "sirens/Sirens.h"
9
- using namespace Sirens;
10
-
11
35
  /*---------------------*
12
36
  * Rice class wrappers *
13
37
  *---------------------*/
14
38
 
15
39
  // All of this is just so that we can wrap getSegmentationParameters() to avoid putting the returned pointer in the garbage collector.
16
40
  // Rice requires that we wrap every descendent of Feature. For whatever reason, it won't support things like
17
- // &SpectralCentroid::getSampleRate (the parent classº in the class definition for RiceSpectralCentroid, so it's necessary to provide
18
- // delegate functions for every parameter.
41
+ // &SpectralCentroid::getSampleRate (the parent class) in the class definition for RiceSpectralCentroid, so it's necessary to wrap
42
+ // every accessor.
19
43
 
20
44
  class RiceFeature : public Feature {
21
45
  public:
@@ -26,7 +50,13 @@ public:
26
50
 
27
51
  class RiceLoudness : public Loudness, public RiceFeature {};
28
52
  class RiceSpectralSparsity : public SpectralSparsity, public RiceFeature {};
29
- class RiceTemporalSparsity : public TemporalSparsity, public RiceFeature {};
53
+
54
+ class RiceTemporalSparsity : public TemporalSparsity, public RiceFeature {
55
+ public:
56
+ void setWindowSize(int value) {TemporalSparsity::setWindowSize(value);}
57
+ int getWindowSize() {return TemporalSparsity::getWindowSize();}
58
+ };
59
+
30
60
  class RiceSpectralCentroid : public SpectralCentroid, public RiceFeature {
31
61
  public:
32
62
  void setSpectrumSize(int value) {SpectralCentroid::setSpectrumSize(value);}
@@ -120,7 +150,7 @@ vector<int> from_ruby<vector<int> >(Object x) {
120
150
  return values;
121
151
  }
122
152
 
123
- // 2D double vector
153
+ // 2D double vector.
124
154
  template <>
125
155
  Object to_ruby<vector<double> >(vector<double> const & x) {
126
156
  return Array(x.begin(), x.end());
@@ -152,6 +182,33 @@ vector<vector<double> > from_ruby<vector<vector<double> > >(Object x) {
152
182
  return matrix;
153
183
  }
154
184
 
185
+ // 2D int vector.
186
+ template <>
187
+ Object to_ruby<vector<vector<int> > >(vector<vector<int> > const & x) {
188
+ return Array(x.begin(), x.end());
189
+ }
190
+
191
+ template <>
192
+ vector<vector<int> > from_ruby<vector<vector<int> > >(Object x) {
193
+ vector<vector<int> > matrix;
194
+
195
+ Array ruby_matrix(x);
196
+
197
+ for (unsigned int i = 0; i < ruby_matrix.size(); i++) {
198
+ vector<int> row;
199
+ Array ruby_row(ruby_matrix[i]);
200
+
201
+ for (unsigned int j = 0; j < ruby_row.size(); j++) {
202
+ int* value = (int*)(ruby_row[j].value());
203
+ row.push_back(*value);
204
+ }
205
+
206
+ matrix.push_back(row);
207
+ }
208
+
209
+ return matrix;
210
+ }
211
+
155
212
  /*------------------------*
156
213
  * Rice class definitions *
157
214
  *------------------------*/
@@ -188,11 +245,12 @@ extern "C" void Init_sirens() {
188
245
  Data_Type<FeatureSet> rb_cFeatureSet =
189
246
  define_class_under<FeatureSet>(rb_mSirens, "FeatureSet")
190
247
  .define_constructor(Constructor<FeatureSet>())
248
+ .define_method("addSampleFeature", &FeatureSet::addSampleFeature)
249
+ .define_method("addSpectralFeature", &FeatureSet::addSpectralFeature)
191
250
  .define_method("sampleFeatures", &FeatureSet::getSampleFeatures)
192
- .define_method("sampleFeatures=", &FeatureSet::setSampleFeatures)
193
251
  .define_method("spectralFeatures", &FeatureSet::getSpectralFeatures)
194
- .define_method("spectralFeatures=", &FeatureSet::setSpectralFeatures)
195
- .define_method("features", &FeatureSet::getFeatures);
252
+ .define_method("features", &FeatureSet::getFeatures)
253
+ .define_method("minHistorySize", &FeatureSet::getMinHistorySize);
196
254
 
197
255
  Data_Type<SegmentationParameters> rb_cSegmentationParameters =
198
256
  define_class_under<SegmentationParameters>(rb_mSirens, "SegmentationParameters")
@@ -220,14 +278,24 @@ extern "C" void Init_sirens() {
220
278
  Data_Type<Segmenter> rb_cSegmenter =
221
279
  define_class_under<Segmenter>(rb_mSirens, "Segmenter")
222
280
  .define_constructor(Constructor<Segmenter>())
281
+ .define_method("features=", &Segmenter::setFeatures)
282
+ .define_method("features", &Segmenter::getFeatures)
223
283
  .define_method("pNew", &Segmenter::getPNew)
224
284
  .define_method("pNew=", &Segmenter::setPNew)
225
285
  .define_method("pOff", &Segmenter::getPOff)
226
286
  .define_method("pOff=", &Segmenter::setPOff)
227
287
  .define_method("segments", &Segmenter::getSegments)
228
288
  .define_method("modes", &Segmenter::getModes)
229
- .define_method("segment", &Segmenter::getSegments);
230
-
289
+ .define_method("segment", &Segmenter::segment);
290
+
291
+ Data_Type<SoundComparator> rb_cSoundComparator =
292
+ define_class_under<SoundComparator>(rb_mSirens, "SoundComparator")
293
+ .define_constructor(Constructor<SoundComparator>())
294
+ .define_method("features=", &SoundComparator::setFeatures)
295
+ .define_method("features", &SoundComparator::getFeatures)
296
+ .define_method("compare", &SoundComparator::compare)
297
+ .define_method("initializeModel", &SoundComparator::initialize);
298
+
231
299
  /*
232
300
  FeatureBase is an unused base class that implements Feature. Feature is the
233
301
  actual class that implements RiceFeature, the wrapper Feature class that
@@ -237,7 +305,7 @@ extern "C" void Init_sirens() {
237
305
  Data_Type<Feature> rb_cFeature =
238
306
  define_class_under<Feature>(rb_mSirens, "FeatureBase")
239
307
  .define_constructor(Constructor<Feature>())
240
- .define_method("to_s", &Feature::toString)
308
+ .define_method("featureName", &Feature::toString)
241
309
  .define_method("history", &Feature::getHistory)
242
310
  .define_method("history[]", &Feature::getHistoryFrame)
243
311
  .define_method("maxHistorySize", &Feature::getMaxHistorySize)
data/sirens.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{sirens}
5
- s.version = "0.3.0"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Brandon Mechtley"]
9
- s.date = %q{2009-08-25}
9
+ s.date = %q{2009-09-01}
10
10
  s.description = %q{Ruby gem that implements Sirens, a library for segmentation, indexing, and retrieval of environmental and natural sounds.}
11
11
  s.email = %q{bmechtley+github@gmail.com}
12
12
  s.extensions = ["ext/sirens/extconf.rb"]
@@ -19,9 +19,13 @@ Gem::Specification.new do |s|
19
19
  "README.markdown",
20
20
  "Rakefile",
21
21
  "VERSION",
22
+ "examples/features.rb",
23
+ "examples/retrieval.rb",
22
24
  "examples/segmentation.rb",
23
- "examples/sound.wav",
24
- "examples/three_features.rb",
25
+ "examples/sounds/whistle1.wav",
26
+ "examples/sounds/whistle2.wav",
27
+ "examples/sounds/whistle3.wav",
28
+ "examples/sounds/whistle4.wav",
25
29
  "ext/sirens/extconf.rb",
26
30
  "ext/sirens/extconf.rb",
27
31
  "ext/sirens/sirens.cpp",
@@ -34,8 +38,9 @@ Gem::Specification.new do |s|
34
38
  s.rubygems_version = %q{1.3.3}
35
39
  s.summary = %q{Ruby gem that for the Sirens library.}
36
40
  s.test_files = [
37
- "examples/segmentation.rb",
38
- "examples/three_features.rb"
41
+ "examples/features.rb",
42
+ "examples/retrieval.rb",
43
+ "examples/segmentation.rb"
39
44
  ]
40
45
 
41
46
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plant-sirens
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Mechtley
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-25 00:00:00 -07:00
12
+ date: 2009-09-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -36,15 +36,18 @@ files:
36
36
  - README.markdown
37
37
  - Rakefile
38
38
  - VERSION
39
+ - examples/features.rb
40
+ - examples/retrieval.rb
39
41
  - examples/segmentation.rb
40
- - examples/sound.wav
41
- - examples/three_features.rb
42
+ - examples/sounds/whistle1.wav
43
+ - examples/sounds/whistle2.wav
44
+ - examples/sounds/whistle3.wav
45
+ - examples/sounds/whistle4.wav
42
46
  - ext/sirens/extconf.rb
43
47
  - ext/sirens/sirens.cpp
44
48
  - sirens.gemspec
45
49
  has_rdoc: false
46
50
  homepage: http://github.com/plant/sirens-ruby
47
- licenses:
48
51
  post_install_message:
49
52
  rdoc_options:
50
53
  - --charset=UTF-8
@@ -65,10 +68,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
68
  requirements: []
66
69
 
67
70
  rubyforge_project:
68
- rubygems_version: 1.3.5
71
+ rubygems_version: 1.2.0
69
72
  signing_key:
70
73
  specification_version: 3
71
74
  summary: Ruby gem that for the Sirens library.
72
75
  test_files:
76
+ - examples/features.rb
77
+ - examples/retrieval.rb
73
78
  - examples/segmentation.rb
74
- - examples/three_features.rb
@@ -1,27 +0,0 @@
1
- require 'rubygems'
2
- require 'sirens'
3
- include Sirens
4
-
5
- s = Sound.new
6
- s.frameLength = 0.04
7
- s.hopLength = 0.02
8
- s.open('sound.wav')
9
- l = Loudness.new
10
- ss = SpectralSparsity.new
11
- ts = TemporalSparsity.new
12
-
13
- [l, ss, ts].each do |f|
14
- f.maxHistorySize = s.frames
15
- end
16
-
17
- s.sampleFeatures = [l, ts]
18
- s.spectralFeatures = [ss]
19
-
20
- s.extractFeatures
21
-
22
- s.close
23
-
24
- [l, ss, ts].each do |f|
25
- f.history.each {|value| print value, ','}
26
- print "\n"
27
- end