|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* ! 25: * audio_mix.c ! 26: * ! 27: * Copyright (c) 1991, NeXT Computer, Inc. All rights reserved. ! 28: * ! 29: * Audio driver mixing. ! 30: * ! 31: * HISTORY ! 32: * 07/14/92/mtm Original coding. ! 33: */ ! 34: ! 35: #import "audioLog.h" ! 36: #import "audio_mix.h" ! 37: #import "audio_peak.h" ! 38: #import "audio_mulaw.h" ! 39: #import <architecture/byte_order.h> ! 40: #import <limits.h> ! 41: #import <bsd/string.h> ! 42: ! 43: #define MULAW_MAX 128 ! 44: #define MULAW_MIN 0 ! 45: ! 46: /* ! 47: * Macros to clip int to short/byte/mulaw-byte and load into pointer. ! 48: * Increments destination pointer. ! 49: * Increments clip count. ! 50: */ ! 51: #define clip16(i,p,c) if (i > SHRT_MAX) { \ ! 52: *p++ = SHRT_MAX; \ ! 53: c++; \ ! 54: } else if (i < SHRT_MIN) { \ ! 55: *p++ = SHRT_MIN; \ ! 56: c++; \ ! 57: } else \ ! 58: *p++ = (short)i; ! 59: ! 60: #define clip8(i,p,c) if (i > SCHAR_MAX) { \ ! 61: *p++ = SCHAR_MAX; \ ! 62: c++; \ ! 63: } else if (i < SCHAR_MIN) { \ ! 64: *p++ = SCHAR_MIN; \ ! 65: c++; \ ! 66: } else \ ! 67: *p++ = (char)i; ! 68: ! 69: /* xor the high bit to convert between 2's comp and 1's comp (unary) */ ! 70: #define unary(i) (((i) ^ (char)0x80) | ((i) & (char)0x7f)) ! 71: ! 72: #define clipUnary8(i,p,c) if (i > SCHAR_MAX) { \ ! 73: *p++ = unary(SCHAR_MAX); \ ! 74: c++; \ ! 75: } else if (i < SCHAR_MIN) { \ ! 76: *p++ = unary(SCHAR_MIN); \ ! 77: c++; \ ! 78: } else \ ! 79: *p++ = unary((char)i); ! 80: ! 81: #define clipMulaw8(i,p,c) if (i > SHRT_MAX) { \ ! 82: *p++ = MULAW_MAX; \ ! 83: c++; \ ! 84: } else if (i < SHRT_MIN) { \ ! 85: *p++ = MULAW_MIN; \ ! 86: c++; \ ! 87: } else \ ! 88: *p++ = audio_shortToMulaw((short)i); ! 89: ! 90: ! 91: void audio_swapSamples(short *src, short *dest, u_int count) ! 92: { ! 93: #if defined(hppa) || defined(sparc) ! 94: // I have noticed that src is not aligned to short boundary when two samples with ! 95: // different sampling rate are played at the same time. Also this happens at the end of ! 96: // second sample. This results in an alignment trap in hppa leading to system crash. ! 97: // Therefore I am providing this workaround of forcing the alignment to even bounary, ! 98: // instead of a complete fix. This is ! 99: // a late stage for us to make big changes for FCS (6/6/94). ! 100: // This has to be fixed for 3.3 ! 101: // TBD: Fix the alignment probs ! 102: unsigned int ptr,ptr1; ! 103: ptr = (unsigned int)src; ! 104: ptr1 = (unsigned int)dest; ! 105: ! 106: // if (!count) return; ! 107: if ((ptr & 1)){ ! 108: // printf("The source is not aligned %x\n",src); ! 109: ptr &= 0xfffffffe; //forcing the alignment ! 110: src = (short *)ptr; ! 111: } ! 112: if ((ptr1 & 1)){ ! 113: // printf("The Dest is not aligned %x \n",dest); ! 114: ptr1 &= 0xfffffffe; //forcing the alignment ! 115: dest = (short *)ptr1; ! 116: } ! 117: #endif ! 118: while (count--) ! 119: *dest++ = NXSwapBigShortToHost(*src++); ! 120: } ! 121: ! 122: void audio_twosComp8ToUnary(char *src, char *dest, u_int count) ! 123: { ! 124: while (count--) { ! 125: /* xor the high bit */ ! 126: *dest++ = unary(*src); ! 127: src++; ! 128: } ! 129: } ! 130: ! 131: /* ! 132: * Scale samples, return number of times clipped. ! 133: */ ! 134: u_int audio_scaleSamples(char *src, char *dest, u_int count, ! 135: IOAudioDataFormat format, u_int chanCount, ! 136: int leftGain, int rightGain) ! 137: { ! 138: short *shortSrc, *shortDest; ! 139: u_int clips = 0; ! 140: int val = 0; ! 141: int leftGain8, rightGain8, monoGain = 0; ! 142: unsigned char *uSrc, *uDest; ! 143: ! 144: /* ! 145: * Gains MUST be signed values when used in the following ! 146: * calculations. It is not clear (to me) why. ! 147: */ ! 148: ! 149: switch (format) { ! 150: case IOAudioDataFormatLinear16: ! 151: count /= 2; ! 152: shortSrc = (short *)src; ! 153: shortDest = (short *)dest; ! 154: switch (chanCount) { ! 155: case 1: ! 156: monoGain = (leftGain + rightGain) / 2; ! 157: while (count--) { ! 158: val = (((int)*shortSrc++)*monoGain)>>15; ! 159: clip16(val, shortDest, clips); ! 160: } ! 161: break; ! 162: case 2: ! 163: count /= 2; ! 164: while (count--) { ! 165: val = (((int)*shortSrc++)*leftGain)>>15; ! 166: /* ! 167: * FIXME: clipping not working. ! 168: */ ! 169: *shortDest++ = (short)val; ! 170: //clip16(val, shortDest, clips); ! 171: val = (((int)*shortSrc++)*rightGain)>>15; ! 172: *shortDest++ = (short)val; ! 173: //clip16(val, shortDest, clips); ! 174: } ! 175: break; ! 176: default: ! 177: break; ! 178: } ! 179: break; ! 180: case IOAudioDataFormatLinear8: ! 181: /* Gains are passed in 16-bit range */ ! 182: leftGain8 = leftGain >> 8; ! 183: rightGain8 = rightGain >> 8; ! 184: switch (chanCount) { ! 185: case 1: ! 186: monoGain = (leftGain8 + rightGain8) / 2; ! 187: while (count--) { ! 188: val = (((int)*src++)*monoGain)>>7; ! 189: clip8(val, dest, clips); ! 190: } ! 191: break; ! 192: case 2: ! 193: count /= 2; ! 194: while (count--) { ! 195: val = (((int)*src++)*leftGain8)>>7; ! 196: clip8(val, dest, clips); ! 197: val = (((int)*src++)*rightGain8)>>7; ! 198: clip8(val, dest, clips); ! 199: } ! 200: break; ! 201: default: ! 202: break; ! 203: } ! 204: break; ! 205: case IOAudioDataFormatMulaw8: ! 206: /* Gains are passed in 16-bit range */ ! 207: leftGain8 = leftGain >> 8; ! 208: rightGain8 = rightGain >> 8; ! 209: uSrc = (unsigned char *)src; ! 210: uDest = (unsigned char *)dest; ! 211: switch (chanCount) { ! 212: case 1: ! 213: monoGain = (leftGain8 + rightGain8) / 2; ! 214: while (count--) { ! 215: val = (((int)audio_muLaw[(unsigned int)*uSrc++])*monoGain)>>7; ! 216: clipMulaw8(val, uDest, clips); ! 217: } ! 218: break; ! 219: case 2: ! 220: count /= 2; ! 221: while (count--) { ! 222: val = (((int)audio_muLaw[(unsigned int)*uSrc++])*leftGain8)>>7; ! 223: clipMulaw8(val, uDest, clips); ! 224: val = (((int)audio_muLaw[(unsigned int)*uSrc++])* ! 225: rightGain8)>>7; ! 226: clipMulaw8(val, uDest, clips); ! 227: } ! 228: break; ! 229: default: ! 230: break; ! 231: } ! 232: break; ! 233: default: ! 234: IOLog("Audio: unrecognized format %d in scaleSamples\n", format); ! 235: break; ! 236: } ! 237: ! 238: return clips; ! 239: } ! 240: ! 241: void audio_resample22To44(char *src, char *dest, u_int count, ! 242: IOAudioDataFormat format, u_int channelCount) ! 243: { ! 244: if ( channelCount == 1 ) ! 245: { ! 246: /* Just double samples! */ ! 247: audio_convertMonoToStereo(src, dest, count, format); ! 248: } ! 249: else ! 250: { ! 251: short *shortSrc, *shortDest; ! 252: ! 253: shortSrc = (short *)src; ! 254: shortDest = (short *)dest; ! 255: ! 256: count /= 2; ! 257: while (count--) ! 258: { ! 259: *(shortDest+2) = *shortSrc; ! 260: *shortDest++ = *shortSrc++; ! 261: *(shortDest+2) = *shortSrc; ! 262: *shortDest++ = *shortSrc++; ! 263: shortDest += 2; ! 264: } ! 265: } ! 266: } ! 267: ! 268: void audio_resample44To22(char *src, char *dest, u_int count, ! 269: IOAudioDataFormat format, u_int *phase) ! 270: { ! 271: short *shortSrc, *shortDest; ! 272: ! 273: /* ! 274: * FIXME: implement phase. ! 275: */ ! 276: ! 277: count /= 2; /* src is incremented twice each loop */ ! 278: ! 279: switch (format) { ! 280: case IOAudioDataFormatLinear16: ! 281: count /= 2; ! 282: shortSrc = (short *)src; ! 283: shortDest = (short *)dest; ! 284: while (count--) { ! 285: *shortDest++ = *shortSrc++; ! 286: shortSrc++; ! 287: } ! 288: break; ! 289: case IOAudioDataFormatLinear8: ! 290: case IOAudioDataFormatMulaw8: ! 291: while (count--) { ! 292: *dest++ = *src++; ! 293: src++; ! 294: } ! 295: break; ! 296: default: ! 297: IOLog("Audio: unrecognized format %d in resample\n", format); ! 298: break; ! 299: } ! 300: } ! 301: ! 302: void audio_convertMonoToStereo(char *src, char *dest, u_int count, ! 303: IOAudioDataFormat format) ! 304: { ! 305: short *shortSrc, *shortDest; ! 306: ! 307: switch (format) { ! 308: case IOAudioDataFormatLinear16: ! 309: count /= 2; ! 310: shortSrc = (short *)src; ! 311: shortDest = (short *)dest; ! 312: while (count--) { ! 313: *shortDest++ = *shortSrc; ! 314: *shortDest++ = *shortSrc++; ! 315: } ! 316: break; ! 317: case IOAudioDataFormatLinear8: ! 318: case IOAudioDataFormatMulaw8: ! 319: while (count--) { ! 320: *dest++ = *src; ! 321: *dest++ = *src++; ! 322: } ! 323: break; ! 324: default: ! 325: IOLog("Audio: unrecognized format %d in convMono\n", format); ! 326: break; ! 327: } ! 328: } ! 329: ! 330: void audio_convertStereoToMono(char *src, char *dest, u_int count, ! 331: IOAudioDataFormat format, u_int *phase) ! 332: { ! 333: short *shortSrc, *shortDest; ! 334: unsigned char *uSrc, *uDest; ! 335: int sample; ! 336: ! 337: /* ! 338: * FIXME: implement phase. ! 339: */ ! 340: ! 341: count /= 2; /* src is incremented twice each loop */ ! 342: ! 343: switch (format) { ! 344: case IOAudioDataFormatLinear16: ! 345: count /= 2; ! 346: shortSrc = (short *)src; ! 347: shortDest = (short *)dest; ! 348: while (count--) { ! 349: sample = *shortSrc++; ! 350: sample += *shortSrc++; ! 351: sample += sample & 1; /* round up if odd */ ! 352: sample /= 2; ! 353: *shortDest++ = (short)sample; ! 354: } ! 355: break; ! 356: case IOAudioDataFormatLinear8: ! 357: while (count--) { ! 358: sample = *src++; ! 359: sample += *src++; ! 360: sample += sample & 1; ! 361: sample /= 2; ! 362: *dest++ = (char)sample; ! 363: } ! 364: break; ! 365: case IOAudioDataFormatMulaw8: ! 366: uSrc = (unsigned char *)src; ! 367: uDest = (unsigned char *)dest; ! 368: while (count--) { ! 369: sample = audio_muLaw[(unsigned int)*uSrc++]; ! 370: sample += audio_muLaw[(unsigned int)*uSrc++]; ! 371: sample += sample & 1; ! 372: sample /= 2; ! 373: *uDest++ = audio_shortToMulaw((short)sample); ! 374: } ! 375: break; ! 376: default: ! 377: IOLog("Audio: unrecognized format %d in convMono\n", format); ! 378: break; ! 379: } ! 380: } ! 381: ! 382: void audio_convertLinear8ToLinear16(char *src, short *dest, u_int count) ! 383: { ! 384: while (count--) ! 385: *dest++ = *src++ << 8; ! 386: } ! 387: ! 388: void audio_convertLinear8ToMulaw8(char *src, char *dest, u_int count) ! 389: { ! 390: while (count--) ! 391: *dest = audio_shortToMulaw((short)(*src++) << 8); ! 392: } ! 393: ! 394: void audio_convertLinear16ToLinear8(short *src, char *dest, u_int count, ! 395: u_int *phase) ! 396: { ! 397: while (count--) ! 398: *dest++ = *src++ >> 8; ! 399: } ! 400: ! 401: void audio_convertLinear16ToMulaw8(short *src, char *dest, u_int count, ! 402: u_int *phase) ! 403: { ! 404: while (count--) ! 405: *dest = audio_shortToMulaw(*src++); ! 406: } ! 407: ! 408: void audio_convertMulaw8ToLinear16(char *src, short *dest, u_int count) ! 409: { ! 410: unsigned char *uSrc = (unsigned char *)src; ! 411: unsigned char *uDest = (unsigned char *)dest; ! 412: ! 413: while (count--) ! 414: *uDest++ = audio_muLaw[(unsigned int)*uSrc++]; ! 415: } ! 416: ! 417: void audio_convertMulaw8ToLinear8(char *src, char *dest, u_int count) ! 418: { ! 419: return; ! 420: } ! 421: ! 422: /* ! 423: * Mix source into destination. ! 424: * Return number of times mix clipped. ! 425: */ ! 426: u_int audio_mix(char *src, char *dest, u_int count, IOAudioDataFormat format, ! 427: boolean_t virgin) ! 428: { ! 429: int sum; ! 430: u_int clips = 0; ! 431: short *shortSrc, *shortDest; ! 432: unsigned char *uSrc, *uDest; ! 433: ! 434: if (count == 0) ! 435: return 0; ! 436: ! 437: if (virgin) { ! 438: if (format == IOAudioDataFormatLinear8) ! 439: audio_twosComp8ToUnary(src, dest, count); ! 440: else ! 441: bcopy(src, dest, count); ! 442: } else switch (format) { ! 443: case IOAudioDataFormatLinear16: ! 444: count /= 2; ! 445: shortSrc = (short *)src; ! 446: shortDest = (short *)dest; ! 447: while (count--) { ! 448: sum = (int)*shortDest + (int)*shortSrc++; ! 449: clip16(sum, shortDest, clips); ! 450: } ! 451: break; ! 452: case IOAudioDataFormatLinear8: ! 453: while (count--) { ! 454: /* ! 455: * FIXME: only convert to unary if devIsUnary. ! 456: */ ! 457: sum = (int)unary(*dest) + (int)*src++; ! 458: clipUnary8(sum, dest, clips); ! 459: } ! 460: break; ! 461: case IOAudioDataFormatMulaw8: ! 462: uSrc = (unsigned char *)src; ! 463: uDest = (unsigned char *)dest; ! 464: while (count--) { ! 465: sum = (int)audio_muLaw[(unsigned int)*uDest] + ! 466: (int)audio_muLaw[(unsigned int)*uSrc++]; ! 467: clipMulaw8(sum, uDest, clips); ! 468: } ! 469: break; ! 470: default: ! 471: IOLog("Audio: unrecognized format %d in mix\n", format); ! 472: break; ! 473: } ! 474: ! 475: return clips; ! 476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.