forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcrossover.h
More file actions
162 lines (140 loc) · 4.83 KB
/
crossover.h
File metadata and controls
162 lines (140 loc) · 4.83 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2020 Google LLC. All rights reserved.
*
* Author: Sebastiano Carlucci <scarlucci@google.com>
*/
#ifndef __SOF_AUDIO_CROSSOVER_CROSSOVER_H__
#define __SOF_AUDIO_CROSSOVER_CROSSOVER_H__
#include <sof/audio/module_adapter/module/module_interface.h>
#include <sof/math/iir_df2t.h>
#include <sof/platform.h>
#include <user/crossover.h>
#include <stdint.h>
struct comp_buffer;
struct comp_dev;
/* Maximum number of LR4 highpass OR lowpass filters */
#define CROSSOVER_MAX_LR4 3
/* Number of delay slots allocated for LR4 Filters */
#define CROSSOVER_NUM_DELAYS_LR4 4
/* Number of sinks for a 2 way crossover filter */
#define CROSSOVER_2WAY_NUM_SINKS 2
/* Number of sinks for a 3 way crossover filter */
#define CROSSOVER_3WAY_NUM_SINKS 3
/* Number of sinks for a 4 way crossover filter */
#define CROSSOVER_4WAY_NUM_SINKS 4
/**
* The Crossover filter will have from 2 to 4 outputs.
* Diagram of a 4-way Crossover filter (6 LR4 Filters).
*
* o---- LR4 LO-PASS --> y1(n)
* |
* o--- LR4 LO-PASS --o
* | |
* | o--- LR4 HI-PASS --> y2(n)
* x(n) --- o
* | o--- LR4 LO-PASS --> y3(n)
* | |
* o--- LR4 HI-PASS --o
* |
* o--- LR4 HI-PASS --> y4(n)
*
* Refer to include/user/crossover.h for diagrams of 2-way and 3-way crossovers
* The low and high pass LR4 filters have opposite phase responses, causing
* the intermediary outputs to be out of phase by 180 degrees.
* For 2-way and 3-way, the phases of the signals need to be synchronized.
*
* Each LR4 is made of two butterworth filters in series with the same params.
*
* x(n) --> BIQUAD --> z(n) --> BIQUAD --> y(n)
*
* In total, we keep track of the state of at most 6 IIRs each made of two
* biquads in series.
*
*/
/**
* Stores the state of one channel of the Crossover filter
*/
struct crossover_state {
/* Store the state for each LR4 filter. */
struct iir_state_df2t lowpass[CROSSOVER_MAX_LR4];
struct iir_state_df2t highpass[CROSSOVER_MAX_LR4];
};
struct comp_data;
typedef void (*crossover_process)(struct comp_data *cd,
struct input_stream_buffer *bsource,
struct output_stream_buffer *bsinks[],
int32_t num_sinks,
uint32_t frames);
typedef void (*crossover_split)(int32_t in, int32_t out[],
struct crossover_state *state);
/* Crossover component private data */
struct comp_data {
/**< filter state */
struct crossover_state state[PLATFORM_MAX_CHANNELS];
#if CONFIG_IPC_MAJOR_4
uint32_t output_pin_index[SOF_CROSSOVER_MAX_STREAMS];
uint32_t num_output_pins;
#endif
struct comp_data_blob_handler *model_handler;
struct sof_crossover_config *config; /**< pointer to setup blob */
enum sof_ipc_frame source_format; /**< source frame format */
crossover_process crossover_process; /**< processing function */
crossover_split crossover_split; /**< split function */
};
struct crossover_proc_fnmap {
enum sof_ipc_frame frame_fmt;
crossover_process crossover_proc_func;
};
extern const struct crossover_proc_fnmap crossover_proc_fnmap[];
extern const struct crossover_proc_fnmap crossover_proc_fnmap_pass[];
extern const size_t crossover_proc_fncount;
/**
* \brief Returns Crossover processing function.
*/
static inline crossover_process
crossover_find_proc_func(enum sof_ipc_frame src_fmt)
{
int i;
/* Find suitable processing function from map */
for (i = 0; i < crossover_proc_fncount; i++)
if (src_fmt == crossover_proc_fnmap[i].frame_fmt)
return crossover_proc_fnmap[i].crossover_proc_func;
return NULL;
}
/**
* \brief Returns Crossover passthrough functions.
*/
static inline crossover_process
crossover_find_proc_func_pass(enum sof_ipc_frame src_fmt)
{
int i;
/* Find suitable processing function from map */
for (i = 0; i < crossover_proc_fncount; i++)
if (src_fmt == crossover_proc_fnmap_pass[i].frame_fmt)
return crossover_proc_fnmap_pass[i].crossover_proc_func;
return NULL;
}
extern const crossover_split crossover_split_fnmap[];
extern const size_t crossover_split_fncount;
/**
* \brief Returns Crossover split function.
*/
static inline crossover_split crossover_find_split_func(int32_t num_sinks)
{
if (num_sinks < CROSSOVER_2WAY_NUM_SINKS ||
num_sinks > CROSSOVER_4WAY_NUM_SINKS)
return NULL;
// The functions in the map are offset by 2 indices.
return crossover_split_fnmap[num_sinks - CROSSOVER_2WAY_NUM_SINKS];
}
/*
* \brief Runs input in through the LR4 filter and returns it's output.
*/
static inline int32_t crossover_generic_process_lr4(int32_t in,
struct iir_state_df2t *lr4)
{
/* Cascade two biquads with same coefficients in series. */
return iir_df2t(lr4, in);
}
#endif // __SOF_AUDIO_CROSSOVER_CROSSOVER_H__