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,918 @@
1
+ /*
2
+ * Ooura FFT library interface
3
+ *
4
+ * Copyright (C) 2016 Hiroshi Kuwagata <kgt9221@gmail.com>
5
+ */
6
+
7
+ /*
8
+ * $Id$
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 "fft.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 FMT_U8 0x0001
28
+ #define FMT_U16LE 0x0002
29
+ #define FMT_U16BE 0x0012
30
+ #define FMT_S16LE 0x0102
31
+ #define FMT_S16BE 0x0112
32
+ #define FMT_S24LE 0x0203
33
+ #define FMT_S24BE 0x0213
34
+
35
+ typedef struct {
36
+ int pos;
37
+ int n;
38
+ } lc_t;
39
+
40
+ extern void rdft(int, int, double *, int *, double *);
41
+
42
+ int
43
+ fft_new(char* _fmt, int capa, fft_t** _obj)
44
+ {
45
+ int ret;
46
+ fft_t* obj;
47
+
48
+ int fmt;
49
+
50
+ double* data;
51
+ double* wtbl;
52
+ lc_t* line;
53
+
54
+ double* a;
55
+ int* ip;
56
+ double* w;
57
+
58
+ /*
59
+ * initialize
60
+ */
61
+ ret = 0;
62
+
63
+ obj = NULL;
64
+ data = NULL;
65
+ wtbl = NULL;
66
+ a = NULL;
67
+ ip = NULL;
68
+ w = NULL;
69
+
70
+ /*
71
+ * argument check
72
+ */
73
+ if (_fmt == NULL) ret = ERR;
74
+ if (!capa || !IS_POW2(capa)) ret = ERR;
75
+ if (_obj == NULL) ret = ERR;
76
+
77
+ if (strcasecmp("u8", _fmt) == 0) {
78
+ fmt = FMT_U8;
79
+
80
+ } else if (strcasecmp("u16be", _fmt) == 0) {
81
+ fmt = FMT_U16BE;
82
+
83
+ } else if (strcasecmp("u16le", _fmt) == 0) {
84
+ fmt = FMT_U16LE;
85
+
86
+ } else if (strcasecmp("s16be", _fmt) == 0) {
87
+ fmt = FMT_S16BE;
88
+
89
+ } else if (strcasecmp("s16le", _fmt) == 0) {
90
+ fmt = FMT_S16LE;
91
+
92
+ } else if (strcasecmp("s24be", _fmt) == 0) {
93
+ fmt = FMT_S24BE;
94
+
95
+ } else if (strcasecmp("s24le", _fmt) == 0) {
96
+ fmt = FMT_S24LE;
97
+
98
+ } else {
99
+ ret = ERR;
100
+ }
101
+
102
+ /*
103
+ * memory allocation
104
+ */
105
+ if (!ret) {
106
+ obj = ALLOC(fft_t);
107
+ if (obj == NULL) ret = ERR;
108
+ }
109
+
110
+ if (!ret) {
111
+ data = NALLOC(double, capa);
112
+ if (data == NULL) ret = ERR;
113
+ }
114
+
115
+ if (!ret) {
116
+ wtbl = NALLOC(double, capa);
117
+ if (wtbl == NULL) ret = ERR;
118
+ }
119
+
120
+ if (!ret) {
121
+ line = NALLOC(lc_t, capa / 2);
122
+ if (line == NULL) ret = ERR;
123
+ }
124
+
125
+ if (!ret) {
126
+ a = NALLOC(double, capa);
127
+ if (a == NULL) ret = ERR;
128
+ }
129
+
130
+ if (!ret) {
131
+ ip = NALLOC(int, 2 + (int)sqrt(capa / 2));
132
+ if (ip == NULL) ret = ERR;
133
+ }
134
+
135
+ if (!ret) {
136
+ w = NALLOC(double, capa / 2);
137
+ if (w == NULL) ret = ERR;
138
+ }
139
+
140
+ /*
141
+ * set return parameter
142
+ */
143
+ if (!ret) {
144
+ ip[0] = 0;
145
+ rdft(capa, 1, a, ip, w);
146
+
147
+ memset(data, 0, sizeof(double) * capa);
148
+
149
+ obj->data = data;
150
+ obj->wtbl = wtbl;
151
+
152
+ obj->line = line;
153
+ obj->width = capa / 2;
154
+
155
+ obj->fmt = fmt;
156
+
157
+ obj->capa = capa;
158
+ obj->used = 0;
159
+
160
+ obj->magnify = 1;
161
+
162
+ obj->mode = FFT_LOGSCALE_MODE;
163
+ obj->fq_s = 44100;
164
+ obj->fq_h = 16000;
165
+ obj->fq_l = 100;
166
+
167
+ obj->a = a;
168
+ obj->ip = ip;
169
+ obj->w = w;
170
+
171
+ fft_set_window(obj, FFT_WINDOW_BLACKMAN);
172
+ fft_set_width(obj, 480);
173
+
174
+ *_obj = obj;
175
+ }
176
+
177
+ /*
178
+ * post process
179
+ */
180
+ if (ret) {
181
+ if (obj != NULL) free(obj);
182
+ if (data != NULL) free(data);
183
+ if (wtbl != NULL) free(wtbl);
184
+ if (line != NULL) free(line);
185
+ if (a != NULL) free(a);
186
+ if (ip != NULL) free(ip);
187
+ if (w != NULL) free(w);
188
+ }
189
+
190
+ return ret;
191
+ }
192
+
193
+ int
194
+ fft_destroy(fft_t* fft)
195
+ {
196
+ int ret;
197
+
198
+ /*
199
+ * initialize
200
+ */
201
+ ret = 0;
202
+
203
+ /*
204
+ * argument check
205
+ */
206
+ if (fft == NULL) ret = ERR;
207
+
208
+ /*
209
+ * release memory
210
+ */
211
+ if (!ret) {
212
+ free(fft->data);
213
+ free(fft->wtbl);
214
+ free(fft->line);
215
+ free(fft->a);
216
+ free(fft->ip);
217
+ free(fft->w);
218
+
219
+ free(fft);
220
+ }
221
+
222
+ return ret;
223
+ }
224
+
225
+ static void
226
+ import_u8(double* dst, uint8_t* src, int n)
227
+ {
228
+ int i;
229
+
230
+ for (i = 0; i < n; i++) {
231
+ dst[i] = ((double)src[i] - 128.0) / 128.0;
232
+ }
233
+ }
234
+
235
+ static void
236
+ import_u16le(double* dst, uint8_t* src, int n)
237
+ {
238
+ int i;
239
+ uint16_t smpl;
240
+
241
+ for (i = 0; i < n; i++, src += 2) {
242
+ smpl = ((((uint16_t)src[0] << 0) & 0x00ff)|
243
+ (((uint16_t)src[1] << 8) & 0xff00));
244
+
245
+ dst[i] = ((double)smpl - 32768.0) / 32768.0;
246
+ }
247
+ }
248
+
249
+ static void
250
+ import_u16be(double* dst, uint8_t* src, int n)
251
+ {
252
+ int i;
253
+ uint16_t smpl;
254
+
255
+ for (i = 0; i < n; i++, src += 2) {
256
+ smpl = ((((uint16_t)src[1] << 0) & 0x00ff)|
257
+ (((uint16_t)src[0] << 8) & 0xff00));
258
+
259
+ dst[i] = ((double)smpl - 32768.0) / 32768.0;
260
+ }
261
+ }
262
+
263
+ static void
264
+ import_s16le(double* dst, uint8_t* src, int n)
265
+ {
266
+ int i;
267
+ int16_t smpl;
268
+
269
+ for (i = 0; i < n; i++, src += 2) {
270
+ smpl = ((((int16_t)src[0] << 0) & 0x00ff)|
271
+ (((int16_t)src[1] << 8) & 0xff00));
272
+
273
+ dst[i] = (double)smpl / 32768.0;
274
+ }
275
+ }
276
+
277
+ static void
278
+ import_s16be(double* dst, uint8_t* src, int n)
279
+ {
280
+ int i;
281
+ int16_t smpl;
282
+
283
+ for (i = 0; i < n; i++, src += 2) {
284
+ smpl = ((((int16_t)src[1] << 0) & 0x00ff)|
285
+ (((int16_t)src[0] << 8) & 0xff00));
286
+
287
+ dst[i] = (double)smpl / 32768.0;
288
+ }
289
+ }
290
+
291
+ static void
292
+ import_s24le(double* dst, uint8_t* src, int n)
293
+ {
294
+ int i;
295
+ int32_t smpl;
296
+
297
+ for (i = 0; i < n; i++, src += 3) {
298
+ smpl = ((((int32_t)src[0] << 8) & 0x0000ff00)|
299
+ (((int32_t)src[1] << 16) & 0x00ff0000)|
300
+ (((int32_t)src[2] << 24) & 0xff000000));
301
+
302
+ dst[i] = (double)smpl / 2147483648.0;
303
+ }
304
+ }
305
+
306
+ static void
307
+ import_s24be(double* dst, uint8_t* src, int n)
308
+ {
309
+ int i;
310
+ int32_t smpl;
311
+
312
+ for (i = 0; i < n; i++, src += 3) {
313
+ smpl = ((((int32_t)src[2] << 8) & 0x0000ff00)|
314
+ (((int32_t)src[1] << 16) & 0x00ff0000)|
315
+ (((int32_t)src[0] << 24) & 0xff000000));
316
+
317
+ dst[i] = (double)smpl / 2147483648.0;
318
+ }
319
+ }
320
+
321
+ int
322
+ fft_shift_in(fft_t* fft, void* src, int n)
323
+ {
324
+ int ret;
325
+ double* dst;
326
+
327
+ /*
328
+ * initialize
329
+ */
330
+ ret = 0;
331
+
332
+ /*
333
+ * argument check
334
+ */
335
+ if (fft == NULL) ret = ERR;
336
+ if (src == NULL) ret = ERR;
337
+ if (n < 0) ret = ERR;
338
+
339
+ if (!ret) {
340
+ if (n > fft->capa) ret = ERR;
341
+ }
342
+
343
+ /*
344
+ * do import
345
+ */
346
+ if (!ret) {
347
+ memmove(fft->data, fft->data + n, sizeof(double) * (fft->capa - n));
348
+
349
+ dst = fft->data + (fft->capa - n);
350
+ switch (fft->fmt) {
351
+ case FMT_U8:
352
+ import_u8(dst, src, n);
353
+ break;
354
+
355
+ case FMT_U16BE:
356
+ import_u16be(dst, src, n);
357
+ break;
358
+
359
+ case FMT_U16LE:
360
+ import_u16le(dst, src, n);
361
+ break;
362
+
363
+ case FMT_S16BE:
364
+ import_s16be(dst, src, n);
365
+ break;
366
+
367
+ case FMT_S16LE:
368
+ import_s16le(dst, src, n);
369
+ break;
370
+
371
+ case FMT_S24BE:
372
+ import_s24be(dst, src, n);
373
+ break;
374
+
375
+ case FMT_S24LE:
376
+ import_s24le(dst, src, n);
377
+ break;
378
+ }
379
+
380
+ fft->used += n;
381
+
382
+ if (fft->used > fft->capa) {
383
+ fft->used = fft->capa;
384
+ }
385
+ }
386
+
387
+ return ret;
388
+ }
389
+
390
+ int
391
+ fft_reset(fft_t* fft)
392
+ {
393
+ int ret;
394
+
395
+ /*
396
+ * initialize
397
+ */
398
+ ret = 0;
399
+
400
+ /*
401
+ * argument check
402
+ */
403
+ if (fft == NULL) ret = ERR;
404
+
405
+ /*
406
+ * do reset buffer
407
+ */
408
+ if (!ret) {
409
+ memset(fft->data, 0, sizeof(double) * fft->capa);
410
+
411
+ fft->used = 0;
412
+ }
413
+
414
+ return ret;
415
+ }
416
+
417
+
418
+ static void
419
+ set_rectangular_window(double* dst, int n)
420
+ {
421
+ int i;
422
+
423
+ for (i = 0; i <= n; i++) {
424
+ dst[i] = 1.0;
425
+ }
426
+ }
427
+
428
+ static void
429
+ set_hamming_window(double* dst, int n)
430
+ {
431
+ int i;
432
+ double x;
433
+
434
+ n--;
435
+
436
+ for (i = 0; i <= n; i++) {
437
+ x = ((double)i / (double)n) * M_PI * 2.0;
438
+ dst[i] = 0.54 - (0.46 * cos(x));
439
+ }
440
+ }
441
+
442
+ static void
443
+ set_hann_window(double* dst, int n)
444
+ {
445
+ int i;
446
+ double x;
447
+
448
+ n--;
449
+
450
+ for (i = 0; i <= n; i++) {
451
+ x = ((double)i / (double)n) * M_PI * 2.0;
452
+ dst[i] = 0.50 - (0.50 * cos(x));
453
+ }
454
+ }
455
+
456
+ static void
457
+ set_blackman_window(double* dst, int n)
458
+ {
459
+ int i;
460
+ double x;
461
+
462
+ n--;
463
+
464
+ for (i = 0; i <= n; i++) {
465
+ x = ((double)i / (double)n) * M_PI;
466
+ dst[i] = 0.42 - (0.50 * cos(2.0 * x)) + (0.08 * cos(4.0 * x));
467
+ }
468
+ }
469
+
470
+ static void
471
+ set_blackman_nuttall_window(double* dst, int n)
472
+ {
473
+ int i;
474
+ double x;
475
+
476
+ n--;
477
+
478
+ for (i = 0; i <= n; i++) {
479
+ x = ((double)i / (double)n) * M_PI * 2.0;
480
+ dst[i] = 0.3635819 - (0.4891775 * cos(x)) +
481
+ (0.1365995 * cos(2.0 * x)) - (0.0106411 * cos(3.0 * x));
482
+ }
483
+ }
484
+
485
+ static void
486
+ set_flat_top_window(double* dst, int n)
487
+ {
488
+ int i;
489
+ double x;
490
+
491
+ n--;
492
+
493
+ for (i = 0; i <= n; i++) {
494
+ x = ((double)i / (double)n) * M_PI * 2.0;
495
+ dst[i] = 1.0 - (1.93 * cos(x)) + (1.29 * cos(2.0 * x)) -
496
+ (0.388 * cos(3.0 * x)) + (0.032 * cos(4.0 * x));
497
+ }
498
+ }
499
+
500
+ int
501
+ fft_set_window(fft_t* fft, int type)
502
+ {
503
+ int ret;
504
+
505
+ /*
506
+ * initialize
507
+ */
508
+ ret = 0;
509
+
510
+ /*
511
+ * argument chack
512
+ */
513
+ if (fft == NULL) ret = ERR;
514
+
515
+ /*
516
+ * set window function
517
+ */
518
+ switch (type) {
519
+ case FFT_WINDOW_RECTANGULAR:
520
+ set_rectangular_window(fft->wtbl, fft->capa);
521
+ break;
522
+
523
+ case FFT_WINDOW_HAMMING:
524
+ set_hamming_window(fft->wtbl, fft->capa);
525
+ break;
526
+
527
+ case FFT_WINDOW_HANN:
528
+ set_hann_window(fft->wtbl, fft->capa);
529
+ break;
530
+
531
+ case FFT_WINDOW_BLACKMAN:
532
+ set_blackman_window(fft->wtbl, fft->capa);
533
+ break;
534
+
535
+ case FFT_WINDOW_BLACKMAN_NUTTALL:
536
+ set_blackman_nuttall_window(fft->wtbl, fft->capa);
537
+ break;
538
+
539
+ case FFT_WINDOW_FLAT_TOP:
540
+ set_flat_top_window(fft->wtbl, fft->capa);
541
+ break;
542
+
543
+ default:
544
+ ret = ERR;
545
+ break;
546
+ }
547
+
548
+ return ret;
549
+ }
550
+
551
+ static void
552
+ set_linear_mapping(fft_t* fft)
553
+ {
554
+ double pos;
555
+ double step;
556
+ int head;
557
+ int tail;
558
+ lc_t* lc;
559
+ int i;
560
+
561
+ pos = fft->capa * (fft->fq_l / fft->fq_s);
562
+ step = (fft->capa * ((fft->fq_h - fft->fq_l) / fft->fq_s)) / fft->width;
563
+ head = (int)round(pos);
564
+ lc = (lc_t*)fft->line;
565
+
566
+ for (i = 0; i < fft->width; i++) {
567
+ pos += step;
568
+ tail = (int)round(pos);
569
+
570
+ lc->pos = head;
571
+ lc->n = (tail == head)? 1: (tail - head);
572
+
573
+ head = tail;
574
+ lc++;
575
+ }
576
+ }
577
+
578
+ static void
579
+ set_log_mapping(fft_t* fft)
580
+ {
581
+ double pos;
582
+ double step;
583
+ int i;
584
+ int head;
585
+ int tail;
586
+ lc_t* lc;
587
+
588
+ pos = fft->capa * (fft->fq_l / fft->fq_s);
589
+ step = pow((fft->fq_h / fft->fq_l), (1.0 / fft->width));
590
+ head = (int)round(pos);
591
+ lc = (lc_t*)fft->line;
592
+
593
+ for (i = 0; i < fft->width; i++) {
594
+ pos *= step;
595
+ tail = (int)round(pos);
596
+
597
+ lc->pos = head;
598
+ lc->n = (tail == head)? 1: (tail - head);
599
+
600
+ head = tail;
601
+ lc++;
602
+ }
603
+ }
604
+
605
+ static void
606
+ set_line_mapping(fft_t* fft)
607
+ {
608
+ /*
609
+ * calc step
610
+ */
611
+ switch (fft->mode) {
612
+ case FFT_LINEARSCALE_MODE:
613
+ set_linear_mapping(fft);
614
+ break;
615
+
616
+ case FFT_LOGSCALE_MODE:
617
+ set_log_mapping(fft);
618
+ break;
619
+ }
620
+ }
621
+
622
+ int
623
+ fft_set_width(fft_t* fft, int width)
624
+ {
625
+ int ret;
626
+ lc_t* line;
627
+
628
+ /*
629
+ * initialize
630
+ */
631
+ ret = 0;
632
+ line = NULL;
633
+
634
+ /*
635
+ * argument check
636
+ */
637
+ if (fft == NULL) ret = ERR;
638
+ if (!ret) {
639
+ if (width > (fft->capa / 2)) ret = ERR;
640
+ }
641
+
642
+ /*
643
+ * alloc spectrum line buffer
644
+ */
645
+ if (!ret) {
646
+ line = NALLOC(lc_t, width);
647
+ if (line == NULL) ret = ERR;
648
+ }
649
+
650
+ /*
651
+ * modify FFT context
652
+ */
653
+ if (!ret) {
654
+ if (fft->line) free(fft->line);
655
+ fft->line = line;
656
+ fft->width = width;
657
+
658
+ set_line_mapping(fft);
659
+ }
660
+
661
+ return ret;
662
+ }
663
+
664
+ int
665
+ fft_set_scale_mode(fft_t* fft, int mode)
666
+ {
667
+ int ret;
668
+
669
+ do {
670
+ /*
671
+ * argument check
672
+ */
673
+ if (fft == NULL) {
674
+ ret = ERR;
675
+ break;
676
+ }
677
+
678
+ if (mode != FFT_LOGSCALE_MODE &&
679
+ mode != FFT_LINEARSCALE_MODE) {
680
+ ret = ERR;
681
+ break;
682
+ }
683
+
684
+ /*
685
+ * modify FFT context
686
+ */
687
+ fft->mode = mode;
688
+ set_line_mapping(fft);
689
+
690
+ /*
691
+ * mark success
692
+ */
693
+ ret = 0;
694
+ } while(0);
695
+
696
+ return ret;
697
+ }
698
+
699
+ int
700
+ fft_set_frequency(fft_t* fft, double s, double l, double h)
701
+ {
702
+ int ret;
703
+
704
+ do {
705
+ /*
706
+ * argument check
707
+ */
708
+ if (fft == NULL) {
709
+ ret = ERR;
710
+ break;
711
+ }
712
+
713
+ if (h > (s / 2.0)) {
714
+ ret = ERR;
715
+ break;
716
+ }
717
+
718
+ if (l > h) {
719
+ ret = ERR;
720
+ break;
721
+ }
722
+
723
+ /*
724
+ * modify FFT context
725
+ */
726
+ fft->fq_s = s;
727
+ fft->fq_h = h;
728
+ fft->fq_l = l;
729
+
730
+ set_line_mapping(fft);
731
+
732
+ /*
733
+ * mark success
734
+ */
735
+ ret = 0;
736
+ } while(0);
737
+
738
+ return ret;
739
+ }
740
+
741
+ int
742
+ fft_transform(fft_t* fft)
743
+ {
744
+ int ret;
745
+ int i;
746
+
747
+ /*
748
+ * initialize
749
+ */
750
+ ret = 0;
751
+
752
+ /*
753
+ * argument chack
754
+ */
755
+ if (fft == NULL) ret = ERR;
756
+
757
+ /*
758
+ * do transform
759
+ */
760
+ if (!ret) {
761
+ for (i = 0; i < fft->capa; i++) {
762
+ fft->a[i] = fft->data[i] * fft->wtbl[i];
763
+ }
764
+
765
+ rdft(fft->capa, 1, fft->a, fft->ip, fft->w);
766
+ }
767
+
768
+ return ret;
769
+ }
770
+
771
+ int
772
+ fft_calc_spectrum(fft_t* fft, double* dst)
773
+ {
774
+ int ret;
775
+ int i;
776
+ int j;
777
+ double* a;
778
+ double v;
779
+ lc_t* lc;
780
+
781
+ do {
782
+ /*
783
+ * argument check
784
+ */
785
+ if (fft == NULL) {
786
+ ret = ERR;
787
+ break;
788
+ }
789
+
790
+ if (dst == NULL) {
791
+ ret = ERR;
792
+ break;
793
+ }
794
+
795
+ /*
796
+ * calc power spectrum
797
+ */
798
+ for (i = 0, lc = (lc_t*)fft->line; i < fft->width; i++, lc++) {
799
+ v = 0;
800
+
801
+ for(j = 0, a = fft->a + (lc->pos * 2); j < lc->n; j++, a += 2) {
802
+ v += (10 * log10((a[0] * a[0]) + (a[1] * a[1])));
803
+ }
804
+
805
+ dst[i] = v / j;
806
+ }
807
+
808
+ /*
809
+ * mark success
810
+ */
811
+ ret = 0;
812
+ } while(0);
813
+
814
+ return ret;
815
+ }
816
+
817
+ /*
818
+ * 注意
819
+ * この関数はfft_calcs_spectrum()と異なり、dB値への変換を
820
+ * 行った結果を返します。
821
+ */
822
+ int
823
+ fft_calc_amplitude(fft_t* fft, double* dst)
824
+ {
825
+ int ret;
826
+ int i;
827
+ int j;
828
+ double* a;
829
+ double v;
830
+ double base;
831
+ lc_t* lc;
832
+
833
+ do {
834
+ /*
835
+ * argument check
836
+ */
837
+ if (fft == NULL) {
838
+ ret = ERR;
839
+ break;
840
+ }
841
+
842
+ if (dst == NULL) {
843
+ ret = ERR;
844
+ break;
845
+ }
846
+
847
+ /*
848
+ * calc power spectrum
849
+ */
850
+ base = (double)fft->used;
851
+
852
+ for (i = 0, lc = (lc_t*)fft->line; i < fft->width; i++, lc++) {
853
+ v = 0;
854
+
855
+ for(j = 0, a = fft->a + (lc->pos * 2); j < lc->n; j++, a += 2) {
856
+ v += 20.0 * log10(sqrt((a[0] * a[0]) + (a[1] * a[1])) / base);
857
+ }
858
+
859
+ dst[i] = v / j;
860
+ }
861
+
862
+ /*
863
+ * mark success
864
+ */
865
+ ret = 0;
866
+ } while(0);
867
+
868
+ return ret;
869
+ }
870
+
871
+ int
872
+ fft_calc_absolute(fft_t* fft, double* dst)
873
+ {
874
+ int ret;
875
+ int i;
876
+ int j;
877
+ double* a;
878
+ double v;
879
+ double base;
880
+ lc_t* lc;
881
+
882
+ do {
883
+ /*
884
+ * argument check
885
+ */
886
+ if (fft == NULL) {
887
+ ret = ERR;
888
+ break;
889
+ }
890
+
891
+ if (dst == NULL) {
892
+ ret = ERR;
893
+ break;
894
+ }
895
+
896
+ /*
897
+ * calc power spectrum
898
+ */
899
+ base = (double)fft->used;
900
+
901
+ for (i = 0, lc = (lc_t*)fft->line; i < fft->width; i++, lc++) {
902
+ v = 0;
903
+
904
+ for(j = 0, a = fft->a + (lc->pos * 2); j < lc->n; j++, a += 2) {
905
+ v += (sqrt((a[0] * a[0]) + (a[1] * a[1])) / base);
906
+ }
907
+
908
+ dst[i] = v / j;
909
+ }
910
+
911
+ /*
912
+ * mark success
913
+ */
914
+ ret = 0;
915
+ } while(0);
916
+
917
+ return ret;
918
+ }