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,803 @@
1
+ /*
2
+ * wavelet transform library
3
+ *
4
+ * Copyright (C) 2016 Hiroshi Kuwagata <kgt9221@gmail.com>
5
+ */
6
+
7
+ /*
8
+ * $Id: walet.c 149 2017-07-28 02:23:16Z kgt $
9
+ */
10
+
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+ #include <stdint.h>
14
+ #include <string.h>
15
+ #include <math.h>
16
+
17
+ #include "walet.h"
18
+
19
+ #define N(x) (sizeof(x)/sizeof(*x))
20
+ #define IS_POW2(n) (!((n) & ((n) - 1)))
21
+ #define ALLOC(t) ((t*)malloc(sizeof(t)))
22
+ #define NALLOC(t,n) ((t*)malloc(sizeof(t) * (n)))
23
+ #define MAX(m,n) (((m) > (n))? (m): (n))
24
+
25
+ #define ERR __LINE__
26
+
27
+ #define M_PI2 (M_PI * 2.0)
28
+
29
+ #define DEFAULT_BASE_FREQ 44100.0
30
+ #define DEFAULT_LOW_FREQ 100.0
31
+ #define DEFAULT_HIGH_FREQ 2000.0
32
+ #define DEFAULT_SIGMA 3.0
33
+ #define DEFAULT_OUTPUT_WIDTH 360
34
+ #define DEFAULT_SCALE_MODE WALET_LOGSCALE_MODE
35
+
36
+ #define GABOR_THRESHOLD 0.01
37
+
38
+ #define F_DIRTY 0x00000001
39
+
40
+ #define CALC_WK0(sig) ((sig) * sqrt(-2.0 * log(GABOR_THRESHOLD)))
41
+ #define CALC_WK1(sig) (1.0 / sqrt(M_PI2 * (sig) * (sig)))
42
+ #define CALC_WK2(sig) (2.0 * (sig) * (sig))
43
+
44
+ static double
45
+ calc_step(int mode, double low, double high, int width)
46
+ {
47
+ double ret;
48
+
49
+ switch (mode) {
50
+ case WALET_LINEARSCALE_MODE:
51
+ ret = (high - low) / width;
52
+ break;
53
+
54
+ case WALET_LOGSCALE_MODE:
55
+ ret = pow(high / low, 1.0 / (double)width);
56
+ break;
57
+
58
+ default:
59
+ ret = NAN;
60
+ break;
61
+ }
62
+
63
+ return ret;
64
+ }
65
+
66
+ static void
67
+ reset_window_size_table(walet_t* ptr)
68
+ {
69
+ int i;
70
+ double fq;
71
+
72
+ fq = ptr->fq_l;
73
+ for (i = 0; i < ptr->width; i++) {
74
+ ptr->ws[i] = (int)(((1.0 / fq) * ptr->wk0) * ptr->fq_s);
75
+
76
+ if (ptr->mode == WALET_LINEARSCALE_MODE) {
77
+ fq += ptr->step;
78
+ } else {
79
+ fq *= ptr->step;
80
+ }
81
+ }
82
+ }
83
+
84
+ int
85
+ walet_new(walet_t** _obj)
86
+ {
87
+ int ret;
88
+ walet_t* obj;
89
+ int* ws;
90
+ double* wt;
91
+
92
+ /*
93
+ * initialize
94
+ */
95
+ ret = 0;
96
+ obj = NULL;
97
+ wt = NULL;
98
+ ws = NULL;
99
+
100
+ do {
101
+ /*
102
+ * chack argument
103
+ */
104
+ if (_obj == NULL) {
105
+ ret = ERR;
106
+ break;
107
+ }
108
+
109
+ /*
110
+ * alloc new object
111
+ */
112
+ obj = ALLOC(walet_t);
113
+ if (obj == NULL) {
114
+ ret = ERR;
115
+ break;
116
+ }
117
+
118
+ ws = NALLOC(int, DEFAULT_OUTPUT_WIDTH);
119
+ if (ws == NULL) {
120
+ ret = ERR;
121
+ break;
122
+ }
123
+
124
+ wt = NALLOC(double, DEFAULT_OUTPUT_WIDTH * 2);
125
+ if (wt == NULL) {
126
+ ret = ERR;
127
+ break;
128
+ }
129
+
130
+ /*
131
+ * set initial parameter
132
+ */
133
+ obj->flags = F_DIRTY;
134
+ obj->fq_s = DEFAULT_BASE_FREQ;
135
+ obj->fq_l = DEFAULT_LOW_FREQ;
136
+ obj->fq_h = DEFAULT_HIGH_FREQ;
137
+ obj->sigma = DEFAULT_SIGMA;
138
+ obj->wk0 = CALC_WK0(DEFAULT_SIGMA);
139
+ obj->wk1 = CALC_WK1(DEFAULT_SIGMA);
140
+ obj->wk2 = CALC_WK2(DEFAULT_SIGMA);
141
+ obj->width = DEFAULT_OUTPUT_WIDTH;
142
+ obj->mode = DEFAULT_SCALE_MODE;
143
+ obj->step = calc_step(obj->mode, obj->fq_l, obj->fq_h, obj->width);
144
+ obj->smpl = NULL;
145
+ obj->ws = ws;
146
+ obj->wt = wt;
147
+
148
+ /*
149
+ * put return parameter
150
+ */
151
+ *_obj = obj;
152
+ } while (0);
153
+
154
+ /*
155
+ * post process
156
+ */
157
+ if (ret) {
158
+ if (obj != NULL) free(obj);
159
+ if (wt != NULL) free(wt);
160
+ if (ws != NULL) free(ws);
161
+ }
162
+
163
+ return ret;
164
+ }
165
+
166
+ int
167
+ walet_set_sigma(walet_t* ptr, double sigma)
168
+ {
169
+ int ret;
170
+
171
+ /*
172
+ * initialize
173
+ */
174
+ ret = 0;
175
+
176
+ /*
177
+ * argument check
178
+ */
179
+ if (ptr == NULL) ret = ERR;
180
+
181
+ /*
182
+ * set parameter
183
+ */
184
+ if (!ret) {
185
+ ptr->sigma = sigma;
186
+ ptr->wk0 = CALC_WK0(sigma);
187
+ ptr->wk1 = CALC_WK1(sigma);
188
+ ptr->wk2 = CALC_WK2(sigma);
189
+
190
+ ptr->flags |= F_DIRTY;
191
+ }
192
+
193
+ return ret;
194
+ }
195
+
196
+ int
197
+ walet_set_frequency(walet_t* ptr, double freq)
198
+ {
199
+ int ret;
200
+
201
+ /*
202
+ * initialize
203
+ */
204
+ ret = 0;
205
+
206
+ do {
207
+ /*
208
+ * argument check
209
+ */
210
+ if (ptr == NULL) {
211
+ ret = ERR;
212
+ break;
213
+ }
214
+
215
+ if (freq <= 100) {
216
+ ret = ERR;
217
+ break;
218
+ }
219
+
220
+ /*
221
+ * set parameter
222
+ */
223
+ ptr->fq_s = freq;
224
+ ptr->fq_h = freq / 2.0;
225
+ ptr->fq_l = freq / 5.0;
226
+
227
+ ptr->flags |= F_DIRTY;
228
+ } while (0);
229
+
230
+ return ret;
231
+ }
232
+
233
+ int
234
+ walet_set_range(walet_t* ptr, double low, double high)
235
+ {
236
+ int ret;
237
+ double step;
238
+
239
+ /*
240
+ * initialize
241
+ */
242
+ ret = 0;
243
+
244
+ do {
245
+ /*
246
+ * argument check
247
+ */
248
+ if (ptr == NULL) {
249
+ ret = ERR;
250
+ break;
251
+ }
252
+
253
+ if (high <= 0 || high > (ptr->fq_s / 2.0)) {
254
+ ret = ERR;
255
+ break;
256
+ }
257
+
258
+ if (low >= high) {
259
+ ret = ERR;
260
+ break;
261
+ }
262
+
263
+ /*
264
+ * calc step
265
+ */
266
+ step = calc_step(ptr->mode, low, high, ptr->width);
267
+ if (isnan(step)) {
268
+ ret = ERR;
269
+ break;
270
+ }
271
+
272
+ /*
273
+ * set parameter
274
+ */
275
+ ptr->fq_l = low;
276
+ ptr->fq_h = high;
277
+ ptr->step = step;
278
+
279
+ ptr->flags |= F_DIRTY;
280
+ } while(0);
281
+
282
+ return ret;
283
+ }
284
+
285
+ int
286
+ walet_set_scale_mode(walet_t* ptr, int mode)
287
+ {
288
+ int ret;
289
+ double step;
290
+
291
+ /*
292
+ * initialize
293
+ */
294
+ ret = 0;
295
+
296
+ do {
297
+ /*
298
+ * argument check
299
+ */
300
+ if (ptr == NULL) {
301
+ ret = ERR;
302
+ break;
303
+ }
304
+
305
+ if (mode != WALET_LINEARSCALE_MODE &&
306
+ mode != WALET_LOGSCALE_MODE) {
307
+ ret = ERR;
308
+ break;
309
+ }
310
+
311
+ /*
312
+ * calc step
313
+ */
314
+ step = calc_step(mode, ptr->fq_l, ptr->fq_h, ptr->width);
315
+ if (isnan(step)) {
316
+ ret = ERR;
317
+ break;
318
+ }
319
+
320
+ /*
321
+ * set parameter
322
+ */
323
+ ptr->mode = mode;
324
+ ptr->step = step;
325
+
326
+ ptr->flags |= F_DIRTY;
327
+ } while (0);
328
+
329
+ return ret;
330
+ }
331
+
332
+ int
333
+ walet_set_output_width(walet_t* ptr, int width)
334
+ {
335
+ int ret;
336
+ int* ws;
337
+ double* wt;
338
+ double step;
339
+
340
+ /*
341
+ * initialize
342
+ */
343
+ ret = 0;
344
+ ws = NULL;
345
+ wt = NULL;
346
+
347
+ do {
348
+ /*
349
+ * argument check
350
+ */
351
+ if (ptr == NULL) {
352
+ ret = ERR;
353
+ break;
354
+ }
355
+
356
+ if (width < 32) {
357
+ ret = ERR;
358
+ break;
359
+ }
360
+
361
+ /*
362
+ * alloc window size area
363
+ */
364
+ ws = NALLOC(int, width);
365
+ if (ws == NULL) {
366
+ ret = ERR;
367
+ }
368
+
369
+ /*
370
+ * alloc result area
371
+ */
372
+ wt = NALLOC(double, width * 2);
373
+ if (wt == NULL) {
374
+ ret = ERR;
375
+ }
376
+
377
+ /*
378
+ * calc step
379
+ */
380
+ step = calc_step(ptr->mode, ptr->fq_l, ptr->fq_h, width);
381
+ if (isnan(step)) {
382
+ ret = ERR;
383
+ break;
384
+ }
385
+
386
+ /*
387
+ * set parameter
388
+ */
389
+ if (ptr->wt != NULL) free(ptr->wt);
390
+ if (ptr->ws != NULL) free(ptr->ws);
391
+
392
+ ptr->width = width;
393
+ ptr->ws = ws;
394
+ ptr->wt = wt;
395
+ ptr->step = step;
396
+
397
+ ptr->flags |= F_DIRTY;
398
+ } while (0);
399
+
400
+ /*
401
+ * post process
402
+ */
403
+ if (ret) {
404
+ if (wt != NULL) free(wt);
405
+ if (ws != NULL) free(ws);
406
+ }
407
+
408
+ return ret;
409
+ }
410
+
411
+ static void
412
+ import_u8(double* dst, uint8_t* src, int n)
413
+ {
414
+ int i;
415
+
416
+ for (i = 0; i < n; i++) {
417
+ dst[i] = ((double)src[i] - 128.0) / 128.0;
418
+ }
419
+ }
420
+
421
+ static void
422
+ import_u16le(double* dst, uint8_t* src, int n)
423
+ {
424
+ int i;
425
+ uint16_t smpl;
426
+
427
+ for (i = 0; i < n; i++, src += 2) {
428
+ smpl = ((((uint16_t)src[0] << 0) & 0x00ff)|
429
+ (((uint16_t)src[1] << 8) & 0xff00));
430
+
431
+ dst[i] = ((double)smpl - 32768.0) / 32768.0;
432
+ }
433
+ }
434
+
435
+ static void
436
+ import_u16be(double* dst, uint8_t* src, int n)
437
+ {
438
+ int i;
439
+ uint16_t smpl;
440
+
441
+ for (i = 0; i < n; i++, src += 2) {
442
+ smpl = ((((uint16_t)src[1] << 0) & 0x00ff)|
443
+ (((uint16_t)src[0] << 8) & 0xff00));
444
+
445
+ dst[i] = ((double)smpl - 32768.0) / 32768.0;
446
+ }
447
+ }
448
+
449
+ static void
450
+ import_s16le(double* dst, uint8_t* src, int n)
451
+ {
452
+ int i;
453
+ int16_t smpl;
454
+
455
+ for (i = 0; i < n; i++, src += 2) {
456
+ smpl = ((((int16_t)src[0] << 0) & 0x00ff)|
457
+ (((int16_t)src[1] << 8) & 0xff00));
458
+
459
+ dst[i] = (double)smpl / 32768.0;
460
+ }
461
+ }
462
+
463
+ static void
464
+ import_s16be(double* dst, uint8_t* src, int n)
465
+ {
466
+ int i;
467
+ int16_t smpl;
468
+
469
+ for (i = 0; i < n; i++, src += 2) {
470
+ smpl = ((((int16_t)src[1] << 0) & 0x00ff)|
471
+ (((int16_t)src[0] << 8) & 0xff00));
472
+
473
+ dst[i] = (double)smpl / 32768.0;
474
+ }
475
+ }
476
+
477
+ static void
478
+ import_s24le(double* dst, uint8_t* src, int n)
479
+ {
480
+ int i;
481
+ int32_t smpl;
482
+
483
+ for (i = 0; i < n; i++, src += 3) {
484
+ smpl = ((((int32_t)src[0] << 8) & 0x0000ff00)|
485
+ (((int32_t)src[1] << 16) & 0x00ff0000)|
486
+ (((int32_t)src[2] << 24) & 0xff000000));
487
+
488
+ dst[i] = (double)smpl / 2147483648.0;
489
+ }
490
+ }
491
+
492
+ static void
493
+ import_s24be(double* dst, uint8_t* src, int n)
494
+ {
495
+ int i;
496
+ int32_t smpl;
497
+
498
+ for (i = 0; i < n; i++, src += 3) {
499
+ smpl = ((((int32_t)src[2] << 8) & 0x0000ff00)|
500
+ (((int32_t)src[1] << 16) & 0x00ff0000)|
501
+ (((int32_t)src[0] << 24) & 0xff000000));
502
+
503
+ dst[i] = (double)smpl / 2147483648.0;
504
+ }
505
+ }
506
+
507
+ static void
508
+ import_double(double* dst, double* src, int n)
509
+ {
510
+ memcpy(dst, src, sizeof(double) * n);
511
+ }
512
+
513
+ int
514
+ walet_put_in(walet_t* ptr, char* fmt, void* data, size_t n)
515
+ {
516
+ int ret;
517
+ double* smpl;
518
+
519
+ /*
520
+ * initialize
521
+ */
522
+ ret = 0;
523
+ smpl = NULL;
524
+
525
+
526
+ do {
527
+ /*
528
+ * argument check
529
+ */
530
+ if (ptr == NULL) {
531
+ ret = ERR;
532
+ break;
533
+ }
534
+
535
+ if (ptr == NULL) {
536
+ ret = ERR;
537
+ break;
538
+ }
539
+
540
+ if (data == NULL) {
541
+ ret = ERR;
542
+ break;
543
+ }
544
+
545
+ /*
546
+ * alloc sample buffer
547
+ */
548
+ smpl = NALLOC(double, n);
549
+ if (smpl == NULL) {
550
+ ret = ERR;
551
+ break;
552
+ }
553
+
554
+ /*
555
+ * import samples
556
+ */
557
+ if (strcasecmp("u8", fmt) == 0) {
558
+ import_u8(smpl, data, n);
559
+
560
+ } else if (strcasecmp("u16be", fmt) == 0) {
561
+ import_u16be(smpl, data, n);
562
+
563
+ } else if (strcasecmp("u16le", fmt) == 0) {
564
+ import_u16le(smpl, data, n);
565
+
566
+ } else if (strcasecmp("s16be", fmt) == 0) {
567
+ import_s16be(smpl, data, n);
568
+
569
+ } else if (strcasecmp("s16le", fmt) == 0) {
570
+ import_s16le(smpl, data, n);
571
+
572
+ } else if (strcasecmp("s24be", fmt) == 0) {
573
+ import_s24be(smpl, data, n);
574
+
575
+ } else if (strcasecmp("s24le", fmt) == 0) {
576
+ import_s24le(smpl, data, n);
577
+
578
+ } else if (strcasecmp("dbl", fmt) == 0) {
579
+ import_double(smpl, data, n);
580
+
581
+ } else {
582
+ ret = ERR;
583
+ break;
584
+ }
585
+
586
+ /*
587
+ * put parameter
588
+ */
589
+ ptr->smpl = smpl;
590
+ ptr->n = n;
591
+ } while (0);
592
+
593
+ /*
594
+ * post process
595
+ */
596
+ if (ret) {
597
+ if (smpl != NULL) free(smpl);
598
+ }
599
+
600
+ return ret;
601
+ }
602
+
603
+ int
604
+ walet_transform(walet_t* ptr, int pos)
605
+ {
606
+ int ret;
607
+ double fq;
608
+ int dx;
609
+
610
+ int i;
611
+ int j;
612
+ int st;
613
+ int ed;
614
+
615
+ double t;
616
+ double gss; // as gauss
617
+ double omt; // as omega-t
618
+ double re;
619
+ double im;
620
+ double* wt;
621
+
622
+ /*
623
+ * initialize
624
+ */
625
+ ret = 0;
626
+
627
+ do {
628
+ /*
629
+ * argument check
630
+ */
631
+ if (ptr == NULL) {
632
+ ret = ERR;
633
+ break;
634
+ }
635
+
636
+ if (pos < 0 || pos >= ptr->n) {
637
+ ret = ERR;
638
+ break;
639
+ }
640
+
641
+ /*
642
+ * pre process
643
+ */
644
+ if (ptr->flags & F_DIRTY) {
645
+ reset_window_size_table(ptr);
646
+
647
+ ptr->flags &= ~F_DIRTY;
648
+ }
649
+
650
+ /*
651
+ * integla for window
652
+ */
653
+ fq = ptr->fq_l;
654
+ for (i = 0, wt = ptr->wt; i < ptr->width; i++, wt += 2) {
655
+ dx = ptr->ws[i];
656
+
657
+ st = (dx < pos)? -dx : -pos;
658
+ ed = (dx < (ptr->n - pos))? dx: (ptr->n - (pos + 1));
659
+
660
+ re = 0.0;
661
+ im = 0.0;
662
+
663
+ #ifdef _OPENMP
664
+ #pragma omp parallel for private(t,gss,omt) reduction(+:re,im)
665
+ #endif /* defined(_OPENMP) */
666
+ for (j = st; j <= ed; j++) {
667
+ t = ((double)j / ptr->fq_s) * fq;
668
+ gss = ptr->wk1 * exp(-t * (t / ptr->wk2)) * (ptr->smpl[pos + j]);
669
+ omt = M_PI2 * t;
670
+
671
+ re += cos(omt) * gss;
672
+ im += sin(omt) * gss;
673
+ }
674
+
675
+
676
+ wt[0] = re;
677
+ wt[1] = im;
678
+
679
+ if (ptr->mode == WALET_LINEARSCALE_MODE) {
680
+ fq += ptr->step;
681
+ } else {
682
+ fq *= ptr->step;
683
+ }
684
+ }
685
+
686
+ } while (0);
687
+
688
+ return ret;
689
+ }
690
+
691
+ int
692
+ walet_calc_power(walet_t* ptr, double* dst)
693
+ {
694
+ int ret;
695
+ int i;
696
+ double* wt;
697
+ double base;
698
+
699
+ /*
700
+ * initialize
701
+ */
702
+ ret = 0;
703
+
704
+ do {
705
+ /*
706
+ * argument check
707
+ */
708
+ if (ptr == NULL) {
709
+ ret = ERR;
710
+ break;
711
+ }
712
+
713
+ if (dst == NULL) {
714
+ ret = ERR;
715
+ break;
716
+ }
717
+
718
+ /*
719
+ * put power
720
+ */
721
+
722
+ #ifdef _OPENMP
723
+ #pragma omp parallel private(base,wt)
724
+ #endif /* defined(_OPENMP) */
725
+ for (i = 0; i < ptr->width; i++) {
726
+ wt = ptr->wt + (i * 2);
727
+ base = ptr->ws[i] * 2;
728
+ dst[i] = 10 * log10(((wt[0] * wt[0]) + (wt[1] * wt[1])) / base);
729
+ }
730
+ } while (0);
731
+
732
+ return ret;
733
+ }
734
+
735
+ int
736
+ walet_calc_amplitude(walet_t* ptr, double* dst)
737
+ {
738
+ int ret;
739
+ int i;
740
+ double* wt;
741
+ double base;
742
+
743
+ /*
744
+ * initialize
745
+ */
746
+ ret = 0;
747
+
748
+ do {
749
+ /*
750
+ * argument check
751
+ */
752
+ if (ptr == NULL) {
753
+ ret = ERR;
754
+ break;
755
+ }
756
+
757
+ if (dst == NULL) {
758
+ ret = ERR;
759
+ break;
760
+ }
761
+
762
+ /*
763
+ * put amplitude
764
+ */
765
+ #ifdef _OPENMP
766
+ #pragma omp parallel private(base,wt)
767
+ #endif /* defined(_OPENMP) */
768
+ for (i = 0; i < ptr->width; i++) {
769
+ wt = ptr->wt + (i * 2);
770
+ base = ptr->ws[i] * 2;
771
+ dst[i] = 20.0 * log10(sqrt(((wt[0] * wt[0]) + (wt[1] * wt[1])) / base));
772
+ }
773
+ } while (0);
774
+
775
+ return ret;
776
+ }
777
+
778
+ int
779
+ walet_destroy(walet_t* ptr)
780
+ {
781
+ int ret;
782
+
783
+ /*
784
+ * initialize
785
+ */
786
+ ret = 0;
787
+
788
+ /*
789
+ * argument check
790
+ */
791
+ if (ptr == NULL) ret = ERR;
792
+
793
+ /*
794
+ * release object
795
+ */
796
+ if (!ret) {
797
+ if (ptr->smpl != NULL) free(ptr->smpl);
798
+ if (ptr->wt != NULL) free(ptr->wt);
799
+ free(ptr);
800
+ }
801
+
802
+ return ret;
803
+ }