wavspa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,706 @@
1
+ /*
2
+ * Wavelet library interface for Ruby.
3
+ *
4
+ * Copyright (C) 2016 Hiroshi Kuwagata <kgt9221@gmail.com>
5
+ */
6
+
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+
10
+ #include "ruby.h"
11
+ #include "ruby/thread.h"
12
+ #include "walet.h"
13
+
14
+ #define N(x) (sizeof((x))/sizeof(*(x)))
15
+ #define RUNTIME_ERROR(...) rb_raise(rb_eRuntimeError, __VA_ARGS__)
16
+ #define ARGUMENT_ERROR(...) rb_raise(rb_eArgError, __VA_ARGS__)
17
+ #define RB_FFT(p) ((rb_fft_t*)(p))
18
+ #define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
19
+
20
+ typedef struct {
21
+ walet_t* wl;
22
+ } rb_wavelet_t;
23
+
24
+ static VALUE wavspa_module;
25
+ static VALUE wavelet_klass;
26
+
27
+ static const char* wavelet_opts_keys[] = {
28
+ "sigma", // {float}
29
+ "frequency", // {float}
30
+ "range", // {Range}
31
+ "scale_mode", // {str}
32
+ "output_width", // {int}
33
+ };
34
+
35
+ static ID wavelet_opts_ids[N(wavelet_opts_keys)];
36
+
37
+ VALUE symb_linear_scale;
38
+ VALUE symb_log_scale;
39
+
40
+ static void
41
+ rb_wavelet_free(void* _ptr)
42
+ {
43
+ rb_wavelet_t* ptr;
44
+
45
+ ptr = (rb_wavelet_t*)_ptr;
46
+
47
+ if (ptr->wl != NULL) walet_destroy(ptr->wl);
48
+
49
+ free(ptr);
50
+ }
51
+
52
+ static VALUE
53
+ rb_wavelet_alloc(VALUE self)
54
+ {
55
+ rb_wavelet_t* ptr;
56
+
57
+ ptr = ALLOC(rb_wavelet_t);
58
+ memset(ptr, 0, sizeof(*ptr));
59
+
60
+ return Data_Wrap_Struct(wavelet_klass, 0, rb_wavelet_free, ptr);
61
+ }
62
+
63
+ static void
64
+ eval_wavelet_opt_sigma(rb_wavelet_t* ptr, VALUE opt)
65
+ {
66
+ int err;
67
+
68
+ if (opt != Qundef) {
69
+ err = walet_set_sigma(ptr->wl, NUM2DBL(opt));
70
+ if (err) {
71
+ RUNTIME_ERROR("walet_set_sigma() failed. [err=%d]", err);
72
+ }
73
+ }
74
+ }
75
+
76
+ static void
77
+ eval_wavelet_opt_frequency(rb_wavelet_t* ptr, VALUE opt)
78
+ {
79
+ int err;
80
+
81
+ if (opt != Qundef) {
82
+ err = walet_set_frequency(ptr->wl, NUM2DBL(opt));
83
+ if (err) {
84
+ RUNTIME_ERROR("walet_set_frequency() failed. [err=%d]", err);
85
+ }
86
+ }
87
+ }
88
+
89
+ static void
90
+ eval_wavelet_opt_range(rb_wavelet_t* ptr, VALUE opt)
91
+ {
92
+ VALUE begin;
93
+ VALUE end;
94
+ int err;
95
+
96
+ if (opt != Qundef) {
97
+ begin = rb_funcall(opt, rb_intern("begin"), 0);
98
+ end = rb_funcall(opt, rb_intern("end"), 0);
99
+ err = walet_set_range(ptr->wl, NUM2DBL(begin), NUM2DBL(end));
100
+ if (err) {
101
+ RUNTIME_ERROR("walet_set_range() failed. [err=%d]", err);
102
+ }
103
+ }
104
+ }
105
+
106
+ static void
107
+ eval_wavelet_opt_scale_mode(rb_wavelet_t* ptr, VALUE opt)
108
+ {
109
+ int err;
110
+ int mode;
111
+
112
+ if (opt != Qundef) {
113
+ if (EQ_STR(opt, "LINEARSCALE") || EQ_STR(opt, "LINEAR")) {
114
+ mode = WALET_LINEARSCALE_MODE;
115
+
116
+ } else if (EQ_STR(opt, "LOGSCALE") || EQ_STR(opt, "LOG")) {
117
+ mode = WALET_LOGSCALE_MODE;
118
+
119
+ } else {
120
+ ARGUMENT_ERROR("unsupported value.");
121
+ }
122
+
123
+ err = walet_set_scale_mode(ptr->wl, mode);
124
+ if (err) {
125
+ RUNTIME_ERROR("walet_set_scale_mode() failed. [err=%d]", err);
126
+ }
127
+ }
128
+ }
129
+
130
+ static void
131
+ eval_wavelet_opt_output_width(rb_wavelet_t* ptr, VALUE opt)
132
+ {
133
+ int err;
134
+
135
+ if (opt != Qundef) {
136
+ err = walet_set_output_width(ptr->wl, FIX2INT(opt));
137
+ if (err) {
138
+ RUNTIME_ERROR("walet_set_output_width() failed. [err=%d]", err);
139
+ }
140
+ }
141
+ }
142
+
143
+ static void
144
+ set_wavelet_context(rb_wavelet_t* ptr, VALUE opt)
145
+ {
146
+ VALUE opts[N(wavelet_opts_ids)];
147
+
148
+ /*
149
+ * parse options
150
+ */
151
+ rb_get_kwargs(opt, wavelet_opts_ids, 0, N(wavelet_opts_ids), opts);
152
+
153
+ /*
154
+ * set context
155
+ */
156
+ eval_wavelet_opt_sigma(ptr, opts[0]);
157
+ eval_wavelet_opt_frequency(ptr, opts[1]);
158
+ eval_wavelet_opt_range(ptr, opts[2]);
159
+ eval_wavelet_opt_scale_mode(ptr, opts[3]);
160
+ eval_wavelet_opt_output_width(ptr, opts[4]);
161
+ }
162
+
163
+ static VALUE
164
+ rb_wavelet_initialize(int argc, VALUE argv[], VALUE self)
165
+ {
166
+ rb_wavelet_t* ptr;
167
+ int err;
168
+ VALUE opt;
169
+
170
+ /*
171
+ * strip object
172
+ */
173
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
174
+
175
+ /*
176
+ * parse argument
177
+ */
178
+ rb_scan_args(argc, argv, "01", &opt);
179
+
180
+ if (opt != Qnil) {
181
+ Check_Type(opt, T_HASH);
182
+ }
183
+
184
+ /*
185
+ * create wavelet context
186
+ */
187
+ err = walet_new(&ptr->wl);
188
+ if (err) {
189
+ RUNTIME_ERROR("walet_new() failes [err=%d]\n", err);
190
+ }
191
+
192
+ /*
193
+ * set context
194
+ */
195
+ if (opt != Qnil) {
196
+ set_wavelet_context(ptr, opt);
197
+ }
198
+
199
+ return self;
200
+ }
201
+
202
+ static VALUE
203
+ rb_wavelet_get_sigma(VALUE self)
204
+ {
205
+ VALUE ret;
206
+ rb_wavelet_t* ptr;
207
+
208
+ /*
209
+ * strip object
210
+ */
211
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
212
+
213
+ /*
214
+ * create return paramter
215
+ */
216
+ ret = DBL2NUM(ptr->wl->sigma);
217
+
218
+ return ret;
219
+ }
220
+
221
+ static VALUE
222
+ rb_wavelet_set_sigma(VALUE self, VALUE sigma)
223
+ {
224
+ rb_wavelet_t* ptr;
225
+
226
+ /*
227
+ * strip object
228
+ */
229
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
230
+
231
+ /*
232
+ * call setter function
233
+ */
234
+ eval_wavelet_opt_sigma(ptr, sigma);
235
+
236
+ return sigma;
237
+ }
238
+
239
+ static VALUE
240
+ rb_wavelet_get_frequency(VALUE self)
241
+ {
242
+ VALUE ret;
243
+ rb_wavelet_t* ptr;
244
+
245
+ /*
246
+ * strip object
247
+ */
248
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
249
+
250
+ /*
251
+ * create return paramter
252
+ */
253
+ ret = DBL2NUM(ptr->wl->fq_s);
254
+
255
+ return ret;
256
+ }
257
+
258
+ static VALUE
259
+ rb_wavelet_set_frequency(VALUE self, VALUE fq)
260
+ {
261
+ rb_wavelet_t* ptr;
262
+
263
+ /*
264
+ * strip object
265
+ */
266
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
267
+
268
+ /*
269
+ * call setter function
270
+ */
271
+ eval_wavelet_opt_frequency(ptr, fq);
272
+
273
+ return fq;
274
+ }
275
+
276
+ static VALUE
277
+ rb_wavelet_get_range(VALUE self)
278
+ {
279
+ VALUE ret;
280
+ rb_wavelet_t* ptr;
281
+
282
+ VALUE begin;
283
+ VALUE end;
284
+
285
+ /*
286
+ * strip object
287
+ */
288
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
289
+
290
+ /*
291
+ * create return paramter
292
+ */
293
+ begin = rb_float_new(ptr->wl->fq_l);
294
+ end = rb_float_new(ptr->wl->fq_h);
295
+ ret = rb_range_new(begin, end, 0);
296
+
297
+ return ret;
298
+ }
299
+
300
+ static VALUE
301
+ rb_wavelet_set_range(VALUE self, VALUE range)
302
+ {
303
+ rb_wavelet_t* ptr;
304
+
305
+ /*
306
+ * strip object
307
+ */
308
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
309
+
310
+ /*
311
+ * call setter function
312
+ */
313
+ eval_wavelet_opt_range(ptr, range);
314
+
315
+ return range;
316
+ }
317
+
318
+ static VALUE
319
+ rb_wavelet_get_scale_mode(VALUE self)
320
+ {
321
+ VALUE ret;
322
+ rb_wavelet_t* ptr;
323
+
324
+ /*
325
+ * strip object
326
+ */
327
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
328
+
329
+ /*
330
+ * create return parameter
331
+ */
332
+ switch (ptr->wl->mode) {
333
+ case 1:
334
+ ret = symb_linear_scale;
335
+ break;
336
+
337
+ case 2:
338
+ ret = symb_log_scale;
339
+ break;
340
+
341
+ default:
342
+ RUNTIME_ERROR("Really?");
343
+ }
344
+
345
+ return ret;
346
+ }
347
+
348
+ static VALUE
349
+ rb_wavelet_set_scale_mode(VALUE self, VALUE mode)
350
+ {
351
+ rb_wavelet_t* ptr;
352
+
353
+ /*
354
+ * strip object
355
+ */
356
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
357
+
358
+ /*
359
+ * call setter function
360
+ */
361
+ eval_wavelet_opt_scale_mode(ptr, mode);
362
+
363
+ return mode;
364
+ }
365
+
366
+ static VALUE
367
+ rb_wavelet_get_output_width(VALUE self)
368
+ {
369
+ VALUE ret;
370
+ rb_wavelet_t* ptr;
371
+
372
+ /*
373
+ * strip object
374
+ */
375
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
376
+
377
+ /*
378
+ * create return paramter
379
+ */
380
+ ret = INT2FIX(ptr->wl->width);
381
+
382
+ return ret;
383
+ }
384
+
385
+
386
+ static VALUE
387
+ rb_wavelet_set_output_width(VALUE self, VALUE width)
388
+ {
389
+ rb_wavelet_t* ptr;
390
+
391
+ /*
392
+ * strip object
393
+ */
394
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
395
+
396
+ /*
397
+ * call setter function
398
+ */
399
+ eval_wavelet_opt_output_width(ptr, width);
400
+
401
+ return width;
402
+ }
403
+
404
+ static int
405
+ copy_rb_string(char* dst, VALUE _src, int lim)
406
+ {
407
+ int ret;
408
+ char* src;
409
+ int n;
410
+
411
+ /*
412
+ * initialize
413
+ */
414
+ ret = 0;
415
+ src = RSTRING_PTR(_src);
416
+ n = RSTRING_LEN(_src);
417
+
418
+ do {
419
+ /*
420
+ * check length
421
+ */
422
+ if (n >= lim) {
423
+ ret = !0;
424
+ break;
425
+ }
426
+
427
+ /*
428
+ * copy data
429
+ */
430
+ memset(dst, 0, lim);
431
+ memcpy(dst, src, n);
432
+ } while (0);
433
+
434
+ return ret;
435
+
436
+ }
437
+
438
+ static VALUE
439
+ rb_wavelet_put_in(VALUE self, VALUE _fmt, VALUE _smpl)
440
+ {
441
+ rb_wavelet_t* ptr;
442
+ int err;
443
+ void* smpl;
444
+ char fmt[8];
445
+ int n;
446
+
447
+ /*
448
+ * check argument
449
+ */
450
+ Check_Type(_fmt, T_STRING);
451
+ Check_Type(_smpl, T_STRING);
452
+
453
+ /*
454
+ * stript object
455
+ */
456
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
457
+
458
+ /*
459
+ * unpack argument
460
+ */
461
+ smpl = RSTRING_PTR(_smpl);
462
+ n = RSTRING_LEN(_smpl);
463
+
464
+ err = copy_rb_string(fmt, _fmt, N(fmt));
465
+ if (err) {
466
+ ARGUMENT_ERROR("Illeagal format string.\n");
467
+ }
468
+
469
+ /*
470
+ * eval format
471
+ */
472
+ if (strcasecmp("u8", fmt) == 0) {
473
+ /* Nothing */
474
+
475
+ } else if(strcasecmp("u16be", fmt) == 0 ||
476
+ strcasecmp("u16le", fmt) == 0 ||
477
+ strcasecmp("s16be", fmt) == 0 ||
478
+ strcasecmp("s16le", fmt) == 0 ) {
479
+ n /= 2;
480
+
481
+ } else if(strcasecmp("u24be", fmt) == 0 ||
482
+ strcasecmp("u24le", fmt) == 0) {
483
+ n /= 3;
484
+
485
+ } else {
486
+ ARGUMENT_ERROR("Illeagal format string.\n");
487
+ }
488
+
489
+ /*
490
+ * call base library
491
+ */
492
+ err = walet_put_in(ptr->wl, fmt, smpl, n);
493
+ if (err) {
494
+ RUNTIME_ERROR("walet_put_in() failed [err=%d]\n", err);
495
+ }
496
+
497
+ return self;
498
+ }
499
+
500
+ typedef struct {
501
+ int err;
502
+ walet_t* ptr;
503
+ int pos;
504
+ } transform_arg_t;
505
+
506
+ static void*
507
+ _transform(void* data)
508
+ {
509
+ transform_arg_t* arg;
510
+
511
+ arg = (transform_arg_t*)data;
512
+
513
+ arg->err = walet_transform(arg->ptr, arg->pos);
514
+
515
+ return NULL;
516
+ }
517
+
518
+ static int
519
+ transform(walet_t* ptr, int pos)
520
+ {
521
+ transform_arg_t arg;
522
+
523
+ arg.ptr = ptr;
524
+ arg.pos = pos;
525
+
526
+ rb_thread_call_without_gvl(_transform, &arg, RUBY_UBF_PROCESS, NULL);
527
+
528
+ return arg.err;
529
+ }
530
+
531
+ static VALUE
532
+ rb_wavelet_transform(VALUE self, VALUE pos)
533
+ {
534
+ rb_wavelet_t* ptr;
535
+ int err;
536
+
537
+ /*
538
+ * stript object
539
+ */
540
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
541
+
542
+ /*
543
+ * call base library
544
+ */
545
+ err = transform(ptr->wl, NUM2INT(pos));
546
+ if (err) {
547
+ RUNTIME_ERROR("walet_transform() failed [err=%d]\n", err);
548
+ }
549
+
550
+ return self;
551
+ }
552
+
553
+ typedef struct {
554
+ int err;
555
+ walet_t* ptr;
556
+ double* dst;
557
+ } calc_power_arg_t;
558
+
559
+ static void*
560
+ _calc_power(void* data)
561
+ {
562
+ calc_power_arg_t* arg;
563
+
564
+ arg = (calc_power_arg_t*)data;
565
+
566
+ arg->err = walet_calc_power(arg->ptr, arg->dst);
567
+
568
+ return NULL;
569
+ }
570
+
571
+ static int
572
+ calc_power(walet_t* ptr, double* dst)
573
+ {
574
+ calc_power_arg_t arg;
575
+
576
+ arg.ptr = ptr;
577
+ arg.dst = dst;
578
+
579
+ rb_thread_call_without_gvl(_calc_power, &arg, RUBY_UBF_PROCESS, NULL);
580
+
581
+ return arg.err;
582
+ }
583
+
584
+ static VALUE
585
+ rb_wavelet_power(VALUE self)
586
+ {
587
+ rb_wavelet_t* ptr;
588
+ VALUE ret;
589
+ int err;
590
+
591
+ /*
592
+ * strip object
593
+ */
594
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
595
+
596
+ /*
597
+ * create return buffer
598
+ */
599
+ ret = rb_str_buf_new(sizeof(double) * ptr->wl->width);
600
+ rb_str_set_len(ret, sizeof(double) * ptr->wl->width);
601
+
602
+ /*
603
+ * call base library
604
+ */
605
+ err = calc_power(ptr->wl, (double*)RSTRING_PTR(ret));
606
+ if (err) {
607
+ RUNTIME_ERROR("walet_calc_power() failed [err=%d]\n", err);
608
+ }
609
+
610
+ return ret;
611
+ }
612
+
613
+ typedef struct {
614
+ int err;
615
+ walet_t* ptr;
616
+ double* dst;
617
+ } calc_amplitude_arg_t;
618
+
619
+ static void*
620
+ _calc_amplitude(void* data)
621
+ {
622
+ calc_amplitude_arg_t* arg;
623
+
624
+ arg = (calc_amplitude_arg_t*)data;
625
+
626
+ arg->err = walet_calc_amplitude(arg->ptr, arg->dst);
627
+
628
+ return NULL;
629
+ }
630
+
631
+ static int
632
+ calc_amplitude(walet_t* ptr, double* dst)
633
+ {
634
+ calc_amplitude_arg_t arg;
635
+
636
+ arg.ptr = ptr;
637
+ arg.dst = dst;
638
+
639
+ rb_thread_call_without_gvl(_calc_amplitude, &arg, RUBY_UBF_PROCESS, NULL);
640
+
641
+ return arg.err;
642
+ }
643
+
644
+ static VALUE
645
+ rb_wavelet_amplitude(VALUE self)
646
+ {
647
+ rb_wavelet_t* ptr;
648
+ VALUE ret;
649
+ int err;
650
+
651
+ /*
652
+ * strip object
653
+ */
654
+ Data_Get_Struct(self, rb_wavelet_t, ptr);
655
+
656
+ /*
657
+ * create return buffer
658
+ */
659
+ ret = rb_str_buf_new(sizeof(double) * ptr->wl->width);
660
+ rb_str_set_len(ret, sizeof(double) * ptr->wl->width);
661
+
662
+ /*
663
+ * call base library
664
+ */
665
+ err = calc_amplitude(ptr->wl, (double*)RSTRING_PTR(ret));
666
+ if (err) {
667
+ RUNTIME_ERROR("walet_calc_amplitude() failed [err=%d]\n", err);
668
+ }
669
+
670
+ return ret;
671
+ }
672
+
673
+ void
674
+ Init_wavelet()
675
+ {
676
+ int i;
677
+
678
+ wavspa_module = rb_define_module("WavSpectrumAnalyzer");
679
+ wavelet_klass = rb_define_class_under(wavspa_module, "Wavelet", rb_cObject);
680
+
681
+ rb_define_alloc_func(wavelet_klass, rb_wavelet_alloc);
682
+
683
+ rb_define_method(wavelet_klass, "initialize", rb_wavelet_initialize, -1);
684
+ rb_define_method(wavelet_klass, "sigma", rb_wavelet_get_sigma, 0);
685
+ rb_define_method(wavelet_klass, "sigma=", rb_wavelet_set_sigma, 1);
686
+ rb_define_method(wavelet_klass, "frequency", rb_wavelet_get_frequency, 0);
687
+ rb_define_method(wavelet_klass, "frequency=", rb_wavelet_set_frequency, 1);
688
+ rb_define_method(wavelet_klass, "range", rb_wavelet_get_range, 0);
689
+ rb_define_method(wavelet_klass, "range=", rb_wavelet_set_range, 1);
690
+ rb_define_method(wavelet_klass, "scale_mode", rb_wavelet_get_scale_mode, 0);
691
+ rb_define_method(wavelet_klass, "scale_mode=", rb_wavelet_set_scale_mode, 1);
692
+ rb_define_method(wavelet_klass, "width", rb_wavelet_get_output_width, 0);
693
+ rb_define_method(wavelet_klass, "width=", rb_wavelet_set_output_width, 1);
694
+
695
+ rb_define_method(wavelet_klass, "put_in", rb_wavelet_put_in, 2);
696
+ rb_define_method(wavelet_klass, "transform", rb_wavelet_transform, 1);
697
+ rb_define_method(wavelet_klass, "power", rb_wavelet_power, 0);
698
+ rb_define_method(wavelet_klass, "amplitude", rb_wavelet_amplitude, 0);
699
+
700
+ for (i = 0; i < (int)N(wavelet_opts_keys); i++) {
701
+ wavelet_opts_ids[i] = rb_intern(wavelet_opts_keys[i]);
702
+ }
703
+
704
+ symb_linear_scale = ID2SYM(rb_intern_const("LINEAR_SCALE"));
705
+ symb_log_scale = ID2SYM(rb_intern_const("LOG_SCALE"));
706
+ }