wavspa 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,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")