1#if 0 2//#if defined(__i386__) || defined(__x86_64__) 3#define LOCK_PREFIX "lock ; " 4#define ARCH_ADD(p,a) \ 5 __asm__ __volatile__(LOCK_PREFIX "addl %1,%0" \ 6 :"=m" (*p) \ 7 :"ir" (a), "m" (*p)) 8struct __xchg_dummy { unsigned long a[100]; }; 9#define __xg(x) ((struct __xchg_dummy *)(x)) 10static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 11 unsigned long new, int size) 12{ 13 unsigned long prev; 14 switch (size) { 15 case 1: 16 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" 17 : "=a"(prev) 18 : "q"(new), "m"(*__xg(ptr)), "0"(old) 19 : "memory"); 20 return prev; 21 case 2: 22 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" 23 : "=a"(prev) 24 : "q"(new), "m"(*__xg(ptr)), "0"(old) 25 : "memory"); 26 return prev; 27 case 4: 28 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" 29 : "=a"(prev) 30 : "q"(new), "m"(*__xg(ptr)), "0"(old) 31 : "memory"); 32 return prev; 33 } 34 return old; 35} 36 37#define ARCH_CMPXCHG(ptr,o,n)\ 38 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ 39 (unsigned long)(n),sizeof(*(ptr)))) 40#define IS_CONCURRENT 1 /* check race */ 41#endif 42 43#ifndef ARCH_ADD 44#define ARCH_ADD(p,a) (*(p) += (a)) 45#define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */ 46#define NO_CONCURRENT_ACCESS /* use semaphore to avoid race */ 47#define IS_CONCURRENT 0 /* no race check */ 48#endif 49 50#if IS_CONCURRENT 51static void mix_areas_16(unsigned int size, 52 volatile signed short *dst, signed short *src, 53 volatile signed int *sum, size_t dst_step, 54 size_t src_step, size_t sum_step) 55{ 56 register signed int sample, old_sample; 57 58 for (;;) { 59 sample = *src; 60 old_sample = *sum; 61 if (ARCH_CMPXCHG(dst, 0, 1) == 0) 62 sample -= old_sample; 63 ARCH_ADD(sum, sample); 64 do { 65 old_sample = *sum; 66 if (old_sample > 0x7fff) 67 sample = 0x7fff; 68 else if (old_sample < -0x8000) 69 sample = -0x8000; 70 else 71 sample = old_sample; 72 *dst = sample; 73 } while (IS_CONCURRENT && *sum != old_sample); 74 if (!--size) 75 return; 76 src = (signed short *) ((char *)src + src_step); 77 dst = (signed short *) ((char *)dst + dst_step); 78 sum = (signed int *) ((char *)sum + sum_step); 79 } 80} 81 82static void mix_areas_32(unsigned int size, 83 volatile signed int *dst, signed int *src, 84 volatile signed int *sum, size_t dst_step, 85 size_t src_step, size_t sum_step) 86{ 87 register signed int sample, old_sample; 88 89 for (;;) { 90 sample = *src >> 8; 91 old_sample = *sum; 92 if (ARCH_CMPXCHG(dst, 0, 1) == 0) 93 sample -= old_sample; 94 ARCH_ADD(sum, sample); 95 do { 96 old_sample = *sum; 97 if (old_sample > 0x7fffff) 98 sample = 0x7fffffff; 99 else if (old_sample < -0x800000) 100 sample = -0x80000000; 101 else 102 sample = old_sample * 256; 103 *dst = sample; 104 } while (IS_CONCURRENT && *sum != old_sample); 105 if (!--size) 106 return; 107 src = (signed int *) ((char *)src + src_step); 108 dst = (signed int *) ((char *)dst + dst_step); 109 sum = (signed int *) ((char *)sum + sum_step); 110 } 111} 112 113static void mix_select_callbacks(snd_pcm_direct_t *dmix) 114{ 115 dmix->u.dmix.mix_areas_16 = mix_areas_16; 116 dmix->u.dmix.mix_areas_32 = mix_areas_32; 117} 118 119#else 120 121/* non-concurrent version, supporting both endians */ 122#define generic_dmix_supported_format \ 123 ((1ULL << SND_PCM_FORMAT_S16_LE) | (1ULL << SND_PCM_FORMAT_S32_LE) |\ 124 (1ULL << SND_PCM_FORMAT_S16_BE) | (1ULL << SND_PCM_FORMAT_S32_BE) |\ 125 (1ULL << SND_PCM_FORMAT_S24_LE) | (1ULL << SND_PCM_FORMAT_S24_3LE) | \ 126 (1ULL << SND_PCM_FORMAT_U8)) 127 128#include <byteswap.h> 129 130static void generic_mix_areas_16_native(unsigned int size, 131 volatile signed short *dst, 132 signed short *src, 133 volatile signed int *sum, 134 size_t dst_step, 135 size_t src_step, 136 size_t sum_step) 137{ 138 register signed int sample; 139 140 for (;;) { 141 sample = *src; 142 if (! *dst) { 143 *sum = sample; 144 *dst = *src; 145 } else { 146 sample += *sum; 147 *sum = sample; 148 if (sample > 0x7fff) 149 sample = 0x7fff; 150 else if (sample < -0x8000) 151 sample = -0x8000; 152 *dst = sample; 153 } 154 if (!--size) 155 return; 156 src = (signed short *) ((char *)src + src_step); 157 dst = (signed short *) ((char *)dst + dst_step); 158 sum = (signed int *) ((char *)sum + sum_step); 159 } 160} 161 162static void generic_remix_areas_16_native(unsigned int size, 163 volatile signed short *dst, 164 signed short *src, 165 volatile signed int *sum, 166 size_t dst_step, 167 size_t src_step, 168 size_t sum_step) 169{ 170 register signed int sample; 171 172 for (;;) { 173 sample = *src; 174 if (! *dst) { 175 *sum = -sample; 176 *dst = -sample; 177 } else { 178 *sum = sample = *sum - sample; 179 if (sample > 0x7fff) 180 sample = 0x7fff; 181 else if (sample < -0x8000) 182 sample = -0x8000; 183 *dst = sample; 184 } 185 if (!--size) 186 return; 187 src = (signed short *) ((char *)src + src_step); 188 dst = (signed short *) ((char *)dst + dst_step); 189 sum = (signed int *) ((char *)sum + sum_step); 190 } 191} 192 193static void generic_mix_areas_32_native(unsigned int size, 194 volatile signed int *dst, 195 signed int *src, 196 volatile signed int *sum, 197 size_t dst_step, 198 size_t src_step, 199 size_t sum_step) 200{ 201 register signed int sample; 202 203 for (;;) { 204 sample = *src >> 8; 205 if (! *dst) { 206 *sum = sample; 207 *dst = *src; 208 } else { 209 sample += *sum; 210 *sum = sample; 211 if (sample > 0x7fffff) 212 sample = 0x7fffffff; 213 else if (sample < -0x800000) 214 sample = -0x80000000; 215 else 216 sample *= 256; 217 *dst = sample; 218 } 219 if (!--size) 220 return; 221 src = (signed int *) ((char *)src + src_step); 222 dst = (signed int *) ((char *)dst + dst_step); 223 sum = (signed int *) ((char *)sum + sum_step); 224 } 225} 226 227static void generic_remix_areas_32_native(unsigned int size, 228 volatile signed int *dst, 229 signed int *src, 230 volatile signed int *sum, 231 size_t dst_step, 232 size_t src_step, 233 size_t sum_step) 234{ 235 register signed int sample; 236 237 for (;;) { 238 sample = *src >> 8; 239 if (! *dst) { 240 *sum = -sample; 241 *dst = -*src; 242 } else { 243 *sum = sample = *sum - sample; 244 if (sample > 0x7fffff) 245 sample = 0x7fffffff; 246 else if (sample < -0x800000) 247 sample = -0x80000000; 248 else 249 sample *= 256; 250 *dst = sample; 251 } 252 if (!--size) 253 return; 254 src = (signed int *) ((char *)src + src_step); 255 dst = (signed int *) ((char *)dst + dst_step); 256 sum = (signed int *) ((char *)sum + sum_step); 257 } 258} 259 260static void generic_mix_areas_16_swap(unsigned int size, 261 volatile signed short *dst, 262 signed short *src, 263 volatile signed int *sum, 264 size_t dst_step, 265 size_t src_step, 266 size_t sum_step) 267{ 268 register signed int sample; 269 270 for (;;) { 271 sample = (signed short) bswap_16(*src); 272 if (! *dst) { 273 *sum = sample; 274 *dst = *src; 275 } else { 276 sample += *sum; 277 *sum = sample; 278 if (sample > 0x7fff) 279 sample = 0x7fff; 280 else if (sample < -0x8000) 281 sample = -0x8000; 282 *dst = (signed short) bswap_16((signed short) sample); 283 } 284 if (!--size) 285 return; 286 src = (signed short *) ((char *)src + src_step); 287 dst = (signed short *) ((char *)dst + dst_step); 288 sum = (signed int *) ((char *)sum + sum_step); 289 } 290} 291 292static void generic_remix_areas_16_swap(unsigned int size, 293 volatile signed short *dst, 294 signed short *src, 295 volatile signed int *sum, 296 size_t dst_step, 297 size_t src_step, 298 size_t sum_step) 299{ 300 register signed int sample; 301 302 for (;;) { 303 sample = (signed short) bswap_16(*src); 304 if (! *dst) { 305 *sum = -sample; 306 *dst = (signed short) bswap_16((signed short) -sample); 307 } else { 308 *sum = sample = *sum - sample; 309 if (sample > 0x7fff) 310 sample = 0x7fff; 311 else if (sample < -0x8000) 312 sample = -0x8000; 313 *dst = (signed short) bswap_16((signed short) sample); 314 } 315 if (!--size) 316 return; 317 src = (signed short *) ((char *)src + src_step); 318 dst = (signed short *) ((char *)dst + dst_step); 319 sum = (signed int *) ((char *)sum + sum_step); 320 } 321} 322 323static void generic_mix_areas_32_swap(unsigned int size, 324 volatile signed int *dst, 325 signed int *src, 326 volatile signed int *sum, 327 size_t dst_step, 328 size_t src_step, 329 size_t sum_step) 330{ 331 register signed int sample; 332 333 for (;;) { 334 sample = bswap_32(*src) >> 8; 335 if (! *dst) { 336 *sum = sample; 337 *dst = *src; 338 } else { 339 sample += *sum; 340 *sum = sample; 341 if (sample > 0x7fffff) 342 sample = 0x7fffffff; 343 else if (sample < -0x800000) 344 sample = -0x80000000; 345 else 346 sample *= 256; 347 *dst = bswap_32(sample); 348 } 349 if (!--size) 350 return; 351 src = (signed int *) ((char *)src + src_step); 352 dst = (signed int *) ((char *)dst + dst_step); 353 sum = (signed int *) ((char *)sum + sum_step); 354 } 355} 356 357static void generic_remix_areas_32_swap(unsigned int size, 358 volatile signed int *dst, 359 signed int *src, 360 volatile signed int *sum, 361 size_t dst_step, 362 size_t src_step, 363 size_t sum_step) 364{ 365 register signed int sample; 366 367 for (;;) { 368 sample = bswap_32(*src) >> 8; 369 if (! *dst) { 370 *sum = -sample; 371 *dst = bswap_32(-sample); 372 } else { 373 *sum = sample = *sum - sample; 374 if (sample > 0x7fffff) 375 sample = 0x7fffffff; 376 else if (sample < -0x800000) 377 sample = -0x80000000; 378 else 379 sample *= 256; 380 *dst = bswap_32(sample); 381 } 382 if (!--size) 383 return; 384 src = (signed int *) ((char *)src + src_step); 385 dst = (signed int *) ((char *)dst + dst_step); 386 sum = (signed int *) ((char *)sum + sum_step); 387 } 388} 389 390/* always little endian */ 391static void generic_mix_areas_24(unsigned int size, 392 volatile unsigned char *dst, 393 unsigned char *src, 394 volatile signed int *sum, 395 size_t dst_step, 396 size_t src_step, 397 size_t sum_step) 398{ 399 register signed int sample; 400 401 for (;;) { 402 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16); 403 if (!(dst[0] | dst[1] | dst[2])) { 404 *sum = sample; 405 } else { 406 sample += *sum; 407 *sum = sample; 408 if (sample > 0x7fffff) 409 sample = 0x7fffff; 410 else if (sample < -0x800000) 411 sample = -0x800000; 412 } 413 dst[0] = sample; 414 dst[1] = sample >> 8; 415 dst[2] = sample >> 16; 416 if (!--size) 417 return; 418 dst += dst_step; 419 src += src_step; 420 sum = (signed int *) ((char *)sum + sum_step); 421 } 422} 423 424static void generic_remix_areas_24(unsigned int size, 425 volatile unsigned char *dst, 426 unsigned char *src, 427 volatile signed int *sum, 428 size_t dst_step, 429 size_t src_step, 430 size_t sum_step) 431{ 432 register signed int sample; 433 434 for (;;) { 435 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16); 436 if (!(dst[0] | dst[1] | dst[2])) { 437 sample = -sample; 438 *sum = sample; 439 } else { 440 *sum = sample = *sum - sample; 441 if (sample > 0x7fffff) 442 sample = 0x7fffff; 443 else if (sample < -0x800000) 444 sample = -0x800000; 445 } 446 dst[0] = sample; 447 dst[1] = sample >> 8; 448 dst[2] = sample >> 16; 449 if (!--size) 450 return; 451 dst += dst_step; 452 src += src_step; 453 sum = (signed int *) ((char *)sum + sum_step); 454 } 455} 456 457static void generic_mix_areas_u8(unsigned int size, 458 volatile unsigned char *dst, 459 unsigned char *src, 460 volatile signed int *sum, 461 size_t dst_step, 462 size_t src_step, 463 size_t sum_step) 464{ 465 for (;;) { 466 register int sample = *src - 0x80; 467 if (*dst == 0x80) { 468 *sum = sample; 469 } else { 470 sample += *sum; 471 *sum = sample; 472 if (sample > 0x7f) 473 sample = 0x7f; 474 else if (sample < -0x80) 475 sample = -0x80; 476 } 477 *dst = sample + 0x80; 478 if (!--size) 479 return; 480 dst += dst_step; 481 src += src_step; 482 sum = (signed int *) ((char *)sum + sum_step); 483 } 484} 485 486static void generic_remix_areas_u8(unsigned int size, 487 volatile unsigned char *dst, 488 unsigned char *src, 489 volatile signed int *sum, 490 size_t dst_step, 491 size_t src_step, 492 size_t sum_step) 493{ 494 for (;;) { 495 register int sample = *src - 0x80; 496 if (*dst == 0x80) { 497 sample = -sample; 498 *sum = sample; 499 } else { 500 *sum = sample = *sum - sample; 501 if (sample > 0x7f) 502 sample = 0x7f; 503 else if (sample < -0x80) 504 sample = -0x80; 505 } 506 *dst = sample + 0x80; 507 if (!--size) 508 return; 509 dst += dst_step; 510 src += src_step; 511 sum = (signed int *) ((char *)sum + sum_step); 512 } 513} 514 515 516static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix) 517{ 518 if (snd_pcm_format_cpu_endian(dmix->shmptr->s.format)) { 519 dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native; 520 dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native; 521 dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_native; 522 dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_native; 523 } else { 524 dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_swap; 525 dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap; 526 dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_swap; 527 dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_swap; 528 } 529 dmix->u.dmix.mix_areas_24 = generic_mix_areas_24; 530 dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8; 531 dmix->u.dmix.remix_areas_24 = generic_remix_areas_24; 532 dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8; 533} 534 535#endif 536