forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtemplate-generic.c
More file actions
230 lines (205 loc) · 7.39 KB
/
template-generic.c
File metadata and controls
230 lines (205 loc) · 7.39 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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2025 Intel Corporation.
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/component.h>
#include <sof/audio/sink_api.h>
#include <sof/audio/sink_source_utils.h>
#include <sof/audio/source_api.h>
#include <stdint.h>
#include "template.h"
#if CONFIG_FORMAT_S16LE
/**
* template_comp_s16() - Process S16_LE format.
* @mod: Pointer to module data.
* @source: Source for PCM samples data.
* @sink: Sink for PCM samples data.
* @frames: Number of audio data frames to process.
*
* This is the processing function for 16-bit signed integer PCM formats. The
* audio samples in every frame are re-order to channels order defined in
* component data channel_map[].
*
* Return: Value zero for success, otherwise an error code.
*/
static int template_comp_s16(const struct processing_module *mod,
struct sof_source *source,
struct sof_sink *sink,
uint32_t frames)
{
struct template_comp_comp_data *cd = module_get_private_data(mod);
int16_t *x, *x_start, *x_end;
int16_t *y, *y_start, *y_end;
size_t size;
int x_size, y_size;
int source_samples_without_wrap;
int samples_without_wrap;
int samples = frames * cd->channels;
int bytes = frames * cd->frame_bytes;
int ret;
int ch;
int i;
/* Get pointer to source data in circular buffer, get buffer start and size to
* check for wrap. The size in bytes is converted to number of s16 samples to
* control the samples process loop. If the number of bytes requested is not
* possible, an error is returned.
*/
ret = source_get_data(source, bytes, (void const **)&x, (void const **)&x_start, &size);
if (ret)
return ret;
x_size = size >> 1; /* Bytes to number of s16 samples */
/* Similarly get pointer to sink data in circular buffer, buffer start and size. */
ret = sink_get_buffer(sink, bytes, (void **)&y, (void **)&y_start, &size);
if (ret)
return ret;
y_size = size >> 1; /* Bytes to number of s16 samples */
/* Set helper pointers to buffer end for wrap check. Then loop until all
* samples are processed.
*/
x_end = x_start + x_size;
y_end = y_start + y_size;
while (samples) {
/* Find out samples to process before first wrap or end of data. */
source_samples_without_wrap = x_end - x;
samples_without_wrap = y_end - y;
samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap);
samples_without_wrap = MIN(samples_without_wrap, samples);
/* Since the example processing is for frames of audio channels, process
* with step of channels count.
*/
for (i = 0; i < samples_without_wrap; i += cd->channels) {
/* In inner loop process the frame. As example re-arrange the channels
* as defined in array channel_map[].
*/
for (ch = 0; ch < cd->channels; ch++) {
*y = *(x + cd->channel_map[ch]);
y++;
}
x += cd->channels;
}
/* One of the buffers needs a wrap (or end of data), so check for wrap */
x = (x >= x_end) ? x - x_size : x;
y = (y >= y_end) ? y - y_size : y;
/* Update processed samples count for next loop iteration. */
samples -= samples_without_wrap;
}
/* Update the source and sink for bytes consumed and produced. Return success. */
source_release_data(source, bytes);
sink_commit_buffer(sink, bytes);
return 0;
}
#endif /* CONFIG_FORMAT_S16LE */
#if CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S32LE
/**
* template_comp_s32() - Process S32_LE or S24_4LE format.
* @mod: Pointer to module data.
* @source: Source for PCM samples data.
* @sink: Sink for PCM samples data.
* @frames: Number of audio data frames to process.
*
* Processing function for signed integer 32-bit PCM formats. The same
* function works for s24 and s32 formats since the samples values are
* not modified in computation. The audio samples in every frame are
* re-order to channels order defined in component data channel_map[].
*
* Return: Value zero for success, otherwise an error code.
*/
static int template_comp_s32(const struct processing_module *mod,
struct sof_source *source,
struct sof_sink *sink,
uint32_t frames)
{
struct template_comp_comp_data *cd = module_get_private_data(mod);
int32_t *x, *x_start, *x_end;
int32_t *y, *y_start, *y_end;
size_t size;
int x_size, y_size;
int source_samples_without_wrap;
int samples_without_wrap;
int samples = frames * cd->channels;
int bytes = frames * cd->frame_bytes;
int ret;
int ch;
int i;
/* Get pointer to source data in circular buffer, get buffer start and size to
* check for wrap. The size in bytes is converted to number of s16 samples to
* control the samples process loop. If the number of bytes requested is not
* possible, an error is returned.
*/
ret = source_get_data(source, bytes, (void const **)&x, (void const **)&x_start, &size);
if (ret)
return ret;
x_size = size >> 2; /* Bytes to number of s32 samples */
/* Similarly get pointer to sink data in circular buffer, buffer start and size. */
ret = sink_get_buffer(sink, bytes, (void **)&y, (void **)&y_start, &size);
if (ret)
return ret;
y_size = size >> 2; /* Bytes to number of s32 samples */
/* Set helper pointers to buffer end for wrap check. Then loop until all
* samples are processed.
*/
x_end = x_start + x_size;
y_end = y_start + y_size;
while (samples) {
/* Find out samples to process before first wrap or end of data. */
source_samples_without_wrap = x_end - x;
samples_without_wrap = y_end - y;
samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap);
samples_without_wrap = MIN(samples_without_wrap, samples);
/* Since the example processing is for frames of audio channels, process
* with step of channels count.
*/
for (i = 0; i < samples_without_wrap; i += cd->channels) {
/* In inner loop process the frame. As example re-arrange the channels
* as defined in array channel_map[].
*/
for (ch = 0; ch < cd->channels; ch++) {
*y = *(x + cd->channel_map[ch]);
y++;
}
x += cd->channels;
}
/* One of the buffers needs a wrap (or end of data), so check for wrap */
x = (x >= x_end) ? x - x_size : x;
y = (y >= y_end) ? y - y_size : y;
/* Update processed samples count for next loop iteration. */
samples -= samples_without_wrap;
}
/* Update the source and sink for bytes consumed and produced. Return success. */
source_release_data(source, bytes);
sink_commit_buffer(sink, bytes);
return 0;
}
#endif /* CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S24LE */
/* This struct array defines the used processing functions for
* the PCM formats
*/
const struct template_comp_proc_fnmap template_comp_proc_fnmap[] = {
#if CONFIG_FORMAT_S16LE
{ SOF_IPC_FRAME_S16_LE, template_comp_s16 },
#endif
#if CONFIG_FORMAT_S24LE
{ SOF_IPC_FRAME_S24_4LE, template_comp_s32 },
#endif
#if CONFIG_FORMAT_S32LE
{ SOF_IPC_FRAME_S32_LE, template_comp_s32 },
#endif
};
/**
* template_comp_find_proc_func() - Find suitable processing function.
* @src_fmt: Enum value for PCM format.
*
* This function finds the suitable processing function to use for
* the used PCM format. If not found, return NULL.
*
* Return: Pointer to processing function for the requested PCM format.
*/
template_comp_func template_comp_find_proc_func(enum sof_ipc_frame src_fmt)
{
int i;
/* Find suitable processing function from map */
for (i = 0; i < ARRAY_SIZE(template_comp_proc_fnmap); i++)
if (src_fmt == template_comp_proc_fnmap[i].frame_fmt)
return template_comp_proc_fnmap[i].template_comp_proc_func;
return NULL;
}