wavspa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,458 @@
1
+ /*
2
+ * Ooura FFT library interface fro Ruby
3
+ *
4
+ * Copyright (C) 2016 Hiroshi Kuwagata <kgt9221@gmail.com>
5
+ */
6
+
7
+ #include "ruby.h"
8
+ #include "fft.h"
9
+
10
+ #include <stdint.h>
11
+ #include <string.h>
12
+
13
+ #define N(x) (sizeof((x))/sizeof(*(x)))
14
+ #define RUNTIME_ERROR(...) rb_raise(rb_eRuntimeError, __VA_ARGS__)
15
+ #define ARGUMENT_ERROR(...) rb_raise(rb_eArgError, __VA_ARGS__)
16
+ #define RB_FFT(p) ((rb_fft_t*)(p))
17
+ #define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
18
+
19
+ typedef struct {
20
+ fft_t* fft;
21
+ } rb_fft_t;
22
+
23
+ static VALUE wavspa_module;
24
+ static VALUE fft_klass;
25
+
26
+ static void
27
+ rb_fft_free(void* ptr)
28
+ {
29
+ fft_destroy(RB_FFT(ptr)->fft);
30
+ free(ptr);
31
+ }
32
+
33
+ static VALUE
34
+ rb_fft_alloc(VALUE self)
35
+ {
36
+ rb_fft_t* ptr;
37
+
38
+ ptr = xmalloc(sizeof(rb_fft_t));
39
+
40
+ ptr->fft = NULL;
41
+
42
+ return Data_Make_Struct(fft_klass, rb_fft_t, 0, rb_fft_free, ptr);
43
+ }
44
+
45
+ static VALUE
46
+ rb_fft_initialize(VALUE self, VALUE fmt, VALUE capa)
47
+ {
48
+ rb_fft_t* ptr;
49
+ int err;
50
+
51
+ /*
52
+ * check argument
53
+ */
54
+ Check_Type(fmt, T_STRING);
55
+ Check_Type(capa, T_FIXNUM);
56
+
57
+ /*
58
+ * strip object
59
+ */
60
+ Data_Get_Struct(self, rb_fft_t, ptr);
61
+
62
+ /*
63
+ * create fft context
64
+ */
65
+ err = fft_new(RSTRING_PTR(fmt), FIX2INT(capa), &ptr->fft);
66
+ if (err) {
67
+ RUNTIME_ERROR( "fft_new() failed. [err = %d]\n", err);
68
+ }
69
+
70
+ return Qtrue;
71
+ }
72
+
73
+ static VALUE
74
+ rb_fft_shift_in(VALUE self, VALUE data)
75
+ {
76
+ rb_fft_t* ptr;
77
+ int err;
78
+ void* src;
79
+ int n;
80
+
81
+ /*
82
+ * check argument
83
+ */
84
+ Check_Type(data, T_STRING);
85
+
86
+ /*
87
+ * strip object
88
+ */
89
+ Data_Get_Struct(self, rb_fft_t, ptr);
90
+
91
+ /*
92
+ * call fft library
93
+ */
94
+
95
+ src = RSTRING_PTR(data);
96
+ n = RSTRING_LEN(data) / (ptr->fft->fmt & 0x000f);
97
+
98
+ err = fft_shift_in(ptr->fft, src, n);
99
+ if (err) {
100
+ RUNTIME_ERROR( "fft_shift_in() failed. [err = %d]\n", err);
101
+ }
102
+
103
+ return self;
104
+ }
105
+
106
+ static VALUE
107
+ rb_fft_reset(VALUE self)
108
+ {
109
+ rb_fft_t* ptr;
110
+ int err;
111
+
112
+ /*
113
+ * strip object
114
+ */
115
+ Data_Get_Struct(self, rb_fft_t, ptr);
116
+
117
+ /*
118
+ * call fft library
119
+ */
120
+ err = fft_reset(ptr->fft);
121
+
122
+ if (err) {
123
+ RUNTIME_ERROR( "fft_reset() failed. [err = %d]\n", err);
124
+ }
125
+
126
+ return self;
127
+ }
128
+
129
+ static VALUE
130
+ rb_fft_transform(VALUE self)
131
+ {
132
+ rb_fft_t* ptr;
133
+ int err;
134
+
135
+ /*
136
+ * strip object
137
+ */
138
+ Data_Get_Struct(self, rb_fft_t, ptr);
139
+
140
+ /*
141
+ * call transform function
142
+ */
143
+ err = fft_transform(ptr->fft);
144
+ if (err) {
145
+ RUNTIME_ERROR( "fft_transform() failed. [err = %d]\n", err);
146
+ }
147
+
148
+ return self;
149
+ }
150
+
151
+ static VALUE
152
+ rb_fft_enqueue(VALUE self, VALUE data)
153
+ {
154
+ rb_fft_shift_in(self, data);
155
+ rb_fft_transform(self);
156
+
157
+ return self;
158
+ }
159
+
160
+ static VALUE
161
+ rb_fft_set_window(VALUE self, VALUE _type)
162
+ {
163
+ rb_fft_t* ptr;
164
+ int type;
165
+ int err;
166
+
167
+ /*
168
+ * check argument
169
+ */
170
+ if (TYPE(_type) != T_STRING && TYPE(_type) != T_SYMBOL) {
171
+ RUNTIME_ERROR( "Window type is unsupported data");
172
+
173
+ } else if (EQ_STR(_type, "RECTANGULAR")) {
174
+ type = FFT_WINDOW_RECTANGULAR;
175
+
176
+ } else if (EQ_STR(_type, "HAMMING")) {
177
+ type = FFT_WINDOW_HAMMING;
178
+
179
+ } else if (EQ_STR(_type, "HANN")) {
180
+ type = FFT_WINDOW_HANN;
181
+
182
+ } else if (EQ_STR(_type, "BLACKMAN")) {
183
+ type = FFT_WINDOW_BLACKMAN;
184
+
185
+ } else if (EQ_STR(_type, "BLACKMAN_NUTTALL")) {
186
+ type = FFT_WINDOW_BLACKMAN_NUTTALL;
187
+
188
+ } else if (EQ_STR(_type, "FLAT_TOP")) {
189
+ type = FFT_WINDOW_FLAT_TOP;
190
+
191
+ } else {
192
+ RUNTIME_ERROR( "Unknown window type");
193
+ }
194
+
195
+ /*
196
+ * strip object
197
+ */
198
+ Data_Get_Struct(self, rb_fft_t, ptr);
199
+
200
+ /*
201
+ * call set window
202
+ */
203
+ err = fft_set_window(ptr->fft, type);
204
+ if (err) {
205
+ RUNTIME_ERROR( "fft_set_window() failed. [err = %d]\n", err);
206
+ }
207
+
208
+ return _type;
209
+ }
210
+
211
+ static VALUE
212
+ rb_fft_get_width(VALUE self)
213
+ {
214
+ rb_fft_t* ptr;
215
+
216
+ Data_Get_Struct(self, rb_fft_t, ptr);
217
+
218
+ return INT2FIX(ptr->fft->width);
219
+ }
220
+
221
+ static VALUE
222
+ rb_fft_set_width(VALUE self, VALUE width)
223
+ {
224
+ rb_fft_t* ptr;
225
+ int err;
226
+
227
+ /*
228
+ * check argument
229
+ */
230
+ Check_Type(width, T_FIXNUM);
231
+
232
+ /*
233
+ * strip object
234
+ */
235
+ Data_Get_Struct(self, rb_fft_t, ptr);
236
+
237
+ /*
238
+ * call set window
239
+ */
240
+ err = fft_set_width(ptr->fft, FIX2INT(width));
241
+ if (err) {
242
+ RUNTIME_ERROR( "fft_set_width() failed. [err = %d]\n", err);
243
+ }
244
+
245
+ return width;
246
+ }
247
+
248
+ static VALUE
249
+ rb_fft_get_scale_mode(VALUE self)
250
+ {
251
+ VALUE ret;
252
+ rb_fft_t* ptr;
253
+
254
+ Data_Get_Struct(self, rb_fft_t, ptr);
255
+
256
+ switch (ptr->fft->mode) {
257
+ case FFT_LOGSCALE_MODE:
258
+ ret = ID2SYM(rb_intern("LOGSCALE"));
259
+ break;
260
+
261
+ case FFT_LINEARSCALE_MODE:
262
+ ret = ID2SYM(rb_intern("LINEARSCALE"));
263
+ break;
264
+
265
+ default:
266
+ RUNTIME_ERROR( "Really?");
267
+ }
268
+
269
+ return ret;
270
+ }
271
+
272
+ static VALUE
273
+ rb_fft_set_scale_mode(VALUE self, VALUE _mode)
274
+ {
275
+ rb_fft_t* ptr;
276
+ int err;
277
+ int mode;
278
+
279
+ /*
280
+ * check argument
281
+ */
282
+ if (EQ_STR(_mode, "LOGSCALE") || EQ_STR(_mode, "LOG")) {
283
+ mode = FFT_LOGSCALE_MODE;
284
+
285
+ } else if (EQ_STR(_mode, "LINEARSCALE") || EQ_STR(_mode, "LINEAR")) {
286
+ mode = FFT_LINEARSCALE_MODE;
287
+
288
+ } else {
289
+ ARGUMENT_ERROR("not supported value");
290
+ }
291
+
292
+ /*
293
+ * strip object
294
+ */
295
+ Data_Get_Struct(self, rb_fft_t, ptr);
296
+
297
+ /*
298
+ * call set scale mode function
299
+ */
300
+ err = fft_set_scale_mode(ptr->fft, mode);
301
+ if (err) {
302
+ RUNTIME_ERROR( "fft_set_scale_mode() failed. [err = %d]\n", err);
303
+ }
304
+
305
+ return _mode;
306
+ }
307
+
308
+ static VALUE
309
+ rb_fft_set_frequency(VALUE self, VALUE freq)
310
+ {
311
+ rb_fft_t* ptr;
312
+ int err;
313
+ double s;
314
+ double h;
315
+ double l;
316
+
317
+ /*
318
+ * check argument
319
+ */
320
+ Check_Type(freq, T_ARRAY);
321
+ if (RARRAY_LEN(freq) != 3) {
322
+ ARGUMENT_ERROR("frequency set shall be 3 entries contain.");
323
+ }
324
+
325
+ /*
326
+ * strip object
327
+ */
328
+ Data_Get_Struct(self, rb_fft_t, ptr);
329
+
330
+ /*
331
+ * call set fequency
332
+ */
333
+ s = NUM2DBL(RARRAY_AREF(freq, 0));
334
+ l = NUM2DBL(RARRAY_AREF(freq, 1));
335
+ h = NUM2DBL(RARRAY_AREF(freq, 2));
336
+ err = fft_set_frequency(ptr->fft, s, l, h);
337
+ if (err) {
338
+ RUNTIME_ERROR( "fft_set_frequency() failed. [err = %d]\n", err);
339
+ }
340
+
341
+ return freq;
342
+ }
343
+
344
+
345
+ static VALUE
346
+ rb_fft_spectrum(VALUE self)
347
+ {
348
+ rb_fft_t* ptr;
349
+ VALUE ret;
350
+ int err;
351
+
352
+ /*
353
+ * strip object
354
+ */
355
+ Data_Get_Struct(self, rb_fft_t, ptr);
356
+
357
+ /*
358
+ * alloc return object
359
+ */
360
+ ret = rb_str_buf_new(sizeof(double) * ptr->fft->width);
361
+ rb_str_set_len(ret, sizeof(double) * ptr->fft->width);
362
+
363
+ /*
364
+ * call inverse function
365
+ */
366
+ err = fft_calc_spectrum(ptr->fft, (double*)RSTRING_PTR(ret));
367
+ if (err) {
368
+ RUNTIME_ERROR( "fft_calc_spectrum() failed. [err = %d]\n", err);
369
+ }
370
+
371
+ return ret;
372
+ }
373
+
374
+ static VALUE
375
+ rb_fft_amplitude(VALUE self)
376
+ {
377
+ rb_fft_t* ptr;
378
+ VALUE ret;
379
+ int err;
380
+
381
+ /*
382
+ * strip object
383
+ */
384
+ Data_Get_Struct(self, rb_fft_t, ptr);
385
+
386
+ /*
387
+ * alloc return object
388
+ */
389
+ ret = rb_str_buf_new(sizeof(double) * ptr->fft->width);
390
+ rb_str_set_len(ret, sizeof(double) * ptr->fft->width);
391
+
392
+ /*
393
+ * call inverse function
394
+ */
395
+ err = fft_calc_amplitude(ptr->fft, (double*)RSTRING_PTR(ret));
396
+ if (err) {
397
+ RUNTIME_ERROR( "fft_calc_amplitude() failed. [err = %d]\n", err);
398
+ }
399
+
400
+ return ret;
401
+ }
402
+
403
+ static VALUE
404
+ rb_fft_absolute(VALUE self)
405
+ {
406
+ rb_fft_t* ptr;
407
+ VALUE ret;
408
+ int err;
409
+
410
+ /*
411
+ * strip object
412
+ */
413
+ Data_Get_Struct(self, rb_fft_t, ptr);
414
+
415
+ /*
416
+ * alloc return object
417
+ */
418
+ ret = rb_str_buf_new(sizeof(double) * ptr->fft->width);
419
+ rb_str_set_len(ret, sizeof(double) * ptr->fft->width);
420
+
421
+ /*
422
+ * call inverse function
423
+ */
424
+ err = fft_calc_absolute(ptr->fft, (double*)RSTRING_PTR(ret));
425
+ if (err) {
426
+ RUNTIME_ERROR( "fft_calc_absolute() failed. [err = %d]\n", err);
427
+ }
428
+
429
+ return ret;
430
+ }
431
+
432
+
433
+ void
434
+ Init_fft()
435
+ {
436
+ wavspa_module = rb_define_module("WavSpectrumAnalyzer");
437
+ fft_klass = rb_define_class_under(wavspa_module, "FFT", rb_cObject);
438
+
439
+ rb_define_alloc_func(fft_klass, rb_fft_alloc);
440
+
441
+ rb_define_method(fft_klass, "initialize", rb_fft_initialize, 2);
442
+
443
+ rb_define_method(fft_klass, "window=", rb_fft_set_window, 1);
444
+ rb_define_method(fft_klass, "width", rb_fft_get_width, 0);
445
+ rb_define_method(fft_klass, "width=", rb_fft_set_width, 1);
446
+ rb_define_method(fft_klass, "scale_mode", rb_fft_get_scale_mode, 0);
447
+ rb_define_method(fft_klass, "scale_mode=", rb_fft_set_scale_mode, 1);
448
+ rb_define_method(fft_klass, "frequency=", rb_fft_set_frequency, 1);
449
+
450
+ rb_define_method(fft_klass, "shift_in", rb_fft_shift_in, 1);
451
+ rb_define_method(fft_klass, "reset", rb_fft_reset, 0);
452
+ rb_define_method(fft_klass, "transform", rb_fft_transform, 0);
453
+ rb_define_method(fft_klass, "enqueue", rb_fft_enqueue, 1);
454
+ rb_define_method(fft_klass, "<<", rb_fft_enqueue, 1);
455
+ rb_define_method(fft_klass, "spectrum", rb_fft_spectrum, 0);
456
+ rb_define_method(fft_klass, "amplitude", rb_fft_amplitude, 0);
457
+ rb_define_method(fft_klass, "absolute", rb_fft_absolute, 0);
458
+ }
@@ -0,0 +1,37 @@
1
+ require 'mkmf'
2
+ require 'optparse'
3
+ require 'rbconfig'
4
+
5
+ omp_path = nil
6
+ omp_name = "gomp"
7
+
8
+ OptionParser.new { |opt|
9
+ opt.on("", "--with-openmp=PATH", String) { |path|
10
+ omp_path = path
11
+ }
12
+
13
+ opt.on("--omp-name=NAME", String) { |name|
14
+ omp_name = name
15
+ }
16
+
17
+ opt.parse!(ARGV)
18
+ }
19
+
20
+ $CFLAGS << " -fopenmp"
21
+ if omp_path
22
+ $CFLAGS << " -L#{omp_path}"
23
+ $LDFLAGS << " -L#{omp_path}"
24
+
25
+ case RbConfig::CONFIG['arch']
26
+ when /-darwin/
27
+ $LDFLAGS << " -Wl,-rpath,#{omp_path}"
28
+
29
+ else
30
+ # nothing
31
+ end
32
+ end
33
+
34
+ have_library("m")
35
+ have_library(omp_name)
36
+
37
+ create_makefile( "wavspa/wavelet")