1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 /* non-concurrent version, only supporting little endians */
35 #define generic_dmix_supported_format \
36 ((1ULL << SND_PCM_FORMAT_S16_LE) | (1ULL << SND_PCM_FORMAT_S32_LE) |\
37 (1ULL << SND_PCM_FORMAT_S24_LE) | (1ULL << SND_PCM_FORMAT_S24_3LE) | \
38 (1ULL << SND_PCM_FORMAT_U8))
39
generic_mix_areas_16_native(unsigned int size,volatile signed short * dst,signed short * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)40 static void generic_mix_areas_16_native(unsigned int size,
41 volatile signed short *dst,
42 signed short *src,
43 volatile signed int *sum,
44 size_t dst_step,
45 size_t src_step,
46 size_t sum_step)
47 {
48 register signed int sample;
49
50 for (;;) {
51 sample = *src;
52 if (! *dst) {
53 *sum = sample;
54 *dst = *src;
55 } else {
56 sample += *sum;
57 *sum = sample;
58 if (sample > 0x7fff)
59 sample = 0x7fff;
60 else if (sample < -0x8000)
61 sample = -0x8000;
62 *dst = sample;
63 }
64 if (!--size)
65 return;
66 src = (signed short *) ((char *)src + src_step);
67 dst = (signed short *) ((char *)dst + dst_step);
68 sum = (signed int *) ((char *)sum + sum_step);
69 }
70 }
71
generic_remix_areas_16_native(unsigned int size,volatile signed short * dst,signed short * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)72 static void generic_remix_areas_16_native(unsigned int size,
73 volatile signed short *dst,
74 signed short *src,
75 volatile signed int *sum,
76 size_t dst_step,
77 size_t src_step,
78 size_t sum_step)
79 {
80 register signed int sample;
81
82 for (;;) {
83 sample = *src;
84 if (! *dst) {
85 *sum = -sample;
86 *dst = -sample;
87 } else {
88 *sum = sample = *sum - sample;
89 if (sample > 0x7fff)
90 sample = 0x7fff;
91 else if (sample < -0x8000)
92 sample = -0x8000;
93 *dst = sample;
94 }
95 if (!--size)
96 return;
97 src = (signed short *) ((char *)src + src_step);
98 dst = (signed short *) ((char *)dst + dst_step);
99 sum = (signed int *) ((char *)sum + sum_step);
100 }
101 }
102
generic_mix_areas_32_native(unsigned int size,volatile signed int * dst,signed int * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)103 static void generic_mix_areas_32_native(unsigned int size,
104 volatile signed int *dst,
105 signed int *src,
106 volatile signed int *sum,
107 size_t dst_step,
108 size_t src_step,
109 size_t sum_step)
110 {
111 register signed int sample;
112
113 for (;;) {
114 sample = *src >> 8;
115 if (! *dst) {
116 *sum = sample;
117 *dst = *src;
118 } else {
119 sample += *sum;
120 *sum = sample;
121 if (sample > 0x7fffff)
122 sample = 0x7fffffff;
123 else if (sample < -0x800000)
124 sample = -0x80000000;
125 else
126 sample *= 256;
127 *dst = sample;
128 }
129 if (!--size)
130 return;
131 src = (signed int *) ((char *)src + src_step);
132 dst = (signed int *) ((char *)dst + dst_step);
133 sum = (signed int *) ((char *)sum + sum_step);
134 }
135 }
136
generic_remix_areas_32_native(unsigned int size,volatile signed int * dst,signed int * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)137 static void generic_remix_areas_32_native(unsigned int size,
138 volatile signed int *dst,
139 signed int *src,
140 volatile signed int *sum,
141 size_t dst_step,
142 size_t src_step,
143 size_t sum_step)
144 {
145 register signed int sample;
146
147 for (;;) {
148 sample = *src >> 8;
149 if (! *dst) {
150 *sum = -sample;
151 *dst = -*src;
152 } else {
153 *sum = sample = *sum - sample;
154 if (sample > 0x7fffff)
155 sample = 0x7fffffff;
156 else if (sample < -0x800000)
157 sample = -0x80000000;
158 else
159 sample *= 256;
160 *dst = sample;
161 }
162 if (!--size)
163 return;
164 src = (signed int *) ((char *)src + src_step);
165 dst = (signed int *) ((char *)dst + dst_step);
166 sum = (signed int *) ((char *)sum + sum_step);
167 }
168 }
169
170 /* always little endian */
generic_mix_areas_24(unsigned int size,volatile unsigned char * dst,unsigned char * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)171 static void generic_mix_areas_24(unsigned int size,
172 volatile unsigned char *dst,
173 unsigned char *src,
174 volatile signed int *sum,
175 size_t dst_step,
176 size_t src_step,
177 size_t sum_step)
178 {
179 register signed int sample;
180
181 for (;;) {
182 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
183 if (!(dst[0] | dst[1] | dst[2])) {
184 *sum = sample;
185 } else {
186 sample += *sum;
187 *sum = sample;
188 if (sample > 0x7fffff)
189 sample = 0x7fffff;
190 else if (sample < -0x800000)
191 sample = -0x800000;
192 }
193 dst[0] = sample;
194 dst[1] = sample >> 8;
195 dst[2] = sample >> 16;
196 if (!--size)
197 return;
198 dst += dst_step;
199 src += src_step;
200 sum = (signed int *) ((char *)sum + sum_step);
201 }
202 }
203
generic_remix_areas_24(unsigned int size,volatile unsigned char * dst,unsigned char * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)204 static void generic_remix_areas_24(unsigned int size,
205 volatile unsigned char *dst,
206 unsigned char *src,
207 volatile signed int *sum,
208 size_t dst_step,
209 size_t src_step,
210 size_t sum_step)
211 {
212 register signed int sample;
213
214 for (;;) {
215 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
216 if (!(dst[0] | dst[1] | dst[2])) {
217 sample = -sample;
218 *sum = sample;
219 } else {
220 *sum = sample = *sum - sample;
221 if (sample > 0x7fffff)
222 sample = 0x7fffff;
223 else if (sample < -0x800000)
224 sample = -0x800000;
225 }
226 dst[0] = sample;
227 dst[1] = sample >> 8;
228 dst[2] = sample >> 16;
229 if (!--size)
230 return;
231 dst += dst_step;
232 src += src_step;
233 sum = (signed int *) ((char *)sum + sum_step);
234 }
235 }
236
generic_mix_areas_u8(unsigned int size,volatile unsigned char * dst,unsigned char * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)237 static void generic_mix_areas_u8(unsigned int size,
238 volatile unsigned char *dst,
239 unsigned char *src,
240 volatile signed int *sum,
241 size_t dst_step,
242 size_t src_step,
243 size_t sum_step)
244 {
245 for (;;) {
246 register int sample = *src - 0x80;
247 if (*dst == 0x80) {
248 *sum = sample;
249 } else {
250 sample += *sum;
251 *sum = sample;
252 if (sample > 0x7f)
253 sample = 0x7f;
254 else if (sample < -0x80)
255 sample = -0x80;
256 }
257 *dst = sample + 0x80;
258 if (!--size)
259 return;
260 dst += dst_step;
261 src += src_step;
262 sum = (signed int *) ((char *)sum + sum_step);
263 }
264 }
265
generic_remix_areas_u8(unsigned int size,volatile unsigned char * dst,unsigned char * src,volatile signed int * sum,size_t dst_step,size_t src_step,size_t sum_step)266 static void generic_remix_areas_u8(unsigned int size,
267 volatile unsigned char *dst,
268 unsigned char *src,
269 volatile signed int *sum,
270 size_t dst_step,
271 size_t src_step,
272 size_t sum_step)
273 {
274 for (;;) {
275 register int sample = *src - 0x80;
276 if (*dst == 0x80) {
277 sample = -sample;
278 *sum = sample;
279 } else {
280 *sum = sample = *sum - sample;
281 if (sample > 0x7f)
282 sample = 0x7f;
283 else if (sample < -0x80)
284 sample = -0x80;
285 }
286 *dst = sample + 0x80;
287 if (!--size)
288 return;
289 dst += dst_step;
290 src += src_step;
291 sum = (signed int *) ((char *)sum + sum_step);
292 }
293 }
294
295
generic_mix_select_callbacks(snd_pcm_direct_t * dmix)296 static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
297 {
298 /* only support native version, not support swap version */
299
300 dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native;
301 dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native;
302 dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_native;
303 dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_native;
304
305 dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
306 dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
307 dmix->u.dmix.remix_areas_24 = generic_remix_areas_24;
308 dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8;
309 }
310