1 From 3f179d6cc7c222dfa42fe094b7ef1e21685a05bc Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Tue, 22 Jul 2014 11:55:40 +0200
4 Subject: [PATCH] pcm: route: Use get32 for multi-source route calculation
6 The PCM route plugin can assign the destination value from average of
7 multiple sources with attenuation. This requires the read of each
8 channel value, sums and writes the resultant value in the requested
11 Currently, get_labels is used for reading source values while
12 put32_labels is used for writing the dest value. This is, however,
13 a buggy implementation; get_labels gives the value as is only with
14 endianness and signedness conversions, but put32_labels assumes that
15 the value is normalized to 32bit int and it shifts down to the dest
16 format. In addition, the current code lacks get_labels entries for
17 the 24bit formats, as Shengjiu Wang spotted out.
19 For fixing these bugs, this patch replaces the read with
20 get32_labels and use always 64bit int for sum. This simplifies the
21 code a lot and drops many lines.
23 Commit fd84adc63e307572d05274be44c782a787087cda in master branch
25 Upstream Status: Backported
27 Signed-off-by: Takashi Iwai <tiwai@suse.de>
29 src/pcm/pcm_route.c | 128 +++++++++-----------------------------------------
30 src/pcm/plugin_ops.h | 81 --------------------------------
31 2 files changed, 23 insertions(+), 186 deletions(-)
33 diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
34 index 2beedf6..1ed9c5f 100644
35 --- a/src/pcm/pcm_route.c
36 +++ b/src/pcm/pcm_route.c
37 @@ -60,7 +60,7 @@ typedef struct {
38 typedef struct snd_pcm_route_ttable_dst snd_pcm_route_ttable_dst_t;
41 - enum {UINT32=0, UINT64=1, FLOAT=2} sum_idx;
42 + enum {UINT64, FLOAT} sum_idx;
45 unsigned int conv_idx;
46 @@ -232,55 +232,34 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
47 const snd_pcm_route_ttable_dst_t* ttable,
48 const snd_pcm_route_params_t *params)
53 #include "plugin_ops.h"
57 - static void *const zero_labels[3] = {
58 - &&zero_int32, &&zero_int64,
59 + static void *const zero_labels[2] = {
61 #if SND_PCM_PLUGIN_ROUTE_FLOAT
66 - static void *const add_labels[3 * 2] = {
67 - &&add_int32_noatt, &&add_int32_att,
68 + static void *const add_labels[2 * 2] = {
69 &&add_int64_noatt, &&add_int64_att,
70 #if SND_PCM_PLUGIN_ROUTE_FLOAT
71 &&add_float_noatt, &&add_float_att
74 - /* sum_type att shift */
75 - static void *const norm_labels[3 * 2 * 4] = {
77 - &&norm_int32_8_noatt,
78 - &&norm_int32_16_noatt,
79 - &&norm_int32_24_noatt,
82 - &&norm_int32_16_att,
83 - &&norm_int32_24_att,
84 - &&norm_int64_0_noatt,
85 - &&norm_int64_8_noatt,
86 - &&norm_int64_16_noatt,
87 - &&norm_int64_24_noatt,
90 - &&norm_int64_16_att,
91 - &&norm_int64_24_att,
93 + static void *const norm_labels[2 * 2] = {
96 #if SND_PCM_PLUGIN_ROUTE_FLOAT
109 - void *zero, *get, *add, *norm, *put32;
110 + void *zero, *get32, *add, *norm, *put32;
111 int nsrcs = ttable->nsrcs;
114 @@ -322,9 +301,9 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
117 zero = zero_labels[params->sum_idx];
118 - get = gets_labels[params->get_idx];
119 + get32 = get32_labels[params->get_idx];
120 add = add_labels[params->sum_idx * 2 + ttable->att];
121 - norm = norm_labels[params->sum_idx * 8 + ttable->att * 4 + 4 - params->src_size];
122 + norm = norm_labels[params->sum_idx * 2 + ttable->att];
123 put32 = put32_labels[params->put_idx];
124 dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
125 dst_step = snd_pcm_channel_area_step(dst_area);
126 @@ -335,9 +314,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
136 @@ -351,21 +327,14 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
137 const char *src = srcs[srcidx];
141 -#define GETS_END after_get
143 +#define GET32_END after_get
144 #include "plugin_ops.h"
152 - sum.as_sint32 += sample * ttp->as_int;
156 - sum.as_sint32 += sample;
159 sum.as_sint64 += (int64_t) sample * ttp->as_int;
161 @@ -389,48 +358,10 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
166 - sum.as_sint64 = sum.as_sint32;
168 - sum.as_sint64 <<= 8;
170 - div(sum.as_sint64);
174 - sum.as_sint64 = sum.as_sint32;
176 - sum.as_sint64 <<= 16;
182 - sum.as_sint64 = sum.as_sint32;
184 - sum.as_sint64 <<= 24;
185 - div(sum.as_sint64);
188 - norm_int32_8_noatt:
189 - sum.as_sint64 = sum.as_sint32;
190 - norm_int64_8_noatt:
191 - sum.as_sint64 <<= 8;
194 - norm_int32_16_noatt:
195 - sum.as_sint64 = sum.as_sint32;
196 - norm_int64_16_noatt:
197 - sum.as_sint64 <<= 16;
200 - norm_int32_24_noatt:
201 - sum.as_sint64 = sum.as_sint32;
202 - norm_int64_24_noatt:
203 - sum.as_sint64 <<= 24;
206 - norm_int64_0_noatt:
210 if (sum.as_sint64 > (int64_t)0x7fffffff)
211 sample = 0x7fffffff; /* maximum positive value */
212 else if (sum.as_sint64 < -(int64_t)0x80000000)
213 @@ -440,16 +371,6 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
216 #if SND_PCM_PLUGIN_ROUTE_FLOAT
218 - sum.as_float *= 1 << 8;
221 - sum.as_float *= 1 << 16;
224 - sum.as_float *= 1 << 24;
228 sum.as_float = rint(sum.as_float);
229 if (sum.as_float > (int64_t)0x7fffffff)
230 @@ -644,7 +565,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
232 route->params.use_getput = snd_pcm_format_physical_width(src_format) == 24 ||
233 snd_pcm_format_physical_width(dst_format) == 24;
234 - route->params.get_idx = snd_pcm_linear_get_index(src_format, SND_PCM_FORMAT_S16);
235 + route->params.get_idx = snd_pcm_linear_get32_index(src_format, SND_PCM_FORMAT_S32);
236 route->params.put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, dst_format);
237 route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format);
238 route->params.src_size = snd_pcm_format_width(src_format) / 8;
239 @@ -652,10 +573,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
240 #if SND_PCM_PLUGIN_ROUTE_FLOAT
241 route->params.sum_idx = FLOAT;
243 - if (snd_pcm_format_width(src_format) == 32)
244 - route->params.sum_idx = UINT64;
246 - route->params.sum_idx = UINT32;
247 + route->params.sum_idx = UINT64;
251 diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h
252 index 21535c9..eb8c2c4 100644
253 --- a/src/pcm/plugin_ops.h
254 +++ b/src/pcm/plugin_ops.h
255 @@ -668,87 +668,6 @@ getu_1234_C321: sample = bswap_32(as_u32c(src) ^ 0x80); goto GETU_END;
260 -/* width endswap sign_toggle */
261 -static void *const gets_labels[4 * 2 * 2] = {
262 - &&gets_1_1, /* 8h -> 8h */
263 - &&gets_1_9, /* 8h ^> 8h */
264 - &&gets_1_1, /* 8s -> 8h */
265 - &&gets_1_9, /* 8s ^> 8h */
266 - &&gets_12_12, /* 16h -> 16h */
267 - &&gets_12_92, /* 16h ^> 16h */
268 - &&gets_12_21, /* 16s -> 16h */
269 - &&gets_12_A1, /* 16s ^> 16h */
270 - &&gets_0123_0123, /* 24h -> 24h */
271 - &&gets_0123_0923, /* 24h ^> 24h */
272 - &&gets_1230_0321, /* 24s -> 24h */
273 - &&gets_1230_0B21, /* 24s ^> 24h */
274 - &&gets_1234_1234, /* 32h -> 32h */
275 - &&gets_1234_9234, /* 32h ^> 32h */
276 - &&gets_1234_4321, /* 32s -> 32h */
277 - &&gets_1234_C321, /* 32s ^> 32h */
283 -gets_1_1: sample = as_s8c(src); goto GETS_END;
284 -gets_1_9: sample = (int8_t)(as_s8c(src) ^ 0x80); goto GETS_END;
285 -gets_12_12: sample = as_s16c(src); goto GETS_END;
286 -gets_12_92: sample = (int16_t)(as_s16c(src) ^ 0x8000); goto GETS_END;
287 -gets_12_21: sample = (int16_t)bswap_16(as_s16c(src)); goto GETS_END;
288 -gets_12_A1: sample = (int16_t)bswap_16(as_s16c(src) ^ 0x80); goto GETS_END;
289 -gets_0123_0123: sample = sx24((int32_t)(as_s32c(src) << 8) >> 8); goto GETS_END;
290 -gets_0123_0923: sample = sx24((int32_t)((as_s32c(src) ^ 0x800000) << 8) >> 8); goto GETS_END;
291 -gets_1230_0321: sample = sx24((int32_t)(bswap_32(as_s32c(src)) << 8) >> 8); goto GETS_END;
292 -gets_1230_0B21: sample = sx24((int32_t)(bswap_32(as_s32c(src) ^ 0x8000) << 8) >> 8); goto GETS_END;
293 -gets_1234_1234: sample = as_s32c(src); goto GETS_END;
294 -gets_1234_9234: sample = (int32_t)(as_s32c(src) ^ 0x80000000); goto GETS_END;
295 -gets_1234_4321: sample = (int32_t)bswap_32(as_s32c(src)); goto GETS_END;
296 -gets_1234_C321: sample = (int32_t)bswap_32(as_s32c(src) ^ 0x80); goto GETS_END;
301 -/* width endswap sign_toggle */
302 -static void *const put_labels[4 * 2 * 2] = {
303 - &&put_1_1, /* 8h -> 8h */
304 - &&put_1_9, /* 8h ^> 8h */
305 - &&put_1_1, /* 8h -> 8s */
306 - &&put_1_9, /* 8h ^> 8s */
307 - &&put_12_12, /* 16h -> 16h */
308 - &&put_12_92, /* 16h ^> 16h */
309 - &&put_12_21, /* 16h -> 16s */
310 - &&put_12_29, /* 16h ^> 16s */
311 - &&put_0123_0123, /* 24h -> 24h */
312 - &&put_0123_0923, /* 24h ^> 24h */
313 - &&put_0123_3210, /* 24h -> 24s */
314 - &&put_0123_3290, /* 24h ^> 24s */
315 - &&put_1234_1234, /* 32h -> 32h */
316 - &&put_1234_9234, /* 32h ^> 32h */
317 - &&put_1234_4321, /* 32h -> 32s */
318 - &&put_1234_4329, /* 32h ^> 32s */
323 -put_1_1: as_s8(dst) = sample; goto PUT_END;
324 -put_1_9: as_u8(dst) = sample ^ 0x80; goto PUT_END;
325 -put_12_12: as_s16(dst) = sample; goto PUT_END;
326 -put_12_92: as_u16(dst) = sample ^ 0x8000; goto PUT_END;
327 -put_12_21: as_s16(dst) = bswap_16(sample); goto PUT_END;
328 -put_12_29: as_u16(dst) = bswap_16(sample) ^ 0x80; goto PUT_END;
329 -/* this always writes the unused byte in 24-bit formats as 0x00 */
330 -put_0123_0123: as_s32(dst) = sx24(sample & 0x00ffffff); goto PUT_END;
331 -put_0123_0923: as_u32(dst) = sx24((sample & 0x00ffffff) ^ 0x800000); goto PUT_END;
332 -put_0123_3210: as_s32(dst) = sx24s(bswap_32(sample) & 0xffffff00); goto PUT_END;
333 -put_0123_3290: as_u32(dst) = sx24s((bswap_32(sample) & 0xffffff00) ^ 0x8000); goto PUT_END;
334 -put_1234_1234: as_s32(dst) = sample; goto PUT_END;
335 -put_1234_9234: as_u32(dst) = sample ^ 0x80000000; goto PUT_END;
336 -put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END;
337 -put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
341 /* type (0 = float, 1 = float64), endswap */
342 static void *const put32float_labels[2 * 2] = {