• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 This software is part of pffft/pfdsp, a set of simple DSP routines.
3 
4 Copyright (c) 2014, Andras Retzler <randras@sdr.hu>
5 Copyright (c) 2020  Hayati Ayguen <h_ayguen@web.de>
6 All rights reserved.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10     * Redistributions of source code must retain the above copyright
11       notice, this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15     * Neither the name of the copyright holder nor the
16       names of its contributors may be used to endorse or promote products
17       derived from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #pragma once
32 
33 #include <stdio.h>
34 #include <stdint.h>
35 
36 #include "pf_cplx.h"
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 
43 // =================================================================================
44 
45 int have_sse_shift_mixer_impl();
46 
47 
48 /*********************************************************************/
49 
50 /**************/
51 /*** ALGO A ***/
52 /**************/
53 
54 float shift_math_cc(const complexf *input, complexf* output, int input_size, float rate, float starting_phase);
55 
56 
57 /*********************************************************************/
58 
59 /**************/
60 /*** ALGO B ***/
61 /**************/
62 
63 typedef struct shift_table_data_s
64 {
65     float* table;
66     int table_size;
67 } shift_table_data_t;
68 
69 void shift_table_deinit(shift_table_data_t table_data);
70 shift_table_data_t shift_table_init(int table_size);
71 float shift_table_cc(complexf* input, complexf* output, int input_size, float rate, shift_table_data_t table_data, float starting_phase);
72 
73 /*********************************************************************/
74 
75 /**************/
76 /*** ALGO C ***/
77 /**************/
78 
79 typedef struct shift_addfast_data_s
80 {
81     float dsin[4];
82     float dcos[4];
83     float phase_increment;
84 } shift_addfast_data_t;
85 
86 shift_addfast_data_t shift_addfast_init(float rate);
87 float shift_addfast_cc(complexf *input, complexf* output, int input_size, shift_addfast_data_t* d, float starting_phase);
88 float shift_addfast_inp_c(complexf *in_out, int N_cplx, shift_addfast_data_t* d, float starting_phase);
89 
90 
91 /*********************************************************************/
92 
93 /**************/
94 /*** ALGO D ***/
95 /**************/
96 
97 typedef struct shift_unroll_data_s
98 {
99     float* dsin;
100     float* dcos;
101     float phase_increment;
102     int size;
103 } shift_unroll_data_t;
104 
105 shift_unroll_data_t shift_unroll_init(float rate, int size);
106 void shift_unroll_deinit(shift_unroll_data_t* d);
107 float shift_unroll_cc(complexf *input, complexf* output, int size, shift_unroll_data_t* d, float starting_phase);
108 float shift_unroll_inp_c(complexf* in_out, int size, shift_unroll_data_t* d, float starting_phase);
109 
110 
111 /*********************************************************************/
112 
113 /**************/
114 /*** ALGO E ***/
115 /**************/
116 
117 /* similar to shift_unroll_cc() - but, have fixed and limited precalc size
118  * idea: smaller cache usage by table
119  * size must be multiple of CSDR_SHIFT_LIMITED_SIMD (= 4)
120  */
121 #define PF_SHIFT_LIMITED_UNROLL_SIZE  128
122 #define PF_SHIFT_LIMITED_SIMD_SZ  4
123 
124 typedef struct shift_limited_unroll_data_s
125 {
126     float dcos[PF_SHIFT_LIMITED_UNROLL_SIZE];
127     float dsin[PF_SHIFT_LIMITED_UNROLL_SIZE];
128     complexf complex_phase;
129     float phase_increment;
130 } shift_limited_unroll_data_t;
131 
132 shift_limited_unroll_data_t shift_limited_unroll_init(float rate);
133 /* size must be multiple of PF_SHIFT_LIMITED_SIMD_SZ */
134 /* starting_phase for next call is kept internal in state */
135 void shift_limited_unroll_cc(const complexf *input, complexf* output, int size, shift_limited_unroll_data_t* d);
136 void shift_limited_unroll_inp_c(complexf* in_out, int size, shift_limited_unroll_data_t* d);
137 
138 
139 /*********************************************************************/
140 
141 /**************/
142 /*** ALGO F ***/
143 /**************/
144 
145 typedef struct shift_limited_unroll_A_sse_data_s
146 {
147     /* small/limited trig table */
148     float dcos[PF_SHIFT_LIMITED_UNROLL_SIZE+PF_SHIFT_LIMITED_SIMD_SZ];
149     float dsin[PF_SHIFT_LIMITED_UNROLL_SIZE+PF_SHIFT_LIMITED_SIMD_SZ];
150     /* 4 times complex phase */
151     float phase_state_i[PF_SHIFT_LIMITED_SIMD_SZ];
152     float phase_state_q[PF_SHIFT_LIMITED_SIMD_SZ];
153     /* N_cplx_per_block times increment - for future parallel variants */
154     float dcos_blk;
155     float dsin_blk;
156     /* */
157     float phase_increment;
158 } shift_limited_unroll_A_sse_data_t;
159 
160 shift_limited_unroll_A_sse_data_t shift_limited_unroll_A_sse_init(float relative_freq, float phase_start_rad);
161 void shift_limited_unroll_A_sse_inp_c(complexf* in_out, int N_cplx, shift_limited_unroll_A_sse_data_t* d);
162 
163 
164 /*********************************************************************/
165 
166 /**************/
167 /*** ALGO G ***/
168 /**************/
169 
170 typedef struct shift_limited_unroll_B_sse_data_s
171 {
172     /* small/limited trig table */
173     float dtrig[PF_SHIFT_LIMITED_UNROLL_SIZE+PF_SHIFT_LIMITED_SIMD_SZ];
174     /* 4 times complex phase */
175     float phase_state_i[PF_SHIFT_LIMITED_SIMD_SZ];
176     float phase_state_q[PF_SHIFT_LIMITED_SIMD_SZ];
177     /* N_cplx_per_block times increment - for future parallel variants */
178     float dcos_blk;
179     float dsin_blk;
180     /* */
181     float phase_increment;
182 } shift_limited_unroll_B_sse_data_t;
183 
184 shift_limited_unroll_B_sse_data_t shift_limited_unroll_B_sse_init(float relative_freq, float phase_start_rad);
185 void shift_limited_unroll_B_sse_inp_c(complexf* in_out, int N_cplx, shift_limited_unroll_B_sse_data_t* d);
186 
187 /*********************************************************************/
188 
189 /**************/
190 /*** ALGO H ***/
191 /**************/
192 
193 typedef struct shift_limited_unroll_C_sse_data_s
194 {
195     /* small/limited trig table - interleaved: 4 cos, 4 sin, 4 cos, .. */
196     float dinterl_trig[2*(PF_SHIFT_LIMITED_UNROLL_SIZE+PF_SHIFT_LIMITED_SIMD_SZ)];
197     /* 4 times complex phase */
198     float phase_state_i[PF_SHIFT_LIMITED_SIMD_SZ];
199     float phase_state_q[PF_SHIFT_LIMITED_SIMD_SZ];
200     /* N_cplx_per_block times increment - for future parallel variants */
201     float dcos_blk;
202     float dsin_blk;
203     /* */
204     float phase_increment;
205 } shift_limited_unroll_C_sse_data_t;
206 
207 shift_limited_unroll_C_sse_data_t shift_limited_unroll_C_sse_init(float relative_freq, float phase_start_rad);
208 void shift_limited_unroll_C_sse_inp_c(complexf* in_out, int N_cplx, shift_limited_unroll_C_sse_data_t* d);
209 
210 
211 
212 /*********************************************************************/
213 
214 /**************/
215 /*** ALGO I ***/
216 /**************/
217 
218 /* Recursive Quadrature Oscillator functions "recursive_osc"
219  * see https://www.vicanek.de/articles/QuadOsc.pdf
220  */
221 #define PF_SHIFT_RECURSIVE_SIMD_SZ  8
222 typedef struct shift_recursive_osc_s
223 {
224     float u_cos[PF_SHIFT_RECURSIVE_SIMD_SZ];
225     float v_sin[PF_SHIFT_RECURSIVE_SIMD_SZ];
226 } shift_recursive_osc_t;
227 
228 typedef struct shift_recursive_osc_conf_s
229 {
230     float k1;
231     float k2;
232 } shift_recursive_osc_conf_t;
233 
234 void shift_recursive_osc_init(float rate, float starting_phase, shift_recursive_osc_conf_t *conf, shift_recursive_osc_t *state);
235 void shift_recursive_osc_update_rate(float rate, shift_recursive_osc_conf_t *conf, shift_recursive_osc_t* state);
236 
237 /* size must be multiple of PF_SHIFT_LIMITED_SIMD_SZ */
238 /* starting_phase for next call is kept internal in state */
239 void shift_recursive_osc_cc(const complexf *input, complexf* output, int size, const shift_recursive_osc_conf_t *conf, shift_recursive_osc_t* state);
240 void shift_recursive_osc_inp_c(complexf* output, int size, const shift_recursive_osc_conf_t *conf, shift_recursive_osc_t* state);
241 void gen_recursive_osc_c(complexf* output, int size, const shift_recursive_osc_conf_t *conf, shift_recursive_osc_t* state);
242 
243 /*********************************************************************/
244 
245 /**************/
246 /*** ALGO J ***/
247 /**************/
248 
249 #define PF_SHIFT_RECURSIVE_SIMD_SSE_SZ  4
250 typedef struct shift_recursive_osc_sse_s
251 {
252     float u_cos[PF_SHIFT_RECURSIVE_SIMD_SSE_SZ];
253     float v_sin[PF_SHIFT_RECURSIVE_SIMD_SSE_SZ];
254 } shift_recursive_osc_sse_t;
255 
256 typedef struct shift_recursive_osc_sse_conf_s
257 {
258     float k1;
259     float k2;
260 } shift_recursive_osc_sse_conf_t;
261 
262 void shift_recursive_osc_sse_init(float rate, float starting_phase, shift_recursive_osc_sse_conf_t *conf, shift_recursive_osc_sse_t *state);
263 void shift_recursive_osc_sse_update_rate(float rate, shift_recursive_osc_sse_conf_t *conf, shift_recursive_osc_sse_t* state);
264 void shift_recursive_osc_sse_inp_c(complexf* in_out, int N_cplx, const shift_recursive_osc_sse_conf_t *conf, shift_recursive_osc_sse_t* state_ext);
265 
266 
267 #ifdef __cplusplus
268 }
269 #endif
270 
271