summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/alsa/alsa-lib/0001-pcm-route-Use-get32-for-multi-source-route-calculati.patch
blob: 89363d55d216bc56468578e7b542e7f2a83656ac (plain)
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
From 3f179d6cc7c222dfa42fe094b7ef1e21685a05bc Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 22 Jul 2014 11:55:40 +0200
Subject: [PATCH] pcm: route: Use get32 for multi-source route calculation

The PCM route plugin can assign the destination value from average of
multiple sources with attenuation. This requires the read of each
channel value, sums and writes the resultant value in the requested
format.

Currently, get_labels is used for reading source values while
put32_labels is used for writing the dest value.  This is, however,
a buggy implementation; get_labels gives the value as is only with
endianness and signedness conversions, but put32_labels assumes that
the value is normalized to 32bit int and it shifts down to the dest
format.  In addition, the current code lacks get_labels entries for
the 24bit formats, as Shengjiu Wang spotted out.

For fixing these bugs, this patch replaces the read with
get32_labels and use always 64bit int for sum.  This simplifies the
code a lot and drops many lines.

Commit fd84adc63e307572d05274be44c782a787087cda in master branch

Upstream Status: Backported

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/pcm/pcm_route.c  |  128 +++++++++-----------------------------------------
 src/pcm/plugin_ops.h |   81 --------------------------------
 2 files changed, 23 insertions(+), 186 deletions(-)

diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
index 2beedf6..1ed9c5f 100644
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -60,7 +60,7 @@ typedef struct {
 typedef struct snd_pcm_route_ttable_dst snd_pcm_route_ttable_dst_t;
 
 typedef struct {
-	enum {UINT32=0, UINT64=1, FLOAT=2} sum_idx;
+	enum {UINT64, FLOAT} sum_idx;
 	unsigned int get_idx;
 	unsigned int put_idx;
 	unsigned int conv_idx;
@@ -232,55 +232,34 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 					const snd_pcm_route_ttable_dst_t* ttable,
 					const snd_pcm_route_params_t *params)
 {
-#define GETS_LABELS
+#define GET32_LABELS
 #define PUT32_LABELS
 #include "plugin_ops.h"
-#undef GETS_LABELS
+#undef GET32_LABELS
 #undef PUT32_LABELS
-	static void *const zero_labels[3] = {
-		&&zero_int32, &&zero_int64,
+	static void *const zero_labels[2] = {
+		&&zero_int64,
 #if SND_PCM_PLUGIN_ROUTE_FLOAT
 		&&zero_float
 #endif
 	};
 	/* sum_type att */
-	static void *const add_labels[3 * 2] = {
-		&&add_int32_noatt, &&add_int32_att,
+	static void *const add_labels[2 * 2] = {
 		&&add_int64_noatt, &&add_int64_att,
 #if SND_PCM_PLUGIN_ROUTE_FLOAT
 		&&add_float_noatt, &&add_float_att
 #endif
 	};
-	/* sum_type att shift */
-	static void *const norm_labels[3 * 2 * 4] = {
-		0,
-		&&norm_int32_8_noatt,
-		&&norm_int32_16_noatt,
-		&&norm_int32_24_noatt,
-		0,
-		&&norm_int32_8_att,
-		&&norm_int32_16_att,
-		&&norm_int32_24_att,
-		&&norm_int64_0_noatt,
-		&&norm_int64_8_noatt,
-		&&norm_int64_16_noatt,
-		&&norm_int64_24_noatt,
-		&&norm_int64_0_att,
-		&&norm_int64_8_att,
-		&&norm_int64_16_att,
-		&&norm_int64_24_att,
+	/* sum_type att */
+	static void *const norm_labels[2 * 2] = {
+		&&norm_int64_noatt,
+		&&norm_int64_att,
 #if SND_PCM_PLUGIN_ROUTE_FLOAT
-		&&norm_float_0,
-		&&norm_float_8,
-		&&norm_float_16,
-		&&norm_float_24,
-		&&norm_float_0,
-		&&norm_float_8,
-		&&norm_float_16,
-		&&norm_float_24,
+		&&norm_float,
+		&&norm_float,
 #endif
 	};
-	void *zero, *get, *add, *norm, *put32;
+	void *zero, *get32, *add, *norm, *put32;
 	int nsrcs = ttable->nsrcs;
 	char *dst;
 	int dst_step;
@@ -322,9 +301,9 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 	}
 
 	zero = zero_labels[params->sum_idx];
-	get = gets_labels[params->get_idx];
+	get32 = get32_labels[params->get_idx];
 	add = add_labels[params->sum_idx * 2 + ttable->att];
-	norm = norm_labels[params->sum_idx * 8 + ttable->att * 4 + 4 - params->src_size];
+	norm = norm_labels[params->sum_idx * 2 + ttable->att];
 	put32 = put32_labels[params->put_idx];
 	dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
 	dst_step = snd_pcm_channel_area_step(dst_area);
@@ -335,9 +314,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 
 		/* Zero sum */
 		goto *zero;
-	zero_int32:
-		sum.as_sint32 = 0;
-		goto zero_end;
 	zero_int64: 
 		sum.as_sint64 = 0;
 		goto zero_end;
@@ -351,21 +327,14 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 			const char *src = srcs[srcidx];
 			
 			/* Get sample */
-			goto *get;
-#define GETS_END after_get
+			goto *get32;
+#define GET32_END after_get
 #include "plugin_ops.h"
-#undef GETS_END
+#undef GET32_END
 		after_get:
 
 			/* Sum */
 			goto *add;
-		add_int32_att:
-			sum.as_sint32 += sample * ttp->as_int;
-			goto after_sum;
-		add_int32_noatt:
-			if (ttp->as_int)
-				sum.as_sint32 += sample;
-			goto after_sum;
 		add_int64_att:
 			sum.as_sint64 += (int64_t) sample * ttp->as_int;
 			goto after_sum;
@@ -389,48 +358,10 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 		
 		/* Normalization */
 		goto *norm;
-	norm_int32_8_att:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_8_att:
-		sum.as_sint64 <<= 8;
-	norm_int64_0_att:
-		div(sum.as_sint64);
-		goto norm_int;
-
-	norm_int32_16_att:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_16_att:
-		sum.as_sint64 <<= 16;
+	norm_int64_att:
 		div(sum.as_sint64);
-		goto norm_int;
-
-	norm_int32_24_att:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_24_att:
-		sum.as_sint64 <<= 24;
-		div(sum.as_sint64);
-		goto norm_int;
-
-	norm_int32_8_noatt:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_8_noatt:
-		sum.as_sint64 <<= 8;
-		goto norm_int;
-
-	norm_int32_16_noatt:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_16_noatt:
-		sum.as_sint64 <<= 16;
-		goto norm_int;
-
-	norm_int32_24_noatt:
-		sum.as_sint64 = sum.as_sint32;
-	norm_int64_24_noatt:
-		sum.as_sint64 <<= 24;
-		goto norm_int;
-
-	norm_int64_0_noatt:
-	norm_int:
+		/* fallthru */
+	norm_int64_noatt:
 		if (sum.as_sint64 > (int64_t)0x7fffffff)
 			sample = 0x7fffffff;	/* maximum positive value */
 		else if (sum.as_sint64 < -(int64_t)0x80000000)
@@ -440,16 +371,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 		goto after_norm;
 
 #if SND_PCM_PLUGIN_ROUTE_FLOAT
-	norm_float_8:
-		sum.as_float *= 1 << 8;
-		goto norm_float;
-	norm_float_16:
-		sum.as_float *= 1 << 16;
-		goto norm_float;
-	norm_float_24:
-		sum.as_float *= 1 << 24;
-		goto norm_float;
-	norm_float_0:
 	norm_float:
 		sum.as_float = rint(sum.as_float);
 		if (sum.as_float > (int64_t)0x7fffffff)
@@ -644,7 +565,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
 		return err;
 	route->params.use_getput = snd_pcm_format_physical_width(src_format) == 24 ||
 		snd_pcm_format_physical_width(dst_format) == 24;
-	route->params.get_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S16);
+	route->params.get_idx = snd_pcm_linear_get32_index(src_format, SND_PCM_FORMAT_S32);
 	route->params.put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format);
 	route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format);
 	route->params.src_size = snd_pcm_format_width(src_format) / 8;
@@ -652,10 +573,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
 #if SND_PCM_PLUGIN_ROUTE_FLOAT
 	route->params.sum_idx = FLOAT;
 #else
-	if (snd_pcm_format_width(src_format) == 32)
-		route->params.sum_idx = UINT64;
-	else
-		route->params.sum_idx = UINT32;
+	route->params.sum_idx = UINT64;
 #endif
 	return 0;
 }
diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h
index 21535c9..eb8c2c4 100644
--- a/src/pcm/plugin_ops.h
+++ b/src/pcm/plugin_ops.h
@@ -668,87 +668,6 @@ getu_1234_C321: sample = bswap_32(as_u32c(src) ^ 0x80); goto GETU_END;
 }
 #endif
 
