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,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
+ }