| /* |
| * Copyright 2023 Google LLC |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "audio_prep/util.h" |
| |
| #include <math.h> |
| |
| #ifndef M_SQRT2 |
| #define M_SQRT2 1.41421356237309504880 |
| #endif |
| |
| // Evenly linear spaced array |
| void linspace(float* x, float start, float end, int n) { |
| float step = (end - start) / (n - 1); |
| for (int i = 0; i < n; i++) { |
| x[i] = start + i * step; |
| } |
| } |
| |
| // Calculate the dot product of two vectors |
| float dot_product(float* v, float* u, int n) { |
| float result = 0.0; |
| for (int i = 0; i < n; i++) { |
| result += v[i] * u[i]; |
| } |
| return result; |
| } |
| |
| /*--------------------------------------------------------------------------- |
| * FUNCTION NAME: rfft |
| * |
| * PURPOSE: Real valued, in-place split-radix FFT |
| * |
| * INPUT: |
| * x Pointer to input and output array |
| * m 2^m = n is the Length of FFT |
| * |
| * OUTPUT Output order |
| * Re(0), Re(1), ..., Re(n/2), Im(N/2-1), ..., Im(1) |
| * |
| * RETURN VALUE |
| * none |
| * |
| * DESIGN REFERENCE: |
| * IEEE Transactions on Acoustic, Speech, and Signal Processing, |
| * Vol. ASSP-35. No. 6, June 1987, pp. 849-863. |
| * |
| * Subroutine adapted from fortran routine pp. 858-859. |
| * Note corrected printing errors on page 859: |
| * SS1 = SIN(A3) -> should be SS1 = SIN(A); |
| * CC3 = COS(3) -> should be CC3 = COS(A3) |
| * |
| *---------------------------------------------------------------------------*/ |
| |
| void rfft(float* x, int m) { |
| int n = 1 << m; |
| int j, i, k, is, id; |
| int i0, i1, i2, i3, i4, i5, i6, i7, i8; |
| int n2, n4, n8; |
| float xt, a0, e, a, a3; |
| float t1, t2, t3, t4, t5, t6; |
| float cc1, ss1, cc3, ss3; |
| float* r0; |
| |
| /* Digit reverse counter */ |
| |
| j = 0; |
| r0 = x; |
| |
| for (i = 0; i < n - 1; i++) { |
| if (i < j) { |
| xt = x[j]; |
| x[j] = *r0; |
| *r0 = xt; |
| } |
| r0++; |
| |
| k = n >> 1; |
| |
| while (k <= j) { |
| j = j - k; |
| k >>= 1; |
| } |
| j += k; |
| } |
| |
| /* Length two butterflies */ |
| is = 0; |
| id = 4; |
| |
| while (is < n - 1) { |
| for (i0 = is; i0 < n; i0 += id) { |
| i1 = i0 + 1; |
| a0 = x[i0]; |
| x[i0] += x[i1]; |
| x[i1] = a0 - x[i1]; |
| } |
| |
| is = (id << 1) - 2; |
| id <<= 2; |
| } |
| |
| /* L shaped butterflies */ |
| n2 = 2; |
| for (k = 1; k < m; k++) { |
| n2 <<= 1; |
| n4 = n2 >> 2; |
| n8 = n2 >> 3; |
| e = (M_PI * 2) / n2; |
| is = 0; |
| id = n2 << 1; |
| while (is < n) { |
| for (i = is; i <= n - 1; i += id) { |
| i1 = i; |
| i2 = i1 + n4; |
| i3 = i2 + n4; |
| i4 = i3 + n4; |
| t1 = x[i4] + x[i3]; |
| x[i4] -= x[i3]; |
| x[i3] = x[i1] - t1; |
| x[i1] += t1; |
| |
| if (n4 != 1) { |
| i1 += n8; |
| i2 += n8; |
| i3 += n8; |
| i4 += n8; |
| t1 = (x[i3] + x[i4]) / M_SQRT2; |
| t2 = (x[i3] - x[i4]) / M_SQRT2; |
| x[i4] = x[i2] - t1; |
| x[i3] = -x[i2] - t1; |
| x[i2] = x[i1] - t2; |
| x[i1] = x[i1] + t2; |
| } |
| } |
| is = (id << 1) - n2; |
| id <<= 2; |
| } |
| |
| for (j = 1; j < n8; j++) { |
| a = j * e; |
| a3 = 3 * a; |
| cc1 = cosf(a); |
| ss1 = sinf(a); |
| cc3 = cosf(a3); |
| ss3 = sinf(a3); |
| |
| is = 0; |
| id = n2 << 1; |
| |
| while (is < n) { |
| for (i = is; i <= n - 1; i += id) { |
| i1 = i + j; |
| i2 = i1 + n4; |
| i3 = i2 + n4; |
| i4 = i3 + n4; |
| i5 = i + n4 - j; |
| i6 = i5 + n4; |
| i7 = i6 + n4; |
| i8 = i7 + n4; |
| t1 = x[i3] * cc1 + x[i7] * ss1; |
| t2 = x[i7] * cc1 - x[i3] * ss1; |
| t3 = x[i4] * cc3 + x[i8] * ss3; |
| t4 = x[i8] * cc3 - x[i4] * ss3; |
| t5 = t1 + t3; |
| t6 = t2 + t4; |
| t3 = t1 - t3; |
| t4 = t2 - t4; |
| t2 = x[i6] + t6; |
| x[i3] = t6 - x[i6]; |
| x[i8] = t2; |
| t2 = x[i2] - t3; |
| x[i7] = -x[i2] - t3; |
| x[i4] = t2; |
| t1 = x[i1] + t5; |
| x[i6] = x[i1] - t5; |
| x[i1] = t1; |
| t1 = x[i5] + t4; |
| x[i5] = x[i5] - t4; |
| x[i2] = t1; |
| } |
| is = (id << 1) - n2; |
| id <<= 2; |
| } |
| } |
| } |
| } |