forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfft_multi.c
More file actions
140 lines (117 loc) · 3.51 KB
/
fft_multi.c
File metadata and controls
140 lines (117 loc) · 3.51 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2025 Intel Corporation.
//
// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
#include <sof/audio/coefficients/fft/twiddle_3072_32.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/format.h>
#include <sof/math/icomplex32.h>
#include <sof/trace/trace.h>
#include <sof/lib/uuid.h>
#include <sof/common.h>
#include <rtos/alloc.h>
#include <sof/math/fft.h>
#include "fft_common.h"
LOG_MODULE_REGISTER(math_fft_multi, CONFIG_SOF_LOG_LEVEL);
SOF_DEFINE_REG_UUID(math_fft_multi);
DECLARE_TR_CTX(math_fft_multi_tr, SOF_UUID(math_fft_multi_uuid), LOG_LEVEL_INFO);
struct fft_multi_plan *mod_fft_multi_plan_new(struct processing_module *mod, void *inb,
void *outb, uint32_t size, int bits)
{
struct fft_multi_plan *plan;
size_t tmp_size;
const int size_div3 = size / 3;
int i;
if (!inb || !outb) {
comp_cl_err(mod->dev, "Null buffers");
return NULL;
}
if (size < FFT_SIZE_MIN) {
comp_cl_err(mod->dev, "Invalid FFT size %d", size);
return NULL;
}
plan = mod_zalloc(mod, sizeof(struct fft_multi_plan));
if (!plan)
return NULL;
if (is_power_of_2(size)) {
plan->num_ffts = 1;
} else if (size_div3 * 3 == size) {
plan->num_ffts = 3;
} else {
comp_cl_err(mod->dev, "Not supported FFT size %d", size);
goto err;
}
/* Allocate common bit reverse table for all FFT plans */
plan->total_size = size;
plan->fft_size = size / plan->num_ffts;
if (plan->fft_size > FFT_SIZE_MAX) {
comp_cl_err(mod->dev, "Requested size %d FFT is too large", size);
goto err;
}
plan->bit_reverse_idx = mod_zalloc(mod, plan->fft_size * sizeof(uint16_t));
if (!plan->bit_reverse_idx) {
comp_cl_err(mod->dev, "Failed to allocate FFT plan");
goto err;
}
switch (bits) {
case 32:
plan->inb32 = inb;
plan->outb32 = outb;
if (plan->num_ffts > 1) {
/* Allocate input/output buffers for FFTs */
tmp_size = 2 * plan->num_ffts * plan->fft_size * sizeof(struct icomplex32);
plan->tmp_i32[0] = mod_balloc(mod, tmp_size);
if (!plan->tmp_i32[0]) {
comp_cl_err(mod->dev, "Failed to allocate FFT buffers");
goto err_free_bit_reverse;
}
/* Set up buffers */
plan->tmp_o32[0] = plan->tmp_i32[0] + plan->fft_size;
for (i = 1; i < plan->num_ffts; i++) {
plan->tmp_i32[i] = plan->tmp_o32[i - 1] + plan->fft_size;
plan->tmp_o32[i] = plan->tmp_i32[i] + plan->fft_size;
}
} else {
plan->tmp_i32[0] = inb;
plan->tmp_o32[0] = outb;
}
for (i = 0; i < plan->num_ffts; i++) {
plan->fft_plan[i] = fft_plan_common_new(mod,
plan->tmp_i32[i],
plan->tmp_o32[i],
plan->fft_size, 32);
if (!plan->fft_plan[i])
goto err_free_buffer;
plan->fft_plan[i]->bit_reverse_idx = plan->bit_reverse_idx;
}
break;
default:
comp_cl_err(mod->dev, "Not supported word length %d", bits);
goto err;
}
/* Set up common bit index reverse table */
fft_plan_init_bit_reverse(plan->bit_reverse_idx, plan->fft_plan[0]->size,
plan->fft_plan[0]->len);
return plan;
err_free_buffer:
mod_free(mod, plan->tmp_i32[0]);
err_free_bit_reverse:
mod_free(mod, plan->bit_reverse_idx);
err:
mod_free(mod, plan);
return NULL;
}
void mod_fft_multi_plan_free(struct processing_module *mod, struct fft_multi_plan *plan)
{
int i;
if (!plan)
return;
for (i = 0; i < plan->num_ffts; i++)
mod_free(mod, plan->fft_plan[i]);
/* If single FFT, the internal buffers were not allocated. */
if (plan->num_ffts > 1)
mod_free(mod, plan->tmp_i32[0]);
mod_free(mod, plan->bit_reverse_idx);
mod_free(mod, plan);
}