Instrument Neutral Distributed Interface INDI 2.2.5
fft.c
Go to the documentation of this file.
1/*
2* DSP API - a digital signal processing library for astronomy usage
3* Copyright © 2017-2022 Ilia Platone
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU Lesser General Public
7* License as published by the Free Software Foundation; either
8* version 3 of the License, or (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13* Lesser General Public License for more details.
14*
15* You should have received a copy of the GNU Lesser General Public License
16* along with this program; if not, write to the Free Software Foundation,
17* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "dsp.h"
21#include <fftw3.h>
22
23static void dsp_fourier_dft_magnitude(dsp_stream_p stream)
24{
25 if(stream->magnitude)
26 stream->magnitude->buf = dsp_fourier_complex_array_get_magnitude(stream->dft, stream->len);
27}
28
29static void dsp_fourier_dft_phase(dsp_stream_p stream)
30{
31 if(stream->phase)
32 stream->phase->buf = dsp_fourier_complex_array_get_phase(stream->dft, stream->len);
33}
34
36{
37 int x, y;
38 complex_t *dft = (complex_t*)malloc(sizeof(complex_t) * stream->len);
39 memcpy(dft, stream->dft.pairs, sizeof(complex_t) * stream->len);
40 y = 0;
41 for(x = 0; x < stream->len && y < stream->len; x++) {
42 int *pos = dsp_stream_get_position(stream, x);
43 if(pos[0] <= stream->sizes[0] / 2) {
44 stream->dft.pairs[x][0] = dft[y][0];
45 stream->dft.pairs[x][1] = dft[y][1];
46 stream->dft.pairs[stream->len-1-x][0] = dft[y][0];
47 stream->dft.pairs[stream->len-1-x][1] = dft[y][1];
48 y++;
49 }
50 free(pos);
51 }
52 dsp_fourier_dft_magnitude(stream);
54 dsp_fourier_dft_phase(stream);
55 dsp_buffer_shift(stream->phase);
56}
57
59{
60 int x, y;
61 if(!stream->phase || !stream->magnitude) return;
63 dsp_buffer_shift(stream->phase);
64 dsp_fourier_phase_mag_array_get_complex(stream->magnitude->buf, stream->phase->buf, (complex_t*)stream->dft.pairs, stream->len);
65 complex_t *dft = (complex_t*)malloc(sizeof(complex_t) * stream->len);
66 memcpy(dft, stream->dft.pairs, sizeof(complex_t) * stream->len);
67 dsp_buffer_set(stream->dft.buf, stream->len*2, 0);
68 y = 0;
69 for(x = 0; x < stream->len; x++) {
70 int *pos = dsp_stream_get_position(stream, x);
71 if(pos[0] <= stream->sizes[0] / 2) {
72 stream->dft.pairs[y][0] = dft[x][0];
73 stream->dft.pairs[y][1] = dft[x][1];
74 y++;
75 }
76 free(pos);
77 }
78 free(dft);
79}
80
82{
83 int i;
84 double* out = (double*)malloc(sizeof(double) * len);
85 for(i = 0; i < len; i++) {
86 double real = in.complex[i].real;
87 double imaginary = in.complex[i].imaginary;
88 out [i] = sqrt (pow(real, 2)+pow(imaginary, 2));
89 }
90 return out;
91}
92
94{
95 int i;
96 double* out = (double*)malloc(sizeof(double) * len);
97 for(i = 0; i < len; i++) {
98 out [i] = 0;
99 if (in.complex[i].real != 0) {
100 double real = in.complex[i].real;
101 double imaginary = in.complex[i].imaginary;
102 double mag = sqrt(pow(real, 2)+pow(imaginary, 2));
103 double rad = 0.0;
104 if(mag > 0.0) {
105 rad = acos (imaginary / (mag > 0.0 ? mag : 1.0));
106 if(real < 0 && rad != 0)
107 rad = M_PI*2-rad;
108 }
109 out [i] = rad;
110 }
111 }
112 return out;
113}
114
115void dsp_fourier_phase_mag_array_get_complex(double* mag, double* phi, complex_t* out, int len)
116{
117 int i;
118 for(i = 0; i < len; i++) {
119 double real = sin(phi[i])*mag[i];
120 double imaginary = cos(phi[i])*mag[i];
121 out[i][0] = real;
122 out[i][1] = imaginary;
123 }
124}
125
126static void* dsp_stream_dft_th(void* arg)
127{
128 struct {
129 int exp;
130 dsp_stream_p stream;
131 } *arguments = arg;
132 dsp_fourier_dft(arguments->stream, arguments->exp);
133 return NULL;
134}
135void dsp_fourier_dft(dsp_stream_p stream, int exp)
136{
137 if(exp < 1)
138 return;
139 double* buf = (double*)malloc(sizeof(double) * stream->len);
140 if(stream->phase == NULL)
141 stream->phase = dsp_stream_copy(stream);
142 if(stream->magnitude == NULL)
143 stream->magnitude = dsp_stream_copy(stream);
144 dsp_buffer_set(stream->dft.buf, stream->len * 2, 0);
145 dsp_buffer_copy(stream->buf, buf, stream->len);
146 int *sizes = (int*)malloc(sizeof(int)*stream->dims);
147 dsp_buffer_copy(stream->sizes, sizes, stream->dims);
148 dsp_buffer_reverse(sizes, stream->dims);
149 fftw_plan plan = fftw_plan_dft_r2c(stream->dims, sizes, buf, stream->dft.pairs, FFTW_ESTIMATE_PATIENT);
150 fftw_execute(plan);
151 fftw_free(plan);
152 free(sizes);
153 free(buf);
154 dsp_fourier_2dsp(stream);
155 if(exp > 1) {
156 exp--;
157 pthread_t th[2];
158 struct {
159 int exp;
160 dsp_stream_p stream;
161 } thread_arguments[2];
162 thread_arguments[0].exp = exp;
163 thread_arguments[0].stream = stream->phase;
164 pthread_create(&th[0], NULL, dsp_stream_dft_th, &thread_arguments[0]);
165 thread_arguments[1].exp = exp;
166 thread_arguments[1].stream = stream->magnitude;
167 pthread_create(&th[1], NULL, dsp_stream_dft_th, &thread_arguments[1]);
168 pthread_join(th[0], NULL);
169 pthread_join(th[1], NULL);
170 }
171}
172
174{
175 double *buf = (double*)malloc(sizeof(double)*stream->len);
176 dsp_t mn = dsp_stats_min(stream->buf, stream->len);
177 dsp_t mx = dsp_stats_max(stream->buf, stream->len);
178 dsp_buffer_set(buf, stream->len, 0);
180 int *sizes = (int*)malloc(sizeof(int)*stream->dims);
181 dsp_buffer_copy(stream->sizes, sizes, stream->dims);
182 dsp_buffer_reverse(sizes, stream->dims);
183 fftw_plan plan = fftw_plan_dft_c2r(stream->dims, sizes, stream->dft.pairs, buf, FFTW_ESTIMATE_PATIENT);
184 fftw_execute(plan);
185 fftw_free(plan);
186 free(sizes);
187 dsp_buffer_stretch(buf, stream->len, mn, mx);
188 dsp_buffer_copy(buf, stream->buf, stream->len);
190 dsp_buffer_shift(stream->phase);
191 free(buf);
192}
std::thread th
#define M_PI
Definition dsp.h:52
double dsp_t
Definition dsp.h:76
double complex_t[2]
Definition dsp.h:77
struct dsp_stream_t * phase
Fourier transform phase.
Definition dsp.h:429
double imaginary
Imaginary part of the complex number.
Definition dsp.h:321
int * sizes
Sizes of each dimension.
Definition dsp.h:389
dsp_complex dft
Fourier transform.
Definition dsp.h:393
double * buf
Linear double array containing complex numbers.
Definition dsp.h:326
struct dsp_complex::@413 * complex
Complex struct type array.
struct dsp_stream_t * magnitude
Fourier transform magnitude.
Definition dsp.h:427
int dims
Number of dimensions of the buffers.
Definition dsp.h:387
dsp_t * buf
buffer
Definition dsp.h:391
int len
The buffers length.
Definition dsp.h:385
double real
Real part of the complex number.
Definition dsp.h:319
complex_t * pairs
Complex number type array used with libFFTW.
Definition dsp.h:324
#define dsp_buffer_copy(in, out, len)
Fill the output buffer with the values of the elements of the input stream by casting them to the out...
Definition dsp.h:1054
void dsp_buffer_shift(dsp_stream_p stream)
Shift a stream on each dimension.
Definition buffer.c:24
#define dsp_buffer_set(buf, len, _val)
Fill the buffer with the passed value.
Definition dsp.h:831
#define dsp_buffer_reverse(buf, len)
Reverse the order of the buffer elements.
Definition dsp.h:1007
#define dsp_buffer_stretch(buf, len, _mn, _mx)
Stretch minimum and maximum values of the input stream.
Definition dsp.h:808
DLL_EXPORT dsp_stream_p dsp_stream_copy(dsp_stream_p stream)
Create a copy of the DSP stream passed as argument.
Definition stream.c:200
DLL_EXPORT int * dsp_stream_get_position(dsp_stream_p stream, int index)
Return the multidimensional positional indexes of a DSP stream by specify a linear index.
Definition stream.c:451
void dsp_fourier_idft(dsp_stream_p stream)
Perform an inverse discrete Fourier Transform of a dsp_stream.
Definition fft.c:173
void dsp_fourier_2complex_t(dsp_stream_p stream)
Obtain the complex fourier transform from the current magnitude and phase buffers.
Definition fft.c:58
void dsp_fourier_phase_mag_array_get_complex(double *mag, double *phi, complex_t *out, int len)
Obtain a complex array from phase and magnitude arrays.
Definition fft.c:115
void dsp_fourier_2dsp(dsp_stream_p stream)
Fill the magnitude and phase buffers with the current data in stream->dft.
Definition fft.c:35
double * dsp_fourier_complex_array_get_phase(dsp_complex in, int len)
Obtain a complex number's array phases.
Definition fft.c:93
void dsp_fourier_dft(dsp_stream_p stream, int exp)
Perform a discrete Fourier Transform of a dsp_stream.
Definition fft.c:135
double * dsp_fourier_complex_array_get_magnitude(dsp_complex in, int len)
Obtain a complex number's array magnitudes.
Definition fft.c:81
#define dsp_stats_min(buf, len)
Gets the minimum value of the input stream.
Definition dsp.h:578
#define dsp_stats_max(buf, len)
Gets the maximum value of the input stream.
Definition dsp.h:596
Contains a set of information and data relative to a buffer and how to use it.
Definition dsp.h:379
Complex number array struct, used in Fourier Transform functions.
Definition dsp.h:314