wavspa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }