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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +196 -0
- data/Rakefile +2 -0
- data/bin/wavfft +167 -0
- data/bin/wavlet +160 -0
- data/example/Call_To_Quarters-fft.png +0 -0
- data/example/Call_To_Quarters-wavelet.png +0 -0
- data/ext/wavspa/fb/extconf.rb +3 -0
- data/ext/wavspa/fb/rb_fb.c +690 -0
- data/ext/wavspa/fft/extconf.rb +6 -0
- data/ext/wavspa/fft/fft.c +918 -0
- data/ext/wavspa/fft/fft.h +62 -0
- data/ext/wavspa/fft/fftsg.c +3314 -0
- data/ext/wavspa/fft/rb_fft.c +458 -0
- data/ext/wavspa/wavelet/extconf.rb +37 -0
- data/ext/wavspa/wavelet/rb_wavelet.c +706 -0
- data/ext/wavspa/wavelet/walet.c +803 -0
- data/ext/wavspa/wavelet/walet.h +59 -0
- data/lib/wav.rb +87 -0
- data/lib/wavspa/common.rb +74 -0
- data/lib/wavspa/version.rb +3 -0
- data/lib/wavspa/wavfft/main.rb +130 -0
- data/lib/wavspa/wavfft/preset.rb +54 -0
- data/lib/wavspa/wavlet/main.rb +139 -0
- data/lib/wavspa/wavlet/preset.rb +38 -0
- data/wavspa.gemspec +47 -0
- metadata +119 -0
@@ -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")
|