34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'ext/kissfft/main.c', line 34
static VALUE
rbkiss_s_fftr(VALUE class, VALUE r_nfft, VALUE r_rate, VALUE r_buckets, VALUE r_data)
{
kiss_fftr_cfg cfg=NULL;
kiss_fft_scalar *tbuf;
kiss_fft_cpx *fbuf;
float *mag2buf;
int i;
int avgctr=0;
int nrows=0;
int nfft;
int rate;
int navg;
int nfreqs;
int inp_len;
int inp_idx;
// Result set
VALUE res;
VALUE tmp;
VALUE set;
res = rb_ary_new();
if(TYPE(r_nfft) != T_FIXNUM) {
return Qnil;
}
nfft=NUM2INT(r_nfft);
if(TYPE(r_rate) != T_FIXNUM) {
return Qnil;
}
rate=NUM2INT(r_rate);
if(TYPE(r_buckets) != T_FIXNUM) {
return Qnil;
}
navg=NUM2INT(r_buckets);
if(TYPE(r_data) != T_ARRAY) {
return Qnil;
}
if(RARRAY_LEN(r_data) == 0) {
return Qnil;
}
if(TYPE(RARRAY_PTR(r_data)[0]) != T_FIXNUM ) {
return Qnil;
}
nfreqs=nfft/2+1;
CHECKNULL( cfg=kiss_fftr_alloc(nfft,0,0,0) );
CHECKNULL( tbuf=(kiss_fft_scalar*)malloc(sizeof(kiss_fft_scalar)*(nfft + 2) ) );
CHECKNULL( fbuf=(kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx)*(nfft + 2)) );
CHECKNULL( mag2buf=(float*)malloc(sizeof(float)*(nfft + 2) ));
memset(mag2buf,0,sizeof(mag2buf)*nfreqs);
inp_len = RARRAY_LEN(r_data);
inp_idx = 0;
while(inp_idx < inp_len) {
// Fill tbuf with nfft samples
for(i=0;i<nfft;i++) {
if(inp_idx + i >= inp_len) {
tbuf[i] = 0;
} else {
if(TYPE(RARRAY_PTR(r_data)[ inp_idx + i ]) != T_FIXNUM) {
tbuf[i] = 0;
} else {
tbuf[i] = NUM2INT( RARRAY_PTR(r_data)[ inp_idx + i ] );
}
}
}
/* do FFT */
kiss_fftr(cfg,tbuf,fbuf);
for (i=0;i<nfreqs;++i) {
mag2buf[i] += fbuf[i].r * fbuf[i].r + fbuf[i].i * fbuf[i].i;
}
if (++avgctr == navg) {
float eps = 1;
avgctr=0;
++nrows;
// RESULTS
set = rb_ary_new();
for (i=0;i<nfreqs;++i) {
float pwr = 10 * log10( mag2buf[i] / navg + eps );
tmp = rb_ary_new();
rb_ary_push(tmp, rb_float_new( (float)i * ( ( (float)rate / 2) / (float)nfreqs) ));
rb_ary_push(tmp, rb_float_new( pwr));
rb_ary_push(set, tmp);
}
rb_ary_push(res, set);
memset(mag2buf,0,sizeof(mag2buf[0])*nfreqs);
}
inp_idx += nfft;
}
free(cfg);
free(tbuf);
free(fbuf);
free(mag2buf);
return(res);
}
|