farleyknight-sndx 0.1.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.
@@ -0,0 +1,5 @@
1
+
2
+ == 0.1.0
3
+
4
+ First Gem release
5
+
@@ -0,0 +1,9 @@
1
+ Manifest.txt
2
+ README.txt
3
+ CHANGELOG.txt
4
+ Rakefile
5
+ lib/sndx.rb
6
+ test/test_sndx.rb
7
+ ext/sndx/sndx.c
8
+ ext/sndx/extconf.rb
9
+
@@ -0,0 +1,62 @@
1
+ = sndx
2
+
3
+ * http://github.com/farleyknight/sndx
4
+
5
+ == DESCRIPTION:
6
+
7
+ libsndfile + libXtract = Awesome audio analysis library
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Wraps some of libsndfile
12
+ * Wraps some of libXtract
13
+ * Has tests so you see what I got working
14
+ * Doesn't wrap all of libXtract
15
+ * Don't think I really need to wrap much of libsndfile
16
+ * Just numbers so you have no idea what they mean unless you
17
+ put some kind of GUI on it..
18
+
19
+ == SYNOPSIS:
20
+
21
+ >> require 'lib/sndx'
22
+ => true
23
+ >> @file = Sndfile.new("test/assets/48550__gusrikh__Hit_3.wav")
24
+ => #<Sndfile:0xb7def820>
25
+ >> Xtract.analyze(Xtract::MEAN, @file)
26
+ => -7.02867037034594e-05
27
+ >> Xtract.analyze(Xtract::SPECTRAL_CENTROID, @file)
28
+ => 0.114604391157627
29
+
30
+ == REQUIREMENTS:
31
+
32
+ libsndfile [http://www.mega-nerd.com/libsndfile/]
33
+ libXtract [http://libxtract.sourceforge.net]
34
+
35
+ == INSTALL:
36
+
37
+ Not yet
38
+
39
+ == LICENSE:
40
+
41
+ (The MIT License)
42
+
43
+ Copyright (c) 2009
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining
46
+ a copy of this software and associated documentation files (the
47
+ 'Software'), to deal in the Software without restriction, including
48
+ without limitation the rights to use, copy, modify, merge, publish,
49
+ distribute, sublicense, and/or sell copies of the Software, and to
50
+ permit persons to whom the Software is furnished to do so, subject to
51
+ the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be
54
+ included in all copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
57
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ gem 'rake-compiler', '>= 0.4.1'
4
+ require "rake/extensiontask"
5
+
6
+ require 'lib/sndx'
7
+
8
+ HOE = Hoe.spec('sndx') do
9
+ developer('Farley Knight', 'farleyknight@gmail.com')
10
+ self.readme_file = 'README.txt'
11
+ self.history_file = 'CHANGELOG.txt'
12
+ self.version = Sndx::VERSION
13
+ self.spec_extras = { :extensions => ["ext/sndx/extconf.rb"] }
14
+ self.extra_deps = ['rake-compiler', '>= 0.4.1']
15
+ end
16
+
17
+ Rake::ExtensionTask.new("sndx", HOE.spec) do |ext|
18
+ ext.lib_dir = File.join('lib', 'sndx')
19
+ end
20
+
@@ -0,0 +1,15 @@
1
+
2
+ require 'mkmf'
3
+
4
+ unless find_library('sndfile', 'sf_open')
5
+ abort "Couldn't find libsndfile! Make sure it's installed.."
6
+ end
7
+
8
+ unless find_library('xtract', 'xtract_init_mfcc')
9
+ abort "Couldn't find libxtract! Make sure it's installed.."
10
+ end
11
+
12
+
13
+ create_makefile('sndx/sndx')
14
+
15
+
@@ -0,0 +1,312 @@
1
+ #include <ruby.h>
2
+ #include <sndfile.h>
3
+ #include "xtract/libxtract.h"
4
+
5
+
6
+ /*********************************************************
7
+ libsndfile
8
+ **********************************************************/
9
+
10
+ VALUE cSndfile;
11
+
12
+ typedef struct {
13
+ char *filename;
14
+ SNDFILE *sndfile;
15
+ SF_INFO sf_info;
16
+ } sndfile_t;
17
+
18
+
19
+ // TODO: Close file upon dealloc
20
+ // TODO: Should only receive a sndfile_t, not the three args for constructing
21
+ // one
22
+ VALUE Data_Wrap_sndfile_t(char *filename, SNDFILE *infile, SF_INFO sf_info) {
23
+ sndfile_t *sndfile = malloc(sizeof(sndfile_t));
24
+
25
+ sndfile->filename = filename;
26
+ sndfile->sndfile = infile;
27
+ sndfile->sf_info = sf_info;
28
+
29
+ return Data_Wrap_Struct(cSndfile, 0, 0, sndfile);
30
+ }
31
+
32
+ sndfile_t *Data_Get_sndfile_t(VALUE value) {
33
+ sndfile_t *sndfile;
34
+ Data_Get_Struct(value, sndfile_t, sndfile);
35
+ return sndfile;
36
+ }
37
+
38
+ VALUE new(VALUE klass, VALUE filename) {
39
+ Check_Type(filename, T_STRING);
40
+
41
+ SNDFILE *infile;
42
+ SF_INFO info;
43
+
44
+ memset(&info, 0, sizeof (info));
45
+
46
+ infile = sf_open(StringValuePtr(filename), SFM_READ, &info);
47
+
48
+ if (infile == NULL) {
49
+ rb_raise(rb_eRuntimeError, "Error : failed to open file '%s' : %s", StringValuePtr(filename), sf_strerror (NULL));
50
+ return Qnil;
51
+ } else {
52
+ // return Qnil;
53
+ return Data_Wrap_sndfile_t(StringValuePtr(filename), infile, info);
54
+ }
55
+ }
56
+
57
+ VALUE close(VALUE self) {
58
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
59
+
60
+ if (sf_close(sndfile->sndfile)) {
61
+ return Qtrue;
62
+ } else {
63
+ rb_raise(rb_eRuntimeError, "Couldn't close Sndfile '%s'!", StringPtrValue(sndfile->filename));
64
+ return Qfalse;
65
+ }
66
+ }
67
+
68
+
69
+ VALUE read_sample(VALUE self, VALUE index) {
70
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
71
+
72
+ sf_seek(sndfile->sndfile, FIX2INT(index), SEEK_SET);
73
+
74
+ float *buffer = (float *) malloc(sizeof(float)*1);
75
+ sf_readf_float(sndfile->sndfile, buffer, 1);
76
+
77
+ return rb_float_new(buffer[0]);
78
+ }
79
+
80
+ int frame_count(sndfile_t *sndfile) {
81
+ return sndfile->sf_info.frames;
82
+ }
83
+
84
+
85
+ VALUE get(VALUE self, VALUE arg) {
86
+ long begin, length;
87
+
88
+ if (FIXNUM_P(arg)) {
89
+ return get_sample(self, FIX2INT(arg));
90
+ }
91
+
92
+ switch (rb_range_beg_len(arg, &begin, &length, frame_count(Data_Get_sndfile_t(self)), 0)) {
93
+ case Qfalse:
94
+ break;
95
+ case Qnil:
96
+ return Qnil;
97
+ default:
98
+ return get_range(self, begin, length);
99
+ }
100
+
101
+ rb_raise(rb_eRuntimeError, "Type must be either Fixnum or Range!");
102
+ return Qnil;
103
+ }
104
+
105
+
106
+ VALUE frames(VALUE self) {
107
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
108
+
109
+ return INT2FIX(sndfile->sf_info.frames);
110
+ }
111
+
112
+ VALUE samplerate(VALUE self) {
113
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
114
+ return INT2FIX(sndfile->sf_info.samplerate);
115
+ }
116
+
117
+ VALUE filename(VALUE self) {
118
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
119
+ return rb_str_new2(sndfile->filename);
120
+ }
121
+
122
+ int channel_count(sndfile_t *sndfile) {
123
+ return sndfile->sf_info.channels;
124
+ }
125
+
126
+ VALUE channels(VALUE self) {
127
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
128
+ return INT2FIX(sndfile->sf_info.channels);
129
+ }
130
+
131
+ VALUE format_name(int format) {
132
+ VALUE name = rb_str_new2("");
133
+
134
+ if ((format | SF_FORMAT_WAV) == format)
135
+ rb_str_concat(name, rb_str_new2("Microsoft WAV"));
136
+ else if ((format | SF_FORMAT_AIFF) == format)
137
+ rb_str_concat(name, rb_str_new2("Apple/SGI AIFF"));
138
+ else if ((format | SF_FORMAT_AU) == format)
139
+ rb_str_concat(name, rb_str_new2("Sun/NeXT AU"));
140
+ else if ((format | SF_FORMAT_RAW) == format)
141
+ rb_str_concat(name, rb_str_new2("RAW PCM data"));
142
+ else
143
+ rb_str_concat(name, rb_str_new2("Dunno"));
144
+
145
+ if ((format | SF_FORMAT_PCM_S8) == format)
146
+ rb_str_concat(name, rb_str_new2(" 8 bit"));
147
+ else if ((format | SF_FORMAT_PCM_16) == format)
148
+ rb_str_concat(name, rb_str_new2(" 16 bit"));
149
+ else if ((format | SF_FORMAT_PCM_24) == format)
150
+ rb_str_concat(name, rb_str_new2(" 24 bit"));
151
+ else if ((format | SF_FORMAT_PCM_32) == format)
152
+ rb_str_concat(name, rb_str_new2(" 32 bit"));
153
+
154
+ return name;
155
+ }
156
+
157
+
158
+ VALUE format(VALUE self) {
159
+ sndfile_t *sndfile = Data_Get_sndfile_t(self);
160
+ return format_name(sndfile->sf_info.format);
161
+ }
162
+
163
+
164
+ /*********************************************************
165
+ libxtract
166
+ **********************************************************/
167
+
168
+ VALUE mXtract;
169
+
170
+ float *all_samples(sndfile_t *sndfile) {
171
+ long length = frame_count(sndfile);
172
+ int i;
173
+ float *buffer;
174
+
175
+ sf_seek(sndfile->sndfile, 0, SEEK_SET);
176
+
177
+ buffer = calloc(sizeof(float), channel_count(sndfile) * length);
178
+ int samples_read = sf_readf_float(sndfile->sndfile, buffer, length);
179
+
180
+ return buffer;
181
+ }
182
+
183
+ VALUE analyze(VALUE klass, VALUE analysis_code, VALUE sound) {
184
+ Check_Type(analysis_code, T_FIXNUM);
185
+ Check_Type(sound, T_DATA);
186
+
187
+ sndfile_t *sndfile = Data_Get_sndfile_t(sound);
188
+ float result, *samples = all_samples(sndfile);
189
+
190
+ int analysis_type = FIX2INT(analysis_code);
191
+
192
+ int return_code = xtract[analysis_type](samples, frame_count(sndfile), NULL, &result);
193
+
194
+ if (return_code == XTRACT_FEATURE_NOT_IMPLEMENTED) {
195
+ rb_raise(rb_eRuntimeError, "Xtract feature '%d' not implemented", analysis_type);
196
+ return Qnil;
197
+ } else {
198
+ return rb_float_new(result);
199
+ }
200
+ }
201
+
202
+
203
+ void Init_sndx() {
204
+ /*********************************************************
205
+ libsndfile
206
+ **********************************************************/
207
+
208
+ cSndfile = rb_define_class("Sndfile", rb_cObject);
209
+ rb_define_singleton_method(cSndfile, "new", new, 1);
210
+
211
+ // File handling and accessing
212
+ // rb_define_method(cSndfile, "read", read, 2);
213
+ // rb_define_method(cSndfile, "write", write, 1);
214
+ rb_define_method(cSndfile, "[]", get, 1);
215
+ rb_define_method(cSndfile, "read", read_sample, 1);
216
+ // rb_define_method(cSndfile, "read_range", read_sample_range, 1);
217
+ rb_define_method(cSndfile, "close", close, 0);
218
+
219
+ // SF_INFO accessors
220
+ rb_define_method(cSndfile, "frames", frames, 0);
221
+ rb_define_method(cSndfile, "samplerate", samplerate, 0);
222
+ rb_define_method(cSndfile, "filename", filename, 0);
223
+ rb_define_method(cSndfile, "channels", channels, 0);
224
+ rb_define_method(cSndfile, "format", format, 0);
225
+
226
+ /*********************************************************
227
+ libxtract
228
+ **********************************************************/
229
+
230
+ mXtract = rb_define_module("Xtract");
231
+ rb_define_singleton_method(mXtract, "analyze", analyze, 2);
232
+ // rb_define_singleton_method(mXtract, "feature_list", feature_list, 0);
233
+
234
+ // Require no arguments
235
+ rb_define_const(mXtract, "MEAN", INT2FIX(XTRACT_MEAN));
236
+ rb_define_const(mXtract, "SHARPNESS", INT2FIX(XTRACT_SHARPNESS));
237
+ rb_define_const(mXtract, "RMS_AMPLITUDE", INT2FIX(XTRACT_RMS_AMPLITUDE));
238
+ rb_define_const(mXtract, "SPECTRAL_CENTROID", INT2FIX(XTRACT_SPECTRAL_CENTROID));
239
+ rb_define_const(mXtract, "POWER", INT2FIX(XTRACT_POWER));
240
+ rb_define_const(mXtract, "ODD_EVEN_RATIO", INT2FIX(XTRACT_ODD_EVEN_RATIO));
241
+ rb_define_const(mXtract, "NONZERO_COUNT", INT2FIX(XTRACT_NONZERO_COUNT));
242
+ rb_define_const(mXtract, "LOUDNESS", INT2FIX(XTRACT_LOUDNESS));
243
+ rb_define_const(mXtract, "IRREGULARITY_K", INT2FIX(XTRACT_IRREGULARITY_K));
244
+ rb_define_const(mXtract, "IRREGULARITY_J", INT2FIX(XTRACT_IRREGULARITY_J));
245
+ rb_define_const(mXtract, "FLATNESS", INT2FIX(XTRACT_FLATNESS));
246
+ rb_define_const(mXtract, "ZCR", INT2FIX(XTRACT_ZCR));
247
+
248
+
249
+ // Require .. ? arguments
250
+ /*
251
+ rb_define_const(mXtract, "VARIANCE", INT2FIX(XTRACT_VARIANCE));
252
+ rb_define_const(mXtract, "STANDARD_DEVIATION", INT2FIX(XTRACT_STANDARD_DEVIATION));
253
+ rb_define_const(mXtract, "AVERAGE_DEVIATION", INT2FIX(XTRACT_AVERAGE_DEVIATION));
254
+ rb_define_const(mXtract, "SKEWNESS", INT2FIX(XTRACT_SKEWNESS));
255
+ rb_define_const(mXtract, "KURTOSIS", INT2FIX(XTRACT_KURTOSIS));
256
+ */
257
+
258
+
259
+ /*
260
+
261
+ XTRACT_KURTOSIS,
262
+ XTRACT_SPECTRAL_MEAN,
263
+ XTRACT_SPECTRAL_VARIANCE,
264
+ XTRACT_SPECTRAL_STANDARD_DEVIATION,
265
+ XTRACT_SPECTRAL_AVERAGE_DEVIATION,
266
+ XTRACT_SPECTRAL_SKEWNESS,
267
+ XTRACT_SPECTRAL_KURTOSIS,
268
+ XTRACT_IRREGULARITY_K,
269
+ XTRACT_IRREGULARITY_J,
270
+ XTRACT_TRISTIMULUS_1,
271
+ XTRACT_TRISTIMULUS_2,
272
+ XTRACT_TRISTIMULUS_3,
273
+ XTRACT_SMOOTHNESS,
274
+ XTRACT_SPREAD,
275
+ XTRACT_ROLLOFF,
276
+ XTRACT_FLATNESS,
277
+ XTRACT_TONALITY,
278
+ XTRACT_CREST,
279
+ XTRACT_NOISINESS,
280
+ XTRACT_SPECTRAL_INHARMONICITY,
281
+ */
282
+
283
+
284
+
285
+
286
+
287
+ /*
288
+ XTRACT_SPECTRAL_SLOPE,
289
+ XTRACT_LOWEST_VALUE,
290
+ XTRACT_HIGHEST_VALUE,
291
+ XTRACT_SUM,
292
+ XTRACT_NONZERO_COUNT,
293
+ XTRACT_HPS,
294
+ XTRACT_F0,
295
+ XTRACT_FAILSAFE_F0,
296
+ XTRACT_FLUX,
297
+ XTRACT_ATTACK_TIME,
298
+ XTRACT_DECAY_TIME,
299
+ XTRACT_DELTA_FEATURE,
300
+ XTRACT_AUTOCORRELATION,
301
+ XTRACT_AMDF,
302
+ XTRACT_ASDF,
303
+ XTRACT_BARK_COEFFICIENTS,
304
+ XTRACT_PEAK_SPECTRUM,
305
+ XTRACT_SPECTRUM,
306
+ XTRACT_AUTOCORRELATION_FFT,
307
+ XTRACT_MFCC,
308
+ XTRACT_DCT,
309
+ XTRACT_HARMONIC_SPECTRUM
310
+ */
311
+
312
+ }
@@ -0,0 +1,5 @@
1
+ require 'lib/sndx/sndx'
2
+
3
+ module Sndx
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,61 @@
1
+ require "test/unit"
2
+
3
+ require 'lib/sndx'
4
+
5
+ class TestSndfile < Test::Unit::TestCase
6
+ def setup
7
+ @file = Sndfile.new("test/assets/48550__gusrikh__Hit_3.wav")
8
+ end
9
+
10
+ def teardown
11
+ @file.close
12
+ end
13
+
14
+ def test_open_file
15
+ assert_not_nil @file
16
+ end
17
+
18
+ def test_frames
19
+ assert_equal 79332, @file.frames
20
+ end
21
+
22
+ def test_samplerate
23
+ assert_equal 44100, @file.samplerate
24
+ end
25
+
26
+ def test_channels
27
+ assert_equal 2, @file.channels
28
+ end
29
+
30
+ def test_format
31
+ assert_equal "Microsoft WAV 16 bit", @file.format
32
+ end
33
+
34
+ def test_read
35
+ sample_data.each_with_index do |data, i|
36
+ assert_equal [data, i], [@file.read(i), i]
37
+ end
38
+ end
39
+
40
+ def sample_data
41
+ [-0.00054931640625,
42
+ -0.000396728515625,
43
+ -0.000396728515625,
44
+ -0.000396728515625,
45
+ -0.00054931640625,
46
+ -0.000701904296875,
47
+ -0.000274658203125,
48
+ -0.000396728515625,
49
+ 0.00054931640625,
50
+ -0.0001220703125]
51
+ end
52
+
53
+ def test_features_zero_args
54
+ [Xtract::MEAN, Xtract::SHARPNESS, Xtract::RMS_AMPLITUDE, Xtract::SPECTRAL_CENTROID,
55
+ Xtract::ODD_EVEN_RATIO, Xtract::NONZERO_COUNT, Xtract::LOUDNESS,
56
+ Xtract::IRREGULARITY_K, Xtract::IRREGULARITY_J, Xtract::FLATNESS, Xtract::ZCR].each do |analysis_code|
57
+ assert_not_equal nil, Xtract.analyze(analysis_code, @file)
58
+ end
59
+ end
60
+
61
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: farleyknight-sndx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Farley Knight
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-18 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: libsndfile + libXtract = Awesome audio analysis library
17
+ email: farleyknight@gmail.com
18
+ executables: []
19
+
20
+ extensions:
21
+ - ext/sndx/extconf.rb
22
+ extra_rdoc_files:
23
+ - README.txt
24
+ files:
25
+ - Manifest.txt
26
+ - README.txt
27
+ - CHANGELOG.txt
28
+ - Rakefile
29
+ - lib/sndx.rb
30
+ - test/test_sndx.rb
31
+ - ext/sndx/sndx.c
32
+ - ext/sndx/extconf.rb
33
+ has_rdoc: false
34
+ homepage: https://github.com/farleyknight/sndx
35
+ licenses:
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: libsndfile + libXtract = Awesome audio analysis library
60
+ test_files: []
61
+