Annotation of driverkit/libDriver/Kernel/audio_mix.c, revision 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.