-#ifdef GETS_LABELS
-/* width endswap sign_toggle */
-static void *const gets_labels[4 * 2 * 2] = {
-	&&gets_1_1,		/*  8h ->  8h */
-	&&gets_1_9,		/*  8h ^>  8h */
-	&&gets_1_1,		/*  8s ->  8h */
-	&&gets_1_9,		/*  8s ^>  8h */
-	&&gets_12_12,		/* 16h -> 16h */
-	&&gets_12_92,		/* 16h ^> 16h */
-	&&gets_12_21,		/* 16s -> 16h */
-	&&gets_12_A1,		/* 16s ^> 16h */
-	&&gets_0123_0123,	/* 24h -> 24h */
-	&&gets_0123_0923,	/* 24h ^> 24h */
-	&&gets_1230_0321,	/* 24s -> 24h */
-	&&gets_1230_0B21,	/* 24s ^> 24h */
-	&&gets_1234_1234,	/* 32h -> 32h */
-	&&gets_1234_9234,	/* 32h ^> 32h */
-	&&gets_1234_4321,	/* 32s -> 32h */
-	&&gets_1234_C321,	/* 32s ^> 32h */
-};
-#endif
-
-#ifdef GETS_END
-while (0) {
-gets_1_1: sample = as_s8c(src); goto GETS_END;
-gets_1_9: sample = (int8_t)(as_s8c(src) ^ 0x80); goto GETS_END;
-gets_12_12: sample = as_s16c(src); goto GETS_END;
-gets_12_92: sample = (int16_t)(as_s16c(src) ^ 0x8000); goto GETS_END;
-gets_12_21: sample = (int16_t)bswap_16(as_s16c(src)); goto GETS_END;
-gets_12_A1: sample = (int16_t)bswap_16(as_s16c(src) ^ 0x80); goto GETS_END;
-gets_0123_0123: sample = sx24((int32_t)(as_s32c(src) << 8) >> 8); goto GETS_END;
-gets_0123_0923: sample = sx24((int32_t)((as_s32c(src) ^ 0x800000) << 8) >> 8); goto GETS_END;
-gets_1230_0321: sample = sx24((int32_t)(bswap_32(as_s32c(src)) << 8) >> 8); goto GETS_END;
-gets_1230_0B21: sample = sx24((int32_t)(bswap_32(as_s32c(src) ^ 0x8000) << 8) >> 8); goto GETS_END;
-gets_1234_1234: sample = as_s32c(src); goto GETS_END;
-gets_1234_9234: sample = (int32_t)(as_s32c(src) ^ 0x80000000); goto GETS_END;
-gets_1234_4321: sample = (int32_t)bswap_32(as_s32c(src)); goto GETS_END;
-gets_1234_C321: sample = (int32_t)bswap_32(as_s32c(src) ^ 0x80); goto GETS_END;
-}
-#endif
-
-#ifdef PUT_LABELS
-/* width endswap sign_toggle */
-static void *const put_labels[4 * 2 * 2] = {
-	&&put_1_1,		/*  8h ->  8h */
-	&&put_1_9,		/*  8h ^>  8h */
-	&&put_1_1,		/*  8h ->  8s */
-	&&put_1_9,		/*  8h ^>  8s */
-	&&put_12_12,		/* 16h -> 16h */
-	&&put_12_92,		/* 16h ^> 16h */
-	&&put_12_21,		/* 16h -> 16s */
-	&&put_12_29,		/* 16h ^> 16s */
-	&&put_0123_0123,	/* 24h -> 24h */
-	&&put_0123_0923,	/* 24h ^> 24h */
-	&&put_0123_3210,	/* 24h -> 24s */
-	&&put_0123_3290,	/* 24h ^> 24s */
-	&&put_1234_1234,	/* 32h -> 32h */
-	&&put_1234_9234,	/* 32h ^> 32h */
-	&&put_1234_4321,	/* 32h -> 32s */
-	&&put_1234_4329,	/* 32h ^> 32s */
-};
-#endif
-
-#ifdef PUT_END
-put_1_1: as_s8(dst) = sample; goto PUT_END;
-put_1_9: as_u8(dst) = sample ^ 0x80; goto PUT_END;
-put_12_12: as_s16(dst) = sample; goto PUT_END;
-put_12_92: as_u16(dst) = sample ^ 0x8000; goto PUT_END;
-put_12_21: as_s16(dst) = bswap_16(sample); goto PUT_END;
-put_12_29: as_u16(dst) = bswap_16(sample) ^ 0x80; goto PUT_END;
-/* this always writes the unused byte in 24-bit formats as 0x00 */
-put_0123_0123: as_s32(dst) = sx24(sample & 0x00ffffff); goto PUT_END;
-put_0123_0923: as_u32(dst) = sx24((sample & 0x00ffffff) ^ 0x800000); goto PUT_END;
-put_0123_3210: as_s32(dst) = sx24s(bswap_32(sample) & 0xffffff00); goto PUT_END;
-put_0123_3290: as_u32(dst) = sx24s((bswap_32(sample) & 0xffffff00) ^ 0x8000); goto PUT_END;
-put_1234_1234: as_s32(dst) = sample; goto PUT_END;
-put_1234_9234: as_u32(dst) = sample ^ 0x80000000; goto PUT_END;
-put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END;
-put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
-#endif
-
 #ifdef PUT32F_LABELS
 /* type (0 = float, 1 = float64), endswap */
 static void *const put32float_labels[2 * 2] = {
-- 
1.7.9.5