1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2020 Intel Corporation. All rights reserved.
4 *
5 * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
6 */
7
8 #ifndef __SOF_AUDIO_TDFB_CONFIG_H__
9 #define __SOF_AUDIO_TDFB_CONFIG_H__
10
11 #include <sof/audio/module_adapter/module/generic.h>
12 #include <sof/audio/audio_stream.h>
13 #include <sof/math/fir_generic.h>
14 #include <sof/math/fir_hifi2ep.h>
15 #include <sof/math/fir_hifi3.h>
16 #include <sof/math/iir_df1.h>
17 #include <sof/platform.h>
18 #include <user/tdfb.h>
19
20 /* Select optimized code variant when xt-xcc compiler is used */
21 #if defined __XCC__
22 #include <xtensa/config/core-isa.h>
23 #if XCHAL_HAVE_HIFI2EP == 1
24 #define TDFB_GENERIC 0
25 #define TDFB_HIFIEP 1
26 #define TDFB_HIFI3 0
27 #elif XCHAL_HAVE_HIFI3 == 1
28 #define TDFB_HIFI3 1
29 #define TDFB_HIFIEP 0
30 #define TDFB_GENERIC 0
31 #else
32 #error "No HIFIEP or HIFI3 found. Cannot build TDFB module."
33 #endif
34 #else
35 /* GCC */
36 #define TDFB_GENERIC 1
37 #define TDFB_HIFIEP 0
38 #define TDFB_HIFI3 0
39 #endif
40
41 #define TDFB_IN_BUF_LENGTH (2 * PLATFORM_MAX_CHANNELS)
42 #define TDFB_OUT_BUF_LENGTH (2 * PLATFORM_MAX_CHANNELS)
43
44 /* When set to one only one IPC is sent to host. There is not other requests
45 * triggered. If set to zero the IPC sent will be empty and the driver will
46 * issue an actual control get. In simple case with known # of control channels
47 * including is more efficient.
48 */
49 #define TDFB_ADD_DIRECTION_TO_GET_CMD 1
50
51 /* Allocate size is header plus single control value */
52 #define TDFB_GET_CTRL_DATA_SIZE (sizeof(struct sof_ipc_ctrl_data) + \
53 sizeof(struct sof_ipc_ctrl_value_chan))
54
55 /* Process max 10% more frames than one period */
56 #define TDFB_MAX_FRAMES_MULT_Q14 Q_CONVERT_FLOAT(1.10, 14)
57
58 /* TDFB component private data */
59
60 struct tdfb_direction_data {
61 struct iir_state_df1 emphasis[PLATFORM_MAX_CHANNELS];
62 int32_t timediff[PLATFORM_MAX_CHANNELS];
63 int32_t timediff_iter[PLATFORM_MAX_CHANNELS];
64 int64_t level_ambient;
65 uint32_t trigger;
66 int32_t level;
67 int32_t unit_delay; /* Q1.31 seconds */
68 int32_t frame_count_since_control;
69 int32_t *df1_delay;
70 int32_t *r;
71 int16_t *d;
72 int16_t *d_end;
73 int16_t *wp;
74 int16_t *rp;
75 int16_t step_sign;
76 int16_t az_slow;
77 int16_t az;
78 int16_t max_lag;
79 size_t d_size;
80 size_t r_size;
81 bool line_array; /* Limit scan to -90 to 90 degrees */
82 };
83
84 struct tdfb_comp_data {
85 struct fir_state_32x16 fir[SOF_TDFB_FIR_MAX_COUNT]; /**< FIR state */
86 struct comp_data_blob_handler *model_handler;
87 struct sof_tdfb_config *config; /**< pointer to setup blob */
88 struct sof_tdfb_angle *filter_angles;
89 struct sof_tdfb_mic_location *mic_locations;
90 struct sof_ipc_ctrl_data *ctrl_data;
91 struct ipc_msg *msg;
92 struct tdfb_direction_data direction;
93 int32_t in[TDFB_IN_BUF_LENGTH]; /**< input samples buffer */
94 int32_t out[TDFB_IN_BUF_LENGTH]; /**< output samples mix buffer */
95 int32_t *fir_delay; /**< pointer to allocated RAM */
96 int16_t *input_channel_select; /**< For each FIR define in ch */
97 int16_t *output_channel_mix; /**< For each FIR define out ch */
98 int16_t *output_stream_mix; /**< for each FIR define stream */
99 int16_t az_value; /**< beam steer azimuth as in control enum */
100 int16_t az_value_estimate; /**< beam steer azimuth as in control enum */
101 size_t fir_delay_size; /**< allocated size */
102 unsigned int max_frames; /**< max frames to process */
103 bool direction_updates:1; /**< set true if direction angle control is updated */
104 bool direction_change:1; /**< set if direction value has significant change */
105 bool beam_on:1; /**< set true if beam is off */
106 bool update:1; /**< set true if control enum has been received */
107 void (*tdfb_func)(struct tdfb_comp_data *cd,
108 struct input_stream_buffer *bsource,
109 struct output_stream_buffer *bsink,
110 int frames);
111 };
112
113 #if CONFIG_FORMAT_S16LE
114 void tdfb_fir_s16(struct tdfb_comp_data *cd,
115 struct input_stream_buffer *bsource,
116 struct output_stream_buffer *bsink, int frames);
117 #endif
118
119 #if CONFIG_FORMAT_S24LE
120 void tdfb_fir_s24(struct tdfb_comp_data *cd,
121 struct input_stream_buffer *bsource,
122 struct output_stream_buffer *bsink, int frames);
123 #endif
124
125 #if CONFIG_FORMAT_S32LE
126 void tdfb_fir_s32(struct tdfb_comp_data *cd,
127 struct input_stream_buffer *bsource,
128 struct output_stream_buffer *bsink, int frames);
129 #endif
130
131 int tdfb_direction_init(struct tdfb_comp_data *cd, int32_t fs, int channels);
132 void tdfb_direction_copy_emphasis(struct tdfb_comp_data *cd, int channels, int *channel, int32_t x);
133 void tdfb_direction_estimate(struct tdfb_comp_data *cd, int frames, int channels);
134 void tdfb_direction_free(struct tdfb_comp_data *cd);
135
tdfb_cinc_s16(int16_t ** ptr,int16_t * end,size_t size)136 static inline void tdfb_cinc_s16(int16_t **ptr, int16_t *end, size_t size)
137 {
138 if (*ptr >= end)
139 *ptr = (int16_t *)((uint8_t *)*ptr - size);
140 }
141
tdfb_cdec_s16(int16_t ** ptr,int16_t * start,size_t size)142 static inline void tdfb_cdec_s16(int16_t **ptr, int16_t *start, size_t size)
143 {
144 if (*ptr < start)
145 *ptr = (int16_t *)((uint8_t *)*ptr + size);
146 }
147
148 #ifdef UNIT_TEST
149 void sys_comp_module_tdfb_interface_init(void);
150 #endif
151
152 #endif /* __SOF_AUDIO_TDFB_CONFIG_H__ */
153