forked from WavX/bioacoustics
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fft.cpp
120 lines (103 loc) · 3.01 KB
/
fft.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
//------------------------------------------------------------------------------
// Copyright (C) 2017-2019 WavX, inc. (www.wavx.ca)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with This program. If not, see <https://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include <algorithm>
#include <cmath>
#include <math.h>
#include <string>
#include <vector>
#include "fft.h"
FFT::FFT() {}
FFT::FFT(size_t fft_sz, FFT::WIN_TYPE win_type)
{
this->fft_size = fft_sz;
set_window(win_type);
set_plan(fft_sz);
}
void FFT::set_plan(const size_t &fft_sz)
{
original.resize(fft_sz, 0);
transformed.resize(fft_sz, 0);
magnitude.resize(fft_sz / 2, 0);
plan = fftw_plan_r2r_1d(fft_sz, &original[0], &transformed[0], FFTW_R2HC, FFTW_PATIENT);
}
void FFT::set_window(const WIN_TYPE& win_type)
{
window.resize(fft_size, 0);
z = M_PI / (fft_size-1);
switch(win_type)
{
case WIN_TYPE::BLACKMAN_HARRIS_4 :
blackman_harris_4 (fft_size);
break;
case WIN_TYPE::BLACKMAN_HARRIS_7 :
blackman_harris_7 (fft_size);
break;
case WIN_TYPE::HANN :
hann (fft_size);
break;
}
double sum { std::accumulate(window.begin(), window.end(), 0.0) };
normalise = 1. / sum;
}
// FFT windows
FFT::WIN_TYPE fft_win_str_to_enum(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
FFT::WIN_TYPE win_type;
if (s == "hann")
{
win_type = FFT::WIN_TYPE::HANN;
}
else if (s == "blackman4")
{
win_type = FFT::WIN_TYPE::BLACKMAN_HARRIS_4;
}
else if (s == "blackman7")
{
win_type = FFT::WIN_TYPE::BLACKMAN_HARRIS_7;
}
else Rcpp::stop("This type of window is not implemented.");
return win_type;
}
void FFT::blackman_harris_4 (size_t fft_sz)
{
for (size_t i = 0; i < fft_sz; i++)
{
window[i] = 0.35875 - 0.48829 * std::cos(2*z*i) + \
0.14128 * std::cos(4*z*i) - \
0.01168 * std::cos(6*z*i);
}
}
void FFT::blackman_harris_7 (size_t fft_sz)
{
// doi:10.1109/icassp.2001.940309
for (size_t i = 0; i < fft_sz; i++)
{
window[i] = 0.2712203606 - 0.4334446123 * std::cos(2*z*i) + \
0.21800412 * std::cos(4*z*i) - 0.0657853433 * std::cos(6*z*i) + \
0.0107618673 * std::cos(8*z*i) - 0.0007700127 * std::cos(10*z*i) + \
0.00001368088 * std::cos(12*z*i);
}
}
void FFT::hann (size_t fft_sz)
{
for (size_t i = 0; i < fft_sz; i++)
{
window[i] = 0.5 * (1 - std::cos(2*z*i));
}
}
FFT::~FFT() { fftw_destroy_plan( plan ); }