|
| 1 | +// SPDX-License-Identifier: BSD-3-Clause |
| 2 | +// |
| 3 | +// Copyright(c) 2026 Intel Corporation. |
| 4 | +// |
| 5 | +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> |
| 6 | +// |
| 7 | + |
| 8 | +#include <rtos/symbol.h> |
| 9 | +#include <sof/audio/format.h> |
| 10 | +#include <sof/math/icomplex32.h> |
| 11 | +#include <sof/math/sqrt.h> |
| 12 | +#include <stdint.h> |
| 13 | + |
| 14 | +/* sofm_icomplex32_to_polar() - Convert (re, im) complex number to polar. */ |
| 15 | +void sofm_icomplex32_to_polar(struct icomplex32 *complex, struct ipolar32 *polar) |
| 16 | +{ |
| 17 | + struct icomplex32 c = *complex; |
| 18 | + int64_t squares_sum; |
| 19 | + int32_t sqrt_arg; |
| 20 | + int32_t acos_arg; |
| 21 | + int32_t acos_val; |
| 22 | + |
| 23 | + /* Calculate square of magnitudes Q1.31, result is Q2.62 */ |
| 24 | + squares_sum = (int64_t)c.real * c.real + (int64_t)c.imag * c.imag; |
| 25 | + |
| 26 | + /* Square root */ |
| 27 | + sqrt_arg = Q_SHIFT_RND(squares_sum, 62, 30); |
| 28 | + polar->magnitude = sofm_sqrt_int32(sqrt_arg); /* Q2.30 */ |
| 29 | + |
| 30 | + /* Avoid divide by zero and ambiguous angle for a zero vector. */ |
| 31 | + if (polar->magnitude == 0) { |
| 32 | + polar->angle = 0; |
| 33 | + return; |
| 34 | + } |
| 35 | + |
| 36 | + /* Calculate phase angle with acos( complex->real / polar->magnitude) */ |
| 37 | + acos_arg = sat_int32((((int64_t)c.real) << 29) / polar->magnitude); /* Q2.30 */ |
| 38 | + acos_val = acos_fixed_32b(acos_arg); /* Q3.29 */ |
| 39 | + polar->angle = (c.imag < 0) ? -acos_val : acos_val; |
| 40 | +} |
| 41 | +EXPORT_SYMBOL(sofm_icomplex32_to_polar); |
| 42 | + |
| 43 | +/* sofm_ipolar32_to_complex() - Convert complex number from polar to normal (re, im) format. */ |
| 44 | +void sofm_ipolar32_to_complex(struct ipolar32 *polar, struct icomplex32 *complex) |
| 45 | +{ |
| 46 | + struct cordic_cmpx cexp; |
| 47 | + int32_t phase; |
| 48 | + int32_t magnitude; |
| 49 | + |
| 50 | + /* The conversion can happen in-place, so load copies of the values first */ |
| 51 | + magnitude = polar->magnitude; |
| 52 | + phase = Q_SHIFT_RND(polar->angle, 29, 28); /* Q3.29 to Q2.28 */ |
| 53 | + cmpx_exp_32b(phase, &cexp); /* Q2.30 */ |
| 54 | + complex->real = sat_int32(Q_MULTSR_32X32((int64_t)magnitude, cexp.re, 30, 30, 31)); |
| 55 | + complex->imag = sat_int32(Q_MULTSR_32X32((int64_t)magnitude, cexp.im, 30, 30, 31)); |
| 56 | +} |
| 57 | +EXPORT_SYMBOL(sofm_ipolar32_to_complex); |
0 commit comments