Annotation of driverkit/libDriver/Kernel/audio_mix.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.